From ffc74eb959c619f79afeabc6e672083559bc92dd Mon Sep 17 00:00:00 2001 From: Tobias Schultze Date: Sun, 1 Oct 2017 17:08:32 +0200 Subject: [PATCH 01/19] [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 d819ff0a6c..7bbcfe0375 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 @@ use Doctrine\DBAL\Platforms\SQLServer2008Platform; * @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 978373da0c..7af50a6507 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 1c9c82bc12..8d46bf9e63 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/HttpFoundation/DbalSessionHandlerTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/HttpFoundation/DbalSessionHandlerTest.php @@ -18,6 +18,8 @@ use Symfony\Bridge\Doctrine\HttpFoundation\DbalSessionHandler; * Test class for DbalSessionHandler. * * @author Drak + * + * @group legacy */ class DbalSessionHandlerTest extends TestCase { From bbc52a1d14358500b39073ba7cb46ed95fbc5810 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Tue, 3 Oct 2017 11:44:07 +0200 Subject: [PATCH 02/19] [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 870965201e..11161d46eb 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 77a0288308..593c02f145 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Controller/ControllerTrait.php +++ b/src/Symfony/Bundle/FrameworkBundle/Controller/ControllerTrait.php @@ -39,6 +39,34 @@ use Doctrine\Bundle\DoctrineBundle\Registry; */ 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 @@ trait ControllerTrait * @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 @@ trait ControllerTrait * @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 @@ trait ControllerTrait * @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 @@ trait ControllerTrait * @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 @@ trait ControllerTrait * @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 @@ trait ControllerTrait * @param string $message The message * * @throws \LogicException + * + * @final since version 3.4 */ protected function addFlash($type, $message) { @@ -167,6 +209,8 @@ trait ControllerTrait * @return bool * * @throws \LogicException + * + * @final since version 3.4 */ protected function isGranted($attributes, $subject = null) { @@ -186,6 +230,8 @@ trait ControllerTrait * @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 @@ trait ControllerTrait * @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 @@ trait ControllerTrait * @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 @@ trait ControllerTrait * @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 @@ trait ControllerTrait * @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 @@ trait ControllerTrait * @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 @@ trait ControllerTrait * @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 @@ trait ControllerTrait * @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 @@ trait ControllerTrait * @return Registry * * @throws \LogicException If DoctrineBundle is not available + * + * @final since version 3.4 */ protected function getDoctrine() { @@ -368,6 +430,8 @@ trait ControllerTrait * @throws \LogicException If SecurityBundle is not available * * @see TokenInterface::getUser() + * + * @final since version 3.4 */ protected function getUser() { @@ -394,6 +458,8 @@ trait ControllerTrait * @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 ed57e748dc26c5210581d205b698f1d89e05d09a Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Tue, 3 Oct 2017 15:54:22 +0200 Subject: [PATCH 03/19] 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 ba3eff0f0d..d01f5f45e1 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 04/19] 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 12d99a20bf..1ba3c57c59 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 b81871730c..82391b216d 100644 --- a/src/Symfony/Component/Yaml/Parser.php +++ b/src/Symfony/Component/Yaml/Parser.php @@ -201,6 +201,8 @@ class Parser 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 @@ class Parser } $context = 'mapping'; - Inline::initialize($flags, $this->getRealCurrentLineNb(), $this->filename); try { $i = 0; $evaluateKey = !(Yaml::PARSE_KEYS_AS_STRINGS & $flags); @@ -402,7 +403,6 @@ class Parser // 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 @@ class Parser } } - 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 38ee2e0605..868545683e 100644 --- a/src/Symfony/Component/Yaml/Tests/ParserTest.php +++ b/src/Symfony/Component/Yaml/Tests/ParserTest.php @@ -1853,8 +1853,8 @@ YAML; /** * @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 05/19] [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 f49eb6dbc2..49fd03165a 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 4a594d3ae7..3c5ba3e93d 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 @@ class AboutCommand extends ContainerAwareCommand /** @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 @@ class AboutCommand extends ContainerAwareCommand 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 @@ class AboutCommand extends ContainerAwareCommand 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 06/19] 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 611bbac3ae..7d40c0597f 100644 --- a/src/Symfony/Component/Yaml/Parser.php +++ b/src/Symfony/Component/Yaml/Parser.php @@ -384,6 +384,7 @@ class Parser if (0 === $this->currentLineNb) { $parseError = false; $previousLineWasNewline = false; + $previousLineWasTerminatedWithBackslash = false; $value = ''; foreach ($this->lines as $line) { @@ -401,13 +402,25 @@ class Parser 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 @@ class Parser } 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 4c62f9bd17..67ed642084 100644 --- a/src/Symfony/Component/Yaml/Tests/ParserTest.php +++ b/src/Symfony/Component/Yaml/Tests/ParserTest.php @@ -1543,6 +1543,17 @@ EOT; $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 07/19] [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 94eafb5d0a..6817e71ea8 100644 --- a/src/Symfony/Component/Yaml/Parser.php +++ b/src/Symfony/Component/Yaml/Parser.php @@ -181,7 +181,7 @@ class Parser $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 @@ class Parser $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 @@ class Parser } } 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 1ff5e3e8a5..9be278f67e 100644 --- a/src/Symfony/Component/Yaml/Tests/ParserTest.php +++ b/src/Symfony/Component/Yaml/Tests/ParserTest.php @@ -1179,6 +1179,34 @@ bar: 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 08/19] [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 6eceb0defe..2d43ba7a60 100644 --- a/src/Symfony/Component/DependencyInjection/Container.php +++ b/src/Symfony/Component/DependencyInjection/Container.php @@ -190,6 +190,7 @@ class Container implements ResettableContainerInterface unset($this->aliases[$id]); } + $wasSet = isset($this->services[$id]); $this->services[$id] = $service; if (null === $service) { @@ -203,11 +204,11 @@ class Container implements ResettableContainerInterface } 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 e2478ea22b..5cd988714a 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/ContainerTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/ContainerTest.php @@ -186,15 +186,29 @@ class ContainerTest extends TestCase /** * @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 @@ class ContainerTest extends TestCase /** * @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 a1422bf96a..d832a220c7 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php @@ -269,7 +269,7 @@ class PhpDumperTest extends TestCase /** * @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 @@ class PhpDumperTest extends TestCase 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 @@ class PhpDumperTest extends TestCase 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 09/19] [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 1e0617ebe2..d8ea346038 100644 --- a/src/Symfony/Component/Cache/Adapter/TagAwareAdapter.php +++ b/src/Symfony/Component/Cache/Adapter/TagAwareAdapter.php @@ -250,19 +250,12 @@ class TagAwareAdapter implements TagAwareAdapterInterface $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 10/19] [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 e5b6434c37..3996618fc1 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 2d2e04899c..a9a382b8e9 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 609d772e19..97c9c4a092 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 @@ use Symfony\Component\Security\Guard\Token\PostAuthenticationGuardToken; * * @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 0000000000..a1497b0eef --- /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 41a37e6fef..dd5ae2c16b 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\GuardAuthenticatorHandler; 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 @@ use Symfony\Component\Security\Http\RememberMe\RememberMeServicesInterface; * 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 @@ class GuardAuthenticationListener implements ListenerInterface } } - private function executeGuardAuthenticator($uniqueGuardKey, GuardAuthenticatorInterface $guardAuthenticator, GetResponseEvent $event) + private function executeGuardAuthenticator($uniqueGuardKey, AuthenticatorInterface $guardAuthenticator, GetResponseEvent $event) { $request = $event->getRequest(); try { @@ -100,12 +102,38 @@ class GuardAuthenticationListener implements ListenerInterface $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 @@ class GuardAuthenticationListener implements ListenerInterface * 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 5e1351dcc2..c8fb6e394e 100644 --- a/src/Symfony/Component/Security/Guard/GuardAuthenticatorHandler.php +++ b/src/Symfony/Component/Security/Guard/GuardAuthenticatorHandler.php @@ -61,14 +61,14 @@ class GuardAuthenticatorHandler /** * 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 @@ class GuardAuthenticatorHandler * 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 @@ class GuardAuthenticatorHandler * 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 307d70f9e9..2078ad237b 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\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. @@ -28,8 +27,10 @@ use Symfony\Component\Security\Http\EntryPoint\AuthenticationEntryPointInterface * 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 90b9580a3a..c93776a348 100644 --- a/src/Symfony/Component/Security/Guard/Provider/GuardAuthenticationProvider.php +++ b/src/Symfony/Component/Security/Guard/Provider/GuardAuthenticationProvider.php @@ -14,7 +14,7 @@ namespace Symfony\Component\Security\Guard\Provider; 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 @@ use Symfony\Component\Security\Core\Exception\AuthenticationExpiredException; 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 @@ class GuardAuthenticationProvider implements AuthenticationProviderInterface /** * Finds the correct authenticator for the token and calls it. * - * @param GuardTokenInterface $token + * @param TokenInterface|GuardTokenInterface $token * * @return TokenInterface */ @@ -101,7 +101,7 @@ class GuardAuthenticationProvider implements AuthenticationProviderInterface // 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 @@ class GuardAuthenticationProvider implements AuthenticationProviderInterface 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 943ca49247..60f703904c 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 @@ use Symfony\Component\Security\Core\Exception\AuthenticationException; /** * @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 @@ class GuardAuthenticationListenerTest extends TestCase 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 @@ class GuardAuthenticationListenerTest extends TestCase ->expects($this->once()) ->method('handleAuthenticationFailure') ->willReturn(new Response()); + // the second authenticator should *never* be called $authenticator2 ->expects($this->never()) @@ -112,10 +123,15 @@ class GuardAuthenticationListenerTest extends TestCase 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 @@ class GuardAuthenticationListenerTest extends TestCase 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 @@ class GuardAuthenticationListenerTest extends TestCase $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 @@ class GuardAuthenticationListenerTest extends TestCase $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 b46bc4a78d..29199d820e 100644 --- a/src/Symfony/Component/Security/Guard/Tests/GuardAuthenticatorHandlerTest.php +++ b/src/Symfony/Component/Security/Guard/Tests/GuardAuthenticatorHandlerTest.php @@ -128,7 +128,7 @@ class GuardAuthenticatorHandlerTest extends TestCase $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 abbe985c9e..e1b39417d7 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 11/19] [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 a34328ee8f..814ae7fb3b 100644 --- a/src/Symfony/Component/Config/ConfigCache.php +++ b/src/Symfony/Component/Config/ConfigCache.php @@ -149,6 +149,10 @@ class ConfigCache implements ConfigCacheInterface // 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 12/19] [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 e08e385e35..c8a4d5cd3a 100644 --- a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php +++ b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php @@ -899,25 +899,16 @@ EOF; 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 @@ EOF; if ($this->asFiles) { $code .= <<docStar} - * {@inheritdoc} - */ protected function load(\$file, \$lazyLoad = true) { return require \$file; @@ -1125,9 +1113,6 @@ EOF; 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 @@ EOF; return $this->parameters[$name]; } - /** - * {@inheritdoc} - */ public function hasParameter($name) { $name = $this->normalizeParameterName($name); @@ -1154,17 +1136,11 @@ EOF; 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 @@ EOF; } 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 b791398c13..e696dec6ae 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 @@ class Container extends AbstractContainer $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 44c052c0a9..c339856f02 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 @@ class ProjectServiceContainer extends Container $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 4353f7b065..219cf3431b 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 @@ class ProjectServiceContainer extends Container $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 @@ class ProjectServiceContainer extends Container 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 @@ class ProjectServiceContainer extends Container return $this->parameters[$name]; } - /** - * {@inheritdoc} - */ public function hasParameter($name) { $name = $this->normalizeParameterName($name); @@ -96,17 +81,11 @@ class ProjectServiceContainer 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/services12.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services12.php index 9017441bd6..2bd134a9f8 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 @@ class ProjectServiceContainer extends Container $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 @@ class ProjectServiceContainer extends Container 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 @@ class ProjectServiceContainer extends Container return $this->parameters[$name]; } - /** - * {@inheritdoc} - */ public function hasParameter($name) { $name = $this->normalizeParameterName($name); @@ -100,17 +85,11 @@ class ProjectServiceContainer 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/services13.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services13.php index a7fe891692..4cc353ca27 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 @@ class ProjectServiceContainer extends Container $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 e6870bcc45..0a6b97e65d 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 @@ class ProjectServiceContainer extends Container $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 7cff4f35bb..7546b1765a 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 @@ class ProjectServiceContainer extends Container $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 c802c9ae09..7dc51d12af 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 @@ class Symfony_DI_PhpDumper_Test_EnvParameters extends Container $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 @@ class Symfony_DI_PhpDumper_Test_EnvParameters extends Container 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 @@ class Symfony_DI_PhpDumper_Test_EnvParameters extends Container return $this->parameters[$name]; } - /** - * {@inheritdoc} - */ public function hasParameter($name) { $name = $this->normalizeParameterName($name); @@ -102,17 +87,11 @@ class Symfony_DI_PhpDumper_Test_EnvParameters 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/services31.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services31.php index 51d9626372..ffc76d8922 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 @@ class ProjectServiceContainer extends Container $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 af310ce2bd..e36cdcaedb 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 @@ class ProjectServiceContainer extends Container $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 f9de309827..357b8aa697 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 @@ class ProjectServiceContainer extends Container $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 @@ class ProjectServiceContainer extends Container 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 @@ class ProjectServiceContainer extends Container return $this->parameters[$name]; } - /** - * {@inheritdoc} - */ public function hasParameter($name) { $name = $this->normalizeParameterName($name); @@ -83,17 +68,11 @@ class ProjectServiceContainer 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_as_files.txt b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_as_files.txt index ced52118cf..3795ade480 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 c75138447d..7ec609ca5e 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 @@ class ProjectServiceContainer 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); @@ -374,9 +365,6 @@ class ProjectServiceContainer extends Container 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 @@ class ProjectServiceContainer extends Container return $this->parameters[$name]; } - /** - * {@inheritdoc} - */ public function hasParameter($name) { $name = $this->normalizeParameterName($name); @@ -403,17 +388,11 @@ class ProjectServiceContainer 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/services_array_params.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_array_params.php index 9c6f55d259..e5159861b4 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 @@ class ProjectServiceContainer extends Container $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 @@ class ProjectServiceContainer extends Container 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 @@ class ProjectServiceContainer extends Container return $this->parameters[$name]; } - /** - * {@inheritdoc} - */ public function hasParameter($name) { $name = $this->normalizeParameterName($name); @@ -104,17 +89,11 @@ class ProjectServiceContainer 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/services_base64_env.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_base64_env.php index 49fcf6e458..8513e25d2e 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 @@ class Symfony_DI_PhpDumper_Test_Base64Parameters extends Container $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 @@ class Symfony_DI_PhpDumper_Test_Base64Parameters extends Container 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 @@ class Symfony_DI_PhpDumper_Test_Base64Parameters extends Container return $this->parameters[$name]; } - /** - * {@inheritdoc} - */ public function hasParameter($name) { $name = $this->normalizeParameterName($name); @@ -83,17 +68,11 @@ class Symfony_DI_PhpDumper_Test_Base64Parameters 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/services_legacy_privates.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_legacy_privates.php index bedf268d47..fad546d7fc 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 @@ class Symfony_DI_PhpDumper_Test_Legacy_Privates 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); 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 87c8b58003..74e2a8ce09 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 @@ class ProjectServiceContainer extends Container $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 bbb0e9e00e..c7ea243ae8 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 @@ class ProjectServiceContainer extends Container $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 8f3e7aa7fc..8269736c0b 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 @@ class ProjectServiceContainer extends Container $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 0d2bb22b75..3b26928577 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 @@ class Symfony_DI_PhpDumper_Test_Rot13Parameters extends Container $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 @@ class Symfony_DI_PhpDumper_Test_Rot13Parameters extends Container })); } - /** - * {@inheritdoc} - */ public function getParameter($name) { if (!(isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters))) { @@ -102,9 +90,6 @@ class Symfony_DI_PhpDumper_Test_Rot13Parameters extends Container return $this->parameters[$name]; } - /** - * {@inheritdoc} - */ public function hasParameter($name) { $name = $this->normalizeParameterName($name); @@ -112,17 +97,11 @@ class Symfony_DI_PhpDumper_Test_Rot13Parameters 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/services_subscriber.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_subscriber.php index 400b28ca97..a4ab454e3e 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 @@ class ProjectServiceContainer extends Container $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 ef70ffb76c..c47e7c15d1 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 @@ class Symfony_DI_PhpDumper_Test_Uninitialized_Reference extends Container $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 13/19] [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 2d43ba7a60..c878af3d9e 100644 --- a/src/Symfony/Component/DependencyInjection/Container.php +++ b/src/Symfony/Component/DependencyInjection/Container.php @@ -199,16 +199,16 @@ class Container implements ResettableContainerInterface 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 @@ class Container implements ResettableContainerInterface { 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 @@ class Container implements ResettableContainerInterface // 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 5cd988714a..3afc118b3d 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/ContainerTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/ContainerTest.php @@ -186,7 +186,7 @@ class ContainerTest extends TestCase /** * @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 @@ class ContainerTest extends TestCase /** * @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 @@ class ContainerTest extends TestCase /** * @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 @@ class ContainerTest extends TestCase /** * @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 @@ class ContainerTest extends TestCase /** * @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 @@ class ContainerTest extends TestCase /** * @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 d832a220c7..991337681f 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php @@ -269,7 +269,7 @@ class PhpDumperTest extends TestCase /** * @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 @@ class PhpDumperTest extends TestCase /** * @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 8c39bf7845c1517284cacd979db16a0abaf20c83 Mon Sep 17 00:00:00 2001 From: "Alexander M. Turek" Date: Thu, 5 Oct 2017 11:48:08 +0200 Subject: [PATCH 14/19] 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 e5b6434c37..c0573eb219 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 2d2e04899c..5bc486f44f 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 7b55e30efd..373e4b6aca 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 62c6a2381a..bca53ef409 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 @@ class DoctrineDataCollector extends DataCollector ); } + 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 8cbd2c3eac..cc20869c7c 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/DataCollector/DoctrineDataCollectorTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/DataCollector/DoctrineDataCollectorTest.php @@ -101,6 +101,20 @@ class DoctrineDataCollectorTest extends TestCase $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 ec6434fe79..7cd75c5ec1 100644 --- a/src/Symfony/Bridge/Monolog/Logger.php +++ b/src/Symfony/Bridge/Monolog/Logger.php @@ -45,6 +45,16 @@ class Logger extends BaseLogger implements DebugLoggerInterface 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 22a4faac5c..8774045192 100644 --- a/src/Symfony/Bridge/Monolog/Processor/DebugProcessor.php +++ b/src/Symfony/Bridge/Monolog/Processor/DebugProcessor.php @@ -55,4 +55,13 @@ class DebugProcessor implements DebugLoggerInterface { 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 c24c7a4133..a5fab0583c 100644 --- a/src/Symfony/Bridge/Monolog/Tests/LoggerTest.php +++ b/src/Symfony/Bridge/Monolog/Tests/LoggerTest.php @@ -128,4 +128,17 @@ class LoggerTest extends TestCase $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 d5efaa8053..66f2a764e7 100644 --- a/src/Symfony/Bridge/Twig/DataCollector/TwigDataCollector.php +++ b/src/Symfony/Bridge/Twig/DataCollector/TwigDataCollector.php @@ -44,6 +44,16 @@ class TwigDataCollector extends DataCollector implements LateDataCollectorInterf { } + /** + * {@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 e1e86408cf..bf4deb3f6e 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 0e136bfe43..9067371981 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php @@ -609,9 +609,9 @@ class FrameworkExtension extends Extension } } - 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 fbd146452f..086cea89d9 100644 --- a/src/Symfony/Bundle/SecurityBundle/DataCollector/SecurityDataCollector.php +++ b/src/Symfony/Bundle/SecurityBundle/DataCollector/SecurityDataCollector.php @@ -203,6 +203,14 @@ class SecurityDataCollector extends DataCollector implements LateDataCollectorIn } } + /** + * {@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 07ddaf3f47..62d502f01f 100644 --- a/src/Symfony/Component/Cache/DataCollector/CacheDataCollector.php +++ b/src/Symfony/Component/Cache/DataCollector/CacheDataCollector.php @@ -53,6 +53,15 @@ class CacheDataCollector extends DataCollector implements LateDataCollectorInter $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 736bd84903..c6aa5389ac 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 3f1035e13d..2fb795f77b 100644 --- a/src/Symfony/Component/EventDispatcher/Debug/TraceableEventDispatcher.php +++ b/src/Symfony/Component/EventDispatcher/Debug/TraceableEventDispatcher.php @@ -212,6 +212,11 @@ class TraceableEventDispatcher implements TraceableEventDispatcherInterface 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 5483e81506..f0212753be 100644 --- a/src/Symfony/Component/EventDispatcher/Debug/TraceableEventDispatcherInterface.php +++ b/src/Symfony/Component/EventDispatcher/Debug/TraceableEventDispatcherInterface.php @@ -15,6 +15,8 @@ use Symfony\Component\EventDispatcher\EventDispatcherInterface; /** * @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 a1cf6708b3..53a3421afa 100644 --- a/src/Symfony/Component/EventDispatcher/Tests/Debug/TraceableEventDispatcherTest.php +++ b/src/Symfony/Component/EventDispatcher/Tests/Debug/TraceableEventDispatcherTest.php @@ -124,6 +124,21 @@ class TraceableEventDispatcherTest extends TestCase $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 378edf563b..db854b01bf 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 @@ class FormDataCollector extends DataCollector implements FormDataCollectorInterf { } + 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 24c0f8e871..7e591d414e 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 @@ class FormDataCollectorTest extends TestCase $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 1da376f7ad..fb29f76962 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 b8405d5945..370a874fe5 100644 --- a/src/Symfony/Component/HttpKernel/DataCollector/AjaxDataCollector.php +++ b/src/Symfony/Component/HttpKernel/DataCollector/AjaxDataCollector.php @@ -26,6 +26,11 @@ class AjaxDataCollector extends DataCollector // 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 965342191b..0a6aa82b26 100644 --- a/src/Symfony/Component/HttpKernel/DataCollector/ConfigDataCollector.php +++ b/src/Symfony/Component/HttpKernel/DataCollector/ConfigDataCollector.php @@ -95,6 +95,14 @@ class ConfigDataCollector extends DataCollector implements LateDataCollectorInte } } + /** + * {@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 2820ad5b28..c0a0c0a982 100644 --- a/src/Symfony/Component/HttpKernel/DataCollector/DataCollectorInterface.php +++ b/src/Symfony/Component/HttpKernel/DataCollector/DataCollectorInterface.php @@ -18,6 +18,8 @@ use Symfony\Component\HttpFoundation\Response; * 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 3d75f322d8..ab44405edb 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 @@ class EventDataCollector extends DataCollector implements LateDataCollectorInter ); } + 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 9fe826446b..7a25f14921 100644 --- a/src/Symfony/Component/HttpKernel/DataCollector/ExceptionDataCollector.php +++ b/src/Symfony/Component/HttpKernel/DataCollector/ExceptionDataCollector.php @@ -34,6 +34,14 @@ class ExceptionDataCollector extends DataCollector } } + /** + * {@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 92fd0da71e..ee645d53e8 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 @@ class LoggerDataCollector extends DataCollector implements LateDataCollectorInte // 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 b7f61f46fd..8d8cc1a04d 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 @@ class MemoryDataCollector extends DataCollector implements LateDataCollectorInte $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 7049844f9e..d27940266a 100644 --- a/src/Symfony/Component/HttpKernel/DataCollector/RequestDataCollector.php +++ b/src/Symfony/Component/HttpKernel/DataCollector/RequestDataCollector.php @@ -156,6 +156,12 @@ class RequestDataCollector extends DataCollector implements EventSubscriberInter $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 76d9623461..59f77c4ba2 100644 --- a/src/Symfony/Component/HttpKernel/DataCollector/RouterDataCollector.php +++ b/src/Symfony/Component/HttpKernel/DataCollector/RouterDataCollector.php @@ -23,17 +23,14 @@ use Symfony\Component\HttpKernel\Event\FilterControllerEvent; */ 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 @@ class RouterDataCollector extends DataCollector 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 2d39156e69..6588304935 100644 --- a/src/Symfony/Component/HttpKernel/DataCollector/TimeDataCollector.php +++ b/src/Symfony/Component/HttpKernel/DataCollector/TimeDataCollector.php @@ -49,6 +49,14 @@ class TimeDataCollector extends DataCollector implements LateDataCollectorInterf ); } + /** + * {@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 5635a2184f..f0606d3b0e 100644 --- a/src/Symfony/Component/HttpKernel/Log/DebugLoggerInterface.php +++ b/src/Symfony/Component/HttpKernel/Log/DebugLoggerInterface.php @@ -15,6 +15,8 @@ namespace Symfony\Component\HttpKernel\Log; * 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 2580b4fffa..85a71641be 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 @@ class Profiler 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 @@ class Profiler */ 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 afad9f58af..178f1f01a3 100644 --- a/src/Symfony/Component/HttpKernel/Tests/DataCollector/ExceptionDataCollectorTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/DataCollector/ExceptionDataCollectorTest.php @@ -37,4 +37,23 @@ class ExceptionDataCollectorTest extends TestCase $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 62bf2c00c7..3dec3bd7f8 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 @@ class LoggerDataCollectorTest extends TestCase */ 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 @@ class LoggerDataCollectorTest extends TestCase } } + 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 867ccdce57..89dec36af4 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 @@ class CloneVarDataCollector extends DataCollector $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 da7ef5bd60..ca2e6a693d 100644 --- a/src/Symfony/Component/HttpKernel/Tests/Fixtures/TestEventDispatcher.php +++ b/src/Symfony/Component/HttpKernel/Tests/Fixtures/TestEventDispatcher.php @@ -25,4 +25,8 @@ class TestEventDispatcher extends EventDispatcher implements TraceableEventDispa { 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 1a6f54636a..243c3c5c5a 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 @@ class ProfilerTest extends TestCase $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 1696fc71ff..da45cce31e 100644 --- a/src/Symfony/Component/Translation/DataCollector/TranslationDataCollector.php +++ b/src/Symfony/Component/Translation/DataCollector/TranslationDataCollector.php @@ -58,6 +58,14 @@ class TranslationDataCollector extends DataCollector implements LateDataCollecto { } + /** + * {@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 d2b3f46262..aa8c61f96b 100644 --- a/src/Symfony/Component/Validator/DataCollector/ValidatorDataCollector.php +++ b/src/Symfony/Component/Validator/DataCollector/ValidatorDataCollector.php @@ -19,6 +19,7 @@ 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\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 @@ class ValidatorDataCollector extends DataCollector implements LateDataCollectorI // 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 @@ class ValidatorDataCollector extends DataCollector implements LateDataCollectorI { $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 811a55829a..c078d28350 100644 --- a/src/Symfony/Component/Validator/Tests/DataCollector/ValidatorDataCollectorTest.php +++ b/src/Symfony/Component/Validator/Tests/DataCollector/ValidatorDataCollectorTest.php @@ -50,6 +50,33 @@ class ValidatorDataCollectorTest extends TestCase $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 019559ae00..96134e2767 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 @@ class TraceableValidator implements ValidatorInterface } /** - * @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 15/19] 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 3996618fc1..c410d5c4cc 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 a9a382b8e9..bd645e3444 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 25e89572a5..bd1b7b59eb 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 97c9c4a092..5eceb8470a 100644 --- a/src/Symfony/Component/Security/Guard/AbstractGuardAuthenticator.php +++ b/src/Symfony/Component/Security/Guard/AbstractGuardAuthenticator.php @@ -23,17 +23,13 @@ use Symfony\Component\Security\Guard\Token\PostAuthenticationGuardToken; 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 a1497b0eef..f68b8d6f43 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 @@ use Symfony\Component\Security\Http\EntryPoint\AuthenticationEntryPointInterface * @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 @@ interface AuthenticatorInterface 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. + * as any type (e.g. an associate array). * * Whatever value you return here will be passed to getUser() and checkCredentials() * @@ -65,106 +55,9 @@ interface AuthenticatorInterface extends AuthenticationEntryPointInterface * * @param Request $request * - * @return mixed|null + * @return mixed Any non-null value + * + * @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); - - /** - * 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 dd5ae2c16b..4ec0b8f326 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\Request; 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 @@ class GuardAuthenticationListener implements ListenerInterface } } - private function executeGuardAuthenticator($uniqueGuardKey, AuthenticatorInterface $guardAuthenticator, GetResponseEvent $event) + private function executeGuardAuthenticator($uniqueGuardKey, GuardAuthenticatorInterface $guardAuthenticator, GetResponseEvent $event) { $request = $event->getRequest(); try { @@ -102,38 +102,29 @@ class GuardAuthenticationListener implements ListenerInterface $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 @@ class GuardAuthenticationListener implements ListenerInterface * @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 c8fb6e394e..abe263d888 100644 --- a/src/Symfony/Component/Security/Guard/GuardAuthenticatorHandler.php +++ b/src/Symfony/Component/Security/Guard/GuardAuthenticatorHandler.php @@ -29,6 +29,8 @@ use Symfony\Component\Security\Http\SecurityEvents; * 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 @@ class GuardAuthenticatorHandler * * @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 @@ class GuardAuthenticatorHandler * * @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 @@ class GuardAuthenticatorHandler * * @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 2078ad237b..0d11573c03 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\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. @@ -28,9 +29,9 @@ use Symfony\Component\Security\Guard\Token\GuardTokenInterface; * * @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 c93776a348..2f2678035f 100644 --- a/src/Symfony/Component/Security/Guard/Provider/GuardAuthenticationProvider.php +++ b/src/Symfony/Component/Security/Guard/Provider/GuardAuthenticationProvider.php @@ -56,7 +56,7 @@ class GuardAuthenticationProvider implements AuthenticationProviderInterface /** * Finds the correct authenticator for the token and calls it. * - * @param TokenInterface|GuardTokenInterface $token + * @param GuardTokenInterface $token * * @return TokenInterface */ @@ -101,7 +101,7 @@ class GuardAuthenticationProvider implements AuthenticationProviderInterface // 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 @@ class GuardAuthenticationProvider implements AuthenticationProviderInterface 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 60f703904c..5af9f130f8 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 @@ namespace Symfony\Component\Security\Guard\Tests\Firewall; 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 @@ class GuardAuthenticationListenerTest extends TestCase 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 @@ class GuardAuthenticationListenerTest extends TestCase ->expects($this->once()) ->method('handleAuthenticationFailure') ->willReturn(new Response()); - // the second authenticator should *never* be called $authenticator2 ->expects($this->never()) @@ -123,8 +125,8 @@ class GuardAuthenticationListenerTest extends TestCase 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 @@ class GuardAuthenticationListenerTest extends TestCase 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 @@ class GuardAuthenticationListenerTest extends TestCase */ 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 @@ class GuardAuthenticationListenerTest extends TestCase */ 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 @@ class GuardAuthenticationListenerTest extends TestCase 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 @@ class GuardAuthenticationListenerTest extends TestCase /** * @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 29199d820e..c67f38e9ef 100644 --- a/src/Symfony/Component/Security/Guard/Tests/GuardAuthenticatorHandlerTest.php +++ b/src/Symfony/Component/Security/Guard/Tests/GuardAuthenticatorHandlerTest.php @@ -14,6 +14,7 @@ namespace Symfony\Component\Security\Guard\Tests; 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 @@ class GuardAuthenticatorHandlerTest extends TestCase $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 ed3920533f..9d8301fce8 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 @@ class GuardAuthenticationProviderTest extends TestCase { $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 16/19] [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 e5b6434c37..c6d5675d78 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 2d2e04899c..04fd5197ad 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 d60ebdfe8d..608bac2d6d 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 80ecc1cc3c..20e1a897e4 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 17/19] [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 24a5843f64..2d44cad225 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 92258f06fa..2219386bc2 100644 --- a/src/Symfony/Component/VarDumper/Caster/MongoCaster.php +++ b/src/Symfony/Component/VarDumper/Caster/MongoCaster.php @@ -13,10 +13,14 @@ 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 { From 5d29dd0d28aaf3e15967c393d889dbb400721d13 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Thu, 5 Oct 2017 10:44:57 +0200 Subject: [PATCH 18/19] [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 8a8eafe0ce..7d47d59585 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Controller/ControllerTrait.php +++ b/src/Symfony/Bundle/FrameworkBundle/Controller/ControllerTrait.php @@ -231,10 +231,10 @@ trait ControllerTrait 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 @@ trait ControllerTrait $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 3feabfd12e..8321ebd5b4 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/ControllerTraitTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/ControllerTraitTest.php @@ -451,7 +451,7 @@ abstract class ControllerTraitTest extends TestCase 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 19/19] [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 c353e36e66..af5ccaa1ab 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 @@ use Doctrine\Common\Persistence\AbstractManagerRegistry; */ 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 fa3037a609..d1596a1968 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/ManagerRegistryTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/ManagerRegistryTest.php @@ -31,7 +31,7 @@ class ManagerRegistryTest extends TestCase $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 @@ class ManagerRegistryTest extends TestCase 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 b88ad0cc7d..a688abbaba 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Controller/ControllerResolver.php +++ b/src/Symfony/Bundle/FrameworkBundle/Controller/ControllerResolver.php @@ -48,13 +48,7 @@ class ControllerResolver extends ContainerControllerResolver $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 @@ class ControllerResolver extends ContainerControllerResolver */ 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 b2cb1d1acc..6edee88ce5 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 @@ use Symfony\Component\Routing\Generator\UrlGeneratorInterface; * 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 @@ class RedirectController implements ContainerAwareInterface } } - 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 @@ class RedirectController implements ContainerAwareInterface 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 @@ class RedirectController implements ContainerAwareInterface 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 42ebd33bad..5d13355208 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 6856512e20..ed8dbfe8d7 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 14b6e4428e..a95083a382 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\Response; 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 @@ class RedirectControllerTest extends TestCase $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 @@ class RedirectControllerTest extends TestCase $this->assertEquals(302, $returnResponse->getStatusCode()); } - public function testUrlRedirectDefaultPortParameters() + public function testUrlRedirectDefaultPorts() { $host = 'www.example.com'; $baseUrl = '/base'; @@ -151,6 +143,30 @@ class RedirectControllerTest extends TestCase $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 @@ class RedirectControllerTest extends TestCase } 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 6afb5e3203..497c112eed 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 @@ class TemplateControllerTest extends TestCase $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 @@ class TemplateControllerTest extends TestCase $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 @@ class TemplateControllerTest extends TestCase */ 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 74366863f7..9b28f066d6 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 @@ use Symfony\Component\HttpFoundation\Session\Storage\Handler\MongoDbSessionHandl /** * @author Markus Bachmann * @group time-sensitive + * @group legacy */ class MongoDbSessionHandlerTest extends TestCase {