From 16da6861be359906f26b4212214ae0877b0eb094 Mon Sep 17 00:00:00 2001 From: David Maicher Date: Wed, 17 May 2017 20:41:55 +0200 Subject: [PATCH 001/106] [Security] fix switch user _exit without having current token --- .../Security/Http/Firewall/SwitchUserListener.php | 2 +- .../Http/Tests/Firewall/SwitchUserListenerTest.php | 11 +++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/Security/Http/Firewall/SwitchUserListener.php b/src/Symfony/Component/Security/Http/Firewall/SwitchUserListener.php index 7de83d2513369..606392de8a16c 100644 --- a/src/Symfony/Component/Security/Http/Firewall/SwitchUserListener.php +++ b/src/Symfony/Component/Security/Http/Firewall/SwitchUserListener.php @@ -158,7 +158,7 @@ private function attemptSwitchUser(Request $request) */ private function attemptExitUser(Request $request) { - if (false === $original = $this->getOriginalToken($this->tokenStorage->getToken())) { + if (null === ($currentToken = $this->tokenStorage->getToken()) || false === $original = $this->getOriginalToken($currentToken)) { throw new AuthenticationCredentialsNotFoundException('Could not find original Token object.'); } diff --git a/src/Symfony/Component/Security/Http/Tests/Firewall/SwitchUserListenerTest.php b/src/Symfony/Component/Security/Http/Tests/Firewall/SwitchUserListenerTest.php index 43013520c36ba..6b6cb246c985f 100644 --- a/src/Symfony/Component/Security/Http/Tests/Firewall/SwitchUserListenerTest.php +++ b/src/Symfony/Component/Security/Http/Tests/Firewall/SwitchUserListenerTest.php @@ -65,6 +65,17 @@ public function testEventIsIgnoredIfUsernameIsNotPassedWithTheRequest() $this->assertNull($this->tokenStorage->getToken()); } + /** + * @expectedException \Symfony\Component\Security\Core\Exception\AuthenticationCredentialsNotFoundException + */ + public function testExitUserThrowsAuthenticationExceptionIfNoCurrentToken() + { + $this->tokenStorage->setToken(null); + $this->request->query->set('_switch_user', '_exit'); + $listener = new SwitchUserListener($this->tokenStorage, $this->userProvider, $this->userChecker, 'provider123', $this->accessDecisionManager); + $listener->handle($this->event); + } + /** * @expectedException \Symfony\Component\Security\Core\Exception\AuthenticationCredentialsNotFoundException */ From 65297de3aa44953ca39243fd3b713d4a83a20900 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Kurzeja?= Date: Tue, 30 May 2017 10:18:53 +0200 Subject: [PATCH 002/106] #22839 - changed debug toolbar dump section to relative and use full window width --- .../Resources/views/Profiler/toolbar.css.twig | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/toolbar.css.twig b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/toolbar.css.twig index 22a11b03a4361..7a2d92e134a5f 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/toolbar.css.twig +++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/toolbar.css.twig @@ -350,6 +350,15 @@ 100% { background: #222; } } +.sf-toolbar-block.sf-toolbar-block-dump { + position: static; +} + +.sf-toolbar-block.sf-toolbar-block-dump .sf-toolbar-info { + max-width: none; + right: 0; +} + .sf-toolbar-block-dump pre.sf-dump { background-color: #222; border-color: #777; From 21ef0655942c0e75a3d58cc989f8ab26beb693e0 Mon Sep 17 00:00:00 2001 From: Maxime Steinhausser Date: Thu, 1 Jun 2017 11:17:30 +0200 Subject: [PATCH 003/106] [HttpKernel][Debug] Fix missing trace on deprecations collected during bootstrapping & silenced errors --- src/Symfony/Component/Debug/ErrorHandler.php | 54 ++++++++++++++----- .../Debug/Exception/SilencedErrorContext.php | 14 ++++- .../Debug/Tests/ErrorHandlerTest.php | 8 ++- .../DataCollector/LoggerDataCollector.php | 46 ++++++++++++---- src/Symfony/Component/HttpKernel/Kernel.php | 21 +++++++- .../VarDumper/Caster/ExceptionCaster.php | 14 +++-- 6 files changed, 124 insertions(+), 33 deletions(-) diff --git a/src/Symfony/Component/Debug/ErrorHandler.php b/src/Symfony/Component/Debug/ErrorHandler.php index d6c4d10d2934a..e25b5a6dd8b2a 100644 --- a/src/Symfony/Component/Debug/ErrorHandler.php +++ b/src/Symfony/Component/Debug/ErrorHandler.php @@ -100,6 +100,8 @@ class ErrorHandler private static $stackedErrors = array(); private static $stackedErrorLevels = array(); private static $toStringException = null; + private static $silencedErrorCache = array(); + private static $silencedErrorCount = 0; private static $exitCode = 0; /** @@ -407,7 +409,24 @@ public function handleError($type, $message, $file, $line) $errorAsException = self::$toStringException; self::$toStringException = null; } elseif (!$throw && !($type & $level)) { - $errorAsException = new SilencedErrorContext($type, $file, $line); + if (isset(self::$silencedErrorCache[$message])) { + $lightTrace = null; + $errorAsException = self::$silencedErrorCache[$message]; + ++$errorAsException->count; + } else { + $lightTrace = $this->tracedErrors & $type ? $this->cleanTrace(debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS), $type, $file, $line, false) : array(); + $errorAsException = new SilencedErrorContext($type, $file, $line, $lightTrace); + } + + if (100 < ++self::$silencedErrorCount) { + self::$silencedErrorCache = $lightTrace = array(); + self::$silencedErrorCount = 1; + } + self::$silencedErrorCache[$message] = $errorAsException; + + if (null === $lightTrace) { + return; + } } else { if ($scope) { $errorAsException = new ContextErrorException($logMessage, 0, $type, $file, $line, $context); @@ -418,19 +437,7 @@ public function handleError($type, $message, $file, $line) // Clean the trace by removing function arguments and the first frames added by the error handler itself. if ($throw || $this->tracedErrors & $type) { $backtrace = $backtrace ?: $errorAsException->getTrace(); - $lightTrace = $backtrace; - - for ($i = 0; isset($backtrace[$i]); ++$i) { - if (isset($backtrace[$i]['file'], $backtrace[$i]['line']) && $backtrace[$i]['line'] === $line && $backtrace[$i]['file'] === $file) { - $lightTrace = array_slice($lightTrace, 1 + $i); - break; - } - } - if (!($throw || $this->scopedErrors & $type)) { - for ($i = 0; isset($lightTrace[$i]); ++$i) { - unset($lightTrace[$i]['args']); - } - } + $lightTrace = $this->cleanTrace($backtrace, $type, $file, $line, $throw); $this->traceReflector->setValue($errorAsException, $lightTrace); } else { $this->traceReflector->setValue($errorAsException, array()); @@ -687,4 +694,23 @@ protected function getFatalErrorHandlers() new ClassNotFoundFatalErrorHandler(), ); } + + private function cleanTrace($backtrace, $type, $file, $line, $throw) + { + $lightTrace = $backtrace; + + for ($i = 0; isset($backtrace[$i]); ++$i) { + if (isset($backtrace[$i]['file'], $backtrace[$i]['line']) && $backtrace[$i]['line'] === $line && $backtrace[$i]['file'] === $file) { + $lightTrace = array_slice($lightTrace, 1 + $i); + break; + } + } + if (!($throw || $this->scopedErrors & $type)) { + for ($i = 0; isset($lightTrace[$i]); ++$i) { + unset($lightTrace[$i]['args']); + } + } + + return $lightTrace; + } } diff --git a/src/Symfony/Component/Debug/Exception/SilencedErrorContext.php b/src/Symfony/Component/Debug/Exception/SilencedErrorContext.php index 0c3a0e1d9fb58..4be83491b9df7 100644 --- a/src/Symfony/Component/Debug/Exception/SilencedErrorContext.php +++ b/src/Symfony/Component/Debug/Exception/SilencedErrorContext.php @@ -18,15 +18,20 @@ */ class SilencedErrorContext implements \JsonSerializable { + public $count = 1; + private $severity; private $file; private $line; + private $trace; - public function __construct($severity, $file, $line) + public function __construct($severity, $file, $line, array $trace = array(), $count = 1) { $this->severity = $severity; $this->file = $file; $this->line = $line; + $this->trace = $trace; + $this->count = $count; } public function getSeverity() @@ -44,12 +49,19 @@ public function getLine() return $this->line; } + public function getTrace() + { + return $this->trace; + } + public function JsonSerialize() { return array( 'severity' => $this->severity, 'file' => $this->file, 'line' => $this->line, + 'trace' => $this->trace, + 'count' => $this->count, ); } } diff --git a/src/Symfony/Component/Debug/Tests/ErrorHandlerTest.php b/src/Symfony/Component/Debug/Tests/ErrorHandlerTest.php index 2fccf2dbe7a9b..a14accf3df9a0 100644 --- a/src/Symfony/Component/Debug/Tests/ErrorHandlerTest.php +++ b/src/Symfony/Component/Debug/Tests/ErrorHandlerTest.php @@ -221,12 +221,17 @@ public function testHandleError() $logger = $this->getMockBuilder('Psr\Log\LoggerInterface')->getMock(); - $logArgCheck = function ($level, $message, $context) { + $line = null; + $logArgCheck = function ($level, $message, $context) use (&$line) { $this->assertEquals('Notice: Undefined variable: undefVar', $message); $this->assertArrayHasKey('exception', $context); $exception = $context['exception']; $this->assertInstanceOf(SilencedErrorContext::class, $exception); $this->assertSame(E_NOTICE, $exception->getSeverity()); + $this->assertSame(__FILE__, $exception->getFile()); + $this->assertSame($line, $exception->getLine()); + $this->assertNotEmpty($exception->getTrace()); + $this->assertSame(1, $exception->count); }; $logger @@ -239,6 +244,7 @@ public function testHandleError() $handler->setDefaultLogger($logger, E_NOTICE); $handler->screamAt(E_NOTICE); unset($undefVar); + $line = __LINE__ + 1; @$undefVar++; restore_error_handler(); diff --git a/src/Symfony/Component/HttpKernel/DataCollector/LoggerDataCollector.php b/src/Symfony/Component/HttpKernel/DataCollector/LoggerDataCollector.php index 7ae1fbbd61537..f45f99718d318 100644 --- a/src/Symfony/Component/HttpKernel/DataCollector/LoggerDataCollector.php +++ b/src/Symfony/Component/HttpKernel/DataCollector/LoggerDataCollector.php @@ -49,10 +49,8 @@ public function collect(Request $request, Response $response, \Exception $except public function lateCollect() { if (null !== $this->logger) { - $this->data = $this->computeErrorsCount(); - $containerDeprecationLogs = $this->getContainerDeprecationLogs(); - $this->data['deprecation_count'] += count($containerDeprecationLogs); + $this->data = $this->computeErrorsCount($containerDeprecationLogs); $this->data['compiler_logs'] = $this->getContainerCompilerLogs(); $this->data['logs'] = $this->sanitizeLogs(array_merge($this->logger->getLogs(), $containerDeprecationLogs)); $this->data = $this->cloneVar($this->data); @@ -113,11 +111,10 @@ private function getContainerDeprecationLogs() return array(); } - $stubs = array(); $bootTime = filemtime($file); $logs = array(); foreach (unserialize(file_get_contents($file)) as $log) { - $log['context'] = array('exception' => new SilencedErrorContext($log['type'], $log['file'], $log['line'])); + $log['context'] = array('exception' => new SilencedErrorContext($log['type'], $log['file'], $log['line'], $log['trace'], $log['count'])); $log['timestamp'] = $bootTime; $log['priority'] = 100; $log['priorityName'] = 'DEBUG'; @@ -159,15 +156,34 @@ private function sanitizeLogs($logs) continue; } + $message = $log['message']; $exception = $log['context']['exception']; - $errorId = md5("{$exception->getSeverity()}/{$exception->getLine()}/{$exception->getFile()}\0{$log['message']}", true); + + if ($exception instanceof SilencedErrorContext) { + if (isset($silencedLogs[$h = spl_object_hash($exception)])) { + continue; + } + $silencedLogs[$h] = true; + + if (!isset($sanitizedLogs[$message])) { + $sanitizedLogs[$message] = $log + array( + 'errorCount' => 0, + 'scream' => true, + ); + } + $sanitizedLogs[$message]['errorCount'] += $exception->count; + + continue; + } + + $errorId = md5("{$exception->getSeverity()}/{$exception->getLine()}/{$exception->getFile()}\0{$message}", true); if (isset($sanitizedLogs[$errorId])) { ++$sanitizedLogs[$errorId]['errorCount']; } else { $log += array( 'errorCount' => 1, - 'scream' => $exception instanceof SilencedErrorContext, + 'scream' => false, ); $sanitizedLogs[$errorId] = $log; @@ -196,8 +212,9 @@ private function isSilencedOrDeprecationErrorLog(array $log) return false; } - private function computeErrorsCount() + private function computeErrorsCount(array $containerDeprecationLogs) { + $silencedLogs = array(); $count = array( 'error_count' => $this->logger->countErrors(), 'deprecation_count' => 0, @@ -220,14 +237,23 @@ private function computeErrorsCount() } if ($this->isSilencedOrDeprecationErrorLog($log)) { - if ($log['context']['exception'] instanceof SilencedErrorContext) { - ++$count['scream_count']; + $exception = $log['context']['exception']; + if ($exception instanceof SilencedErrorContext) { + if (isset($silencedLogs[$h = spl_object_hash($exception)])) { + continue; + } + $silencedLogs[$h] = true; + $count['scream_count'] += $exception->count; } else { ++$count['deprecation_count']; } } } + foreach ($containerDeprecationLogs as $deprecationLog) { + $count['deprecation_count'] += $deprecationLog['count']; + } + ksort($count['priorities']); return $count; diff --git a/src/Symfony/Component/HttpKernel/Kernel.php b/src/Symfony/Component/HttpKernel/Kernel.php index c9724c61f9ab9..5c5f6a0921625 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -545,11 +545,28 @@ protected function initializeContainer() return $previousHandler ? $previousHandler($type, $message, $file, $line) : false; } - $collectedLogs[] = array( + if (isset($collectedLogs[$message])) { + ++$collectedLogs[$message]['count']; + + return; + } + + $backtrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS); + // Clean the trace by removing first frames added by the error handler itself. + for ($i = 0; isset($backtrace[$i]); ++$i) { + if (isset($backtrace[$i]['file'], $backtrace[$i]['line']) && $backtrace[$i]['line'] === $line && $backtrace[$i]['file'] === $file) { + $backtrace = array_slice($backtrace, 1 + $i); + break; + } + } + + $collectedLogs[$message] = array( 'type' => $type, 'message' => $message, 'file' => $file, 'line' => $line, + 'trace' => $backtrace, + 'count' => 1, ); }); } @@ -562,7 +579,7 @@ protected function initializeContainer() if ($this->debug) { restore_error_handler(); - file_put_contents($this->getCacheDir().'/'.$class.'Deprecations.log', serialize($collectedLogs)); + file_put_contents($this->getCacheDir().'/'.$class.'Deprecations.log', serialize(array_values($collectedLogs))); file_put_contents($this->getCacheDir().'/'.$class.'Compiler.log', null !== $container ? implode("\n", $container->getCompiler()->getLog()) : ''); } } diff --git a/src/Symfony/Component/VarDumper/Caster/ExceptionCaster.php b/src/Symfony/Component/VarDumper/Caster/ExceptionCaster.php index e2a4200c52503..11ddf25b0b056 100644 --- a/src/Symfony/Component/VarDumper/Caster/ExceptionCaster.php +++ b/src/Symfony/Component/VarDumper/Caster/ExceptionCaster.php @@ -83,7 +83,6 @@ public static function castThrowingCasterException(ThrowingCasterException $e, a public static function castSilencedErrorContext(SilencedErrorContext $e, array $a, Stub $stub, $isNested) { $sPrefix = "\0".SilencedErrorContext::class."\0"; - $xPrefix = "\0Exception\0"; if (!isset($a[$s = $sPrefix.'severity'])) { return $a; @@ -93,12 +92,17 @@ public static function castSilencedErrorContext(SilencedErrorContext $e, array $ $a[$s] = new ConstStub(self::$errorTypes[$a[$s]], $a[$s]); } - $trace = array( + $trace = array(array( 'file' => $a[$sPrefix.'file'], 'line' => $a[$sPrefix.'line'], - ); - unset($a[$sPrefix.'file'], $a[$sPrefix.'line']); - $a[Caster::PREFIX_VIRTUAL.'trace'] = new TraceStub(array($trace)); + )); + + if (isset($a[$sPrefix.'trace'])) { + $trace = array_merge($trace, $a[$sPrefix.'trace']); + } + + unset($a[$sPrefix.'file'], $a[$sPrefix.'line'], $a[$sPrefix.'trace']); + $a[Caster::PREFIX_VIRTUAL.'trace'] = new TraceStub($trace); return $a; } From 7061bfbf3a5e2f32a20f9934ed80e5df010103b2 Mon Sep 17 00:00:00 2001 From: Yonel Ceruto Date: Mon, 5 Jun 2017 13:09:00 -0400 Subject: [PATCH 004/106] show unique inherited roles --- .../SecurityBundle/DataCollector/SecurityDataCollector.php | 2 +- .../Tests/DataCollector/SecurityDataCollectorTest.php | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Bundle/SecurityBundle/DataCollector/SecurityDataCollector.php b/src/Symfony/Bundle/SecurityBundle/DataCollector/SecurityDataCollector.php index 092c627fa9862..c9f2599526a70 100644 --- a/src/Symfony/Bundle/SecurityBundle/DataCollector/SecurityDataCollector.php +++ b/src/Symfony/Bundle/SecurityBundle/DataCollector/SecurityDataCollector.php @@ -82,7 +82,7 @@ public function collect(Request $request, Response $response, \Exception $except 'token_class' => get_class($token), 'user' => $token->getUsername(), 'roles' => array_map(function (RoleInterface $role) { return $role->getRole(); }, $assignedRoles), - 'inherited_roles' => array_map(function (RoleInterface $role) { return $role->getRole(); }, $inheritedRoles), + 'inherited_roles' => array_unique(array_map(function (RoleInterface $role) { return $role->getRole(); }, $inheritedRoles)), 'supports_role_hierarchy' => null !== $this->roleHierarchy, ); } diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DataCollector/SecurityDataCollectorTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/DataCollector/SecurityDataCollectorTest.php index 0357b612060c4..e8f808f98ee94 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/DataCollector/SecurityDataCollectorTest.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DataCollector/SecurityDataCollectorTest.php @@ -111,6 +111,11 @@ public function provideRoles() array('ROLE_ADMIN'), array('ROLE_USER', 'ROLE_ALLOWED_TO_SWITCH'), ), + array( + array('ROLE_ADMIN', 'ROLE_OPERATOR'), + array('ROLE_ADMIN', 'ROLE_OPERATOR'), + array('ROLE_USER', 'ROLE_ALLOWED_TO_SWITCH'), + ), ); } @@ -118,6 +123,7 @@ private function getRoleHierarchy() { return new RoleHierarchy(array( 'ROLE_ADMIN' => array('ROLE_USER', 'ROLE_ALLOWED_TO_SWITCH'), + 'ROLE_OPERATOR' => array('ROLE_USER'), )); } From f322107d64f574f5832c8695d962ce23d6ed30a6 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Mon, 5 Jun 2017 21:14:06 -0700 Subject: [PATCH 005/106] bumped Symfony version to 3.3.3 --- src/Symfony/Component/HttpKernel/Kernel.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Symfony/Component/HttpKernel/Kernel.php b/src/Symfony/Component/HttpKernel/Kernel.php index 0cab79884c08c..081e0e7bbaa21 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -61,12 +61,12 @@ abstract class Kernel implements KernelInterface, TerminableInterface private $projectDir; - const VERSION = '3.3.2'; - const VERSION_ID = 30302; + const VERSION = '3.3.3-DEV'; + const VERSION_ID = 30303; const MAJOR_VERSION = 3; const MINOR_VERSION = 3; - const RELEASE_VERSION = 2; - const EXTRA_VERSION = ''; + const RELEASE_VERSION = 3; + const EXTRA_VERSION = 'DEV'; const END_OF_MAINTENANCE = '01/2018'; const END_OF_LIFE = '07/2018'; From f1edfa7ec22c52b07882cdc2ff2b2d7092fe7f65 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9goire=20Pineau?= Date: Tue, 6 Jun 2017 17:10:52 +0200 Subject: [PATCH 006/106] [MonologBridge] Do not silence errors in ServerLogHandler::formatRecord --- src/Symfony/Bridge/Monolog/Handler/ServerLogHandler.php | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Bridge/Monolog/Handler/ServerLogHandler.php b/src/Symfony/Bridge/Monolog/Handler/ServerLogHandler.php index fb258808f3836..d1d4968df4cda 100644 --- a/src/Symfony/Bridge/Monolog/Handler/ServerLogHandler.php +++ b/src/Symfony/Bridge/Monolog/Handler/ServerLogHandler.php @@ -51,9 +51,15 @@ public function handle(array $record) if (!$this->socket = $this->socket ?: $this->createSocket()) { return false === $this->bubble; } + } finally { + restore_error_handler(); + } - $recordFormatted = $this->formatRecord($record); + $recordFormatted = $this->formatRecord($record); + set_error_handler(self::class.'::nullErrorHandler'); + + try { if (-1 === stream_socket_sendto($this->socket, $recordFormatted)) { stream_socket_shutdown($this->socket, STREAM_SHUT_RDWR); From b58f060fda0953139abc4b9ff99ff4878e3d4638 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Wed, 7 Jun 2017 09:53:54 +0200 Subject: [PATCH 007/106] [FrameworkBundle] Fix perf issue in CacheClearCommand::warmup() --- .../FrameworkBundle/Command/CacheClearCommand.php | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/CacheClearCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/CacheClearCommand.php index 84c2fae7d4db8..5e9014bfc5ddd 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/CacheClearCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/CacheClearCommand.php @@ -141,7 +141,7 @@ protected function warmup($warmupDir, $realCacheDir, $enableOptionalWarmers = tr $safeTempKernel = str_replace('\\', '\\\\', get_class($tempKernel)); $realKernelFQN = get_class($realKernel); - foreach (Finder::create()->files()->name('*.meta')->in($warmupDir) as $file) { + foreach (Finder::create()->files()->depth('<3')->name('*.meta')->in($warmupDir) as $file) { file_put_contents($file, preg_replace( '/(C\:\d+\:)"'.$safeTempKernel.'"/', sprintf('$1"%s"', $realKernelFQN), @@ -153,14 +153,16 @@ protected function warmup($warmupDir, $realCacheDir, $enableOptionalWarmers = tr $search = array($warmupDir, str_replace('\\', '\\\\', $warmupDir)); $replace = str_replace('\\', '/', $realCacheDir); foreach (Finder::create()->files()->in($warmupDir) as $file) { - $content = str_replace($search, $replace, file_get_contents($file)); - file_put_contents($file, $content); + $content = str_replace($search, $replace, file_get_contents($file), $count); + if ($count) { + file_put_contents($file, $content); + } } // fix references to container's class $tempContainerClass = get_class($tempKernel->getContainer()); $realContainerClass = get_class($realKernel->getContainer()); - foreach (Finder::create()->files()->name($tempContainerClass.'*')->in($warmupDir) as $file) { + foreach (Finder::create()->files()->depth('<2')->name($tempContainerClass.'*')->in($warmupDir) as $file) { $content = str_replace($tempContainerClass, $realContainerClass, file_get_contents($file)); file_put_contents($file, $content); rename($file, str_replace(DIRECTORY_SEPARATOR.$tempContainerClass, DIRECTORY_SEPARATOR.$realContainerClass, $file)); From 4442c636c848dafdd251760a7569a158de869a67 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Wed, 7 Jun 2017 12:41:51 +0200 Subject: [PATCH 008/106] [SecurityBundle] Made 2 service aliases private --- .../Bundle/SecurityBundle/Resources/config/security.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Bundle/SecurityBundle/Resources/config/security.xml b/src/Symfony/Bundle/SecurityBundle/Resources/config/security.xml index 4b7dba5e45be8..79435ff5d4619 100644 --- a/src/Symfony/Bundle/SecurityBundle/Resources/config/security.xml +++ b/src/Symfony/Bundle/SecurityBundle/Resources/config/security.xml @@ -19,7 +19,7 @@ %security.access.always_authenticate_before_granting% - + @@ -59,7 +59,7 @@ - + From 5d13f0dfacb829536472ea2515671c3a63139a99 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Wed, 7 Jun 2017 11:49:46 -0700 Subject: [PATCH 009/106] updated CHANGELOG for 2.7.29 --- CHANGELOG-2.7.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/CHANGELOG-2.7.md b/CHANGELOG-2.7.md index fb402c9aaf2ca..c93959532d398 100644 --- a/CHANGELOG-2.7.md +++ b/CHANGELOG-2.7.md @@ -7,6 +7,15 @@ in 2.7 minor versions. To get the diff for a specific change, go to https://github.com/symfony/symfony/commit/XXX where XXX is the change hash To get the diff between two versions, go to https://github.com/symfony/symfony/compare/v2.7.0...v2.7.1 +* 2.7.29 (2017-06-07) + + * bug #23069 [SecurityBundle] Show unique Inherited roles in profile panel (yceruto) + * bug #23073 [TwigBridge] Fix namespaced classes (ogizanagi) + * bug #22936 [Form] Mix attr option between guessed options and user options (yceruto) + * bug #23024 [EventDispatcher] Fix ContainerAwareEventDispatcher::hasListeners(null) (nicolas-grekas) + * bug #22996 [Form] Fix \IntlDateFormatter timezone parameter usage to bypass PHP bug #66323 (romainneutron) + * bug #22994 Harden the debugging of Twig filters and functions (stof) + * 2.7.28 (2017-05-29) * bug #22847 [Console] ChoiceQuestion must have choices (ro0NL) From fc56c4ed8cc1484d114124a28482fe96e74f5c76 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Wed, 7 Jun 2017 11:50:25 -0700 Subject: [PATCH 010/106] update CONTRIBUTORS for 2.7.29 --- CONTRIBUTORS.md | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index 66212cf3bf4c4..532b8a261c4f2 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -20,13 +20,13 @@ Symfony is the result of the work of many people who made the code better - Javier Eguiluz (javier.eguiluz) - Hugo Hamon (hhamon) - Abdellatif Ait boudad (aitboudad) + - Romain Neutron (romain) - Pascal Borreli (pborreli) - Wouter De Jong (wouterj) - - Romain Neutron (romain) - - Grégoire Pineau (lyrixx) - Robin Chalas (chalas_r) - - Joseph Bielawski (stloyd) - Maxime Steinhausser (ogizanagi) + - Grégoire Pineau (lyrixx) + - Joseph Bielawski (stloyd) - Karma Dordrak (drak) - Lukas Kahwe Smith (lsmith) - Martin Hasoň (hason) @@ -72,8 +72,8 @@ Symfony is the result of the work of many people who made the code better - Dariusz Górecki (canni) - Titouan Galopin (tgalopin) - Douglas Greenshields (shieldo) - - Konstantin Myakshin (koc) - Jáchym Toušek (enumag) + - Konstantin Myakshin (koc) - Lee McDermott - Brandon Turner - Luis Cordova (cordoval) @@ -112,10 +112,10 @@ Symfony is the result of the work of many people who made the code better - Jacob Dreesen (jdreesen) - Tobias Nyholm (tobias) - Tomáš Votruba (tomas_votruba) + - Yonel Ceruto González (yonelceruto) - Fabien Pennequin (fabienpennequin) - Gordon Franke (gimler) - Eric GELOEN (gelo) - - Yonel Ceruto González (yonelceruto) - Daniel Wehner (dawehner) - Tugdual Saunier (tucksaun) - Théo FIDRY (theofidry) @@ -130,6 +130,7 @@ Symfony is the result of the work of many people who made the code better - Daniel Gomes (danielcsgomes) - Hidenori Goto (hidenorigoto) - Guilherme Blanco (guilhermeblanco) + - Vincent AUBERT (vincent) - Pablo Godel (pgodel) - Jérémie Augustin (jaugustin) - Andréia Bohner (andreia) @@ -140,10 +141,10 @@ Symfony is the result of the work of many people who made the code better - Joel Wurtz (brouznouf) - Philipp Wahala (hifi) - Vyacheslav Pavlov + - Richard van Laak (rvanlaak) - Javier Spagnoletti (phansys) - Richard Shank (iampersistent) - Thomas Rabaix (rande) - - Vincent AUBERT (vincent) - Rouven Weßling (realityking) - Teoh Han Hui (teohhanhui) - Jérôme Vasseur (jvasseur) @@ -151,7 +152,6 @@ Symfony is the result of the work of many people who made the code better - Helmer Aaviksoo - Grégoire Paris (greg0ire) - Hiromi Hishida (77web) - - Richard van Laak (rvanlaak) - Matthieu Ouellette-Vachon (maoueh) - Michał Pipa (michal.pipa) - Amal Raghav (kertz) @@ -242,6 +242,7 @@ Symfony is the result of the work of many people who made the code better - Uwe Jäger (uwej711) - Eugene Leonovich (rybakit) - Filippo Tessarotto + - Oleg Voronkovich - Joseph Rouff (rouffj) - Félix Labrecque (woodspire) - GordonsLondon @@ -277,7 +278,6 @@ Symfony is the result of the work of many people who made the code better - Jordan Samouh (jordansamouh) - Chris Smith (cs278) - Florian Klein (docteurklein) - - Oleg Voronkovich - Manuel Kiessling (manuelkiessling) - Atsuhiro KUBO (iteman) - Andrew Moore (finewolf) @@ -387,6 +387,7 @@ Symfony is the result of the work of many people who made the code better - Emanuele Gaspari (inmarelibero) - Sébastien Santoro (dereckson) - Brian King + - Frank de Jonge (frenkynet) - Michel Salib (michelsalib) - geoffrey - Steffen Roßkamp @@ -523,7 +524,6 @@ Symfony is the result of the work of many people who made the code better - Romain Pierre (romain-pierre) - Jan Behrens - Mantas Var (mvar) - - Frank de Jonge (frenkynet) - Sebastian Krebs - Jean-Christophe Cuvelier [Artack] - Christopher Davis (chrisguitarguy) @@ -1278,6 +1278,7 @@ Symfony is the result of the work of many people who made the code better - ged15 - Daan van Renterghem - Nicole Cordes + - Martin Kirilov - Bram Van der Sype (brammm) - Christopher Hertel (chertel) - Guile (guile) From c713d698278c665065d5a06102a202d97bd566b3 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Wed, 7 Jun 2017 11:50:32 -0700 Subject: [PATCH 011/106] updated VERSION for 2.7.29 --- src/Symfony/Component/HttpKernel/Kernel.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/HttpKernel/Kernel.php b/src/Symfony/Component/HttpKernel/Kernel.php index d20b6e2a16aed..0ffd46d11f7b1 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -58,12 +58,12 @@ abstract class Kernel implements KernelInterface, TerminableInterface protected $startTime; protected $loadClassCache; - const VERSION = '2.7.29-DEV'; + const VERSION = '2.7.29'; const VERSION_ID = 20729; const MAJOR_VERSION = 2; const MINOR_VERSION = 7; const RELEASE_VERSION = 29; - const EXTRA_VERSION = 'DEV'; + const EXTRA_VERSION = ''; const END_OF_MAINTENANCE = '05/2018'; const END_OF_LIFE = '05/2019'; From bcb80569cb23c74ab500d0507f25db4eb1a45cf3 Mon Sep 17 00:00:00 2001 From: Gonzalo Vilaseca Date: Wed, 7 Jun 2017 20:32:30 +0100 Subject: [PATCH 012/106] Cache ipCheck --- .../Component/HttpFoundation/IpUtils.php | 28 +++++++++++++------ 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/src/Symfony/Component/HttpFoundation/IpUtils.php b/src/Symfony/Component/HttpFoundation/IpUtils.php index 28093be43403f..eba603b15df01 100644 --- a/src/Symfony/Component/HttpFoundation/IpUtils.php +++ b/src/Symfony/Component/HttpFoundation/IpUtils.php @@ -18,6 +18,8 @@ */ class IpUtils { + private static $checkedIps = array(); + /** * This class should not be instantiated. */ @@ -61,26 +63,31 @@ public static function checkIp($requestIp, $ips) */ public static function checkIp4($requestIp, $ip) { + $cacheKey = $requestIp.'-'.$ip; + if (isset(self::$checkedIps[$cacheKey])) { + return self::$checkedIps[$cacheKey]; + } + if (!filter_var($requestIp, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) { - return false; + return self::$checkedIps[$cacheKey] = false; } if (false !== strpos($ip, '/')) { list($address, $netmask) = explode('/', $ip, 2); if ($netmask === '0') { - return filter_var($address, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4); + return self::$checkedIps[$cacheKey] = filter_var($address, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4); } if ($netmask < 0 || $netmask > 32) { - return false; + return self::$checkedIps[$cacheKey] = false; } } else { $address = $ip; $netmask = 32; } - return 0 === substr_compare(sprintf('%032b', ip2long($requestIp)), sprintf('%032b', ip2long($address)), 0, $netmask); + return self::$checkedIps[$cacheKey] = 0 === substr_compare(sprintf('%032b', ip2long($requestIp)), sprintf('%032b', ip2long($address)), 0, $netmask); } /** @@ -100,6 +107,11 @@ public static function checkIp4($requestIp, $ip) */ public static function checkIp6($requestIp, $ip) { + $cacheKey = $requestIp.'-'.$ip; + if (isset(self::$checkedIps[$cacheKey])) { + return self::$checkedIps[$cacheKey]; + } + if (!((extension_loaded('sockets') && defined('AF_INET6')) || @inet_pton('::1'))) { throw new \RuntimeException('Unable to check Ipv6. Check that PHP was not compiled with option "disable-ipv6".'); } @@ -108,7 +120,7 @@ public static function checkIp6($requestIp, $ip) list($address, $netmask) = explode('/', $ip, 2); if ($netmask < 1 || $netmask > 128) { - return false; + return self::$checkedIps[$cacheKey] = false; } } else { $address = $ip; @@ -119,7 +131,7 @@ public static function checkIp6($requestIp, $ip) $bytesTest = unpack('n*', @inet_pton($requestIp)); if (!$bytesAddr || !$bytesTest) { - return false; + return self::$checkedIps[$cacheKey] = false; } for ($i = 1, $ceil = ceil($netmask / 16); $i <= $ceil; ++$i) { @@ -127,10 +139,10 @@ public static function checkIp6($requestIp, $ip) $left = ($left <= 16) ? $left : 16; $mask = ~(0xffff >> $left) & 0xffff; if (($bytesAddr[$i] & $mask) != ($bytesTest[$i] & $mask)) { - return false; + return self::$checkedIps[$cacheKey] = false; } } - return true; + return self::$checkedIps[$cacheKey] = true; } } From ccb6543839c8800841b6721a8581f6a7b9e42158 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Wed, 7 Jun 2017 13:11:41 -0700 Subject: [PATCH 013/106] bumped Symfony version to 2.7.30 --- src/Symfony/Component/HttpKernel/Kernel.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Symfony/Component/HttpKernel/Kernel.php b/src/Symfony/Component/HttpKernel/Kernel.php index 0ffd46d11f7b1..6b540518fcbc4 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -58,12 +58,12 @@ abstract class Kernel implements KernelInterface, TerminableInterface protected $startTime; protected $loadClassCache; - const VERSION = '2.7.29'; - const VERSION_ID = 20729; + const VERSION = '2.7.30-DEV'; + const VERSION_ID = 20730; const MAJOR_VERSION = 2; const MINOR_VERSION = 7; - const RELEASE_VERSION = 29; - const EXTRA_VERSION = ''; + const RELEASE_VERSION = 30; + const EXTRA_VERSION = 'DEV'; const END_OF_MAINTENANCE = '05/2018'; const END_OF_LIFE = '05/2019'; From a9f289abbc556a5e21c1889ab1c4efbf3a6521c4 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Wed, 7 Jun 2017 13:12:24 -0700 Subject: [PATCH 014/106] updated CHANGELOG for 2.8.22 --- CHANGELOG-2.8.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/CHANGELOG-2.8.md b/CHANGELOG-2.8.md index b73a0f1a2b18b..da6f2aeebb9fb 100644 --- a/CHANGELOG-2.8.md +++ b/CHANGELOG-2.8.md @@ -7,6 +7,16 @@ in 2.8 minor versions. To get the diff for a specific change, go to https://github.com/symfony/symfony/commit/XXX where XXX is the change hash To get the diff between two versions, go to https://github.com/symfony/symfony/compare/v2.8.0...v2.8.1 +* 2.8.22 (2017-06-07) + + * bug #23073 [TwigBridge] Fix namespaced classes (ogizanagi) + * bug #22936 [Form] Mix attr option between guessed options and user options (yceruto) + * bug #22988 [PropertyInfo][DoctrineBridge] The bigint Doctrine's type must be converted to string (dunglas) + * bug #23014 Fix optional cache warmers are always instantiated whereas they should be lazy-loaded (romainneutron) + * bug #23024 [EventDispatcher] Fix ContainerAwareEventDispatcher::hasListeners(null) (nicolas-grekas) + * bug #22996 [Form] Fix \IntlDateFormatter timezone parameter usage to bypass PHP bug #66323 (romainneutron) + * bug #22994 Harden the debugging of Twig filters and functions (stof) + * 2.8.21 (2017-05-29) * bug #22847 [Console] ChoiceQuestion must have choices (ro0NL) From 0d52ccb5ff8b757265537e74cef4b82ac52ea87d Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Wed, 7 Jun 2017 13:12:31 -0700 Subject: [PATCH 015/106] updated VERSION for 2.8.22 --- src/Symfony/Component/HttpKernel/Kernel.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/HttpKernel/Kernel.php b/src/Symfony/Component/HttpKernel/Kernel.php index ed7d33b583903..97e83f8d59c80 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -59,12 +59,12 @@ abstract class Kernel implements KernelInterface, TerminableInterface protected $startTime; protected $loadClassCache; - const VERSION = '2.8.22-DEV'; + const VERSION = '2.8.22'; const VERSION_ID = 20822; const MAJOR_VERSION = 2; const MINOR_VERSION = 8; const RELEASE_VERSION = 22; - const EXTRA_VERSION = 'DEV'; + const EXTRA_VERSION = ''; const END_OF_MAINTENANCE = '11/2018'; const END_OF_LIFE = '11/2019'; From e8497bb57d95fe96c0660c9a559c77182e9302f3 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Wed, 7 Jun 2017 13:30:46 -0700 Subject: [PATCH 016/106] bumped Symfony version to 2.8.23 --- src/Symfony/Component/HttpKernel/Kernel.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Symfony/Component/HttpKernel/Kernel.php b/src/Symfony/Component/HttpKernel/Kernel.php index 97e83f8d59c80..37e10de8c64c4 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -59,12 +59,12 @@ abstract class Kernel implements KernelInterface, TerminableInterface protected $startTime; protected $loadClassCache; - const VERSION = '2.8.22'; - const VERSION_ID = 20822; + const VERSION = '2.8.23-DEV'; + const VERSION_ID = 20823; const MAJOR_VERSION = 2; const MINOR_VERSION = 8; - const RELEASE_VERSION = 22; - const EXTRA_VERSION = ''; + const RELEASE_VERSION = 23; + const EXTRA_VERSION = 'DEV'; const END_OF_MAINTENANCE = '11/2018'; const END_OF_LIFE = '11/2019'; From 45b961de2eec3faaebfaea9a1ebde32ec1488efe Mon Sep 17 00:00:00 2001 From: tsufeki Date: Wed, 7 Jun 2017 21:53:51 +0200 Subject: [PATCH 017/106] [PropertyAccess] Do not silence TypeErrors from client code. --- .../PropertyAccess/PropertyAccessor.php | 3 ++ .../Fixtures/TestClassTypeErrorInsideCall.php | 28 +++++++++++++++++++ .../Tests/PropertyAccessorTest.php | 12 ++++++++ 3 files changed, 43 insertions(+) create mode 100644 src/Symfony/Component/PropertyAccess/Tests/Fixtures/TestClassTypeErrorInsideCall.php diff --git a/src/Symfony/Component/PropertyAccess/PropertyAccessor.php b/src/Symfony/Component/PropertyAccess/PropertyAccessor.php index 69d7fc0e9f1aa..cd572d21b5d97 100644 --- a/src/Symfony/Component/PropertyAccess/PropertyAccessor.php +++ b/src/Symfony/Component/PropertyAccess/PropertyAccessor.php @@ -244,6 +244,9 @@ public function setValue(&$objectOrArray, $propertyPath, $value) } } catch (\TypeError $e) { self::throwInvalidArgumentException($e->getMessage(), $e->getTrace(), 0); + + // It wasn't thrown in this class so rethrow it + throw $e; } finally { if (\PHP_VERSION_ID < 70000 && false !== self::$previousErrorHandler) { restore_error_handler(); diff --git a/src/Symfony/Component/PropertyAccess/Tests/Fixtures/TestClassTypeErrorInsideCall.php b/src/Symfony/Component/PropertyAccess/Tests/Fixtures/TestClassTypeErrorInsideCall.php new file mode 100644 index 0000000000000..44a93900fae34 --- /dev/null +++ b/src/Symfony/Component/PropertyAccess/Tests/Fixtures/TestClassTypeErrorInsideCall.php @@ -0,0 +1,28 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\PropertyAccess\Tests\Fixtures; + +class TestClassTypeErrorInsideCall +{ + public function expectsDateTime(\DateTime $date) + { + } + + public function getProperty() + { + } + + public function setProperty($property) + { + $this->expectsDateTime(null); // throws TypeError + } +} diff --git a/src/Symfony/Component/PropertyAccess/Tests/PropertyAccessorTest.php b/src/Symfony/Component/PropertyAccess/Tests/PropertyAccessorTest.php index e2ef9296ed50f..ec928a31e88cd 100644 --- a/src/Symfony/Component/PropertyAccess/Tests/PropertyAccessorTest.php +++ b/src/Symfony/Component/PropertyAccess/Tests/PropertyAccessorTest.php @@ -21,6 +21,7 @@ use Symfony\Component\PropertyAccess\Tests\Fixtures\Ticket5775Object; use Symfony\Component\PropertyAccess\Tests\Fixtures\TestClassSetValue; use Symfony\Component\PropertyAccess\Tests\Fixtures\TestClassIsWritable; +use Symfony\Component\PropertyAccess\Tests\Fixtures\TestClassTypeErrorInsideCall; use Symfony\Component\PropertyAccess\Tests\Fixtures\TypeHinted; class PropertyAccessorTest extends TestCase @@ -578,4 +579,15 @@ public function testThrowTypeErrorWithInterface() $this->propertyAccessor->setValue($object, 'countable', 'This is a string, \Countable expected.'); } + + /** + * @requires PHP 7.0 + * @expectedException \TypeError + */ + public function testThrowTypeErrorInsideSetterCall() + { + $object = new TestClassTypeErrorInsideCall(); + + $this->propertyAccessor->setValue($object, 'property', 'foo'); + } } From 2f350d1d389d697c920b8e62a4a8080b75a7fcd4 Mon Sep 17 00:00:00 2001 From: Javan Eskander Date: Thu, 8 Jun 2017 17:18:54 +1000 Subject: [PATCH 018/106] Fixed PHPdoc return references in FormBuilderInterface --- src/Symfony/Component/Form/FormBuilderInterface.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/Form/FormBuilderInterface.php b/src/Symfony/Component/Form/FormBuilderInterface.php index 1145ab26420c0..c19cc903beeba 100644 --- a/src/Symfony/Component/Form/FormBuilderInterface.php +++ b/src/Symfony/Component/Form/FormBuilderInterface.php @@ -27,7 +27,7 @@ interface FormBuilderInterface extends \Traversable, \Countable, FormConfigBuild * @param string|FormTypeInterface $type * @param array $options * - * @return $this + * @return self */ public function add($child, $type = null, array $options = array()); @@ -58,7 +58,7 @@ public function get($name); * * @param string $name * - * @return $this + * @return self */ public function remove($name); From aadf263db42dfeac706939228d191beaefad886f Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Wed, 7 Jun 2017 11:23:32 +0200 Subject: [PATCH 019/106] [Cache] APCu isSupported() should return true when apc.enable_cli=Off --- src/Symfony/Component/Cache/Adapter/ApcuAdapter.php | 4 ++-- src/Symfony/Component/Cache/Adapter/PhpFilesAdapter.php | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Symfony/Component/Cache/Adapter/ApcuAdapter.php b/src/Symfony/Component/Cache/Adapter/ApcuAdapter.php index 0a3887eba091f..6687bd4272d1d 100644 --- a/src/Symfony/Component/Cache/Adapter/ApcuAdapter.php +++ b/src/Symfony/Component/Cache/Adapter/ApcuAdapter.php @@ -21,7 +21,7 @@ class ApcuAdapter extends AbstractAdapter { public static function isSupported() { - return function_exists('apcu_fetch') && ini_get('apc.enabled') && !('cli' === PHP_SAPI && !ini_get('apc.enable_cli')); + return function_exists('apcu_fetch') && ini_get('apc.enabled'); } public function __construct($namespace = '', $defaultLifetime = 0, $version = null) @@ -69,7 +69,7 @@ protected function doHave($id) */ protected function doClear($namespace) { - return isset($namespace[0]) && class_exists('APCuIterator', false) + return isset($namespace[0]) && class_exists('APCuIterator', false) && ('cli' !== PHP_SAPI || ini_get('apc.enable_cli')) ? apcu_delete(new \APCuIterator(sprintf('/^%s/', preg_quote($namespace, '/')), APC_ITER_KEY)) : apcu_clear_cache(); } diff --git a/src/Symfony/Component/Cache/Adapter/PhpFilesAdapter.php b/src/Symfony/Component/Cache/Adapter/PhpFilesAdapter.php index befa38d8d46df..88107cb9899dc 100644 --- a/src/Symfony/Component/Cache/Adapter/PhpFilesAdapter.php +++ b/src/Symfony/Component/Cache/Adapter/PhpFilesAdapter.php @@ -26,7 +26,7 @@ class PhpFilesAdapter extends AbstractAdapter public static function isSupported() { - return function_exists('opcache_compile_file') && ini_get('opcache.enable'); + return function_exists('opcache_invalidate') && ini_get('opcache.enable'); } public function __construct($namespace = '', $defaultLifetime = 0, $directory = null) @@ -118,7 +118,7 @@ protected function doSave(array $values, $lifetime) $ok = $this->write($file, ' Date: Thu, 8 Jun 2017 15:38:34 +0200 Subject: [PATCH 020/106] [Security] Fix annotation --- .../Core/Authentication/Token/UsernamePasswordToken.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/Security/Core/Authentication/Token/UsernamePasswordToken.php b/src/Symfony/Component/Security/Core/Authentication/Token/UsernamePasswordToken.php index 71d19adc14f2b..7bfc556bdbf25 100644 --- a/src/Symfony/Component/Security/Core/Authentication/Token/UsernamePasswordToken.php +++ b/src/Symfony/Component/Security/Core/Authentication/Token/UsernamePasswordToken.php @@ -27,7 +27,7 @@ class UsernamePasswordToken extends AbstractToken * Constructor. * * @param string|object $user The username (like a nickname, email address, etc.), or a UserInterface instance or an object implementing a __toString method - * @param string $credentials This usually is the password of the user + * @param mixed $credentials This usually is the password of the user * @param string $providerKey The provider key * @param (RoleInterface|string)[] $roles An array of roles * From f82b6185a4c043676fd33df3c0c331a6f97560ae Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Thu, 8 Jun 2017 16:28:59 +0200 Subject: [PATCH 021/106] [Yaml] Remove line number in deprecation notices --- src/Symfony/Component/Yaml/Inline.php | 8 ++++---- src/Symfony/Component/Yaml/Parser.php | 12 ++++++------ src/Symfony/Component/Yaml/Tests/ParserTest.php | 6 +++--- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/Symfony/Component/Yaml/Inline.php b/src/Symfony/Component/Yaml/Inline.php index 7ad53692eb000..6789f79efb6cf 100644 --- a/src/Symfony/Component/Yaml/Inline.php +++ b/src/Symfony/Component/Yaml/Inline.php @@ -493,7 +493,7 @@ private static function parseMapping($mapping, $flags, &$i = 0, $references = ar if (!(Yaml::PARSE_KEYS_AS_STRINGS & $flags)) { $evaluatedKey = self::evaluateScalar($key, $flags, $references); - if ('' !== $key && $evaluatedKey !== $key && !is_string($evaluatedKey)) { + if ('' !== $key && $evaluatedKey !== $key && !is_string($evaluatedKey) && !is_int($evaluatedKey)) { @trigger_error('Implicit casting of incompatible mapping keys to strings is deprecated since version 3.3 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0. Pass the PARSE_KEYS_AS_STRING flag to explicitly enable the type casts.', E_USER_DEPRECATED); } } @@ -519,7 +519,7 @@ private static function parseMapping($mapping, $flags, &$i = 0, $references = ar // Parser cannot abort this mapping earlier, since lines // are processed sequentially. if (isset($output[$key])) { - @trigger_error(sprintf('Duplicate key "%s" detected on line %d whilst parsing YAML. Silent handling of duplicate mapping keys in YAML is deprecated since version 3.2 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0.', $key, self::$parsedLineNumber + 1), E_USER_DEPRECATED); + @trigger_error(sprintf('Duplicate key "%s" detected whilst parsing YAML. Silent handling of duplicate mapping keys in YAML is deprecated since version 3.2 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0.', $key), E_USER_DEPRECATED); $duplicate = true; } break; @@ -530,7 +530,7 @@ private static function parseMapping($mapping, $flags, &$i = 0, $references = ar // Parser cannot abort this mapping earlier, since lines // are processed sequentially. if (isset($output[$key])) { - @trigger_error(sprintf('Duplicate key "%s" detected on line %d whilst parsing YAML. Silent handling of duplicate mapping keys in YAML is deprecated since version 3.2 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0.', $key, self::$parsedLineNumber + 1), E_USER_DEPRECATED); + @trigger_error(sprintf('Duplicate key "%s" detected whilst parsing YAML. Silent handling of duplicate mapping keys in YAML is deprecated since version 3.2 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0.', $key), E_USER_DEPRECATED); $duplicate = true; } break; @@ -540,7 +540,7 @@ private static function parseMapping($mapping, $flags, &$i = 0, $references = ar // Parser cannot abort this mapping earlier, since lines // are processed sequentially. if (isset($output[$key])) { - @trigger_error(sprintf('Duplicate key "%s" detected on line %d whilst parsing YAML. Silent handling of duplicate mapping keys in YAML is deprecated since version 3.2 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0.', $key, self::$parsedLineNumber + 1), E_USER_DEPRECATED); + @trigger_error(sprintf('Duplicate key "%s" detected whilst parsing YAML. Silent handling of duplicate mapping keys in YAML is deprecated since version 3.2 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0.', $key), E_USER_DEPRECATED); $duplicate = true; } --$i; diff --git a/src/Symfony/Component/Yaml/Parser.php b/src/Symfony/Component/Yaml/Parser.php index 4a5f2b91e06bf..29fcf8da5cec8 100644 --- a/src/Symfony/Component/Yaml/Parser.php +++ b/src/Symfony/Component/Yaml/Parser.php @@ -236,9 +236,9 @@ private function doParse($value, $flags) throw $e; } - if (!(Yaml::PARSE_KEYS_AS_STRINGS & $flags) && !is_string($key)) { - $keyType = is_numeric($key) ? 'numeric key' : 'incompatible key type'; - @trigger_error(sprintf('Implicit casting of %s to string on line %d is deprecated since version 3.3 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0. Pass the PARSE_KEYS_AS_STRING flag to explicitly enable the type casts.', $keyType, $this->getRealCurrentLineNb()), E_USER_DEPRECATED); + if (!(Yaml::PARSE_KEYS_AS_STRINGS & $flags) && !is_string($key) && !is_int($key)) { + $keyType = is_numeric($key) ? 'numeric key' : 'non-string key'; + @trigger_error(sprintf('Implicit casting of %s to string is deprecated since version 3.3 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0. Pass the PARSE_KEYS_AS_STRING flag to explicitly enable the type casts.', $keyType), E_USER_DEPRECATED); } // Convert float keys to strings, to avoid being converted to integers by PHP @@ -312,7 +312,7 @@ private function doParse($value, $flags) $data[$key] = null; } } else { - @trigger_error(sprintf('Duplicate key "%s" detected on line %d whilst parsing YAML. Silent handling of duplicate mapping keys in YAML is deprecated since version 3.2 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0.', $key, $this->getRealCurrentLineNb() + 1), E_USER_DEPRECATED); + @trigger_error(sprintf('Duplicate key "%s" detected whilst parsing YAML. Silent handling of duplicate mapping keys in YAML is deprecated since version 3.2 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0.', $key), E_USER_DEPRECATED); } } else { // remember the parsed line number here in case we need it to provide some contexts in error messages below @@ -327,7 +327,7 @@ private function doParse($value, $flags) $data[$key] = $value; } } else { - @trigger_error(sprintf('Duplicate key "%s" detected on line %d whilst parsing YAML. Silent handling of duplicate mapping keys in YAML is deprecated since version 3.2 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0.', $key, $realCurrentLineNbKey + 1), E_USER_DEPRECATED); + @trigger_error(sprintf('Duplicate key "%s" detected whilst parsing YAML. Silent handling of duplicate mapping keys in YAML is deprecated since version 3.2 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0.', $key), E_USER_DEPRECATED); } } } else { @@ -337,7 +337,7 @@ private function doParse($value, $flags) if ($allowOverwrite || !isset($data[$key])) { $data[$key] = $value; } else { - @trigger_error(sprintf('Duplicate key "%s" detected on line %d whilst parsing YAML. Silent handling of duplicate mapping keys in YAML is deprecated since version 3.2 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0.', $key, $this->getRealCurrentLineNb() + 1), E_USER_DEPRECATED); + @trigger_error(sprintf('Duplicate key "%s" detected whilst parsing YAML. Silent handling of duplicate mapping keys in YAML is deprecated since version 3.2 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0.', $key), E_USER_DEPRECATED); } } if ($isRef) { diff --git a/src/Symfony/Component/Yaml/Tests/ParserTest.php b/src/Symfony/Component/Yaml/Tests/ParserTest.php index a6c7b6ad12aff..a296a3300125d 100644 --- a/src/Symfony/Component/Yaml/Tests/ParserTest.php +++ b/src/Symfony/Component/Yaml/Tests/ParserTest.php @@ -853,7 +853,7 @@ public function testMappingDuplicateKeyFlow() /** * @group legacy * @dataProvider getParseExceptionOnDuplicateData - * @expectedDeprecation Duplicate key "%s" detected on line %d whilst parsing YAML. Silent handling of duplicate mapping keys in YAML is deprecated %s. + * @expectedDeprecation Duplicate key "%s" detected whilst parsing YAML. Silent handling of duplicate mapping keys in YAML is deprecated %s. * throws \Symfony\Component\Yaml\Exception\ParseException in 4.0 */ public function testParseExceptionOnDuplicate($input, $duplicateKey, $lineNumber) @@ -1081,7 +1081,7 @@ public function testYamlDirective() /** * @group legacy - * @expectedDeprecation Implicit casting of numeric key to string on line 1 is deprecated since version 3.3 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0. Pass the PARSE_KEYS_AS_STRING flag to explicitly enable the type casts. + * @expectedDeprecation Implicit casting of numeric key to string is deprecated since version 3.3 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0. Pass the PARSE_KEYS_AS_STRING flag to explicitly enable the type casts. */ public function testFloatKeys() { @@ -1103,7 +1103,7 @@ public function testFloatKeys() /** * @group legacy - * @expectedDeprecation Implicit casting of incompatible key type to string on line 1 is deprecated since version 3.3 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0. Pass the PARSE_KEYS_AS_STRING flag to explicitly enable the type casts. + * @expectedDeprecation Implicit casting of non-string key to string is deprecated since version 3.3 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0. Pass the PARSE_KEYS_AS_STRING flag to explicitly enable the type casts. */ public function testBooleanKeys() { From c1fa308c0a9ddf6b22c81fbe5fccae46e1118ca1 Mon Sep 17 00:00:00 2001 From: Robin Chalas Date: Fri, 9 Jun 2017 14:05:05 +0200 Subject: [PATCH 022/106] Fix non-dumped voters in security panel --- .../SecurityBundle/Resources/views/Collector/security.html.twig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Bundle/SecurityBundle/Resources/views/Collector/security.html.twig b/src/Symfony/Bundle/SecurityBundle/Resources/views/Collector/security.html.twig index 073d0d869d8f0..9cd6ec4d78db2 100644 --- a/src/Symfony/Bundle/SecurityBundle/Resources/views/Collector/security.html.twig +++ b/src/Symfony/Bundle/SecurityBundle/Resources/views/Collector/security.html.twig @@ -222,7 +222,7 @@ {% for voter in collector.voters %} {{ loop.index }} - {{ voter }} + {{ profiler_dump(voter) }} {% endfor %} From 8b7de02413a9bc7da7c91127c826570a75b807c4 Mon Sep 17 00:00:00 2001 From: Robin Chalas Date: Fri, 9 Jun 2017 13:21:59 +0200 Subject: [PATCH 023/106] [EventDispatcher] Remove dead code in WrappedListener --- .../EventDispatcher/Debug/WrappedListener.php | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/Symfony/Component/EventDispatcher/Debug/WrappedListener.php b/src/Symfony/Component/EventDispatcher/Debug/WrappedListener.php index 4029883dd98c7..f7b0273e15aaa 100644 --- a/src/Symfony/Component/EventDispatcher/Debug/WrappedListener.php +++ b/src/Symfony/Component/EventDispatcher/Debug/WrappedListener.php @@ -15,7 +15,6 @@ use Symfony\Component\EventDispatcher\Event; use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Symfony\Component\VarDumper\Caster\ClassStub; -use Symfony\Component\VarDumper\Cloner\VarCloner; /** * @author Fabien Potencier @@ -30,8 +29,7 @@ class WrappedListener private $dispatcher; private $pretty; private $stub; - - private static $cloner; + private static $hasClassStub; public function __construct($listener, $name, Stopwatch $stopwatch, EventDispatcherInterface $dispatcher = null) { @@ -58,8 +56,8 @@ public function __construct($listener, $name, Stopwatch $stopwatch, EventDispatc $this->name = $name; } - if (null === self::$cloner) { - self::$cloner = class_exists(ClassStub::class) ? new VarCloner() : false; + if (null === self::$hasClassStub) { + self::$hasClassStub = class_exists(ClassStub::class); } } @@ -86,7 +84,7 @@ public function getPretty() public function getInfo($eventName) { if (null === $this->stub) { - $this->stub = false === self::$cloner ? $this->pretty.'()' : new ClassStub($this->pretty.'()', $this->listener); + $this->stub = self::$hasClassStub ? new ClassStub($this->pretty.'()', $this->listener) : $this->pretty.'()'; } return array( From 232caad8765503ca36a0f675ba37a1d60bc4e42a Mon Sep 17 00:00:00 2001 From: Pierre du Plessis Date: Fri, 9 Jun 2017 21:12:04 +0200 Subject: [PATCH 024/106] Remove deprecated each function --- .../Tests/DependencyInjection/TwigExtensionTest.php | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/TwigExtensionTest.php b/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/TwigExtensionTest.php index fb82ee8266dbf..f5809cc045c42 100644 --- a/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/TwigExtensionTest.php +++ b/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/TwigExtensionTest.php @@ -170,9 +170,10 @@ public function testGlobalsWithDifferentTypesAndValues() $calls = $container->getDefinition('twig')->getMethodCalls(); foreach (array_slice($calls, 1) as $call) { - list($name, $value) = each($globals); - $this->assertEquals($name, $call[1][0]); - $this->assertSame($value, $call[1][1]); + $this->assertEquals(key($globals), $call[1][0]); + $this->assertSame(current($globals), $call[1][1]); + + next($globals); } } From 598ae56cc96bfe0496f0a892085d39cba752304e Mon Sep 17 00:00:00 2001 From: Vladimir Reznichenko Date: Sun, 28 May 2017 16:12:41 +0200 Subject: [PATCH 025/106] SCA with Php Inspections (EA Extended): 2.7 --- .../Bundle/FrameworkBundle/Templating/Helper/AssetsHelper.php | 2 +- src/Symfony/Bundle/TwigBundle/Loader/FilesystemLoader.php | 1 - .../DependencyInjection/Tests/ContainerBuilderTest.php | 2 +- src/Symfony/Component/Filesystem/Tests/LockHandlerTest.php | 2 +- .../Form/ChoiceList/Factory/DefaultChoiceListFactory.php | 2 +- src/Symfony/Component/Form/FormRenderer.php | 2 +- src/Symfony/Component/Security/Acl/Dbal/Schema.php | 2 +- .../Security/Core/Authorization/AccessDecisionManager.php | 2 -- 8 files changed, 6 insertions(+), 9 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/Templating/Helper/AssetsHelper.php b/src/Symfony/Bundle/FrameworkBundle/Templating/Helper/AssetsHelper.php index 6acc04539393d..172417924c921 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Templating/Helper/AssetsHelper.php +++ b/src/Symfony/Bundle/FrameworkBundle/Templating/Helper/AssetsHelper.php @@ -78,7 +78,7 @@ public function getVersion($path = null, $packageName = null) // packageName is null and path not, so path is a path or a packageName try { - $package = $this->packages->getPackage($path); + $this->packages->getPackage($path); } catch (\InvalidArgumentException $e) { // path is not a package, so it should be a path return $this->packages->getVersion($path); diff --git a/src/Symfony/Bundle/TwigBundle/Loader/FilesystemLoader.php b/src/Symfony/Bundle/TwigBundle/Loader/FilesystemLoader.php index 53fe300e29a62..74d1d1214ffed 100644 --- a/src/Symfony/Bundle/TwigBundle/Loader/FilesystemLoader.php +++ b/src/Symfony/Bundle/TwigBundle/Loader/FilesystemLoader.php @@ -73,7 +73,6 @@ protected function findTemplate($template, $throw = true) } $file = null; - $previous = null; try { $file = parent::findTemplate($logicalName); } catch (\Twig_Error_Loader $e) { diff --git a/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php b/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php index cefe0a02aa829..f4274b80a4443 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php @@ -108,7 +108,7 @@ public function testGet() } $builder->register('foobar', 'stdClass')->setScope('container'); - $this->assertTrue($builder->get('bar') === $builder->get('bar'), '->get() always returns the same instance if the service is shared'); + $this->assertSame($builder->get('bar'), $builder->get('bar'), '->get() always returns the same instance if the service is shared'); } /** diff --git a/src/Symfony/Component/Filesystem/Tests/LockHandlerTest.php b/src/Symfony/Component/Filesystem/Tests/LockHandlerTest.php index 0791cebc694b8..9ed871ea5a2a3 100644 --- a/src/Symfony/Component/Filesystem/Tests/LockHandlerTest.php +++ b/src/Symfony/Component/Filesystem/Tests/LockHandlerTest.php @@ -49,7 +49,7 @@ public function testErrorHandlingInLockIfLockPathBecomesUnwritable() $this->markTestSkipped('This test cannot run on Windows.'); } - $lockPath = sys_get_temp_dir().'/'.uniqid(); + $lockPath = sys_get_temp_dir().'/'.uniqid('', true); $e = null; $wrongMessage = null; diff --git a/src/Symfony/Component/Form/ChoiceList/Factory/DefaultChoiceListFactory.php b/src/Symfony/Component/Form/ChoiceList/Factory/DefaultChoiceListFactory.php index e08c9e51276be..fd24ccbeb11da 100644 --- a/src/Symfony/Component/Form/ChoiceList/Factory/DefaultChoiceListFactory.php +++ b/src/Symfony/Component/Form/ChoiceList/Factory/DefaultChoiceListFactory.php @@ -89,7 +89,7 @@ public function createView(ChoiceListInterface $list, $preferredChoices = null, if (!is_callable($preferredChoices) && !empty($preferredChoices)) { $preferredChoices = function ($choice) use ($preferredChoices) { - return false !== array_search($choice, $preferredChoices, true); + return in_array($choice, $preferredChoices, true); }; } diff --git a/src/Symfony/Component/Form/FormRenderer.php b/src/Symfony/Component/Form/FormRenderer.php index 15a8d08430cfe..9d1c075bb5fa7 100644 --- a/src/Symfony/Component/Form/FormRenderer.php +++ b/src/Symfony/Component/Form/FormRenderer.php @@ -316,6 +316,6 @@ public function searchAndRenderBlock(FormView $view, $blockNameSuffix, array $va */ public function humanize($text) { - return ucfirst(trim(strtolower(preg_replace(array('/([A-Z])/', '/[_\s]+/'), array('_$1', ' '), $text)))); + return ucfirst(strtolower(trim(preg_replace(array('/([A-Z])/', '/[_\s]+/'), array('_$1', ' '), $text)))); } } diff --git a/src/Symfony/Component/Security/Acl/Dbal/Schema.php b/src/Symfony/Component/Security/Acl/Dbal/Schema.php index ed9327ce7b139..864d0091af3ef 100644 --- a/src/Symfony/Component/Security/Acl/Dbal/Schema.php +++ b/src/Symfony/Component/Security/Acl/Dbal/Schema.php @@ -21,7 +21,7 @@ */ final class Schema extends BaseSchema { - protected $options; + private $options; /** * Constructor. diff --git a/src/Symfony/Component/Security/Core/Authorization/AccessDecisionManager.php b/src/Symfony/Component/Security/Core/Authorization/AccessDecisionManager.php index b8b6a776e9b8e..c18c2cbf09f0f 100644 --- a/src/Symfony/Component/Security/Core/Authorization/AccessDecisionManager.php +++ b/src/Symfony/Component/Security/Core/Authorization/AccessDecisionManager.php @@ -144,7 +144,6 @@ private function decideConsensus(TokenInterface $token, array $attributes, $obje { $grant = 0; $deny = 0; - $abstain = 0; foreach ($this->voters as $voter) { $result = $voter->vote($token, $object, $attributes); @@ -160,7 +159,6 @@ private function decideConsensus(TokenInterface $token, array $attributes, $obje break; default: - ++$abstain; break; } From 9251a2143d69a9add8520aea485e590d149bdf75 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Mon, 12 Jun 2017 11:39:35 +0200 Subject: [PATCH 026/106] [DI] Fix keys resolution in ResolveParameterPlaceHoldersPass --- .../Compiler/ResolveParameterPlaceHoldersPass.php | 10 +++++++--- .../Compiler/ResolveParameterPlaceHoldersPassTest.php | 8 ++++---- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/src/Symfony/Component/DependencyInjection/Compiler/ResolveParameterPlaceHoldersPass.php b/src/Symfony/Component/DependencyInjection/Compiler/ResolveParameterPlaceHoldersPass.php index 2444e441ee53e..69d48d9ef246b 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/ResolveParameterPlaceHoldersPass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/ResolveParameterPlaceHoldersPass.php @@ -65,10 +65,14 @@ protected function processValue($value, $isRoot = false) if (isset($changes['file'])) { $value->setFile($this->bag->resolveValue($value->getFile())); } - $value->setProperties($this->bag->resolveValue($value->getProperties())); - $value->setMethodCalls($this->bag->resolveValue($value->getMethodCalls())); } - return parent::processValue($value, $isRoot); + $value = parent::processValue($value, $isRoot); + + if ($value && is_array($value)) { + $value = array_combine($this->bag->resolveValue(array_keys($value)), $value); + } + + return $value; } } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveParameterPlaceHoldersPassTest.php b/src/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveParameterPlaceHoldersPassTest.php index 50be82d741119..b9459729e2e80 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveParameterPlaceHoldersPassTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveParameterPlaceHoldersPassTest.php @@ -41,12 +41,12 @@ public function testFactoryParametersShouldBeResolved() public function testArgumentParametersShouldBeResolved() { - $this->assertSame(array('bar', 'baz'), $this->fooDefinition->getArguments()); + $this->assertSame(array('bar', array('bar' => 'baz')), $this->fooDefinition->getArguments()); } public function testMethodCallParametersShouldBeResolved() { - $this->assertSame(array(array('foobar', array('bar', 'baz'))), $this->fooDefinition->getMethodCalls()); + $this->assertSame(array(array('foobar', array('bar', array('bar' => 'baz')))), $this->fooDefinition->getMethodCalls()); } public function testPropertyParametersShouldBeResolved() @@ -71,7 +71,7 @@ private function createContainerBuilder() $containerBuilder->setParameter('foo.class', 'Foo'); $containerBuilder->setParameter('foo.factory.class', 'FooFactory'); $containerBuilder->setParameter('foo.arg1', 'bar'); - $containerBuilder->setParameter('foo.arg2', 'baz'); + $containerBuilder->setParameter('foo.arg2', array('%foo.arg1%' => 'baz')); $containerBuilder->setParameter('foo.method', 'foobar'); $containerBuilder->setParameter('foo.property.name', 'bar'); $containerBuilder->setParameter('foo.property.value', 'baz'); @@ -80,7 +80,7 @@ private function createContainerBuilder() $fooDefinition = $containerBuilder->register('foo', '%foo.class%'); $fooDefinition->setFactory(array('%foo.factory.class%', 'getFoo')); - $fooDefinition->setArguments(array('%foo.arg1%', '%foo.arg2%')); + $fooDefinition->setArguments(array('%foo.arg1%', array('%foo.arg1%' => 'baz'))); $fooDefinition->addMethodCall('%foo.method%', array('%foo.arg1%', '%foo.arg2%')); $fooDefinition->setProperty('%foo.property.name%', '%foo.property.value%'); $fooDefinition->setFile('%foo.file%'); From 79bc4b017d340de96c1e7de705a3ad77140d184f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9goire=20Pineau?= Date: Mon, 12 Jun 2017 13:49:55 +0200 Subject: [PATCH 027/106] [Workflow] Added more keywords in the composer.json --- src/Symfony/Component/Workflow/composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/Workflow/composer.json b/src/Symfony/Component/Workflow/composer.json index b30d50091e1d6..f64d3cf8a4cd7 100644 --- a/src/Symfony/Component/Workflow/composer.json +++ b/src/Symfony/Component/Workflow/composer.json @@ -2,7 +2,7 @@ "name": "symfony/workflow", "type": "library", "description": "Symfony Workflow Component", - "keywords": ["workflow", "petrinet", "place", "transition"], + "keywords": ["workflow", "petrinet", "place", "transition", "statemachine", "state"], "homepage": "http://symfony.com", "license": "MIT", "authors": [ From 0ec8b1c1ff12cf422d846c6750287279762637b9 Mon Sep 17 00:00:00 2001 From: Christophe Coevoet Date: Mon, 12 Jun 2017 15:35:45 +0200 Subject: [PATCH 028/106] Fix the conditional definition of the SymfonyTestsListener --- .../Bridge/PhpUnit/SymfonyTestsListener.php | 82 +++++++++---------- 1 file changed, 41 insertions(+), 41 deletions(-) diff --git a/src/Symfony/Bridge/PhpUnit/SymfonyTestsListener.php b/src/Symfony/Bridge/PhpUnit/SymfonyTestsListener.php index 2dad6ef0095bc..c11fde9526eab 100644 --- a/src/Symfony/Bridge/PhpUnit/SymfonyTestsListener.php +++ b/src/Symfony/Bridge/PhpUnit/SymfonyTestsListener.php @@ -18,53 +18,53 @@ if (class_exists('PHPUnit_Runner_Version') && version_compare(\PHPUnit_Runner_Version::id(), '6.0.0', '<')) { class_alias('Symfony\Bridge\PhpUnit\Legacy\SymfonyTestsListener', 'Symfony\Bridge\PhpUnit\SymfonyTestsListener'); - - return; -} - -/** - * Collects and replays skipped tests. - * - * @author Nicolas Grekas - * - * @final - */ -class SymfonyTestsListener extends BaseTestListener -{ - private $trait; - - public function __construct(array $mockedNamespaces = array()) +// Using an early return instead of a else does not work when using the PHPUnit phar due to some weird PHP behavior (the class +// gets defined without executing the code before it and so the definition is not properly conditional) +} else { + /** + * Collects and replays skipped tests. + * + * @author Nicolas Grekas + * + * @final + */ + class SymfonyTestsListener extends BaseTestListener { - $this->trait = new Legacy\SymfonyTestsListenerTrait($mockedNamespaces); - } + private $trait; - public function globalListenerDisabled() - { - $this->trait->globalListenerDisabled(); - } + public function __construct(array $mockedNamespaces = array()) + { + $this->trait = new Legacy\SymfonyTestsListenerTrait($mockedNamespaces); + } - public function startTestSuite(TestSuite $suite) - { - return $this->trait->startTestSuite($suite); - } + public function globalListenerDisabled() + { + $this->trait->globalListenerDisabled(); + } - public function addSkippedTest(Test $test, \Exception $e, $time) - { - return $this->trait->addSkippedTest($test, $e, $time); - } + public function startTestSuite(TestSuite $suite) + { + return $this->trait->startTestSuite($suite); + } - public function startTest(Test $test) - { - return $this->trait->startTest($test); - } + public function addSkippedTest(Test $test, \Exception $e, $time) + { + return $this->trait->addSkippedTest($test, $e, $time); + } - public function addWarning(Test $test, Warning $e, $time) - { - return $this->trait->addWarning($test, $e, $time); - } + public function startTest(Test $test) + { + return $this->trait->startTest($test); + } - public function endTest(Test $test, $time) - { - return $this->trait->endTest($test, $time); + public function addWarning(Test $test, Warning $e, $time) + { + return $this->trait->addWarning($test, $e, $time); + } + + public function endTest(Test $test, $time) + { + return $this->trait->endTest($test, $time); + } } } From fddd754c0a28e56bc97a8d5693b5ff83d1f3d237 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Mon, 5 Jun 2017 22:55:00 +0200 Subject: [PATCH 029/106] add back support for legacy constant values --- src/Symfony/Component/HttpFoundation/Request.php | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/HttpFoundation/Request.php b/src/Symfony/Component/HttpFoundation/Request.php index 13ff1e05528fe..6fd0707b059ff 100644 --- a/src/Symfony/Component/HttpFoundation/Request.php +++ b/src/Symfony/Component/HttpFoundation/Request.php @@ -672,7 +672,17 @@ public static function setTrustedHeaderName($key, $value) { @trigger_error(sprintf('The "%s()" method is deprecated since version 3.3 and will be removed in 4.0. Use the $trustedHeaderSet argument of the Request::setTrustedProxies() method instead.', __METHOD__), E_USER_DEPRECATED); - if (!array_key_exists($key, self::$trustedHeaders)) { + if ('forwarded' === $key) { + $key = self::HEADER_FORWARDED; + } elseif ('client_ip' === $key) { + $key = self::HEADER_CLIENT_IP; + } elseif ('client_host' === $key) { + $key = self::HEADER_CLIENT_HOST; + } elseif ('client_proto' === $key) { + $key = self::HEADER_CLIENT_PROTO; + } elseif ('client_port' === $key) { + $key = self::HEADER_CLIENT_PORT; + } elseif (!array_key_exists($key, self::$trustedHeaders)) { throw new \InvalidArgumentException(sprintf('Unable to set the trusted header name for key "%s".', $key)); } From 3f7fd432dfb3a2e3ab92b1681d6ec25a32cd1574 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Malte=20Bl=C3=A4ttermann?= Date: Sun, 11 Jun 2017 22:11:35 +0200 Subject: [PATCH 030/106] Fix Usage with anonymous classes Replace forbidden characters in the the class names of Anonymous Classes in form of "class@anonymous /symfony/src/Symfony/Component/PropertyAccess/Tests/PropertyAccessorTest.php0x7f3f5f267ad5" Wrapped in eval to avoid PHP parsing errors < 7 --- .../PropertyAccess/PropertyAccessor.php | 4 +- .../Tests/PropertyAccessorTest.php | 60 +++++++++++++++++++ 2 files changed, 62 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/PropertyAccess/PropertyAccessor.php b/src/Symfony/Component/PropertyAccess/PropertyAccessor.php index 69d7fc0e9f1aa..131576e261fcf 100644 --- a/src/Symfony/Component/PropertyAccess/PropertyAccessor.php +++ b/src/Symfony/Component/PropertyAccess/PropertyAccessor.php @@ -523,7 +523,7 @@ private function readProperty($zval, $property) */ private function getReadAccessInfo($class, $property) { - $key = $class.'..'.$property; + $key = (false !== strpos($class, '@') ? rawurlencode($class) : $class).'..'.$property; if (isset($this->readPropertyCache[$key])) { return $this->readPropertyCache[$key]; @@ -702,7 +702,7 @@ private function writeCollection($zval, $property, $collection, $addMethod, $rem */ private function getWriteAccessInfo($class, $property, $value) { - $key = $class.'..'.$property; + $key = (false !== strpos($class, '@') ? rawurlencode($class) : $class).'..'.$property; if (isset($this->writePropertyCache[$key])) { return $this->writePropertyCache[$key]; diff --git a/src/Symfony/Component/PropertyAccess/Tests/PropertyAccessorTest.php b/src/Symfony/Component/PropertyAccess/Tests/PropertyAccessorTest.php index e2ef9296ed50f..e23f6cd6dba30 100644 --- a/src/Symfony/Component/PropertyAccess/Tests/PropertyAccessorTest.php +++ b/src/Symfony/Component/PropertyAccess/Tests/PropertyAccessorTest.php @@ -578,4 +578,64 @@ public function testThrowTypeErrorWithInterface() $this->propertyAccessor->setValue($object, 'countable', 'This is a string, \Countable expected.'); } + + /** + * @requires PHP 7.0 + */ + public function testAnonymousClassRead() + { + $value = 'bar'; + + $obj = $this->generateAnonymousClass($value); + + $propertyAccessor = new PropertyAccessor(false, false, new ArrayAdapter()); + + $this->assertEquals($value, $propertyAccessor->getValue($obj, 'foo')); + } + + /** + * @requires PHP 7.0 + */ + public function testAnonymousClassWrite() + { + $value = 'bar'; + + $obj = $this->generateAnonymousClass(''); + + $propertyAccessor = new PropertyAccessor(false, false, new ArrayAdapter()); + $propertyAccessor->setValue($obj, 'foo', $value); + + $this->assertEquals($value, $propertyAccessor->getValue($obj, 'foo')); + } + + private function generateAnonymousClass($value) + { + $obj = eval('return new class($value) + { + private $foo; + + public function __construct($foo) + { + $this->foo = $foo; + } + + /** + * @return mixed + */ + public function getFoo() + { + return $this->foo; + } + + /** + * @param mixed $foo + */ + public function setFoo($foo) + { + $this->foo = $foo; + } + };'); + + return $obj; + } } From f09893bed4fe8bedee14af2ccd9562f90282b671 Mon Sep 17 00:00:00 2001 From: Dan Wilga Date: Fri, 9 Jun 2017 15:14:01 -0400 Subject: [PATCH 031/106] [Routing] Revert the change in [#b42018] with respect to Routing/Route.php --- src/Symfony/Component/Routing/Route.php | 6 +---- .../Tests/Fixtures/CustomCompiledRoute.php | 18 +++++++++++++ .../Tests/Fixtures/CustomRouteCompiler.php | 26 +++++++++++++++++++ .../Component/Routing/Tests/RouteTest.php | 18 +++++++++++++ 4 files changed, 63 insertions(+), 5 deletions(-) create mode 100644 src/Symfony/Component/Routing/Tests/Fixtures/CustomCompiledRoute.php create mode 100644 src/Symfony/Component/Routing/Tests/Fixtures/CustomRouteCompiler.php diff --git a/src/Symfony/Component/Routing/Route.php b/src/Symfony/Component/Routing/Route.php index 34b1b75765dc6..69a7cade10c33 100644 --- a/src/Symfony/Component/Routing/Route.php +++ b/src/Symfony/Component/Routing/Route.php @@ -116,11 +116,7 @@ public function serialize() */ public function unserialize($serialized) { - if (\PHP_VERSION_ID >= 70000) { - $data = unserialize($serialized, array('allowed_classes' => array(CompiledRoute::class))); - } else { - $data = unserialize($serialized); - } + $data = unserialize($serialized); $this->path = $data['path']; $this->host = $data['host']; $this->defaults = $data['defaults']; diff --git a/src/Symfony/Component/Routing/Tests/Fixtures/CustomCompiledRoute.php b/src/Symfony/Component/Routing/Tests/Fixtures/CustomCompiledRoute.php new file mode 100644 index 0000000000000..0f6e198c923d9 --- /dev/null +++ b/src/Symfony/Component/Routing/Tests/Fixtures/CustomCompiledRoute.php @@ -0,0 +1,18 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing\Tests\Fixtures; + +use Symfony\Component\Routing\CompiledRoute; + +class CustomCompiledRoute extends CompiledRoute +{ +} diff --git a/src/Symfony/Component/Routing/Tests/Fixtures/CustomRouteCompiler.php b/src/Symfony/Component/Routing/Tests/Fixtures/CustomRouteCompiler.php new file mode 100644 index 0000000000000..c2e2afd9afcd9 --- /dev/null +++ b/src/Symfony/Component/Routing/Tests/Fixtures/CustomRouteCompiler.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing\Tests\Fixtures; + +use Symfony\Component\Routing\Route; +use Symfony\Component\Routing\RouteCompiler; + +class CustomRouteCompiler extends RouteCompiler +{ + /** + * {@inheritdoc} + */ + public static function compile(Route $route) + { + return new CustomCompiledRoute('', '', array(), array()); + } +} diff --git a/src/Symfony/Component/Routing/Tests/RouteTest.php b/src/Symfony/Component/Routing/Tests/RouteTest.php index b65dfb54085c1..ff7e320c5fc95 100644 --- a/src/Symfony/Component/Routing/Tests/RouteTest.php +++ b/src/Symfony/Component/Routing/Tests/RouteTest.php @@ -220,6 +220,24 @@ public function testSerializeWhenCompiled() $this->assertNotSame($route, $unserialized); } + /** + * Tests that unserialization does not fail when the compiled Route is of a + * class other than CompiledRoute, such as a subclass of it. + */ + public function testSerializeWhenCompiledWithClass() + { + $route = new Route('/', array(), array(), array('compiler_class' => '\Symfony\Component\Routing\Tests\Fixtures\CustomRouteCompiler')); + $this->assertInstanceOf('\Symfony\Component\Routing\Tests\Fixtures\CustomCompiledRoute', $route->compile(), '->compile() returned a proper route'); + + $serialized = serialize($route); + try { + $unserialized = unserialize($serialized); + $this->assertInstanceOf('\Symfony\Component\Routing\Tests\Fixtures\CustomCompiledRoute', $unserialized->compile(), 'the unserialized route compiled successfully'); + } catch (\Exception $e) { + $this->fail('unserializing a route which uses a custom compiled route class'); + } + } + /** * Tests that the serialized representation of a route in one symfony version * also works in later symfony versions, i.e. the unserialized route is in the From abd900733749178770242bf85b4bcd0b734928e3 Mon Sep 17 00:00:00 2001 From: Maxime Steinhausser Date: Tue, 13 Jun 2017 20:21:13 +0200 Subject: [PATCH 032/106] [FrameworkBundle] Remove unnecessary use --- .../Bundle/FrameworkBundle/Controller/AbstractController.php | 1 - .../FrameworkBundle/Tests/Controller/AbstractControllerTest.php | 1 - 2 files changed, 2 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/Controller/AbstractController.php b/src/Symfony/Bundle/FrameworkBundle/Controller/AbstractController.php index 6d0cee247da77..def76d9defba2 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Controller/AbstractController.php +++ b/src/Symfony/Bundle/FrameworkBundle/Controller/AbstractController.php @@ -16,7 +16,6 @@ use Symfony\Component\DependencyInjection\ServiceSubscriberInterface; use Symfony\Component\Form\FormFactoryInterface; use Symfony\Component\HttpFoundation\RequestStack; -use Symfony\Component\HttpFoundation\Session\Session; use Symfony\Component\HttpFoundation\Session\SessionInterface; use Symfony\Component\HttpKernel\HttpKernelInterface; use Symfony\Component\Routing\RouterInterface; diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/AbstractControllerTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/AbstractControllerTest.php index 937cbfc7286d0..6783ec25c5ab5 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/AbstractControllerTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/AbstractControllerTest.php @@ -13,7 +13,6 @@ use Psr\Container\ContainerInterface; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; -use Symfony\Component\HttpFoundation\File\File; class AbstractControllerTest extends ControllerTraitTest { From 55a8d35e64c4e8b52eac9ef3941de94f74ead133 Mon Sep 17 00:00:00 2001 From: Robin Chalas Date: Tue, 13 Jun 2017 22:44:19 +0200 Subject: [PATCH 033/106] [Yaml] Fix linting yaml with constants as keys --- src/Symfony/Component/Yaml/Command/LintCommand.php | 3 ++- .../Yaml/Tests/Command/LintCommandTest.php | 14 ++++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/Yaml/Command/LintCommand.php b/src/Symfony/Component/Yaml/Command/LintCommand.php index 48f6d94a03915..271f2d8474109 100644 --- a/src/Symfony/Component/Yaml/Command/LintCommand.php +++ b/src/Symfony/Component/Yaml/Command/LintCommand.php @@ -18,6 +18,7 @@ use Symfony\Component\Console\Style\SymfonyStyle; use Symfony\Component\Yaml\Exception\ParseException; use Symfony\Component\Yaml\Parser; +use Symfony\Component\Yaml\Yaml; /** * Validates YAML files syntax and outputs encountered errors. @@ -111,7 +112,7 @@ private function validate($content, $file = null) }); try { - $this->getParser()->parse($content); + $this->getParser()->parse($content, Yaml::PARSE_CONSTANT); } catch (ParseException $e) { return array('file' => $file, 'valid' => false, 'message' => $e->getMessage()); } finally { diff --git a/src/Symfony/Component/Yaml/Tests/Command/LintCommandTest.php b/src/Symfony/Component/Yaml/Tests/Command/LintCommandTest.php index ce6ad480cf2b6..75aa067f22890 100644 --- a/src/Symfony/Component/Yaml/Tests/Command/LintCommandTest.php +++ b/src/Symfony/Component/Yaml/Tests/Command/LintCommandTest.php @@ -51,6 +51,15 @@ public function testLintIncorrectFile() $this->assertContains('Unable to parse at line 3 (near "bar").', trim($tester->getDisplay())); } + public function testConstantAsKey() + { + $yaml = <<createCommandTester()->execute(array('filename' => $this->createFile($yaml)), array('verbosity' => OutputInterface::VERBOSITY_VERBOSE, 'decorated' => false)); + $this->assertSame(0, $ret, 'lint:yaml exits with code 0 in case of success'); + } + /** * @expectedException \RuntimeException */ @@ -105,3 +114,8 @@ protected function tearDown() rmdir(sys_get_temp_dir().'/framework-yml-lint-test'); } } + +class Foo +{ + const TEST = 'foo'; +} From 78f028cc758338c270011bd826b13e7f485d8dc5 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Tue, 13 Jun 2017 17:54:13 -0700 Subject: [PATCH 034/106] fixed CS --- .../Csrf/EventListener/CsrfValidationListenerTest.php | 1 - src/Symfony/Component/VarDumper/Dumper/CliDumper.php | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Component/Form/Tests/Extension/Csrf/EventListener/CsrfValidationListenerTest.php b/src/Symfony/Component/Form/Tests/Extension/Csrf/EventListener/CsrfValidationListenerTest.php index fc0dee140b047..47f9e43294ba0 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Csrf/EventListener/CsrfValidationListenerTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Csrf/EventListener/CsrfValidationListenerTest.php @@ -12,7 +12,6 @@ namespace Symfony\Component\Form\Tests\Extension\Csrf\EventListener; use PHPUnit\Framework\TestCase; -use Symfony\Component\Form\Form; use Symfony\Component\Form\FormBuilder; use Symfony\Component\Form\FormEvent; use Symfony\Component\Form\Extension\Csrf\EventListener\CsrfValidationListener; diff --git a/src/Symfony/Component/VarDumper/Dumper/CliDumper.php b/src/Symfony/Component/VarDumper/Dumper/CliDumper.php index 59ba119e42914..822736abd5561 100644 --- a/src/Symfony/Component/VarDumper/Dumper/CliDumper.php +++ b/src/Symfony/Component/VarDumper/Dumper/CliDumper.php @@ -125,9 +125,9 @@ public function dumpScalar(Cursor $cursor, $type, $value) $style = 'num'; switch (true) { - case INF === $value: $value = 'INF'; break; + case INF === $value: $value = 'INF'; break; case -INF === $value: $value = '-INF'; break; - case is_nan($value): $value = 'NAN'; break; + case is_nan($value): $value = 'NAN'; break; default: $value = (string) $value; if (false === strpos($value, $this->decimalPoint)) { From 44955bea53f6a9cbc9e8adab2a50db91fdd77b35 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Tue, 13 Jun 2017 20:10:15 +0200 Subject: [PATCH 035/106] [Config] Fix ** GlobResource on Windows --- src/Symfony/Component/Config/Resource/GlobResource.php | 2 +- .../Component/Config/Tests/Resource/GlobResourceTest.php | 9 +++++++++ src/Symfony/Component/Config/composer.json | 2 ++ 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/Config/Resource/GlobResource.php b/src/Symfony/Component/Config/Resource/GlobResource.php index 67625201530f5..20cab1e81d55d 100644 --- a/src/Symfony/Component/Config/Resource/GlobResource.php +++ b/src/Symfony/Component/Config/Resource/GlobResource.php @@ -134,7 +134,7 @@ function (\SplFileInfo $file) { return '.' !== $file->getBasename()[0]; } $prefixLen = strlen($this->prefix); foreach ($finder->followLinks()->sortByName()->in($this->prefix) as $path => $info) { - if (preg_match($regex, substr($path, $prefixLen)) && $info->isFile()) { + if (preg_match($regex, substr('\\' === \DIRECTORY_SEPARATOR ? str_replace('\\', '/', $path) : $path, $prefixLen)) && $info->isFile()) { yield $path => $info; } } diff --git a/src/Symfony/Component/Config/Tests/Resource/GlobResourceTest.php b/src/Symfony/Component/Config/Tests/Resource/GlobResourceTest.php index b84cc9d3ae3b9..bf7291fdd66b8 100644 --- a/src/Symfony/Component/Config/Tests/Resource/GlobResourceTest.php +++ b/src/Symfony/Component/Config/Tests/Resource/GlobResourceTest.php @@ -36,6 +36,15 @@ public function testIterator() $this->assertEquals(array($file => new \SplFileInfo($file)), $paths); $this->assertInstanceOf('SplFileInfo', current($paths)); $this->assertSame($dir, $resource->getPrefix()); + + $resource = new GlobResource($dir, '/**/Resource', true); + + $paths = iterator_to_array($resource); + + $file = $dir.DIRECTORY_SEPARATOR.'Resource'.DIRECTORY_SEPARATOR.'ConditionalClass.php'; + $this->assertEquals(array($file => $file), $paths); + $this->assertInstanceOf('SplFileInfo', current($paths)); + $this->assertSame($dir, $resource->getPrefix()); } public function testIsFreshNonRecursiveDetectsNewFile() diff --git a/src/Symfony/Component/Config/composer.json b/src/Symfony/Component/Config/composer.json index 88090d463da63..7a51c91ed591a 100644 --- a/src/Symfony/Component/Config/composer.json +++ b/src/Symfony/Component/Config/composer.json @@ -20,10 +20,12 @@ "symfony/filesystem": "~2.8|~3.0" }, "require-dev": { + "symfony/finder": "~3.3", "symfony/yaml": "~3.0", "symfony/dependency-injection": "~3.3" }, "conflict": { + "symfony/finder": "<3.3", "symfony/dependency-injection": "<3.3" }, "suggest": { From d8d0f877934ca63403cba4949c9293dfc943fb3a Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Wed, 14 Jun 2017 09:33:02 +0200 Subject: [PATCH 036/106] [TwigBundle] Add Doctrine Cache to dev dependencies --- src/Symfony/Bundle/TwigBundle/composer.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Bundle/TwigBundle/composer.json b/src/Symfony/Bundle/TwigBundle/composer.json index 11f071b19c32b..1b3cc91c1969c 100644 --- a/src/Symfony/Bundle/TwigBundle/composer.json +++ b/src/Symfony/Bundle/TwigBundle/composer.json @@ -35,7 +35,8 @@ "symfony/yaml": "~2.8|~3.0", "symfony/framework-bundle": "^3.2.8", "symfony/web-link": "~3.3", - "doctrine/annotations": "~1.0" + "doctrine/annotations": "~1.0", + "doctrine/cache": "~1.0" }, "conflict": { "symfony/dependency-injection": "<3.3" From 408e56e404973232fac7c114e979025e72464d77 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Wed, 14 Jun 2017 10:52:56 +0200 Subject: [PATCH 037/106] Fix AutowiringTypesTest transient tests --- .../Bundle/FrameworkBundle/Tests/Functional/WebTestCase.php | 2 +- .../Bundle/SecurityBundle/Tests/Functional/WebTestCase.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/WebTestCase.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/WebTestCase.php index 2861297fe0256..a1c50e59fdb90 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/WebTestCase.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/WebTestCase.php @@ -68,6 +68,6 @@ protected static function createKernel(array $options = array()) protected static function getVarDir() { - return substr(strrchr(get_called_class(), '\\'), 1); + return 'FB'.substr(strrchr(get_called_class(), '\\'), 1); } } diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/WebTestCase.php b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/WebTestCase.php index 8bace799a37a8..bb98a2a065ca0 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/WebTestCase.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/WebTestCase.php @@ -68,6 +68,6 @@ protected static function createKernel(array $options = array()) protected static function getVarDir() { - return substr(strrchr(get_called_class(), '\\'), 1); + return 'SB'.substr(strrchr(get_called_class(), '\\'), 1); } } From d7238c9d96df18d7b71306f91b014f946b6c1c7a Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Wed, 14 Jun 2017 17:32:02 +0200 Subject: [PATCH 038/106] [VarDumper] fixes --- src/Symfony/Component/VarDumper/Caster/ResourceCaster.php | 2 +- src/Symfony/Component/VarDumper/Caster/SplCaster.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/VarDumper/Caster/ResourceCaster.php b/src/Symfony/Component/VarDumper/Caster/ResourceCaster.php index 903641f69c636..d70c09ac4da62 100644 --- a/src/Symfony/Component/VarDumper/Caster/ResourceCaster.php +++ b/src/Symfony/Component/VarDumper/Caster/ResourceCaster.php @@ -45,7 +45,7 @@ public static function castStream($stream, array $a, Stub $stub, $isNested) public static function castStreamContext($stream, array $a, Stub $stub, $isNested) { - return stream_context_get_params($stream); + return @stream_context_get_params($stream) ?: $a; } public static function castGd($gd, array $a, Stub $stub, $isNested) diff --git a/src/Symfony/Component/VarDumper/Caster/SplCaster.php b/src/Symfony/Component/VarDumper/Caster/SplCaster.php index b0b57e3cda598..d50419f624394 100644 --- a/src/Symfony/Component/VarDumper/Caster/SplCaster.php +++ b/src/Symfony/Component/VarDumper/Caster/SplCaster.php @@ -86,7 +86,7 @@ public static function castObjectStorage(\SplObjectStorage $c, array $a, Stub $s $storage = array(); unset($a[Caster::PREFIX_DYNAMIC."\0gcdata"]); // Don't hit https://bugs.php.net/65967 - foreach ($c as $obj) { + foreach (clone $c as $obj) { $storage[spl_object_hash($obj)] = array( 'object' => $obj, 'info' => $c->getInfo(), From 71c1b6f5bf2f0aaa42bdca058f3e6a24148ad28e Mon Sep 17 00:00:00 2001 From: Vincent AUBERT Date: Sat, 10 Jun 2017 18:29:28 +0200 Subject: [PATCH 039/106] fixes #21606 --- .../HttpFoundation/Session/Storage/NativeSessionStorage.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php b/src/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php index 36a20550b07cf..987f2f25b47ef 100644 --- a/src/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php +++ b/src/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php @@ -340,6 +340,7 @@ public function setOptions(array $options) 'use_only_cookies', 'use_trans_sid', 'upload_progress.enabled', 'upload_progress.cleanup', 'upload_progress.prefix', 'upload_progress.name', 'upload_progress.freq', 'upload_progress.min-freq', 'url_rewriter.tags', + 'sid_length', 'sid_bits_per_character', 'trans_sid_hosts', 'trans_sid_tags', )); foreach ($options as $key => $value) { From c6b9101e066f85552f6326bdc6594cb335a5dc6f Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Wed, 14 Jun 2017 12:35:44 -0700 Subject: [PATCH 040/106] [HttpFoundation] added missing docs --- .../HttpFoundation/Session/Storage/NativeSessionStorage.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php b/src/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php index 987f2f25b47ef..812f5f2e4fcc0 100644 --- a/src/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php +++ b/src/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php @@ -92,6 +92,10 @@ class NativeSessionStorage implements SessionStorageInterface * upload_progress.freq, "1%" * upload_progress.min-freq, "1" * url_rewriter.tags, "a=href,area=href,frame=src,form=,fieldset=" + * sid_length, "32" + * sid_bits_per_character, "5" + * trans_sid_hosts, $_SERVER['HTTP_HOST'] + * trans_sid_tags, "a=href,area=href,frame=src,form=" * * @param array $options Session configuration options * @param AbstractProxy|NativeSessionHandler|\SessionHandlerInterface|null $handler From 69e84633dd8ce763c8226acae45afc10dff155c2 Mon Sep 17 00:00:00 2001 From: Matthias Pigulla Date: Sat, 10 Jun 2017 12:29:45 +0200 Subject: [PATCH 041/106] Add tests for ResponseCacheStrategy to document some more edge cases --- .../HttpCache/ResponseCacheStrategyTest.php | 62 +++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/src/Symfony/Component/HttpKernel/Tests/HttpCache/ResponseCacheStrategyTest.php b/src/Symfony/Component/HttpKernel/Tests/HttpCache/ResponseCacheStrategyTest.php index f30a3b6ad94ab..a37a85bc436a9 100644 --- a/src/Symfony/Component/HttpKernel/Tests/HttpCache/ResponseCacheStrategyTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/HttpCache/ResponseCacheStrategyTest.php @@ -75,4 +75,66 @@ public function testSharedMaxAgeNotSetIfNotSetInMasterRequest() $this->assertFalse($response->headers->hasCacheControlDirective('s-maxage')); } + + public function testMasterResponseNotCacheableWhenEmbeddedResponseRequiresValidation() + { + $cacheStrategy = new ResponseCacheStrategy(); + + $embeddedResponse = new Response(); + $embeddedResponse->setLastModified(new \DateTime()); + $cacheStrategy->add($embeddedResponse); + + $masterResponse = new Response(); + $masterResponse->setSharedMaxAge(3600); + $cacheStrategy->update($masterResponse); + + $this->assertTrue($masterResponse->headers->hasCacheControlDirective('no-cache')); + $this->assertTrue($masterResponse->headers->hasCacheControlDirective('must-revalidate')); + $this->assertFalse($masterResponse->isFresh()); + } + + public function testValidationOnMasterResponseIsNotPossibleWhenItContainsEmbeddedResponses() + { + $cacheStrategy = new ResponseCacheStrategy(); + + // This master response uses the "validation" model + $masterResponse = new Response(); + $masterResponse->setLastModified(new \DateTime()); + $masterResponse->setEtag('foo'); + + // Embedded response uses "expiry" model + $embeddedResponse = new Response(); + $masterResponse->setSharedMaxAge(3600); + $cacheStrategy->add($embeddedResponse); + + $cacheStrategy->update($masterResponse); + + $this->assertFalse($masterResponse->isValidateable()); + $this->assertFalse($masterResponse->headers->has('Last-Modified')); + $this->assertFalse($masterResponse->headers->has('ETag')); + $this->assertTrue($masterResponse->headers->hasCacheControlDirective('no-cache')); + $this->assertTrue($masterResponse->headers->hasCacheControlDirective('must-revalidate')); + } + + public function testMasterResponseWithValidationIsUnchangedWhenThereIsNoEmbeddedResponse() + { + $cacheStrategy = new ResponseCacheStrategy(); + + $masterResponse = new Response(); + $masterResponse->setLastModified(new \DateTime()); + $cacheStrategy->update($masterResponse); + + $this->assertTrue($masterResponse->isValidateable()); + } + + public function testMasterResponseWithExpirationIsUnchangedWhenThereIsNoEmbeddedResponse() + { + $cacheStrategy = new ResponseCacheStrategy(); + + $masterResponse = new Response(); + $masterResponse->setSharedMaxAge(3600); + $cacheStrategy->update($masterResponse); + + $this->assertTrue($masterResponse->isFresh()); + } } From 3ccbc479da5812d91fa09befe80279ec3cd1ee1f Mon Sep 17 00:00:00 2001 From: VolCh Date: Wed, 7 Jun 2017 14:57:47 +0300 Subject: [PATCH 042/106] [Filesystem] added workaround in Filesystem::rename for PHP bug --- src/Symfony/Component/Filesystem/Filesystem.php | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/Symfony/Component/Filesystem/Filesystem.php b/src/Symfony/Component/Filesystem/Filesystem.php index edfc1b9d46a23..e60d4690738ad 100644 --- a/src/Symfony/Component/Filesystem/Filesystem.php +++ b/src/Symfony/Component/Filesystem/Filesystem.php @@ -276,6 +276,13 @@ public function rename($origin, $target, $overwrite = false) } if (true !== @rename($origin, $target)) { + if (is_dir($origin)) { + // See https://bugs.php.net/bug.php?id=54097 & http://php.net/manual/en/function.rename.php#113943 + $this->mirror($origin, $target, null, array('override' => $overwrite, 'delete' => $overwrite)); + $this->remove($origin); + + return; + } throw new IOException(sprintf('Cannot rename "%s" to "%s".', $origin, $target), 0, null, $target); } } From 2a9e65dea9f4afb13d8e47a87ea754e4a182fc31 Mon Sep 17 00:00:00 2001 From: Matthias Pigulla Date: Sat, 3 Jun 2017 23:06:14 +0200 Subject: [PATCH 043/106] [Translation][FrameworkBundle] Fix resource loading order inconsistency reported in #23034 --- .../Tests/Translation/TranslatorTest.php | 45 +++++++++++++++++++ .../Translation/Translator.php | 29 +++++++++--- 2 files changed, 67 insertions(+), 7 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Translation/TranslatorTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Translation/TranslatorTest.php index 361bcf001b560..75f4281952227 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Translation/TranslatorTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Translation/TranslatorTest.php @@ -135,6 +135,51 @@ public function testGetDefaultLocale() $this->assertSame('en', $translator->getLocale()); } + /** @dataProvider getDebugModeAndCacheDirCombinations */ + public function testResourceFilesOptionLoadsBeforeOtherAddedResources($debug, $enableCache) + { + $someCatalogue = $this->getCatalogue('some_locale', array()); + + $loader = $this->getMockBuilder('Symfony\Component\Translation\Loader\LoaderInterface')->getMock(); + + $loader->expects($this->at(0)) + ->method('load') + /* The "messages.some_locale.loader" is passed via the resource_file option and shall be loaded first */ + ->with('messages.some_locale.loader', 'some_locale', 'messages') + ->willReturn($someCatalogue); + + $loader->expects($this->at(1)) + ->method('load') + /* This resource is added by an addResource() call and shall be loaded after the resource_files */ + ->with('second_resource.some_locale.loader', 'some_locale', 'messages') + ->willReturn($someCatalogue); + + $options = array( + 'resource_files' => array('some_locale' => array('messages.some_locale.loader')), + 'debug' => $debug, + ); + + if ($enableCache) { + $options['cache_dir'] = $this->tmpDir; + } + + /** @var Translator $translator */ + $translator = $this->createTranslator($loader, $options); + $translator->addResource('loader', 'second_resource.some_locale.loader', 'some_locale', 'messages'); + + $translator->trans('some_message', array(), null, 'some_locale'); + } + + public function getDebugModeAndCacheDirCombinations() + { + return array( + array(false, false), + array(true, false), + array(false, true), + array(true, true), + ); + } + protected function getCatalogue($locale, $messages, $resources = array()) { $catalogue = new MessageCatalogue($locale); diff --git a/src/Symfony/Bundle/FrameworkBundle/Translation/Translator.php b/src/Symfony/Bundle/FrameworkBundle/Translation/Translator.php index fba6d70d6978b..9fdfb645d372a 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Translation/Translator.php +++ b/src/Symfony/Bundle/FrameworkBundle/Translation/Translator.php @@ -37,6 +37,14 @@ class Translator extends BaseTranslator implements WarmableInterface */ private $resourceLocales; + /** + * Holds parameters from addResource() calls so we can defer the actual + * parent::addResource() calls until initialize() is executed. + * + * @var array + */ + private $resources = array(); + /** * Constructor. * @@ -65,9 +73,7 @@ public function __construct(ContainerInterface $container, MessageSelector $sele $this->options = array_merge($this->options, $options); $this->resourceLocales = array_keys($this->options['resource_files']); - if (null !== $this->options['cache_dir'] && $this->options['debug']) { - $this->loadResources(); - } + $this->addResourceFiles($this->options['resource_files']); parent::__construct($container->getParameter('kernel.default_locale'), $selector, $this->options['cache_dir'], $this->options['debug']); } @@ -93,6 +99,11 @@ public function warmUp($cacheDir) } } + public function addResource($format, $resource, $locale, $domain = null) + { + $this->resources[] = array($format, $resource, $locale, $domain); + } + /** * {@inheritdoc} */ @@ -104,7 +115,12 @@ protected function initializeCatalogue($locale) protected function initialize() { - $this->loadResources(); + foreach ($this->resources as $key => $params) { + list($format, $resource, $locale, $domain) = $params; + parent::addResource($format, $resource, $locale, $domain); + } + $this->resources = array(); + foreach ($this->loaderIds as $id => $aliases) { foreach ($aliases as $alias) { $this->addLoader($alias, $this->container->get($id)); @@ -112,14 +128,13 @@ protected function initialize() } } - private function loadResources() + private function addResourceFiles($filesByLocale) { - foreach ($this->options['resource_files'] as $locale => $files) { + foreach ($filesByLocale as $locale => $files) { foreach ($files as $key => $file) { // filename is domain.locale.format list($domain, $locale, $format) = explode('.', basename($file), 3); $this->addResource($format, $file, $locale, $domain); - unset($this->options['resource_files'][$locale][$key]); } } } From 8c26aab0fe34d8dd726c25677f7c27b55b8a847a Mon Sep 17 00:00:00 2001 From: Roland Franssen Date: Wed, 7 Jun 2017 11:18:23 +0200 Subject: [PATCH 044/106] [FrameworkBundle] Dont set pre-defined esi/ssi services --- .../FrameworkBundle/HttpCache/HttpCache.php | 3 +-- .../EventListener/SurrogateListener.php | 18 ++++++++++++++++-- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/HttpCache/HttpCache.php b/src/Symfony/Bundle/FrameworkBundle/HttpCache/HttpCache.php index fad4adc04434d..06aa922210569 100644 --- a/src/Symfony/Bundle/FrameworkBundle/HttpCache/HttpCache.php +++ b/src/Symfony/Bundle/FrameworkBundle/HttpCache/HttpCache.php @@ -54,8 +54,7 @@ public function __construct(HttpKernelInterface $kernel, $cacheDir = null) protected function forward(Request $request, $raw = false, Response $entry = null) { $this->getKernel()->boot(); - $this->getKernel()->getContainer()->set('cache', $this); - $this->getKernel()->getContainer()->set($this->getSurrogate()->getName(), $this->getSurrogate()); + $this->getKernel()->getContainer()->set('cache', $this); // to be removed in 4.0? return parent::forward($request, $raw, $entry); } diff --git a/src/Symfony/Component/HttpKernel/EventListener/SurrogateListener.php b/src/Symfony/Component/HttpKernel/EventListener/SurrogateListener.php index dc815a216f6c0..a207ab673171b 100644 --- a/src/Symfony/Component/HttpKernel/EventListener/SurrogateListener.php +++ b/src/Symfony/Component/HttpKernel/EventListener/SurrogateListener.php @@ -12,6 +12,7 @@ namespace Symfony\Component\HttpKernel\EventListener; use Symfony\Component\HttpKernel\Event\FilterResponseEvent; +use Symfony\Component\HttpKernel\HttpCache\HttpCache; use Symfony\Component\HttpKernel\HttpCache\SurrogateInterface; use Symfony\Component\HttpKernel\KernelEvents; use Symfony\Component\EventDispatcher\EventSubscriberInterface; @@ -42,11 +43,24 @@ public function __construct(SurrogateInterface $surrogate = null) */ public function onKernelResponse(FilterResponseEvent $event) { - if (!$event->isMasterRequest() || null === $this->surrogate) { + if (!$event->isMasterRequest()) { return; } - $this->surrogate->addSurrogateControl($event->getResponse()); + $kernel = $event->getKernel(); + $surrogate = $this->surrogate; + if ($kernel instanceof HttpCache) { + $surrogate = $kernel->getSurrogate(); + if (null !== $this->surrogate && $this->surrogate->getName() !== $surrogate->getName()) { + $surrogate = $this->surrogate; + } + } + + if (null === $surrogate) { + return; + } + + $surrogate->addSurrogateControl($event->getResponse()); } public static function getSubscribedEvents() From b3203cb8abb98148b83bc64fc41783ee8708e1b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20TAMARELLE?= Date: Mon, 29 May 2017 19:01:45 +0200 Subject: [PATCH 045/106] [SecurityBundle] Move cache of the firewall context into the request parameters --- .../SecurityBundle/Security/FirewallMap.php | 21 +++-- .../Tests/Security/FirewallMapTest.php | 79 +++++++++++++++++++ 2 files changed, 95 insertions(+), 5 deletions(-) create mode 100644 src/Symfony/Bundle/SecurityBundle/Tests/Security/FirewallMapTest.php diff --git a/src/Symfony/Bundle/SecurityBundle/Security/FirewallMap.php b/src/Symfony/Bundle/SecurityBundle/Security/FirewallMap.php index f833a63e65966..77fe45f8a8267 100644 --- a/src/Symfony/Bundle/SecurityBundle/Security/FirewallMap.php +++ b/src/Symfony/Bundle/SecurityBundle/Security/FirewallMap.php @@ -11,6 +11,7 @@ namespace Symfony\Bundle\SecurityBundle\Security; +use Symfony\Bundle\SecurityBundle\Security\FirewallContext; use Symfony\Component\Security\Http\FirewallMapInterface; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\DependencyInjection\ContainerInterface; @@ -26,13 +27,11 @@ class FirewallMap implements FirewallMapInterface { protected $container; protected $map; - private $contexts; public function __construct(ContainerInterface $container, array $map) { $this->container = $container; $this->map = $map; - $this->contexts = new \SplObjectStorage(); } /** @@ -63,15 +62,27 @@ public function getFirewallConfig(Request $request) return $context->getConfig(); } + /** + * @return FirewallContext + */ private function getFirewallContext(Request $request) { - if ($this->contexts->contains($request)) { - return $this->contexts[$request]; + if ($request->attributes->has('_firewall_context')) { + $storedContextId = $request->attributes->get('_firewall_context'); + foreach ($this->map as $contextId => $requestMatcher) { + if ($contextId === $storedContextId) { + return $this->container->get($contextId); + } + } + + $request->attributes->remove('_firewall_context'); } foreach ($this->map as $contextId => $requestMatcher) { if (null === $requestMatcher || $requestMatcher->matches($request)) { - return $this->contexts[$request] = $this->container->get($contextId); + $request->attributes->set('_firewall_context', $contextId); + + return $this->container->get($contextId); } } } diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Security/FirewallMapTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/Security/FirewallMapTest.php new file mode 100644 index 0000000000000..a94d8c2026d8f --- /dev/null +++ b/src/Symfony/Bundle/SecurityBundle/Tests/Security/FirewallMapTest.php @@ -0,0 +1,79 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\SecurityBundle\Tests\Security; + +use PHPUnit\Framework\TestCase; +use Symfony\Bundle\SecurityBundle\Security\FirewallContext; +use Symfony\Bundle\SecurityBundle\Security\FirewallMap; +use Symfony\Component\DependencyInjection\Container; +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\RequestMatcherInterface; + +class FirewallMapTest extends TestCase +{ + const ATTRIBUTE_FIREWALL_CONTEXT = '_firewall_context'; + + public function testGetListenersWithEmptyMap() + { + $request = new Request(); + + $map = array(); + $container = $this->getMockBuilder(Container::class)->getMock(); + $container->expects($this->never())->method('get'); + + $firewallMap = new FirewallMap($container, $map); + + $this->assertEquals(array(array(), null), $firewallMap->getListeners($request)); + $this->assertNull($firewallMap->getFirewallConfig($request)); + $this->assertFalse($request->attributes->has(self::ATTRIBUTE_FIREWALL_CONTEXT)); + } + + public function testGetListenersWithInvalidParameter() + { + $request = new Request(); + $request->attributes->set(self::ATTRIBUTE_FIREWALL_CONTEXT, 'foo'); + + $map = array(); + $container = $this->getMockBuilder(Container::class)->getMock(); + $container->expects($this->never())->method('get'); + + $firewallMap = new FirewallMap($container, $map); + + $this->assertEquals(array(array(), null), $firewallMap->getListeners($request)); + $this->assertNull($firewallMap->getFirewallConfig($request)); + $this->assertFalse($request->attributes->has(self::ATTRIBUTE_FIREWALL_CONTEXT)); + } + + public function testGetListeners() + { + $request = new Request(); + + $firewallContext = $this->getMockBuilder(FirewallContext::class)->disableOriginalConstructor()->getMock(); + $firewallContext->expects($this->once())->method('getConfig')->willReturn('CONFIG'); + $firewallContext->expects($this->once())->method('getContext')->willReturn(array('LISTENERS', 'EXCEPTION LISTENER')); + + $matcher = $this->getMockBuilder(RequestMatcherInterface::class)->getMock(); + $matcher->expects($this->once()) + ->method('matches') + ->with($request) + ->willReturn(true); + + $container = $this->getMockBuilder(Container::class)->getMock(); + $container->expects($this->exactly(2))->method('get')->willReturn($firewallContext); + + $firewallMap = new FirewallMap($container, array('security.firewall.map.context.foo' => $matcher)); + + $this->assertEquals(array('LISTENERS', 'EXCEPTION LISTENER'), $firewallMap->getListeners($request)); + $this->assertEquals('CONFIG', $firewallMap->getFirewallConfig($request)); + $this->assertEquals('security.firewall.map.context.foo', $request->attributes->get(self::ATTRIBUTE_FIREWALL_CONTEXT)); + } +} From 01057875ddd468cc26801ca94a80c958cfe0fe99 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Wed, 14 Jun 2017 13:33:13 -0700 Subject: [PATCH 046/106] fixed tests --- .../Bundle/SecurityBundle/Tests/Security/FirewallMapTest.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Security/FirewallMapTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/Security/FirewallMapTest.php index a94d8c2026d8f..da7800cce3037 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/Security/FirewallMapTest.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/Security/FirewallMapTest.php @@ -59,7 +59,8 @@ public function testGetListeners() $firewallContext = $this->getMockBuilder(FirewallContext::class)->disableOriginalConstructor()->getMock(); $firewallContext->expects($this->once())->method('getConfig')->willReturn('CONFIG'); - $firewallContext->expects($this->once())->method('getContext')->willReturn(array('LISTENERS', 'EXCEPTION LISTENER')); + $firewallContext->expects($this->once())->method('getListeners')->willReturn('LISTENERS'); + $firewallContext->expects($this->once())->method('getExceptionListener')->willReturn('EXCEPTION LISTENER'); $matcher = $this->getMockBuilder(RequestMatcherInterface::class)->getMock(); $matcher->expects($this->once()) From 016e97669118ac1045858a36e07ff4da8521d47a Mon Sep 17 00:00:00 2001 From: Roland Franssen Date: Thu, 4 May 2017 19:29:31 +0200 Subject: [PATCH 047/106] [Routing] Expose request in route conditions, if needed and possible --- .../Routing/Matcher/RedirectableUrlMatcher.php | 2 +- .../Routing/Matcher/TraceableUrlMatcher.php | 2 +- .../Component/Routing/Matcher/UrlMatcher.php | 17 ++++++++++++++++- .../Routing/Tests/Matcher/UrlMatcherTest.php | 10 ++++++++++ 4 files changed, 28 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Component/Routing/Matcher/RedirectableUrlMatcher.php b/src/Symfony/Component/Routing/Matcher/RedirectableUrlMatcher.php index 463bc0d056809..900c59fa37392 100644 --- a/src/Symfony/Component/Routing/Matcher/RedirectableUrlMatcher.php +++ b/src/Symfony/Component/Routing/Matcher/RedirectableUrlMatcher.php @@ -49,7 +49,7 @@ public function match($pathinfo) protected function handleRouteRequirements($pathinfo, $name, Route $route) { // expression condition - if ($route->getCondition() && !$this->getExpressionLanguage()->evaluate($route->getCondition(), array('context' => $this->context, 'request' => $this->request))) { + if ($route->getCondition() && !$this->getExpressionLanguage()->evaluate($route->getCondition(), array('context' => $this->context, 'request' => $this->request ?: $this->createRequest($pathinfo)))) { return array(self::REQUIREMENT_MISMATCH, null); } diff --git a/src/Symfony/Component/Routing/Matcher/TraceableUrlMatcher.php b/src/Symfony/Component/Routing/Matcher/TraceableUrlMatcher.php index cb1a35f4d3023..9085be0424886 100644 --- a/src/Symfony/Component/Routing/Matcher/TraceableUrlMatcher.php +++ b/src/Symfony/Component/Routing/Matcher/TraceableUrlMatcher.php @@ -105,7 +105,7 @@ protected function matchCollection($pathinfo, RouteCollection $routes) // check condition if ($condition = $route->getCondition()) { - if (!$this->getExpressionLanguage()->evaluate($condition, array('context' => $this->context, 'request' => $this->request))) { + if (!$this->getExpressionLanguage()->evaluate($condition, array('context' => $this->context, 'request' => $this->request ?: $this->createRequest($pathinfo)))) { $this->addTrace(sprintf('Condition "%s" does not evaluate to "true"', $condition), self::ROUTE_ALMOST_MATCHES, $name, $route); continue; diff --git a/src/Symfony/Component/Routing/Matcher/UrlMatcher.php b/src/Symfony/Component/Routing/Matcher/UrlMatcher.php index 9786a9b42cc60..c646723b3ab08 100644 --- a/src/Symfony/Component/Routing/Matcher/UrlMatcher.php +++ b/src/Symfony/Component/Routing/Matcher/UrlMatcher.php @@ -207,7 +207,7 @@ protected function getAttributes(Route $route, $name, array $attributes) protected function handleRouteRequirements($pathinfo, $name, Route $route) { // expression condition - if ($route->getCondition() && !$this->getExpressionLanguage()->evaluate($route->getCondition(), array('context' => $this->context, 'request' => $this->request))) { + if ($route->getCondition() && !$this->getExpressionLanguage()->evaluate($route->getCondition(), array('context' => $this->context, 'request' => $this->request ?: $this->createRequest($pathinfo)))) { return array(self::REQUIREMENT_MISMATCH, null); } @@ -248,4 +248,19 @@ protected function getExpressionLanguage() return $this->expressionLanguage; } + + /** + * @internal + */ + protected function createRequest($pathinfo) + { + if (!class_exists('Symfony\Component\HttpFoundation\Request')) { + return null; + } + + return Request::create($this->context->getScheme().'://'.$this->context->getHost().$this->context->getBaseUrl().$pathinfo, $this->context->getMethod(), $this->context->getParameters(), array(), array(), array( + 'SCRIPT_FILENAME' => $this->context->getBaseUrl(), + 'SCRIPT_NAME' => $this->context->getBaseUrl(), + )); + } } diff --git a/src/Symfony/Component/Routing/Tests/Matcher/UrlMatcherTest.php b/src/Symfony/Component/Routing/Tests/Matcher/UrlMatcherTest.php index 6d59855d2d8f3..9fd53e9814496 100644 --- a/src/Symfony/Component/Routing/Tests/Matcher/UrlMatcherTest.php +++ b/src/Symfony/Component/Routing/Tests/Matcher/UrlMatcherTest.php @@ -337,6 +337,16 @@ public function testCondition() $matcher->match('/foo'); } + public function testRequestCondition() + { + $coll = new RouteCollection(); + $route = new Route('/foo/{bar}'); + $route->setCondition('request.getBaseUrl() == "/sub/front.php" and request.getPathInfo() == "/foo/bar"'); + $coll->add('foo', $route); + $matcher = new UrlMatcher($coll, new RequestContext('/sub/front.php')); + $this->assertEquals(array('bar' => 'bar', '_route' => 'foo'), $matcher->match('/foo/bar')); + } + public function testDecodeOnce() { $coll = new RouteCollection(); From 94371d052b8474d2dafa170d9c181ee8459ad4bd Mon Sep 17 00:00:00 2001 From: Roland Franssen Date: Thu, 4 May 2017 19:29:31 +0200 Subject: [PATCH 048/106] [Routing] Expose request in route conditions, if needed and possible --- .../Routing/Matcher/RedirectableUrlMatcher.php | 2 +- .../Routing/Matcher/TraceableUrlMatcher.php | 2 +- .../Component/Routing/Matcher/UrlMatcher.php | 17 ++++++++++++++++- .../Routing/Tests/Matcher/UrlMatcherTest.php | 10 ++++++++++ 4 files changed, 28 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Component/Routing/Matcher/RedirectableUrlMatcher.php b/src/Symfony/Component/Routing/Matcher/RedirectableUrlMatcher.php index 463bc0d056809..900c59fa37392 100644 --- a/src/Symfony/Component/Routing/Matcher/RedirectableUrlMatcher.php +++ b/src/Symfony/Component/Routing/Matcher/RedirectableUrlMatcher.php @@ -49,7 +49,7 @@ public function match($pathinfo) protected function handleRouteRequirements($pathinfo, $name, Route $route) { // expression condition - if ($route->getCondition() && !$this->getExpressionLanguage()->evaluate($route->getCondition(), array('context' => $this->context, 'request' => $this->request))) { + if ($route->getCondition() && !$this->getExpressionLanguage()->evaluate($route->getCondition(), array('context' => $this->context, 'request' => $this->request ?: $this->createRequest($pathinfo)))) { return array(self::REQUIREMENT_MISMATCH, null); } diff --git a/src/Symfony/Component/Routing/Matcher/TraceableUrlMatcher.php b/src/Symfony/Component/Routing/Matcher/TraceableUrlMatcher.php index cb1a35f4d3023..9085be0424886 100644 --- a/src/Symfony/Component/Routing/Matcher/TraceableUrlMatcher.php +++ b/src/Symfony/Component/Routing/Matcher/TraceableUrlMatcher.php @@ -105,7 +105,7 @@ protected function matchCollection($pathinfo, RouteCollection $routes) // check condition if ($condition = $route->getCondition()) { - if (!$this->getExpressionLanguage()->evaluate($condition, array('context' => $this->context, 'request' => $this->request))) { + if (!$this->getExpressionLanguage()->evaluate($condition, array('context' => $this->context, 'request' => $this->request ?: $this->createRequest($pathinfo)))) { $this->addTrace(sprintf('Condition "%s" does not evaluate to "true"', $condition), self::ROUTE_ALMOST_MATCHES, $name, $route); continue; diff --git a/src/Symfony/Component/Routing/Matcher/UrlMatcher.php b/src/Symfony/Component/Routing/Matcher/UrlMatcher.php index 9786a9b42cc60..c646723b3ab08 100644 --- a/src/Symfony/Component/Routing/Matcher/UrlMatcher.php +++ b/src/Symfony/Component/Routing/Matcher/UrlMatcher.php @@ -207,7 +207,7 @@ protected function getAttributes(Route $route, $name, array $attributes) protected function handleRouteRequirements($pathinfo, $name, Route $route) { // expression condition - if ($route->getCondition() && !$this->getExpressionLanguage()->evaluate($route->getCondition(), array('context' => $this->context, 'request' => $this->request))) { + if ($route->getCondition() && !$this->getExpressionLanguage()->evaluate($route->getCondition(), array('context' => $this->context, 'request' => $this->request ?: $this->createRequest($pathinfo)))) { return array(self::REQUIREMENT_MISMATCH, null); } @@ -248,4 +248,19 @@ protected function getExpressionLanguage() return $this->expressionLanguage; } + + /** + * @internal + */ + protected function createRequest($pathinfo) + { + if (!class_exists('Symfony\Component\HttpFoundation\Request')) { + return null; + } + + return Request::create($this->context->getScheme().'://'.$this->context->getHost().$this->context->getBaseUrl().$pathinfo, $this->context->getMethod(), $this->context->getParameters(), array(), array(), array( + 'SCRIPT_FILENAME' => $this->context->getBaseUrl(), + 'SCRIPT_NAME' => $this->context->getBaseUrl(), + )); + } } diff --git a/src/Symfony/Component/Routing/Tests/Matcher/UrlMatcherTest.php b/src/Symfony/Component/Routing/Tests/Matcher/UrlMatcherTest.php index 6d59855d2d8f3..9fd53e9814496 100644 --- a/src/Symfony/Component/Routing/Tests/Matcher/UrlMatcherTest.php +++ b/src/Symfony/Component/Routing/Tests/Matcher/UrlMatcherTest.php @@ -337,6 +337,16 @@ public function testCondition() $matcher->match('/foo'); } + public function testRequestCondition() + { + $coll = new RouteCollection(); + $route = new Route('/foo/{bar}'); + $route->setCondition('request.getBaseUrl() == "/sub/front.php" and request.getPathInfo() == "/foo/bar"'); + $coll->add('foo', $route); + $matcher = new UrlMatcher($coll, new RequestContext('/sub/front.php')); + $this->assertEquals(array('bar' => 'bar', '_route' => 'foo'), $matcher->match('/foo/bar')); + } + public function testDecodeOnce() { $coll = new RouteCollection(); From c6e8c07e4df22bdf950954266a255dabefaee69a Mon Sep 17 00:00:00 2001 From: Matthias Pigulla Date: Sun, 11 Jun 2017 00:34:20 +0200 Subject: [PATCH 049/106] Fix two edge cases in ResponseCacheStrategy --- .../HttpCache/ResponseCacheStrategy.php | 2 +- .../HttpCache/ResponseCacheStrategyTest.php | 41 +++++++++++++++++++ 2 files changed, 42 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/HttpKernel/HttpCache/ResponseCacheStrategy.php b/src/Symfony/Component/HttpKernel/HttpCache/ResponseCacheStrategy.php index 39a99e6966c22..6e24016340ed6 100644 --- a/src/Symfony/Component/HttpKernel/HttpCache/ResponseCacheStrategy.php +++ b/src/Symfony/Component/HttpKernel/HttpCache/ResponseCacheStrategy.php @@ -39,7 +39,7 @@ class ResponseCacheStrategy implements ResponseCacheStrategyInterface */ public function add(Response $response) { - if ($response->isValidateable()) { + if ($response->isValidateable() || !$response->isCacheable()) { $this->cacheable = false; } else { $maxAge = $response->getMaxAge(); diff --git a/src/Symfony/Component/HttpKernel/Tests/HttpCache/ResponseCacheStrategyTest.php b/src/Symfony/Component/HttpKernel/Tests/HttpCache/ResponseCacheStrategyTest.php index a37a85bc436a9..4188bb37f243c 100644 --- a/src/Symfony/Component/HttpKernel/Tests/HttpCache/ResponseCacheStrategyTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/HttpCache/ResponseCacheStrategyTest.php @@ -137,4 +137,45 @@ public function testMasterResponseWithExpirationIsUnchangedWhenThereIsNoEmbedded $this->assertTrue($masterResponse->isFresh()); } + + public function testMasterResponseIsNotCacheableWhenEmbeddedResponseIsNotCacheable() + { + $cacheStrategy = new ResponseCacheStrategy(); + + $masterResponse = new Response(); + $masterResponse->setSharedMaxAge(3600); // Public, cacheable + + /* This response has no validation or expiration information. + That makes it uncacheable, it is always stale. + (It does *not* make this private, though.) */ + $embeddedResponse = new Response(); + $this->assertFalse($embeddedResponse->isFresh()); // not fresh, as no lifetime is provided + + $cacheStrategy->add($embeddedResponse); + $cacheStrategy->update($masterResponse); + + $this->assertTrue($masterResponse->headers->hasCacheControlDirective('no-cache')); + $this->assertTrue($masterResponse->headers->hasCacheControlDirective('must-revalidate')); + $this->assertFalse($masterResponse->isFresh()); + } + + public function testEmbeddingPrivateResponseMakesMainResponsePrivate() + { + $cacheStrategy = new ResponseCacheStrategy(); + + $masterResponse = new Response(); + $masterResponse->setSharedMaxAge(3600); // public, cacheable + + // The embedded response might for example contain per-user data that remains valid for 60 seconds + $embeddedResponse = new Response(); + $embeddedResponse->setPrivate(); + $embeddedResponse->setMaxAge(60); // this would implicitly set "private" as well, but let's be explicit + + $cacheStrategy->add($embeddedResponse); + $cacheStrategy->update($masterResponse); + + $this->assertTrue($masterResponse->headers->hasCacheControlDirective('private')); + // Not sure if we should pass "max-age: 60" in this case, as long as the response is private and + // that's the more conservative of both the master and embedded response...? + } } From 8dc00bbe8d901d80c2916295607a82b0e0233ed9 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Wed, 14 Jun 2017 14:54:47 -0700 Subject: [PATCH 050/106] fixed bad merge --- .../Component/PropertyAccess/Tests/PropertyAccessorTest.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Symfony/Component/PropertyAccess/Tests/PropertyAccessorTest.php b/src/Symfony/Component/PropertyAccess/Tests/PropertyAccessorTest.php index 61100c0d68944..275c76e0f3b50 100644 --- a/src/Symfony/Component/PropertyAccess/Tests/PropertyAccessorTest.php +++ b/src/Symfony/Component/PropertyAccess/Tests/PropertyAccessorTest.php @@ -641,6 +641,7 @@ public function setFoo($foo) } /** + * @requires PHP 7.0 * @expectedException \TypeError */ public function testThrowTypeErrorInsideSetterCall() From 09bcbc70e7c7cd9f57d2af10d2e8cd806b87ccc3 Mon Sep 17 00:00:00 2001 From: Matthias Pigulla Date: Sun, 11 Jun 2017 00:58:50 +0200 Subject: [PATCH 051/106] Embedding a response that combines expiration and validation, that should not defeat expiration on the combined response --- .../HttpCache/ResponseCacheStrategy.php | 5 ++- .../HttpCache/ResponseCacheStrategyTest.php | 41 +++++++++++++++++++ 2 files changed, 45 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/HttpKernel/HttpCache/ResponseCacheStrategy.php b/src/Symfony/Component/HttpKernel/HttpCache/ResponseCacheStrategy.php index 6e24016340ed6..027b2b1761334 100644 --- a/src/Symfony/Component/HttpKernel/HttpCache/ResponseCacheStrategy.php +++ b/src/Symfony/Component/HttpKernel/HttpCache/ResponseCacheStrategy.php @@ -39,7 +39,7 @@ class ResponseCacheStrategy implements ResponseCacheStrategyInterface */ public function add(Response $response) { - if ($response->isValidateable() || !$response->isCacheable()) { + if (!$response->isFresh() || !$response->isCacheable()) { $this->cacheable = false; } else { $maxAge = $response->getMaxAge(); @@ -70,6 +70,9 @@ public function update(Response $response) if ($response->isValidateable()) { $response->setEtag(null); $response->setLastModified(null); + } + + if (!$response->isFresh()) { $this->cacheable = false; } diff --git a/src/Symfony/Component/HttpKernel/Tests/HttpCache/ResponseCacheStrategyTest.php b/src/Symfony/Component/HttpKernel/Tests/HttpCache/ResponseCacheStrategyTest.php index 4188bb37f243c..5e4c322223eb3 100644 --- a/src/Symfony/Component/HttpKernel/Tests/HttpCache/ResponseCacheStrategyTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/HttpCache/ResponseCacheStrategyTest.php @@ -178,4 +178,45 @@ public function testEmbeddingPrivateResponseMakesMainResponsePrivate() // Not sure if we should pass "max-age: 60" in this case, as long as the response is private and // that's the more conservative of both the master and embedded response...? } + + public function testResponseIsExiprableWhenEmbeddedResponseCombinesExpiryAndValidation() + { + /* When "expiration wins over validation" (https://symfony.com/doc/current/http_cache/validation.html) + * and both the main and embedded response provide s-maxage, then the more restricting value of both + * should be fine, regardless of whether the embedded response can be validated later on or must be + * completely regenerated. + */ + $cacheStrategy = new ResponseCacheStrategy(); + + $masterResponse = new Response(); + $masterResponse->setSharedMaxAge(3600); + + $embeddedResponse = new Response(); + $embeddedResponse->setSharedMaxAge(60); + $embeddedResponse->setEtag('foo'); + + $cacheStrategy->add($embeddedResponse); + $cacheStrategy->update($masterResponse); + + $this->assertSame('60', $masterResponse->headers->getCacheControlDirective('s-maxage')); + } + + public function testResponseIsExpirableButNotValidateableWhenMasterResponseCombinesExpirationAndValidation() + { + $cacheStrategy = new ResponseCacheStrategy(); + + $masterResponse = new Response(); + $masterResponse->setSharedMaxAge(3600); + $masterResponse->setEtag('foo'); + $masterResponse->setLastModified(new \DateTime()); + + $embeddedResponse = new Response(); + $embeddedResponse->setSharedMaxAge(60); + + $cacheStrategy->add($embeddedResponse); + $cacheStrategy->update($masterResponse); + + $this->assertSame('60', $masterResponse->headers->getCacheControlDirective('s-maxage')); + $this->assertFalse($masterResponse->isValidateable()); + } } From 9e2b408f255ffac5cc494cdb11ebe503612dea8f Mon Sep 17 00:00:00 2001 From: rchoquet Date: Thu, 15 Jun 2017 11:46:38 +0200 Subject: [PATCH 052/106] add content-type header on exception response --- .../Controller/ExceptionController.php | 2 +- .../Controller/ExceptionControllerTest.php | 51 ++++++++++++------- 2 files changed, 35 insertions(+), 18 deletions(-) diff --git a/src/Symfony/Bundle/TwigBundle/Controller/ExceptionController.php b/src/Symfony/Bundle/TwigBundle/Controller/ExceptionController.php index 0eab87de26e2b..1878204003b62 100644 --- a/src/Symfony/Bundle/TwigBundle/Controller/ExceptionController.php +++ b/src/Symfony/Bundle/TwigBundle/Controller/ExceptionController.php @@ -74,7 +74,7 @@ public function showAction(Request $request, FlattenException $exception, DebugL 'logger' => $logger, 'currentContent' => $currentContent, ) - )); + ), 200, array('Content-Type' => $request->getMimeType($request->getRequestFormat()) ?: 'text/html')); } /** diff --git a/src/Symfony/Bundle/TwigBundle/Tests/Controller/ExceptionControllerTest.php b/src/Symfony/Bundle/TwigBundle/Tests/Controller/ExceptionControllerTest.php index 17f3ac17c87f2..7b85d86508273 100644 --- a/src/Symfony/Bundle/TwigBundle/Tests/Controller/ExceptionControllerTest.php +++ b/src/Symfony/Bundle/TwigBundle/Tests/Controller/ExceptionControllerTest.php @@ -22,14 +22,9 @@ class ExceptionControllerTest extends TestCase { public function testShowActionCanBeForcedToShowErrorPage() { - $twig = new Environment( - new ArrayLoader(array( - 'TwigBundle:Exception:error404.html.twig' => 'ok', - )) - ); + $twig = $this->createTwigEnv(array('TwigBundle:Exception:error404.html.twig' => 'not found')); - $request = Request::create('whatever', 'GET'); - $request->headers->set('X-Php-Ob-Level', 1); + $request = $this->createRequest('html'); $request->attributes->set('showException', false); $exception = FlattenException::create(new \Exception(), 404); $controller = new ExceptionController($twig, /* "showException" defaults to --> */ true); @@ -37,25 +32,47 @@ public function testShowActionCanBeForcedToShowErrorPage() $response = $controller->showAction($request, $exception, null); $this->assertEquals(200, $response->getStatusCode()); // successful request - $this->assertEquals('ok', $response->getContent()); // content of the error404.html template + $this->assertEquals('not found', $response->getContent()); } public function testFallbackToHtmlIfNoTemplateForRequestedFormat() { - $twig = new Environment( - new ArrayLoader(array( - 'TwigBundle:Exception:error.html.twig' => 'html', - )) - ); + $twig = $this->createTwigEnv(array('TwigBundle:Exception:error.html.twig' => '')); - $request = Request::create('whatever'); - $request->headers->set('X-Php-Ob-Level', 1); - $request->setRequestFormat('txt'); + $request = $this->createRequest('txt'); $exception = FlattenException::create(new \Exception()); $controller = new ExceptionController($twig, false); - $response = $controller->showAction($request, $exception); + $controller->showAction($request, $exception); $this->assertEquals('html', $request->getRequestFormat()); } + + public function testResponseHasRequestedMimeType() + { + $twig = $this->createTwigEnv(array('TwigBundle:Exception:error.json.twig' => '{}')); + + $request = $this->createRequest('json'); + $exception = FlattenException::create(new \Exception()); + $controller = new ExceptionController($twig, false); + + $response = $controller->showAction($request, $exception); + + $this->assertEquals('json', $request->getRequestFormat()); + $this->assertEquals($request->getMimeType('json'), $response->headers->get('Content-Type')); + } + + private function createRequest($requestFormat) + { + $request = Request::create('whatever'); + $request->headers->set('X-Php-Ob-Level', 1); + $request->setRequestFormat($requestFormat); + + return $request; + } + + private function createTwigEnv(array $templates) + { + return new Environment(new ArrayLoader($templates)); + } } From 6ac0de8c2f3792a03854932eaef6906a05949042 Mon Sep 17 00:00:00 2001 From: Maxime Steinhausser Date: Thu, 15 Jun 2017 13:47:35 +0200 Subject: [PATCH 053/106] [TwigBundle] Remove template.xml services when templating is disabled --- .../TwigBundle/DependencyInjection/Compiler/ExtensionPass.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Symfony/Bundle/TwigBundle/DependencyInjection/Compiler/ExtensionPass.php b/src/Symfony/Bundle/TwigBundle/DependencyInjection/Compiler/ExtensionPass.php index ab9479e46166a..c829cfa4377fb 100644 --- a/src/Symfony/Bundle/TwigBundle/DependencyInjection/Compiler/ExtensionPass.php +++ b/src/Symfony/Bundle/TwigBundle/DependencyInjection/Compiler/ExtensionPass.php @@ -96,6 +96,7 @@ public function process(ContainerBuilder $container) $twigLoader->clearTag('twig.loader'); } else { $container->setAlias('twig.loader.filesystem', new Alias('twig.loader.native_filesystem', false)); + $container->removeDefinition('templating.engine.twig'); } if ($container->has('assets.packages')) { From ee17131fcac065ca45742de629d446f888a325ef Mon Sep 17 00:00:00 2001 From: Ben Scott Date: Wed, 14 Jun 2017 17:24:40 +0100 Subject: [PATCH 054/106] Expose the AbstractController's container to its subclasses Useful if an application provides their own base Controller that references items in the container. It also makes it simpler for that base controller to add additional optional dependencies by only overriding getSubscribedServices instead of having to reimplement setContainer and use ControllerTrait. --- .../Bundle/FrameworkBundle/Controller/AbstractController.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/Controller/AbstractController.php b/src/Symfony/Bundle/FrameworkBundle/Controller/AbstractController.php index def76d9defba2..3ba3b8471edc4 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Controller/AbstractController.php +++ b/src/Symfony/Bundle/FrameworkBundle/Controller/AbstractController.php @@ -35,7 +35,10 @@ abstract class AbstractController implements ServiceSubscriberInterface { use ControllerTrait; - private $container; + /** + * @var ContainerInterface + */ + protected $container; /** * @internal From f927ebadadedb89d255d76e179e0ec992e7612c9 Mon Sep 17 00:00:00 2001 From: meyerbaptiste Date: Thu, 15 Jun 2017 14:58:50 +0200 Subject: [PATCH 055/106] [Yaml] Fix typo: PARSE_KEYS_AS_STRING -> PARSE_KEYS_AS_STRINGS --- src/Symfony/Component/Yaml/Inline.php | 2 +- src/Symfony/Component/Yaml/Parser.php | 2 +- src/Symfony/Component/Yaml/Tests/InlineTest.php | 2 +- src/Symfony/Component/Yaml/Tests/ParserTest.php | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Symfony/Component/Yaml/Inline.php b/src/Symfony/Component/Yaml/Inline.php index 6789f79efb6cf..5aac7cb89490a 100644 --- a/src/Symfony/Component/Yaml/Inline.php +++ b/src/Symfony/Component/Yaml/Inline.php @@ -494,7 +494,7 @@ private static function parseMapping($mapping, $flags, &$i = 0, $references = ar $evaluatedKey = self::evaluateScalar($key, $flags, $references); if ('' !== $key && $evaluatedKey !== $key && !is_string($evaluatedKey) && !is_int($evaluatedKey)) { - @trigger_error('Implicit casting of incompatible mapping keys to strings is deprecated since version 3.3 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0. Pass the PARSE_KEYS_AS_STRING flag to explicitly enable the type casts.', E_USER_DEPRECATED); + @trigger_error('Implicit casting of incompatible mapping keys to strings is deprecated since version 3.3 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0. Pass the PARSE_KEYS_AS_STRINGS flag to explicitly enable the type casts.', E_USER_DEPRECATED); } } diff --git a/src/Symfony/Component/Yaml/Parser.php b/src/Symfony/Component/Yaml/Parser.php index 29fcf8da5cec8..887e2184a0efb 100644 --- a/src/Symfony/Component/Yaml/Parser.php +++ b/src/Symfony/Component/Yaml/Parser.php @@ -238,7 +238,7 @@ private function doParse($value, $flags) if (!(Yaml::PARSE_KEYS_AS_STRINGS & $flags) && !is_string($key) && !is_int($key)) { $keyType = is_numeric($key) ? 'numeric key' : 'non-string key'; - @trigger_error(sprintf('Implicit casting of %s to string is deprecated since version 3.3 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0. Pass the PARSE_KEYS_AS_STRING flag to explicitly enable the type casts.', $keyType), E_USER_DEPRECATED); + @trigger_error(sprintf('Implicit casting of %s to string is deprecated since version 3.3 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0. Pass the PARSE_KEYS_AS_STRINGS flag to explicitly enable the type casts.', $keyType), E_USER_DEPRECATED); } // Convert float keys to strings, to avoid being converted to integers by PHP diff --git a/src/Symfony/Component/Yaml/Tests/InlineTest.php b/src/Symfony/Component/Yaml/Tests/InlineTest.php index 647904a91632b..89950251cb242 100644 --- a/src/Symfony/Component/Yaml/Tests/InlineTest.php +++ b/src/Symfony/Component/Yaml/Tests/InlineTest.php @@ -730,7 +730,7 @@ public function testTheEmptyStringIsAValidMappingKey() /** * @group legacy - * @expectedDeprecation Implicit casting of incompatible mapping keys to strings is deprecated since version 3.3 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0. Pass the PARSE_KEYS_AS_STRING flag to explicitly enable the type casts. + * @expectedDeprecation Implicit casting of incompatible mapping keys to strings is deprecated since version 3.3 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0. Pass the PARSE_KEYS_AS_STRINGS flag to explicitly enable the type casts. * @dataProvider getNotPhpCompatibleMappingKeyData */ public function testImplicitStringCastingOfMappingKeysIsDeprecated($yaml, $expected) diff --git a/src/Symfony/Component/Yaml/Tests/ParserTest.php b/src/Symfony/Component/Yaml/Tests/ParserTest.php index a296a3300125d..c1ce9a161fdab 100644 --- a/src/Symfony/Component/Yaml/Tests/ParserTest.php +++ b/src/Symfony/Component/Yaml/Tests/ParserTest.php @@ -1081,7 +1081,7 @@ public function testYamlDirective() /** * @group legacy - * @expectedDeprecation Implicit casting of numeric key to string is deprecated since version 3.3 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0. Pass the PARSE_KEYS_AS_STRING flag to explicitly enable the type casts. + * @expectedDeprecation Implicit casting of numeric key to string is deprecated since version 3.3 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0. Pass the PARSE_KEYS_AS_STRINGS flag to explicitly enable the type casts. */ public function testFloatKeys() { @@ -1103,7 +1103,7 @@ public function testFloatKeys() /** * @group legacy - * @expectedDeprecation Implicit casting of non-string key to string is deprecated since version 3.3 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0. Pass the PARSE_KEYS_AS_STRING flag to explicitly enable the type casts. + * @expectedDeprecation Implicit casting of non-string key to string is deprecated since version 3.3 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0. Pass the PARSE_KEYS_AS_STRINGS flag to explicitly enable the type casts. */ public function testBooleanKeys() { From 83fd578f9637419698e728515966aa7d308f046d Mon Sep 17 00:00:00 2001 From: Henne Van Och Date: Thu, 15 Jun 2017 15:33:54 +0200 Subject: [PATCH 056/106] Reset redirectCount when throwing exception --- src/Symfony/Component/BrowserKit/Client.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Symfony/Component/BrowserKit/Client.php b/src/Symfony/Component/BrowserKit/Client.php index c69599083802d..b5b2dab50d4cc 100644 --- a/src/Symfony/Component/BrowserKit/Client.php +++ b/src/Symfony/Component/BrowserKit/Client.php @@ -448,6 +448,7 @@ public function followRedirect() if (-1 !== $this->maxRedirects) { if ($this->redirectCount > $this->maxRedirects) { + $this->redirectCount = 0; throw new \LogicException(sprintf('The maximum number (%d) of redirections was reached.', $this->maxRedirects)); } } From 9e047122f1651b1bad1eec221bcdd768de28c24f Mon Sep 17 00:00:00 2001 From: Iltar van der Berg Date: Fri, 16 Jun 2017 14:40:34 +0200 Subject: [PATCH 057/106] Fixed composer resources between web/cli --- .../Config/Resource/ComposerResource.php | 20 ++----------------- 1 file changed, 2 insertions(+), 18 deletions(-) diff --git a/src/Symfony/Component/Config/Resource/ComposerResource.php b/src/Symfony/Component/Config/Resource/ComposerResource.php index 56224d16c01d8..64288ea1db2d6 100644 --- a/src/Symfony/Component/Config/Resource/ComposerResource.php +++ b/src/Symfony/Component/Config/Resource/ComposerResource.php @@ -18,16 +18,13 @@ */ class ComposerResource implements SelfCheckingResourceInterface, \Serializable { - private $versions; private $vendors; - private static $runtimeVersion; private static $runtimeVendors; public function __construct() { self::refresh(); - $this->versions = self::$runtimeVersion; $this->vendors = self::$runtimeVendors; } @@ -51,36 +48,23 @@ public function isFresh($timestamp) { self::refresh(); - if (self::$runtimeVersion !== $this->versions) { - return false; - } - return self::$runtimeVendors === $this->vendors; } public function serialize() { - return serialize(array($this->versions, $this->vendors)); + return serialize($this->vendors); } public function unserialize($serialized) { - list($this->versions, $this->vendors) = unserialize($serialized); + $this->vendors = unserialize($serialized); } private static function refresh() { - if (null !== self::$runtimeVersion) { - return; - } - - self::$runtimeVersion = array(); self::$runtimeVendors = array(); - foreach (get_loaded_extensions() as $ext) { - self::$runtimeVersion[$ext] = phpversion($ext); - } - foreach (get_declared_classes() as $class) { if ('C' === $class[0] && 0 === strpos($class, 'ComposerAutoloaderInit')) { $r = new \ReflectionClass($class); From aeab2fe1f717f5d45dbfe7744412bdfa232b9a8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A1bor=20Egyed?= Date: Wed, 14 Jun 2017 13:38:13 +0200 Subject: [PATCH 058/106] [WebServerBundle] Fix router script path and check existence --- .../Bundle/WebServerBundle/WebServerConfig.php | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Bundle/WebServerBundle/WebServerConfig.php b/src/Symfony/Bundle/WebServerBundle/WebServerConfig.php index 3c639f2034c75..88ed375dd15e8 100644 --- a/src/Symfony/Bundle/WebServerBundle/WebServerConfig.php +++ b/src/Symfony/Bundle/WebServerBundle/WebServerConfig.php @@ -36,7 +36,18 @@ public function __construct($documentRoot, $env, $address = null, $router = null $this->documentRoot = $documentRoot; $this->env = $env; - $this->router = $router ?: __DIR__.'/Resources/router.php'; + + if (null !== $router) { + $absoluteRouterPath = realpath($router); + + if (false === $absoluteRouterPath) { + throw new \InvalidArgumentException(sprintf('Router script "%s" does not exist.', $router)); + } + + $this->router = $absoluteRouterPath; + } else { + $this->router = __DIR__.'/Resources/router.php'; + } if (null === $address) { $this->hostname = '127.0.0.1'; From 50c1d478cee0a0544b68133d3999169dd7d0bbd1 Mon Sep 17 00:00:00 2001 From: Javier Eguiluz Date: Tue, 13 Jun 2017 12:17:26 +0200 Subject: [PATCH 059/106] [WebProfilerBundle] Fix the icon for the Cache panel --- .../Resources/views/Icon/cache.svg | 4 +-- .../Resources/views/Icon/forward.svg | 2 +- .../Resources/views/Icon/menu.svg | 2 +- .../Resources/views/Icon/redirect.svg | 2 +- .../Tests/Resources/IconTest.php | 33 +++++++++++++++++++ 5 files changed, 38 insertions(+), 5 deletions(-) create mode 100644 src/Symfony/Bundle/WebProfilerBundle/Tests/Resources/IconTest.php diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Icon/cache.svg b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Icon/cache.svg index 984a4efd4a475..5b36ae37e0158 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Icon/cache.svg +++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Icon/cache.svg @@ -1,3 +1,3 @@ - - + + diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Icon/forward.svg b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Icon/forward.svg index acb128509a9f5..96a5bd7d22e02 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Icon/forward.svg +++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Icon/forward.svg @@ -1,4 +1,4 @@ - + diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Icon/menu.svg b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Icon/menu.svg index 51870801cf284..3c863393bc1ab 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Icon/menu.svg +++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Icon/menu.svg @@ -1,3 +1,3 @@ - + diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Icon/redirect.svg b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Icon/redirect.svg index 9cb3b89bcfbdd..54ff4187a4c81 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Icon/redirect.svg +++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Icon/redirect.svg @@ -1,4 +1,4 @@ - + .*~s', file_get_contents($iconFilePath), sprintf('The SVG metadata of the %s icon is different than expected (use the same as the other icons).', $iconFilePath)); + } + + public function provideIconFilePaths() + { + return array_map( + function ($filePath) { return (array) $filePath; }, + glob(__DIR__.'/../../Resources/views/Icon/*.svg') + ); + } +} From 1d304d2c9ba7689b46e0e82ac56b2a009fc38e85 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Fri, 16 Jun 2017 10:45:26 -0700 Subject: [PATCH 060/106] fixed CS --- .../Bundle/WebProfilerBundle/Tests/Resources/IconTest.php | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/Symfony/Bundle/WebProfilerBundle/Tests/Resources/IconTest.php b/src/Symfony/Bundle/WebProfilerBundle/Tests/Resources/IconTest.php index 7ac2564c5856e..040d4003f5c54 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Tests/Resources/IconTest.php +++ b/src/Symfony/Bundle/WebProfilerBundle/Tests/Resources/IconTest.php @@ -25,9 +25,6 @@ public function testIconFileContents($iconFilePath) public function provideIconFilePaths() { - return array_map( - function ($filePath) { return (array) $filePath; }, - glob(__DIR__.'/../../Resources/views/Icon/*.svg') - ); + return array_map(function ($filePath) { return (array) $filePath; }, glob(__DIR__.'/../../Resources/views/Icon/*.svg')); } } From 180f178f43571327f34ff319580e77530eafa1f7 Mon Sep 17 00:00:00 2001 From: Nicolas Pion Date: Thu, 15 Jun 2017 14:05:42 +0200 Subject: [PATCH 061/106] [FrameworkBundle] [Command] Clean bundle directory, fixes #23177 --- .../FrameworkBundle/Command/AssetsInstallCommand.php | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/AssetsInstallCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/AssetsInstallCommand.php index 94daa82cc9a26..0a3ea2871deb3 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/AssetsInstallCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/AssetsInstallCommand.php @@ -89,6 +89,7 @@ protected function execute(InputInterface $input, OutputInterface $output) $output->writeln('Installing assets as hard copies.'); } + $validAssetDirs = array(); foreach ($this->getContainer()->get('kernel')->getBundles() as $bundle) { if (is_dir($originDir = $bundle->getPath().'/Resources/public')) { $targetDir = $bundlesDir.preg_replace('/bundle$/', '', strtolower($bundle->getName())); @@ -131,6 +132,13 @@ protected function execute(InputInterface $input, OutputInterface $output) } else { $this->hardCopy($originDir, $targetDir); } + $validAssetDirs[] = $targetDir; + } + } + // remove the assets of the bundles that no longer exist + foreach (new \FilesystemIterator($bundlesDir) as $dir) { + if (!in_array($dir, $validAssetDirs)) { + $filesystem->remove($dir); } } } From 90e192e8249d447676ef5bda949e9e63f77b461d Mon Sep 17 00:00:00 2001 From: Dawid Nowak Date: Wed, 17 May 2017 18:18:47 +0200 Subject: [PATCH 062/106] Sessions: configurable "use_strict_mode" option for NativeSessionStorage https://github.com/symfony/symfony/pull/22352#issuecomment-302113533 --- .../FrameworkBundle/DependencyInjection/Configuration.php | 1 + .../FrameworkBundle/DependencyInjection/FrameworkExtension.php | 2 +- .../FrameworkBundle/Resources/config/schema/symfony-1.0.xsd | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php index b21b3ee8df769..404bd60ced98d 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php @@ -348,6 +348,7 @@ private function addSessionSection(ArrayNodeDefinition $rootNode) ->scalarNode('gc_divisor')->end() ->scalarNode('gc_probability')->defaultValue(1)->end() ->scalarNode('gc_maxlifetime')->end() + ->booleanNode('use_strict_mode')->end() ->scalarNode('save_path')->defaultValue('%kernel.cache_dir%/sessions')->end() ->integerNode('metadata_update_threshold') ->defaultValue('0') diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php index 3d125d616d393..85a1a9ba208f3 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php @@ -402,7 +402,7 @@ private function registerSessionConfiguration(array $config, ContainerBuilder $c // session storage $container->setAlias('session.storage', $config['storage_id']); $options = array(); - foreach (array('name', 'cookie_lifetime', 'cookie_path', 'cookie_domain', 'cookie_secure', 'cookie_httponly', 'gc_maxlifetime', 'gc_probability', 'gc_divisor') as $key) { + foreach (array('name', 'cookie_lifetime', 'cookie_path', 'cookie_domain', 'cookie_secure', 'cookie_httponly', 'gc_maxlifetime', 'gc_probability', 'gc_divisor', 'use_strict_mode') as $key) { if (isset($config[$key])) { $options[$key] = $config[$key]; } diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/schema/symfony-1.0.xsd b/src/Symfony/Bundle/FrameworkBundle/Resources/config/schema/symfony-1.0.xsd index fa7aa2b2bd808..0f0874829bcdb 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/schema/symfony-1.0.xsd +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/schema/symfony-1.0.xsd @@ -111,6 +111,7 @@ + From e76ee7a542a72f2593980a7dbf61efe8ddd436af Mon Sep 17 00:00:00 2001 From: Maxime Steinhausser Date: Sat, 17 Jun 2017 21:00:18 +0200 Subject: [PATCH 063/106] [Translation] Fix FileLoader::loadResource() php doc --- src/Symfony/Component/Translation/Loader/FileLoader.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/Translation/Loader/FileLoader.php b/src/Symfony/Component/Translation/Loader/FileLoader.php index a7f24f41a6535..1885963a99550 100644 --- a/src/Symfony/Component/Translation/Loader/FileLoader.php +++ b/src/Symfony/Component/Translation/Loader/FileLoader.php @@ -54,7 +54,7 @@ public function load($resource, $locale, $domain = 'messages') return $catalogue; } - /* + /** * @param string $resource * * @return array From 9f877efb3918f919f593d90ec56c70b498295eed Mon Sep 17 00:00:00 2001 From: Maxime Steinhausser Date: Sat, 17 Jun 2017 20:39:10 +0200 Subject: [PATCH 064/106] [DI] Dedup tags when using instanceof/autoconfigure --- .../ResolveInstanceofConditionalsPass.php | 3 +++ .../ResolveInstanceofConditionalsPassTest.php | 23 +++++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/src/Symfony/Component/DependencyInjection/Compiler/ResolveInstanceofConditionalsPass.php b/src/Symfony/Component/DependencyInjection/Compiler/ResolveInstanceofConditionalsPass.php index a2e62f4e536a5..82f13ed2d0e17 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/ResolveInstanceofConditionalsPass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/ResolveInstanceofConditionalsPass.php @@ -107,6 +107,9 @@ private function processDefinition(ContainerBuilder $container, $id, Definition while (0 <= --$i) { foreach ($instanceofTags[$i] as $k => $v) { foreach ($v as $v) { + if ($definition->hasTag($k) && in_array($v, $definition->getTag($k))) { + continue; + } $definition->addTag($k, $v); } } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveInstanceofConditionalsPassTest.php b/src/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveInstanceofConditionalsPassTest.php index c6c3681025606..164ab25941d64 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveInstanceofConditionalsPassTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveInstanceofConditionalsPassTest.php @@ -130,6 +130,29 @@ public function testProcessUsesAutoconfiguredInstanceof() $this->assertSame(array('local_instanceof_tag' => array(array()), 'autoconfigured_tag' => array(array())), $def->getTags()); } + public function testAutoconfigureInstanceofDoesNotDuplicateTags() + { + $container = new ContainerBuilder(); + $def = $container->register('normal_service', self::class); + $def + ->addTag('duplicated_tag') + ->addTag('duplicated_tag', array('and_attributes' => 1)) + ; + $def->setInstanceofConditionals(array( + parent::class => (new ChildDefinition(''))->addTag('duplicated_tag'), + )); + $def->setAutoconfigured(true); + $container->registerForAutoconfiguration(parent::class) + ->addTag('duplicated_tag', array('and_attributes' => 1)) + ; + + (new ResolveInstanceofConditionalsPass())->process($container); + (new ResolveDefinitionTemplatesPass())->process($container); + + $def = $container->getDefinition('normal_service'); + $this->assertSame(array('duplicated_tag' => array(array(), array('and_attributes' => 1))), $def->getTags()); + } + public function testProcessDoesNotUseAutoconfiguredInstanceofIfNotEnabled() { $container = new ContainerBuilder(); From f6a94cb56fc544f66e39e0658143976c852a14bb Mon Sep 17 00:00:00 2001 From: Oleg Voronkovich Date: Sun, 18 Jun 2017 21:08:05 +0300 Subject: [PATCH 065/106] [Routing] Fix XmlFileLoader exception message --- src/Symfony/Component/Routing/Loader/XmlFileLoader.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/Routing/Loader/XmlFileLoader.php b/src/Symfony/Component/Routing/Loader/XmlFileLoader.php index b5c24f9871c2f..9e219ad37ecca 100644 --- a/src/Symfony/Component/Routing/Loader/XmlFileLoader.php +++ b/src/Symfony/Component/Routing/Loader/XmlFileLoader.php @@ -250,7 +250,7 @@ private function parseConfigs(\DOMElement $node, $path) $condition = trim($n->textContent); break; default: - throw new \InvalidArgumentException(sprintf('Unknown tag "%s" used in file "%s". Expected "default", "requirement" or "option".', $n->localName, $path)); + throw new \InvalidArgumentException(sprintf('Unknown tag "%s" used in file "%s". Expected "default", "requirement", "option" or "condition".', $n->localName, $path)); } } From 44ff4b1a49ef1c450c10a3597309546bf8e06386 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Mon, 19 Jun 2017 16:33:26 +0200 Subject: [PATCH 066/106] [Validator] replace hardcoded service id --- .../DependencyInjection/AddConstraintValidatorsPass.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/Validator/DependencyInjection/AddConstraintValidatorsPass.php b/src/Symfony/Component/Validator/DependencyInjection/AddConstraintValidatorsPass.php index ec68bc0a8c828..207a1ad49d487 100644 --- a/src/Symfony/Component/Validator/DependencyInjection/AddConstraintValidatorsPass.php +++ b/src/Symfony/Component/Validator/DependencyInjection/AddConstraintValidatorsPass.php @@ -49,7 +49,7 @@ public function process(ContainerBuilder $container) } $container - ->getDefinition('validator.validator_factory') + ->getDefinition($this->validatorFactoryServiceId) ->replaceArgument(0, ServiceLocatorTagPass::register($container, $validators)) ; } From 78f1fdeb1cc74985b2da91ce6824afb2abf97bc9 Mon Sep 17 00:00:00 2001 From: Nikolay Labinskiy Date: Tue, 20 Jun 2017 10:52:59 +0300 Subject: [PATCH 067/106] [WebProfilerBundle] Eliminate line wrap on count columnt (routing) --- .../WebProfilerBundle/Resources/views/Router/panel.html.twig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Router/panel.html.twig b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Router/panel.html.twig index 8a6929c4df916..3da1cee28785d 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Router/panel.html.twig +++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Router/panel.html.twig @@ -54,7 +54,7 @@ {% for trace in traces %}
- {{ loop.index }} + {{ loop.index }} {{ trace.name }} {{ trace.path }} From 5a18553bf125452644d961ebeebb079a51cc0b30 Mon Sep 17 00:00:00 2001 From: Javier Eguiluz Date: Tue, 20 Jun 2017 13:28:19 +0200 Subject: [PATCH 068/106] Improved the exception page when there is no message --- .../TwigBundle/Resources/views/Exception/exception.html.twig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Symfony/Bundle/TwigBundle/Resources/views/Exception/exception.html.twig b/src/Symfony/Bundle/TwigBundle/Resources/views/Exception/exception.html.twig index 4b35e4fad77db..8ed5226ad5ffa 100644 --- a/src/Symfony/Bundle/TwigBundle/Resources/views/Exception/exception.html.twig +++ b/src/Symfony/Bundle/TwigBundle/Resources/views/Exception/exception.html.twig @@ -13,6 +13,7 @@ + {% if exception.message is not empty %}

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

+ {% endif %}
From 1c091eb7036c69a18c4c9220dc37b972220796cd Mon Sep 17 00:00:00 2001 From: Oleg Voronkovich Date: Tue, 20 Jun 2017 23:21:43 +0300 Subject: [PATCH 069/106] [Console] Fix catching exception type in QuestionHelper --- src/Symfony/Component/Console/Helper/QuestionHelper.php | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Component/Console/Helper/QuestionHelper.php b/src/Symfony/Component/Console/Helper/QuestionHelper.php index 3707ffee08f76..f0ca9e545322f 100644 --- a/src/Symfony/Component/Console/Helper/QuestionHelper.php +++ b/src/Symfony/Component/Console/Helper/QuestionHelper.php @@ -111,8 +111,7 @@ public function getName() * * @return bool|mixed|null|string * - * @throws \Exception - * @throws \RuntimeException + * @throws RuntimeException In case the fallback is deactivated and the response cannot be hidden */ public function doAsk(OutputInterface $output, Question $question) { @@ -126,7 +125,7 @@ public function doAsk(OutputInterface $output, Question $question) if ($question->isHidden()) { try { $ret = trim($this->getHiddenResponse($output, $inputStream)); - } catch (\RuntimeException $e) { + } catch (RuntimeException $e) { if (!$question->isHiddenFallback()) { throw $e; } From dabecdee9973a0a3b42c2bd45b8718bd30ce6bc1 Mon Sep 17 00:00:00 2001 From: Robin Chalas Date: Wed, 21 Jun 2017 09:43:17 +0200 Subject: [PATCH 070/106] [Dotenv] Test load() with multiple paths --- .../Component/Dotenv/Tests/DotenvTest.php | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/Symfony/Component/Dotenv/Tests/DotenvTest.php b/src/Symfony/Component/Dotenv/Tests/DotenvTest.php index 85204e5c476ac..fd0398f318a28 100644 --- a/src/Symfony/Component/Dotenv/Tests/DotenvTest.php +++ b/src/Symfony/Component/Dotenv/Tests/DotenvTest.php @@ -146,6 +146,28 @@ public function getEnvData() return $tests; } + public function testLoad() + { + @mkdir($tmpdir = sys_get_temp_dir().'/dotenv'); + + $path1 = tempnam($tmpdir, 'sf-'); + $path2 = tempnam($tmpdir, 'sf-'); + + file_put_contents($path1, 'FOO=BAR'); + file_put_contents($path2, 'BAR=BAZ'); + + (new DotEnv())->load($path1, $path2); + + $this->assertSame('BAR', getenv('FOO')); + $this->assertSame('BAZ', getenv('BAR')); + + putenv('FOO'); + putenv('BAR'); + unlink($path1); + unlink($path2); + rmdir($tmpdir); + } + /** * @expectedException \Symfony\Component\Dotenv\Exception\PathException */ From a85d5b01f7a5a16d656de36877a19975b825d5a3 Mon Sep 17 00:00:00 2001 From: Florent Olivaud Date: Tue, 20 Jun 2017 17:06:22 +0200 Subject: [PATCH 071/106] Fix Predis client cluster with pipeline --- src/Symfony/Component/Cache/Traits/RedisTrait.php | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Component/Cache/Traits/RedisTrait.php b/src/Symfony/Component/Cache/Traits/RedisTrait.php index f28da39346627..b45d65adc8530 100644 --- a/src/Symfony/Component/Cache/Traits/RedisTrait.php +++ b/src/Symfony/Component/Cache/Traits/RedisTrait.php @@ -12,6 +12,7 @@ namespace Symfony\Component\Cache\Traits; use Predis\Connection\Factory; +use Predis\Connection\Aggregate\ClusterInterface; use Predis\Connection\Aggregate\PredisCluster; use Predis\Connection\Aggregate\RedisCluster; use Predis\Response\Status; @@ -284,7 +285,7 @@ private function pipeline(\Closure $generator) { $ids = array(); - if ($this->redis instanceof \Predis\Client) { + if ($this->redis instanceof \Predis\Client && !$this->redis->getConnection() instanceof ClusterInterface) { $results = $this->redis->pipeline(function ($redis) use ($generator, &$ids) { foreach ($generator() as $command => $args) { call_user_func_array(array($redis, $command), $args); @@ -308,9 +309,10 @@ private function pipeline(\Closure $generator) foreach ($results as $k => list($h, $c)) { $results[$k] = $connections[$h][$c]; } - } elseif ($this->redis instanceof \RedisCluster) { - // phpredis doesn't support pipelining with RedisCluster + } elseif ($this->redis instanceof \RedisCluster || ($this->redis instanceof \Predis\Client && $this->redis->getConnection() instanceof ClusterInterface)) { + // phpredis & predis don't support pipelining with RedisCluster // see https://github.com/phpredis/phpredis/blob/develop/cluster.markdown#pipelining + // see https://github.com/nrk/predis/issues/267#issuecomment-123781423 $results = array(); foreach ($generator() as $command => $args) { $results[] = call_user_func_array(array($this->redis, $command), $args); From 3c21650d9ec713c36ebbbc3667b8120646ebc6dc Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Wed, 21 Jun 2017 13:02:23 +0200 Subject: [PATCH 072/106] return fallback locales whenever possible --- src/Symfony/Component/Translation/DataCollectorTranslator.php | 2 +- src/Symfony/Component/Translation/LoggingTranslator.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/Translation/DataCollectorTranslator.php b/src/Symfony/Component/Translation/DataCollectorTranslator.php index b2049d47511ce..0243d8aa21596 100644 --- a/src/Symfony/Component/Translation/DataCollectorTranslator.php +++ b/src/Symfony/Component/Translation/DataCollectorTranslator.php @@ -95,7 +95,7 @@ public function getCatalogue($locale = null) */ public function getFallbackLocales() { - if ($this->translator instanceof Translator) { + if ($this->translator instanceof Translator || method_exists($this->translator, 'getFallbackLocales')) { return $this->translator->getFallbackLocales(); } diff --git a/src/Symfony/Component/Translation/LoggingTranslator.php b/src/Symfony/Component/Translation/LoggingTranslator.php index b259df5e0aa49..85ab3c47f55c8 100644 --- a/src/Symfony/Component/Translation/LoggingTranslator.php +++ b/src/Symfony/Component/Translation/LoggingTranslator.php @@ -95,7 +95,7 @@ public function getCatalogue($locale = null) */ public function getFallbackLocales() { - if ($this->translator instanceof Translator) { + if ($this->translator instanceof Translator || method_exists($this->translator, 'getFallbackLocales')) { return $this->translator->getFallbackLocales(); } From 2d8fdd9622e0c797ea6ef35e46aaf18e56f7ad13 Mon Sep 17 00:00:00 2001 From: "Alexander M. Turek" Date: Tue, 13 Jun 2017 17:15:58 +0200 Subject: [PATCH 073/106] Add Doctrine Cache to dev dependencies to fix failing unit tests. --- src/Symfony/Bundle/TwigBundle/composer.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Bundle/TwigBundle/composer.json b/src/Symfony/Bundle/TwigBundle/composer.json index 9b984f97ecdec..ef1a183e822d4 100644 --- a/src/Symfony/Bundle/TwigBundle/composer.json +++ b/src/Symfony/Bundle/TwigBundle/composer.json @@ -34,7 +34,8 @@ "symfony/templating": "~2.8|~3.0", "symfony/yaml": "~2.8|~3.0", "symfony/framework-bundle": "^3.2.2", - "doctrine/annotations": "~1.0" + "doctrine/annotations": "~1.0", + "doctrine/cache": "~1.0" }, "autoload": { "psr-4": { "Symfony\\Bundle\\TwigBundle\\": "" }, From 0ee3f57533aededf488e326bc0b30ca54d8dd1e2 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Wed, 21 Jun 2017 18:08:25 +0200 Subject: [PATCH 074/106] render hidden _method field in form_rest() --- .../views/Form/form_div_layout.html.twig | 15 +++++++++++++++ src/Symfony/Bridge/Twig/composer.json | 5 ++++- src/Symfony/Component/Form/FormView.php | 15 +++++++++++++++ 3 files changed, 34 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Bridge/Twig/Resources/views/Form/form_div_layout.html.twig b/src/Symfony/Bridge/Twig/Resources/views/Form/form_div_layout.html.twig index 04988d1539b24..0a52cc5110c82 100644 --- a/src/Symfony/Bridge/Twig/Resources/views/Form/form_div_layout.html.twig +++ b/src/Symfony/Bridge/Twig/Resources/views/Form/form_div_layout.html.twig @@ -262,6 +262,7 @@ {%- endblock form -%} {%- block form_start -%} + {%- do form.setMethodRendered() -%} {% set method = method|upper %} {%- if method in ["GET", "POST"] -%} {% set form_method = method %} @@ -301,6 +302,20 @@ {{- form_row(child) -}} {% endif %} {%- endfor %} + + {% if not form.methodRendered %} + {%- do form.setMethodRendered() -%} + {% set method = method|upper %} + {%- if method in ["GET", "POST"] -%} + {% set form_method = method %} + {%- else -%} + {% set form_method = "POST" %} + {%- endif -%} + + {%- if form_method != method -%} + + {%- endif -%} + {% endif %} {% endblock form_rest %} {# Support #} diff --git a/src/Symfony/Bridge/Twig/composer.json b/src/Symfony/Bridge/Twig/composer.json index 3b6c4356e14ba..9610edc8085b5 100644 --- a/src/Symfony/Bridge/Twig/composer.json +++ b/src/Symfony/Bridge/Twig/composer.json @@ -22,7 +22,7 @@ "require-dev": { "symfony/asset": "~2.7", "symfony/finder": "~2.3", - "symfony/form": "~2.7.26|^2.8.19", + "symfony/form": "~2.7.30|^2.8.23", "symfony/http-kernel": "~2.3", "symfony/intl": "~2.3", "symfony/routing": "~2.2", @@ -36,6 +36,9 @@ "symfony/var-dumper": "~2.7.16|^2.8.9", "symfony/expression-language": "~2.4" }, + "conflict": { + "symfony/form": "<2.7.30|~2.8,<2.8.23" + }, "suggest": { "symfony/finder": "", "symfony/asset": "For using the AssetExtension", diff --git a/src/Symfony/Component/Form/FormView.php b/src/Symfony/Component/Form/FormView.php index c1da5f8fc9bb1..8655bedf6e135 100644 --- a/src/Symfony/Component/Form/FormView.php +++ b/src/Symfony/Component/Form/FormView.php @@ -53,6 +53,8 @@ class FormView implements \ArrayAccess, \IteratorAggregate, \Countable */ private $rendered = false; + private $methodRendered = false; + public function __construct(FormView $parent = null) { $this->parent = $parent; @@ -90,6 +92,19 @@ public function setRendered() return $this; } + /** + * @return bool + */ + public function isMethodRendered() + { + return $this->methodRendered; + } + + public function setMethodRendered() + { + $this->methodRendered = true; + } + /** * Returns a child by name (implements \ArrayAccess). * From cc7275bccce951d1d6a509f52723657b572d0083 Mon Sep 17 00:00:00 2001 From: Javier Eguiluz Date: Thu, 22 Jun 2017 18:11:34 +0200 Subject: [PATCH 075/106] Display a better error message when the toolbar cannot be displayed --- .../Resources/views/Profiler/toolbar_js.html.twig | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/toolbar_js.html.twig b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/toolbar_js.html.twig index 91ad9ad10ecf1..57537f61a3feb 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/toolbar_js.html.twig +++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/toolbar_js.html.twig @@ -57,8 +57,17 @@ } }, function(xhr) { + var errorToolbarHtml = ' + +
An error occurred while loading the web debug toolbar. Open the web profiler.
+ '; + if (xhr.status !== 0) { - confirm('An error occurred while loading the web debug toolbar (' + xhr.status + ': ' + xhr.statusText + ').\n\nDo you want to open the profiler?') && (window.location = '{{ path("_profiler", { "token": token }) }}'); + window.document.body.insertAdjacentHTML('beforeend', errorToolbarHtml); } }, {'maxTries': 5} From 99931a994b83a0ed35a1a8358c224a8117a18d5f Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Thu, 22 Jun 2017 21:48:55 +0200 Subject: [PATCH 076/106] allow SSI fragments configuration in XML files --- .../Resources/config/schema/symfony-1.0.xsd | 5 +++++ .../Tests/DependencyInjection/Fixtures/php/full.php | 3 +++ .../Tests/DependencyInjection/Fixtures/xml/full.xml | 1 + .../Tests/DependencyInjection/Fixtures/yml/full.yml | 2 ++ .../Tests/DependencyInjection/FrameworkExtensionTest.php | 7 +++++++ 5 files changed, 18 insertions(+) diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/schema/symfony-1.0.xsd b/src/Symfony/Bundle/FrameworkBundle/Resources/config/schema/symfony-1.0.xsd index 0f0874829bcdb..2d866ff1b5cac 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/schema/symfony-1.0.xsd +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/schema/symfony-1.0.xsd @@ -22,6 +22,7 @@ + @@ -64,6 +65,10 @@ + + + + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/full.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/full.php index 5022aeaf9f207..6861844b49233 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/full.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/full.php @@ -16,6 +16,9 @@ 'esi' => array( 'enabled' => true, ), + 'ssi' => array( + 'enabled' => true, + ), 'profiler' => array( 'only_exceptions' => true, 'enabled' => false, diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/full.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/full.xml index 5b16a59796091..c0d8a85a1c5d7 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/full.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/full.xml @@ -12,6 +12,7 @@ + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/full.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/full.yml index 47dcb575317e3..3e000ca9cc59c 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/full.yml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/full.yml @@ -10,6 +10,8 @@ framework: enabled: true esi: enabled: true + ssi: + enabled: true profiler: only_exceptions: true enabled: false diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php index a782a3f0748bb..5601e6a88b236 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php @@ -98,6 +98,13 @@ public function testEsi() $this->assertTrue($container->hasDefinition('esi'), '->registerEsiConfiguration() loads esi.xml'); } + public function testSsi() + { + $container = $this->createContainerFromFile('full'); + + $this->assertTrue($container->hasDefinition('ssi'), '->registerSsiConfiguration() loads ssi.xml'); + } + public function testEnabledProfiler() { $container = $this->createContainerFromFile('profiler'); From a433ceca4142aeebf14390c702f71839344f7db7 Mon Sep 17 00:00:00 2001 From: George Mponos Date: Thu, 22 Jun 2017 21:40:34 +0300 Subject: [PATCH 077/106] Show exception is checked twice in ExceptionController of twig --- .../Bundle/TwigBundle/Controller/ExceptionController.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Bundle/TwigBundle/Controller/ExceptionController.php b/src/Symfony/Bundle/TwigBundle/Controller/ExceptionController.php index 1878204003b62..0c31f9bd39f53 100644 --- a/src/Symfony/Bundle/TwigBundle/Controller/ExceptionController.php +++ b/src/Symfony/Bundle/TwigBundle/Controller/ExceptionController.php @@ -125,7 +125,7 @@ protected function findTemplate(Request $request, $format, $code, $showException // default to a generic HTML exception $request->setRequestFormat('html'); - return new TemplateReference('TwigBundle', 'Exception', $showException ? 'exception_full' : $name, 'html', 'twig'); + return new TemplateReference('TwigBundle', 'Exception', $name, 'html', 'twig'); } // to be removed when the minimum required version of Twig is >= 3.0 From 0724ebc5d2845ca64b6bfea7ed41c4f13eda7884 Mon Sep 17 00:00:00 2001 From: Nicolas Date: Fri, 23 Jun 2017 11:32:10 +0200 Subject: [PATCH 078/106] Fix undefined variable $filesystem --- .../Bundle/FrameworkBundle/Command/AssetsInstallCommand.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/AssetsInstallCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/AssetsInstallCommand.php index 0d87397b2e82f..395d3e6d335c1 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/AssetsInstallCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/AssetsInstallCommand.php @@ -154,7 +154,7 @@ protected function execute(InputInterface $input, OutputInterface $output) // remove the assets of the bundles that no longer exist foreach (new \FilesystemIterator($bundlesDir) as $dir) { if (!in_array($dir, $validAssetDirs)) { - $filesystem->remove($dir); + $this->filesystem->remove($dir); } } From 635bccdf8f6b3272acd542aae11437807f122e05 Mon Sep 17 00:00:00 2001 From: Pierre du Plessis Date: Fri, 23 Jun 2017 12:52:30 +0200 Subject: [PATCH 079/106] Dont call count on non countable object --- .../Translation/Dumper/IcuResFileDumper.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Symfony/Component/Translation/Dumper/IcuResFileDumper.php b/src/Symfony/Component/Translation/Dumper/IcuResFileDumper.php index 0fd5b35ae333b..7d4db851fe23b 100644 --- a/src/Symfony/Component/Translation/Dumper/IcuResFileDumper.php +++ b/src/Symfony/Component/Translation/Dumper/IcuResFileDumper.php @@ -52,7 +52,7 @@ public function format(MessageCatalogue $messages, $domain = 'messages') $resOffset = $this->getPosition($data); - $data .= pack('v', count($messages)) + $data .= pack('v', count($messages->all($domain))) .$indexes .$this->writePadding($data) .$resources @@ -63,11 +63,11 @@ public function format(MessageCatalogue $messages, $domain = 'messages') $root = pack('V7', $resOffset + (2 << 28), // Resource Offset + Resource Type 6, // Index length - $keyTop, // Index keys top - $bundleTop, // Index resources top - $bundleTop, // Index bundle top - count($messages), // Index max table length - 0 // Index attributes + $keyTop, // Index keys top + $bundleTop, // Index resources top + $bundleTop, // Index bundle top + count($messages->all($domain)), // Index max table length + 0 // Index attributes ); $header = pack('vC2v4C12@32', From 46c38df0fd82cc762c6fe27ec8b75cd69b1414f4 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Sat, 24 Jun 2017 11:40:57 +0200 Subject: [PATCH 080/106] [TwigBundle] add back exception check --- .../TwigBundle/Controller/ExceptionController.php | 2 +- .../Tests/Controller/ExceptionControllerTest.php | 14 ++++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Bundle/TwigBundle/Controller/ExceptionController.php b/src/Symfony/Bundle/TwigBundle/Controller/ExceptionController.php index 0c31f9bd39f53..1878204003b62 100644 --- a/src/Symfony/Bundle/TwigBundle/Controller/ExceptionController.php +++ b/src/Symfony/Bundle/TwigBundle/Controller/ExceptionController.php @@ -125,7 +125,7 @@ protected function findTemplate(Request $request, $format, $code, $showException // default to a generic HTML exception $request->setRequestFormat('html'); - return new TemplateReference('TwigBundle', 'Exception', $name, 'html', 'twig'); + return new TemplateReference('TwigBundle', 'Exception', $showException ? 'exception_full' : $name, 'html', 'twig'); } // to be removed when the minimum required version of Twig is >= 3.0 diff --git a/src/Symfony/Bundle/TwigBundle/Tests/Controller/ExceptionControllerTest.php b/src/Symfony/Bundle/TwigBundle/Tests/Controller/ExceptionControllerTest.php index 7b85d86508273..82f10c8296fd2 100644 --- a/src/Symfony/Bundle/TwigBundle/Tests/Controller/ExceptionControllerTest.php +++ b/src/Symfony/Bundle/TwigBundle/Tests/Controller/ExceptionControllerTest.php @@ -48,6 +48,20 @@ public function testFallbackToHtmlIfNoTemplateForRequestedFormat() $this->assertEquals('html', $request->getRequestFormat()); } + public function testFallbackToHtmlWithFullExceptionIfNoTemplateForRequestedFormatAndExceptionsShouldBeShown() + { + $twig = $this->createTwigEnv(array('TwigBundle:Exception:exception_full.html.twig' => '')); + + $request = $this->createRequest('txt'); + $request->attributes->set('showException', true); + $exception = FlattenException::create(new \Exception()); + $controller = new ExceptionController($twig, false); + + $controller->showAction($request, $exception); + + $this->assertEquals('html', $request->getRequestFormat()); + } + public function testResponseHasRequestedMimeType() { $twig = $this->createTwigEnv(array('TwigBundle:Exception:error.json.twig' => '{}')); From ddf43684442338229cc0f1e0742f0d6b1af6c241 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Sat, 24 Jun 2017 15:27:17 +0200 Subject: [PATCH 081/106] respect the API in FirewallContext map When being merged up, this will make the SecurityBundle tests on master green again. --- .../Tests/Security/FirewallMapTest.php | 20 ++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Security/FirewallMapTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/Security/FirewallMapTest.php index da7800cce3037..f9047cfdd233e 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/Security/FirewallMapTest.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/Security/FirewallMapTest.php @@ -12,11 +12,15 @@ namespace Symfony\Bundle\SecurityBundle\Tests\Security; use PHPUnit\Framework\TestCase; +use Symfony\Bundle\SecurityBundle\Security\FirewallConfig; use Symfony\Bundle\SecurityBundle\Security\FirewallContext; use Symfony\Bundle\SecurityBundle\Security\FirewallMap; use Symfony\Component\DependencyInjection\Container; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\RequestMatcherInterface; +use Symfony\Component\Security\Core\User\UserCheckerInterface; +use Symfony\Component\Security\Http\Firewall\ExceptionListener; +use Symfony\Component\Security\Http\Firewall\ListenerInterface; class FirewallMapTest extends TestCase { @@ -58,9 +62,15 @@ public function testGetListeners() $request = new Request(); $firewallContext = $this->getMockBuilder(FirewallContext::class)->disableOriginalConstructor()->getMock(); - $firewallContext->expects($this->once())->method('getConfig')->willReturn('CONFIG'); - $firewallContext->expects($this->once())->method('getListeners')->willReturn('LISTENERS'); - $firewallContext->expects($this->once())->method('getExceptionListener')->willReturn('EXCEPTION LISTENER'); + + $firewallConfig = new FirewallConfig('main', $this->getMockBuilder(UserCheckerInterface::class)->getMock()); + $firewallContext->expects($this->once())->method('getConfig')->willReturn($firewallConfig); + + $listener = $this->getMockBuilder(ListenerInterface::class)->getMock(); + $firewallContext->expects($this->once())->method('getListeners')->willReturn(array($listener)); + + $exceptionListener = $this->getMockBuilder(ExceptionListener::class)->disableOriginalConstructor()->getMock(); + $firewallContext->expects($this->once())->method('getExceptionListener')->willReturn($exceptionListener); $matcher = $this->getMockBuilder(RequestMatcherInterface::class)->getMock(); $matcher->expects($this->once()) @@ -73,8 +83,8 @@ public function testGetListeners() $firewallMap = new FirewallMap($container, array('security.firewall.map.context.foo' => $matcher)); - $this->assertEquals(array('LISTENERS', 'EXCEPTION LISTENER'), $firewallMap->getListeners($request)); - $this->assertEquals('CONFIG', $firewallMap->getFirewallConfig($request)); + $this->assertEquals(array(array($listener), $exceptionListener), $firewallMap->getListeners($request)); + $this->assertEquals($firewallConfig, $firewallMap->getFirewallConfig($request)); $this->assertEquals('security.firewall.map.context.foo', $request->attributes->get(self::ATTRIBUTE_FIREWALL_CONTEXT)); } } From 2e435228d143fae98bf4d6d1ccee74fd0036d03f Mon Sep 17 00:00:00 2001 From: Ben Davies Date: Fri, 23 Jun 2017 11:09:44 +0100 Subject: [PATCH 082/106] swiftmailer bridge is gone --- composer.json | 1 - 1 file changed, 1 deletion(-) diff --git a/composer.json b/composer.json index c7994e4db2b59..75e9c916370b2 100644 --- a/composer.json +++ b/composer.json @@ -106,7 +106,6 @@ "Symfony\\Bridge\\Doctrine\\": "src/Symfony/Bridge/Doctrine/", "Symfony\\Bridge\\Monolog\\": "src/Symfony/Bridge/Monolog/", "Symfony\\Bridge\\ProxyManager\\": "src/Symfony/Bridge/ProxyManager/", - "Symfony\\Bridge\\Swiftmailer\\": "src/Symfony/Bridge/Swiftmailer/", "Symfony\\Bridge\\Twig\\": "src/Symfony/Bridge/Twig/", "Symfony\\Bundle\\": "src/Symfony/Bundle/", "Symfony\\Component\\": "src/Symfony/Component/" From bf0063e3d3c43273f56970234b593ebcf70b781d Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Sat, 24 Jun 2017 09:45:07 -0700 Subject: [PATCH 083/106] fixed tests --- .../TwigBundle/Tests/Controller/ExceptionControllerTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Bundle/TwigBundle/Tests/Controller/ExceptionControllerTest.php b/src/Symfony/Bundle/TwigBundle/Tests/Controller/ExceptionControllerTest.php index 5b6dcb76fcc31..5d779c68c2a5e 100644 --- a/src/Symfony/Bundle/TwigBundle/Tests/Controller/ExceptionControllerTest.php +++ b/src/Symfony/Bundle/TwigBundle/Tests/Controller/ExceptionControllerTest.php @@ -50,7 +50,7 @@ public function testFallbackToHtmlIfNoTemplateForRequestedFormat() public function testFallbackToHtmlWithFullExceptionIfNoTemplateForRequestedFormatAndExceptionsShouldBeShown() { - $twig = $this->createTwigEnv(array('TwigBundle:Exception:exception_full.html.twig' => '')); + $twig = $this->createTwigEnv(array('@Twig/Exception/exception_full.html.twig' => '')); $request = $this->createRequest('txt'); $request->attributes->set('showException', true); From 9f9697a57d7e4dc07c1d58f621c40619c5777317 Mon Sep 17 00:00:00 2001 From: Maxime Steinhausser Date: Sun, 25 Jun 2017 18:11:24 +0200 Subject: [PATCH 084/106] [WebProfilerBundle] Fix css trick used for offsetting html anchor from fixed header --- .../WebProfilerBundle/Resources/views/Profiler/open.css.twig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/open.css.twig b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/open.css.twig index 02bc252f12007..7a0941c955a6d 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/open.css.twig +++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/open.css.twig @@ -64,7 +64,7 @@ a.doc:hover { .anchor { position: relative; - padding-top: 7em; - margin-top: -7em; + display: block; + top: -7em; visibility: hidden; } From e9e1534cde99b77188b64dd0db837e57db913aba Mon Sep 17 00:00:00 2001 From: Maxime Steinhausser Date: Sun, 25 Jun 2017 18:46:33 +0200 Subject: [PATCH 085/106] [Validator] Remove property path suggestion for using the Expression validator --- src/Symfony/Component/Validator/composer.json | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Symfony/Component/Validator/composer.json b/src/Symfony/Component/Validator/composer.json index f17085aa98c45..36e404ffe92e7 100644 --- a/src/Symfony/Component/Validator/composer.json +++ b/src/Symfony/Component/Validator/composer.json @@ -43,7 +43,6 @@ "symfony/yaml": "", "symfony/config": "", "egulias/email-validator": "Strict (RFC compliant) email validation", - "symfony/property-access": "For using the Expression validator", "symfony/expression-language": "For using the Expression validator" }, "autoload": { From c5042f35e10288d8a6d40d17c2d7bd5e5075a45c Mon Sep 17 00:00:00 2001 From: Tobias Nyholm Date: Sun, 25 Jun 2017 20:04:17 +0200 Subject: [PATCH 086/106] [Workflow] Added more events to the announce function --- src/Symfony/Component/Workflow/Tests/WorkflowTest.php | 2 ++ src/Symfony/Component/Workflow/Workflow.php | 3 +++ 2 files changed, 5 insertions(+) diff --git a/src/Symfony/Component/Workflow/Tests/WorkflowTest.php b/src/Symfony/Component/Workflow/Tests/WorkflowTest.php index c1efb0182765a..bbc9323c154c4 100644 --- a/src/Symfony/Component/Workflow/Tests/WorkflowTest.php +++ b/src/Symfony/Component/Workflow/Tests/WorkflowTest.php @@ -259,6 +259,8 @@ public function testApplyWithEventDispatcher() 'workflow.workflow_name.enter.b', 'workflow.workflow_name.enter.c', // Following events are fired because of announce() method + 'workflow.announce', + 'workflow.workflow_name.announce', 'workflow.guard', 'workflow.workflow_name.guard', 'workflow.workflow_name.guard.t2', diff --git a/src/Symfony/Component/Workflow/Workflow.php b/src/Symfony/Component/Workflow/Workflow.php index ec49895a3c604..3c0b07be3fbaf 100644 --- a/src/Symfony/Component/Workflow/Workflow.php +++ b/src/Symfony/Component/Workflow/Workflow.php @@ -282,6 +282,9 @@ private function announce($subject, Transition $initialTransition, Marking $mark $event = new Event($subject, $marking, $initialTransition); + $this->dispatcher->dispatch('workflow.announce', $event); + $this->dispatcher->dispatch(sprintf('workflow.%s.announce', $this->name), $event); + foreach ($this->getEnabledTransitions($subject) as $transition) { $this->dispatcher->dispatch(sprintf('workflow.%s.announce.%s', $this->name, $transition->getName()), $event); } From 65d89ec2248cfff57d3a26a89433196988d68f1b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pedro=20Magalh=C3=A3es?= Date: Tue, 27 Jun 2017 18:14:10 +0200 Subject: [PATCH 087/106] Identify tty tests in Component/Process --- src/Symfony/Component/Process/Tests/ProcessTest.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/Symfony/Component/Process/Tests/ProcessTest.php b/src/Symfony/Component/Process/Tests/ProcessTest.php index e034aeb28a743..90689c88cb8e6 100644 --- a/src/Symfony/Component/Process/Tests/ProcessTest.php +++ b/src/Symfony/Component/Process/Tests/ProcessTest.php @@ -439,6 +439,9 @@ public function testExitCodeCommandFailed() $this->assertGreaterThan(0, $process->getExitCode()); } + /** + * @group tty + */ public function testTTYCommand() { if ('\\' === DIRECTORY_SEPARATOR) { @@ -454,6 +457,9 @@ public function testTTYCommand() $this->assertSame(Process::STATUS_TERMINATED, $process->getStatus()); } + /** + * @group tty + */ public function testTTYCommandExitCode() { if ('\\' === DIRECTORY_SEPARATOR) { From 8014b38055272ccfe0aaf68fd03c1ce187f236ae Mon Sep 17 00:00:00 2001 From: Robin Chalas Date: Sat, 24 Jun 2017 14:52:30 +0200 Subject: [PATCH 088/106] [Security] Fix Firewall ExceptionListener priority --- .../Component/Security/Http/Firewall/ExceptionListener.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/Security/Http/Firewall/ExceptionListener.php b/src/Symfony/Component/Security/Http/Firewall/ExceptionListener.php index 2819018a8c2ae..fc279c0b3ab96 100644 --- a/src/Symfony/Component/Security/Http/Firewall/ExceptionListener.php +++ b/src/Symfony/Component/Security/Http/Firewall/ExceptionListener.php @@ -72,7 +72,7 @@ public function __construct(TokenStorageInterface $tokenStorage, AuthenticationT */ public function register(EventDispatcherInterface $dispatcher) { - $dispatcher->addListener(KernelEvents::EXCEPTION, array($this, 'onKernelException')); + $dispatcher->addListener(KernelEvents::EXCEPTION, array($this, 'onKernelException'), 1); } /** From 6cd188bd726746e473ea106568863e187143d181 Mon Sep 17 00:00:00 2001 From: Maxime Steinhausser Date: Thu, 29 Jun 2017 20:05:44 +0200 Subject: [PATCH 089/106] [FrameworkBundle] Display a proper warning on cache:clear without the --no-warmup option --- .../Bundle/FrameworkBundle/Command/CacheClearCommand.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/CacheClearCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/CacheClearCommand.php index 8f740c63178b9..2331afecb4e84 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/CacheClearCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/CacheClearCommand.php @@ -77,7 +77,11 @@ protected function execute(InputInterface $input, OutputInterface $output) if ($input->getOption('no-warmup')) { $filesystem->rename($realCacheDir, $oldCacheDir); } else { - @trigger_error('Calling cache:clear without the --no-warmup option is deprecated since version 3.3. Cache warmup should be done with the cache:warmup command instead.', E_USER_DEPRECATED); + $warning = 'Calling cache:clear without the --no-warmup option is deprecated since version 3.3. Cache warmup should be done with the cache:warmup command instead.'; + + @trigger_error($warning, E_USER_DEPRECATED); + + $io->warning($warning); $this->warmupCache($input, $output, $realCacheDir, $oldCacheDir); } From 2de59a73810c6fb5cf9159a418e61d6fc077a098 Mon Sep 17 00:00:00 2001 From: Maxime Steinhausser Date: Thu, 29 Jun 2017 19:50:07 +0200 Subject: [PATCH 090/106] [Validator] Throw exception on Comparison constraints null options --- .../Constraints/AbstractComparison.php | 4 ++++ .../AbstractComparisonValidatorTestCase.php | 19 +++++++++++++------ .../Constraints/EqualToValidatorTest.php | 2 +- .../GreaterThanOrEqualValidatorTest.php | 2 +- .../Constraints/GreaterThanValidatorTest.php | 2 +- .../Constraints/IdenticalToValidatorTest.php | 2 +- .../LessThanOrEqualValidatorTest.php | 2 +- .../Constraints/LessThanValidatorTest.php | 2 +- .../Constraints/NotEqualToValidatorTest.php | 2 +- .../NotIdenticalToValidatorTest.php | 2 +- 10 files changed, 25 insertions(+), 14 deletions(-) diff --git a/src/Symfony/Component/Validator/Constraints/AbstractComparison.php b/src/Symfony/Component/Validator/Constraints/AbstractComparison.php index fb1f1f3ef7c75..34466c7cb3251 100644 --- a/src/Symfony/Component/Validator/Constraints/AbstractComparison.php +++ b/src/Symfony/Component/Validator/Constraints/AbstractComparison.php @@ -29,6 +29,10 @@ abstract class AbstractComparison extends Constraint */ public function __construct($options = null) { + if (null === $options) { + $options = array(); + } + if (is_array($options) && !isset($options['value'])) { throw new ConstraintDefinitionException(sprintf( 'The %s constraint requires the "value" option to be set.', diff --git a/src/Symfony/Component/Validator/Tests/Constraints/AbstractComparisonValidatorTestCase.php b/src/Symfony/Component/Validator/Tests/Constraints/AbstractComparisonValidatorTestCase.php index 9c8ce50fc3dd1..8843e6077f6d0 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/AbstractComparisonValidatorTestCase.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/AbstractComparisonValidatorTestCase.php @@ -68,14 +68,21 @@ protected static function addPhp5Dot5Comparisons(array $comparisons) return $result; } + public function provideInvalidConstraintOptions() + { + return array( + array(null), + array(array()), + ); + } + /** + * @dataProvider provideInvalidConstraintOptions * @expectedException \Symfony\Component\Validator\Exception\ConstraintDefinitionException */ - public function testThrowsConstraintExceptionIfNoValueOrProperty() + public function testThrowsConstraintExceptionIfNoValueOrProperty($options) { - $comparison = $this->createConstraint(array()); - - $this->validator->validate('some value', $comparison); + $this->createConstraint($options); } /** @@ -169,9 +176,9 @@ public function provideAllInvalidComparisons() abstract public function provideInvalidComparisons(); /** - * @param array $options Options for the constraint + * @param array|null $options Options for the constraint * * @return Constraint */ - abstract protected function createConstraint(array $options); + abstract protected function createConstraint(array $options = null); } diff --git a/src/Symfony/Component/Validator/Tests/Constraints/EqualToValidatorTest.php b/src/Symfony/Component/Validator/Tests/Constraints/EqualToValidatorTest.php index c20db1550ba27..b396601396429 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/EqualToValidatorTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/EqualToValidatorTest.php @@ -30,7 +30,7 @@ protected function createValidator() return new EqualToValidator(); } - protected function createConstraint(array $options) + protected function createConstraint(array $options = null) { return new EqualTo($options); } diff --git a/src/Symfony/Component/Validator/Tests/Constraints/GreaterThanOrEqualValidatorTest.php b/src/Symfony/Component/Validator/Tests/Constraints/GreaterThanOrEqualValidatorTest.php index 41708f65c966e..923c7e61a08aa 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/GreaterThanOrEqualValidatorTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/GreaterThanOrEqualValidatorTest.php @@ -30,7 +30,7 @@ protected function createValidator() return new GreaterThanOrEqualValidator(); } - protected function createConstraint(array $options) + protected function createConstraint(array $options = null) { return new GreaterThanOrEqual($options); } diff --git a/src/Symfony/Component/Validator/Tests/Constraints/GreaterThanValidatorTest.php b/src/Symfony/Component/Validator/Tests/Constraints/GreaterThanValidatorTest.php index 85a2b1dad18d5..094949d97dfb1 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/GreaterThanValidatorTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/GreaterThanValidatorTest.php @@ -30,7 +30,7 @@ protected function createValidator() return new GreaterThanValidator(); } - protected function createConstraint(array $options) + protected function createConstraint(array $options = null) { return new GreaterThan($options); } diff --git a/src/Symfony/Component/Validator/Tests/Constraints/IdenticalToValidatorTest.php b/src/Symfony/Component/Validator/Tests/Constraints/IdenticalToValidatorTest.php index 0b6a4e411af9f..d7db609e17499 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/IdenticalToValidatorTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/IdenticalToValidatorTest.php @@ -30,7 +30,7 @@ protected function createValidator() return new IdenticalToValidator(); } - protected function createConstraint(array $options) + protected function createConstraint(array $options = null) { return new IdenticalTo($options); } diff --git a/src/Symfony/Component/Validator/Tests/Constraints/LessThanOrEqualValidatorTest.php b/src/Symfony/Component/Validator/Tests/Constraints/LessThanOrEqualValidatorTest.php index 75181355109ff..8f1666ea81572 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/LessThanOrEqualValidatorTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/LessThanOrEqualValidatorTest.php @@ -30,7 +30,7 @@ protected function createValidator() return new LessThanOrEqualValidator(); } - protected function createConstraint(array $options) + protected function createConstraint(array $options = null) { return new LessThanOrEqual($options); } diff --git a/src/Symfony/Component/Validator/Tests/Constraints/LessThanValidatorTest.php b/src/Symfony/Component/Validator/Tests/Constraints/LessThanValidatorTest.php index d555870c120b1..6d216e31644b9 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/LessThanValidatorTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/LessThanValidatorTest.php @@ -30,7 +30,7 @@ protected function createValidator() return new LessThanValidator(); } - protected function createConstraint(array $options) + protected function createConstraint(array $options = null) { return new LessThan($options); } diff --git a/src/Symfony/Component/Validator/Tests/Constraints/NotEqualToValidatorTest.php b/src/Symfony/Component/Validator/Tests/Constraints/NotEqualToValidatorTest.php index bc2c348efade0..c969e2a2af099 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/NotEqualToValidatorTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/NotEqualToValidatorTest.php @@ -30,7 +30,7 @@ protected function createValidator() return new NotEqualToValidator(); } - protected function createConstraint(array $options) + protected function createConstraint(array $options = null) { return new NotEqualTo($options); } diff --git a/src/Symfony/Component/Validator/Tests/Constraints/NotIdenticalToValidatorTest.php b/src/Symfony/Component/Validator/Tests/Constraints/NotIdenticalToValidatorTest.php index 43149847b9c5a..3aed5b7bf60b8 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/NotIdenticalToValidatorTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/NotIdenticalToValidatorTest.php @@ -30,7 +30,7 @@ protected function createValidator() return new NotIdenticalToValidator(); } - protected function createConstraint(array $options) + protected function createConstraint(array $options = null) { return new NotIdenticalTo($options); } From e0c5040398ff7b26f71d8ad343850014f1c2424a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Fri, 30 Jun 2017 11:17:50 +0200 Subject: [PATCH 091/106] [PropertyAccess] Fix TypeError discard --- .../PropertyAccess/PropertyAccessor.php | 2 +- .../Tests/Fixtures/ReturnTyped.php | 31 +++++++++++++++++++ .../Tests/PropertyAccessorTest.php | 13 ++++++++ 3 files changed, 45 insertions(+), 1 deletion(-) create mode 100644 src/Symfony/Component/PropertyAccess/Tests/Fixtures/ReturnTyped.php diff --git a/src/Symfony/Component/PropertyAccess/PropertyAccessor.php b/src/Symfony/Component/PropertyAccess/PropertyAccessor.php index cdb075c84621f..a6615f11e7a5e 100644 --- a/src/Symfony/Component/PropertyAccess/PropertyAccessor.php +++ b/src/Symfony/Component/PropertyAccess/PropertyAccessor.php @@ -245,7 +245,7 @@ public static function handleError($type, $message, $file, $line, $context) private static function throwInvalidArgumentException($message, $trace, $i) { - if (isset($trace[$i]['file']) && __FILE__ === $trace[$i]['file']) { + if (isset($trace[$i]['file']) && __FILE__ === $trace[$i]['file'] && isset($trace[$i]['args'][0])) { $pos = strpos($message, $delim = 'must be of the type ') ?: (strpos($message, $delim = 'must be an instance of ') ?: strpos($message, $delim = 'must implement interface ')); $pos += strlen($delim); $type = $trace[$i]['args'][0]; diff --git a/src/Symfony/Component/PropertyAccess/Tests/Fixtures/ReturnTyped.php b/src/Symfony/Component/PropertyAccess/Tests/Fixtures/ReturnTyped.php new file mode 100644 index 0000000000000..b6a9852715d79 --- /dev/null +++ b/src/Symfony/Component/PropertyAccess/Tests/Fixtures/ReturnTyped.php @@ -0,0 +1,31 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\PropertyAccess\Tests\Fixtures; + +/** + * @author Kévin Dunglas + */ +class ReturnTyped +{ + public function getFoos(): array + { + return 'It doesn\'t respect the return type on purpose'; + } + + public function addFoo(\DateTime $dateTime) + { + } + + public function removeFoo(\DateTime $dateTime) + { + } +} diff --git a/src/Symfony/Component/PropertyAccess/Tests/PropertyAccessorTest.php b/src/Symfony/Component/PropertyAccess/Tests/PropertyAccessorTest.php index fc434adb45a0e..bff2c728f1ca2 100644 --- a/src/Symfony/Component/PropertyAccess/Tests/PropertyAccessorTest.php +++ b/src/Symfony/Component/PropertyAccess/Tests/PropertyAccessorTest.php @@ -14,6 +14,7 @@ use PHPUnit\Framework\TestCase; use Symfony\Component\PropertyAccess\Exception\NoSuchIndexException; use Symfony\Component\PropertyAccess\PropertyAccessor; +use Symfony\Component\PropertyAccess\Tests\Fixtures\ReturnTyped; use Symfony\Component\PropertyAccess\Tests\Fixtures\TestClass; use Symfony\Component\PropertyAccess\Tests\Fixtures\TestClassMagicCall; use Symfony\Component\PropertyAccess\Tests\Fixtures\TestClassMagicGet; @@ -566,4 +567,16 @@ public function testThrowTypeErrorWithInterface() $this->propertyAccessor->setValue($object, 'countable', 'This is a string, \Countable expected.'); } + + /** + * @requires PHP 7 + * + * @expectedException \TypeError + */ + public function testDoNotDiscardReturnTypeError() + { + $object = new ReturnTyped(); + + $this->propertyAccessor->setValue($object, 'foos', array(new \DateTime())); + } } From 66a4fd749d0ffe317d6b8842d1e2dea0f7e31fca Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Fri, 30 Jun 2017 20:34:12 +0200 Subject: [PATCH 092/106] parse escaped quotes in unquoted env var values --- src/Symfony/Component/Dotenv/Dotenv.php | 4 ++++ src/Symfony/Component/Dotenv/Tests/DotenvTest.php | 3 +++ 2 files changed, 7 insertions(+) diff --git a/src/Symfony/Component/Dotenv/Dotenv.php b/src/Symfony/Component/Dotenv/Dotenv.php index 1e665fb537a70..3f8623437a473 100644 --- a/src/Symfony/Component/Dotenv/Dotenv.php +++ b/src/Symfony/Component/Dotenv/Dotenv.php @@ -215,6 +215,10 @@ private function lexValue() $notQuoted = true; $prevChr = $this->data[$this->cursor - 1]; while ($this->cursor < $this->end && "\n" !== $this->data[$this->cursor] && !((' ' === $prevChr || "\t" === $prevChr) && '#' === $this->data[$this->cursor])) { + if ('\\' === $this->data[$this->cursor] && isset($this->data[$this->cursor + 1]) && ('"' === $this->data[$this->cursor + 1] || "'" === $this->data[$this->cursor + 1])) { + ++$this->cursor; + } + $value .= $prevChr = $this->data[$this->cursor]; ++$this->cursor; } diff --git a/src/Symfony/Component/Dotenv/Tests/DotenvTest.php b/src/Symfony/Component/Dotenv/Tests/DotenvTest.php index fd0398f318a28..d0dccd7c75541 100644 --- a/src/Symfony/Component/Dotenv/Tests/DotenvTest.php +++ b/src/Symfony/Component/Dotenv/Tests/DotenvTest.php @@ -94,6 +94,9 @@ public function getEnvData() array('FOO=" "', array('FOO' => ' ')), array('PATH="c:\\\\"', array('PATH' => 'c:\\')), array("FOO=\"bar\nfoo\"", array('FOO' => "bar\nfoo")), + array('FOO=BAR\\"', array('FOO' => 'BAR"')), + array("FOO=BAR\\'BAZ", array('FOO' => "BAR'BAZ")), + array('FOO=\\"BAR', array('FOO' => '"BAR')), // concatenated values From d8ba440def44f76ebd7c91cd9e64af34915f3705 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Sat, 1 Jul 2017 09:48:47 +0200 Subject: [PATCH 093/106] [Console] fix description of INF default values --- .../Component/Console/Descriptor/JsonDescriptor.php | 4 ++-- .../Component/Console/Descriptor/TextDescriptor.php | 4 ++++ .../Console/Tests/Descriptor/ObjectsProvider.php | 2 ++ .../Fixtures/input_argument_with_default_inf_value.json | 7 +++++++ .../Fixtures/input_argument_with_default_inf_value.md | 7 +++++++ .../Fixtures/input_argument_with_default_inf_value.txt | 1 + .../Fixtures/input_argument_with_default_inf_value.xml | 7 +++++++ .../Fixtures/input_option_with_default_inf_value.json | 9 +++++++++ .../Fixtures/input_option_with_default_inf_value.md | 9 +++++++++ .../Fixtures/input_option_with_default_inf_value.txt | 1 + .../Fixtures/input_option_with_default_inf_value.xml | 7 +++++++ 11 files changed, 56 insertions(+), 2 deletions(-) create mode 100644 src/Symfony/Component/Console/Tests/Fixtures/input_argument_with_default_inf_value.json create mode 100644 src/Symfony/Component/Console/Tests/Fixtures/input_argument_with_default_inf_value.md create mode 100644 src/Symfony/Component/Console/Tests/Fixtures/input_argument_with_default_inf_value.txt create mode 100644 src/Symfony/Component/Console/Tests/Fixtures/input_argument_with_default_inf_value.xml create mode 100644 src/Symfony/Component/Console/Tests/Fixtures/input_option_with_default_inf_value.json create mode 100644 src/Symfony/Component/Console/Tests/Fixtures/input_option_with_default_inf_value.md create mode 100644 src/Symfony/Component/Console/Tests/Fixtures/input_option_with_default_inf_value.txt create mode 100644 src/Symfony/Component/Console/Tests/Fixtures/input_option_with_default_inf_value.xml diff --git a/src/Symfony/Component/Console/Descriptor/JsonDescriptor.php b/src/Symfony/Component/Console/Descriptor/JsonDescriptor.php index 87e38fdb89071..942fdc96226ac 100644 --- a/src/Symfony/Component/Console/Descriptor/JsonDescriptor.php +++ b/src/Symfony/Component/Console/Descriptor/JsonDescriptor.php @@ -103,7 +103,7 @@ private function getInputArgumentData(InputArgument $argument) 'is_required' => $argument->isRequired(), 'is_array' => $argument->isArray(), 'description' => preg_replace('/\s*[\r\n]\s*/', ' ', $argument->getDescription()), - 'default' => $argument->getDefault(), + 'default' => INF === $argument->getDefault() ? 'INF' : $argument->getDefault(), ); } @@ -121,7 +121,7 @@ private function getInputOptionData(InputOption $option) 'is_value_required' => $option->isValueRequired(), 'is_multiple' => $option->isArray(), 'description' => preg_replace('/\s*[\r\n]\s*/', ' ', $option->getDescription()), - 'default' => $option->getDefault(), + 'default' => INF === $option->getDefault() ? 'INF' : $option->getDefault(), ); } diff --git a/src/Symfony/Component/Console/Descriptor/TextDescriptor.php b/src/Symfony/Component/Console/Descriptor/TextDescriptor.php index c0dd4830c3d2d..5b82b3deefa8e 100644 --- a/src/Symfony/Component/Console/Descriptor/TextDescriptor.php +++ b/src/Symfony/Component/Console/Descriptor/TextDescriptor.php @@ -237,6 +237,10 @@ private function writeText($content, array $options = array()) */ private function formatDefaultValue($default) { + if (INF === $default) { + return 'INF'; + } + if (is_string($default)) { $default = OutputFormatter::escape($default); } elseif (is_array($default)) { diff --git a/src/Symfony/Component/Console/Tests/Descriptor/ObjectsProvider.php b/src/Symfony/Component/Console/Tests/Descriptor/ObjectsProvider.php index 8f825ecb68395..b4f34ada19ec6 100644 --- a/src/Symfony/Component/Console/Tests/Descriptor/ObjectsProvider.php +++ b/src/Symfony/Component/Console/Tests/Descriptor/ObjectsProvider.php @@ -32,6 +32,7 @@ public static function getInputArguments() 'input_argument_3' => new InputArgument('argument_name', InputArgument::OPTIONAL, 'argument description', 'default_value'), 'input_argument_4' => new InputArgument('argument_name', InputArgument::REQUIRED, "multiline\nargument description"), 'input_argument_with_style' => new InputArgument('argument_name', InputArgument::OPTIONAL, 'argument description', 'style'), + 'input_argument_with_default_inf_value' => new InputArgument('argument_name', InputArgument::OPTIONAL, 'argument description', INF), ); } @@ -46,6 +47,7 @@ public static function getInputOptions() 'input_option_6' => new InputOption('option_name', array('o', 'O'), InputOption::VALUE_REQUIRED, 'option with multiple shortcuts'), 'input_option_with_style' => new InputOption('option_name', 'o', InputOption::VALUE_REQUIRED, 'option description', 'style'), 'input_option_with_style_array' => new InputOption('option_name', 'o', InputOption::VALUE_IS_ARRAY | InputOption::VALUE_REQUIRED, 'option description', array('Hello', 'world')), + 'input_option_with_default_inf_value' => new InputOption('option_name', 'o', InputOption::VALUE_OPTIONAL, 'option description', INF), ); } diff --git a/src/Symfony/Component/Console/Tests/Fixtures/input_argument_with_default_inf_value.json b/src/Symfony/Component/Console/Tests/Fixtures/input_argument_with_default_inf_value.json new file mode 100644 index 0000000000000..b61ecf7b8c23c --- /dev/null +++ b/src/Symfony/Component/Console/Tests/Fixtures/input_argument_with_default_inf_value.json @@ -0,0 +1,7 @@ +{ + "name": "argument_name", + "is_required": false, + "is_array": false, + "description": "argument description", + "default": "INF" +} diff --git a/src/Symfony/Component/Console/Tests/Fixtures/input_argument_with_default_inf_value.md b/src/Symfony/Component/Console/Tests/Fixtures/input_argument_with_default_inf_value.md new file mode 100644 index 0000000000000..293d816201271 --- /dev/null +++ b/src/Symfony/Component/Console/Tests/Fixtures/input_argument_with_default_inf_value.md @@ -0,0 +1,7 @@ +**argument_name:** + +* Name: argument_name +* Is required: no +* Is array: no +* Description: argument description +* Default: `INF` diff --git a/src/Symfony/Component/Console/Tests/Fixtures/input_argument_with_default_inf_value.txt b/src/Symfony/Component/Console/Tests/Fixtures/input_argument_with_default_inf_value.txt new file mode 100644 index 0000000000000..c32d768c6f328 --- /dev/null +++ b/src/Symfony/Component/Console/Tests/Fixtures/input_argument_with_default_inf_value.txt @@ -0,0 +1 @@ + argument_name argument description [default: INF] diff --git a/src/Symfony/Component/Console/Tests/Fixtures/input_argument_with_default_inf_value.xml b/src/Symfony/Component/Console/Tests/Fixtures/input_argument_with_default_inf_value.xml new file mode 100644 index 0000000000000..d457260070be0 --- /dev/null +++ b/src/Symfony/Component/Console/Tests/Fixtures/input_argument_with_default_inf_value.xml @@ -0,0 +1,7 @@ + + + argument description + + INF + + diff --git a/src/Symfony/Component/Console/Tests/Fixtures/input_option_with_default_inf_value.json b/src/Symfony/Component/Console/Tests/Fixtures/input_option_with_default_inf_value.json new file mode 100644 index 0000000000000..7c96ad30405c6 --- /dev/null +++ b/src/Symfony/Component/Console/Tests/Fixtures/input_option_with_default_inf_value.json @@ -0,0 +1,9 @@ +{ + "name": "--option_name", + "shortcut": "-o", + "accept_value": true, + "is_value_required": false, + "is_multiple": false, + "description": "option description", + "default": "INF" +} diff --git a/src/Symfony/Component/Console/Tests/Fixtures/input_option_with_default_inf_value.md b/src/Symfony/Component/Console/Tests/Fixtures/input_option_with_default_inf_value.md new file mode 100644 index 0000000000000..b57bd04bf9993 --- /dev/null +++ b/src/Symfony/Component/Console/Tests/Fixtures/input_option_with_default_inf_value.md @@ -0,0 +1,9 @@ +**option_name:** + +* Name: `--option_name` +* Shortcut: `-o` +* Accept value: yes +* Is value required: no +* Is multiple: no +* Description: option description +* Default: `INF` diff --git a/src/Symfony/Component/Console/Tests/Fixtures/input_option_with_default_inf_value.txt b/src/Symfony/Component/Console/Tests/Fixtures/input_option_with_default_inf_value.txt new file mode 100644 index 0000000000000..d467dcf42327b --- /dev/null +++ b/src/Symfony/Component/Console/Tests/Fixtures/input_option_with_default_inf_value.txt @@ -0,0 +1 @@ + -o, --option_name[=OPTION_NAME] option description [default: INF] diff --git a/src/Symfony/Component/Console/Tests/Fixtures/input_option_with_default_inf_value.xml b/src/Symfony/Component/Console/Tests/Fixtures/input_option_with_default_inf_value.xml new file mode 100644 index 0000000000000..5d1d21753e9dc --- /dev/null +++ b/src/Symfony/Component/Console/Tests/Fixtures/input_option_with_default_inf_value.xml @@ -0,0 +1,7 @@ + + From baafc7b40921caac6affb4b9f1d5fc6c1fd8ca6c Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Sat, 1 Jul 2017 11:45:13 +0200 Subject: [PATCH 094/106] [Dotenv] clean up before running assertions If one of the assertions failed, the clean up part would never happen. --- src/Symfony/Component/Dotenv/Tests/DotenvTest.php | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/Dotenv/Tests/DotenvTest.php b/src/Symfony/Component/Dotenv/Tests/DotenvTest.php index fd0398f318a28..62aa94295e9b7 100644 --- a/src/Symfony/Component/Dotenv/Tests/DotenvTest.php +++ b/src/Symfony/Component/Dotenv/Tests/DotenvTest.php @@ -148,6 +148,13 @@ public function getEnvData() public function testLoad() { + unset($_ENV['FOO']); + unset($_ENV['BAR']); + unset($_SERVER['FOO']); + unset($_SERVER['BAR']); + putenv('FOO'); + putenv('BAR'); + @mkdir($tmpdir = sys_get_temp_dir().'/dotenv'); $path1 = tempnam($tmpdir, 'sf-'); @@ -158,14 +165,17 @@ public function testLoad() (new DotEnv())->load($path1, $path2); - $this->assertSame('BAR', getenv('FOO')); - $this->assertSame('BAZ', getenv('BAR')); + $foo = getenv('FOO'); + $bar = getenv('BAR'); putenv('FOO'); putenv('BAR'); unlink($path1); unlink($path2); rmdir($tmpdir); + + $this->assertSame('BAR', $foo); + $this->assertSame('BAZ', $bar); } /** From c183b0e06d1d7babcdaf27f069ec1f4f1e198163 Mon Sep 17 00:00:00 2001 From: David Maicher Date: Sat, 1 Jul 2017 12:17:16 +0200 Subject: [PATCH 095/106] [Cache] fix cleanup of expired items for PdoAdapter --- .../Component/Cache/Adapter/PdoAdapter.php | 2 +- .../Cache/Tests/Adapter/PdoAdapterTest.php | 26 +++++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/Cache/Adapter/PdoAdapter.php b/src/Symfony/Component/Cache/Adapter/PdoAdapter.php index 3fa3a40533d9e..4a462b35c451e 100644 --- a/src/Symfony/Component/Cache/Adapter/PdoAdapter.php +++ b/src/Symfony/Component/Cache/Adapter/PdoAdapter.php @@ -195,7 +195,7 @@ protected function doFetch(array $ids) foreach ($expired as $id) { $stmt->bindValue(++$i, $id); } - $stmt->execute($expired); + $stmt->execute(); } } diff --git a/src/Symfony/Component/Cache/Tests/Adapter/PdoAdapterTest.php b/src/Symfony/Component/Cache/Tests/Adapter/PdoAdapterTest.php index b0d2b9cb8a105..90c9ece8bcc9d 100644 --- a/src/Symfony/Component/Cache/Tests/Adapter/PdoAdapterTest.php +++ b/src/Symfony/Component/Cache/Tests/Adapter/PdoAdapterTest.php @@ -41,4 +41,30 @@ public function createCachePool($defaultLifetime = 0) { return new PdoAdapter('sqlite:'.self::$dbFile, 'ns', $defaultLifetime); } + + public function testCleanupExpiredItems() + { + $pdo = new \PDO('sqlite:'.self::$dbFile); + + $getCacheItemCount = function () use ($pdo) { + return (int) $pdo->query('SELECT COUNT(*) FROM cache_items')->fetch(\PDO::FETCH_COLUMN); + }; + + $this->assertSame(0, $getCacheItemCount()); + + $cache = $this->createCachePool(); + + $item = $cache->getItem('some_nice_key'); + $item->expiresAfter(1); + $item->set(1); + + $cache->save($item); + $this->assertSame(1, $getCacheItemCount()); + + sleep(2); + + $newItem = $cache->getItem($item->getKey()); + $this->assertFalse($newItem->isHit()); + $this->assertSame(0, $getCacheItemCount(), 'PDOAdapter must clean up expired items'); + } } From fd7ad234bc573519134fff1db5a602ebe0e04f71 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Fri, 30 Jun 2017 20:18:03 +0200 Subject: [PATCH 096/106] do not validate empty values --- .../Doctrine/Validator/Constraints/UniqueEntityValidator.php | 4 ++++ .../Core/Validator/Constraints/UserPasswordValidator.php | 4 ++++ src/Symfony/Component/Validator/Constraints/UrlValidator.php | 2 +- 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Bridge/Doctrine/Validator/Constraints/UniqueEntityValidator.php b/src/Symfony/Bridge/Doctrine/Validator/Constraints/UniqueEntityValidator.php index 51181b0714e47..b0d9534a0e98d 100644 --- a/src/Symfony/Bridge/Doctrine/Validator/Constraints/UniqueEntityValidator.php +++ b/src/Symfony/Bridge/Doctrine/Validator/Constraints/UniqueEntityValidator.php @@ -62,6 +62,10 @@ public function validate($entity, Constraint $constraint) throw new ConstraintDefinitionException('At least one field has to be specified.'); } + if (null === $entity) { + return; + } + if ($constraint->em) { $em = $this->registry->getManager($constraint->em); diff --git a/src/Symfony/Component/Security/Core/Validator/Constraints/UserPasswordValidator.php b/src/Symfony/Component/Security/Core/Validator/Constraints/UserPasswordValidator.php index 2dc7fee49992e..5f4c146cab469 100644 --- a/src/Symfony/Component/Security/Core/Validator/Constraints/UserPasswordValidator.php +++ b/src/Symfony/Component/Security/Core/Validator/Constraints/UserPasswordValidator.php @@ -39,6 +39,10 @@ public function validate($password, Constraint $constraint) throw new UnexpectedTypeException($constraint, __NAMESPACE__.'\UserPassword'); } + if (null === $password || '' === $password) { + return; + } + $user = $this->tokenStorage->getToken()->getUser(); if (!$user instanceof UserInterface) { diff --git a/src/Symfony/Component/Validator/Constraints/UrlValidator.php b/src/Symfony/Component/Validator/Constraints/UrlValidator.php index 5cb126d8fe2fe..26246fe6d2aad 100644 --- a/src/Symfony/Component/Validator/Constraints/UrlValidator.php +++ b/src/Symfony/Component/Validator/Constraints/UrlValidator.php @@ -48,7 +48,7 @@ public function validate($value, Constraint $constraint) throw new UnexpectedTypeException($constraint, __NAMESPACE__.'\Url'); } - if (null === $value) { + if (null === $value || '' === $value) { return; } From ed3e403b4bf8b183a1fe76559b9b7849c43a8a3e Mon Sep 17 00:00:00 2001 From: Yonel Ceruto Date: Fri, 23 Jun 2017 00:23:25 -0400 Subject: [PATCH 097/106] Display a better error design when the toolbar cannot be displayed --- .../Resources/views/Profiler/toolbar.css.twig | 30 +++++++++++++++++++ .../views/Profiler/toolbar_js.html.twig | 18 +++++------ 2 files changed, 38 insertions(+), 10 deletions(-) diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/toolbar.css.twig b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/toolbar.css.twig index a01a9017f4a49..2e05fb89abe71 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/toolbar.css.twig +++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/toolbar.css.twig @@ -440,3 +440,33 @@ visibility: hidden; } } + +/***** Error Toolbar *****/ +.sf-error-toolbar .sf-toolbarreset { + background: #222; + color: #f5f5f5; + font: 13px/36px Arial, sans-serif; + height: 36px; + padding: 0 15px; + text-align: left; +} + +.sf-error-toolbar .sf-toolbarreset svg { + height: auto; +} + +.sf-error-toolbar .sf-toolbarreset a { + color: #99cdd8; + margin-left: 5px; + text-decoration: underline; +} + +.sf-error-toolbar .sf-toolbarreset a:hover { + text-decoration: none; +} + +.sf-error-toolbar .sf-toolbarreset .sf-toolbar-icon { + float: left; + padding: 5px 0; + margin-right: 10px; +} diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/toolbar_js.html.twig b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/toolbar_js.html.twig index 57537f61a3feb..3bdd8ef1e843e 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/toolbar_js.html.twig +++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/toolbar_js.html.twig @@ -57,17 +57,15 @@ } }, function(xhr) { - var errorToolbarHtml = ' - -
An error occurred while loading the web debug toolbar. Open the web profiler.
- '; - if (xhr.status !== 0) { - window.document.body.insertAdjacentHTML('beforeend', errorToolbarHtml); + var sfwdt = document.getElementById('sfwdt{{ token }}'); + sfwdt.innerHTML = '\ +
\ +
\ + An error occurred while loading the web debug toolbar. Open the web profiler.\ +
\ + '; + sfwdt.setAttribute('class', 'sf-toolbar sf-error-toolbar'); } }, {'maxTries': 5} From aaaf64ddde2aa22cb90a1c60fd902865589f5b18 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Fri, 30 Jun 2017 20:34:12 +0200 Subject: [PATCH 098/106] [Dotenv] parse concatenated variable values --- src/Symfony/Component/Dotenv/Dotenv.php | 133 +++++++++++------- .../Component/Dotenv/Tests/DotenvTest.php | 5 +- 2 files changed, 89 insertions(+), 49 deletions(-) diff --git a/src/Symfony/Component/Dotenv/Dotenv.php b/src/Symfony/Component/Dotenv/Dotenv.php index 3f8623437a473..00f27bb7b3cdd 100644 --- a/src/Symfony/Component/Dotenv/Dotenv.php +++ b/src/Symfony/Component/Dotenv/Dotenv.php @@ -168,73 +168,110 @@ private function lexValue() throw $this->createFormatException('Whitespace are not supported before the value'); } - $value = ''; - $singleQuoted = false; - $notQuoted = false; - if ("'" === $this->data[$this->cursor]) { - $singleQuoted = true; - ++$this->cursor; - while ("\n" !== $this->data[$this->cursor]) { - if ("'" === $this->data[$this->cursor]) { - if ($this->cursor + 1 === $this->end) { - break; - } - if ("'" !== $this->data[$this->cursor + 1]) { + $v = ''; + + do { + if ("'" === $this->data[$this->cursor]) { + $value = ''; + ++$this->cursor; + + while ("\n" !== $this->data[$this->cursor]) { + if ("'" === $this->data[$this->cursor]) { break; } - + $value .= $this->data[$this->cursor]; ++$this->cursor; - } - $value .= $this->data[$this->cursor]; - ++$this->cursor; - if ($this->cursor === $this->end) { + if ($this->cursor === $this->end) { + throw $this->createFormatException('Missing quote to end the value'); + } + } + if ("\n" === $this->data[$this->cursor]) { throw $this->createFormatException('Missing quote to end the value'); } - } - if ("\n" === $this->data[$this->cursor]) { - throw $this->createFormatException('Missing quote to end the value'); - } - ++$this->cursor; - } elseif ('"' === $this->data[$this->cursor]) { - ++$this->cursor; - while ('"' !== $this->data[$this->cursor] || ('\\' === $this->data[$this->cursor - 1] && '\\' !== $this->data[$this->cursor - 2])) { - $value .= $this->data[$this->cursor]; ++$this->cursor; + $v .= $value; + } elseif ('"' === $this->data[$this->cursor]) { + $value = ''; + ++$this->cursor; + + while ('"' !== $this->data[$this->cursor] || ('\\' === $this->data[$this->cursor - 1] && '\\' !== $this->data[$this->cursor - 2])) { + $value .= $this->data[$this->cursor]; + ++$this->cursor; - if ($this->cursor === $this->end) { + if ($this->cursor === $this->end) { + throw $this->createFormatException('Missing quote to end the value'); + } + } + if ("\n" === $this->data[$this->cursor]) { throw $this->createFormatException('Missing quote to end the value'); } - } - if ("\n" === $this->data[$this->cursor]) { - throw $this->createFormatException('Missing quote to end the value'); - } - ++$this->cursor; - $value = str_replace(array('\\\\', '\\"', '\r', '\n'), array('\\', '"', "\r", "\n"), $value); - } else { - $notQuoted = true; - $prevChr = $this->data[$this->cursor - 1]; - while ($this->cursor < $this->end && "\n" !== $this->data[$this->cursor] && !((' ' === $prevChr || "\t" === $prevChr) && '#' === $this->data[$this->cursor])) { - if ('\\' === $this->data[$this->cursor] && isset($this->data[$this->cursor + 1]) && ('"' === $this->data[$this->cursor + 1] || "'" === $this->data[$this->cursor + 1])) { + ++$this->cursor; + $value = str_replace(array('\\\\', '\\"', '\r', '\n'), array('\\', '"', "\r", "\n"), $value); + $resolvedValue = $value; + $resolvedValue = $this->resolveVariables($resolvedValue); + $resolvedValue = $this->resolveCommands($resolvedValue); + $v .= $resolvedValue; + } else { + $value = ''; + $prevChr = $this->data[$this->cursor - 1]; + while ($this->cursor < $this->end && !in_array($this->data[$this->cursor], array("\n", '"', "'"), true) && !((' ' === $prevChr || "\t" === $prevChr) && '#' === $this->data[$this->cursor])) { + if ('\\' === $this->data[$this->cursor] && isset($this->data[$this->cursor + 1]) && ('"' === $this->data[$this->cursor + 1] || "'" === $this->data[$this->cursor + 1])) { + ++$this->cursor; + } + + $value .= $prevChr = $this->data[$this->cursor]; + + if ('$' === $this->data[$this->cursor] && isset($this->data[$this->cursor + 1]) && '(' === $this->data[$this->cursor + 1]) { + ++$this->cursor; + $value .= '('.$this->lexNestedExpression().')'; + } + ++$this->cursor; } + $value = rtrim($value); + $resolvedValue = $value; + $resolvedValue = $this->resolveVariables($resolvedValue); + $resolvedValue = $this->resolveCommands($resolvedValue); - $value .= $prevChr = $this->data[$this->cursor]; - ++$this->cursor; + if ($resolvedValue === $value && preg_match('/\s+/', $value)) { + throw $this->createFormatException('A value containing spaces must be surrounded by quotes'); + } + + $v .= $resolvedValue; + + if ($this->cursor < $this->end && '#' === $this->data[$this->cursor]) { + break; + } } - $value = rtrim($value); - } + } while ($this->cursor < $this->end && "\n" !== $this->data[$this->cursor]); $this->skipEmptyLines(); - $currentValue = $value; - if (!$singleQuoted) { - $value = $this->resolveVariables($value); - $value = $this->resolveCommands($value); + return $v; + } + + private function lexNestedExpression() + { + ++$this->cursor; + $value = ''; + + while ("\n" !== $this->data[$this->cursor] && ')' !== $this->data[$this->cursor]) { + $value .= $this->data[$this->cursor]; + + if ('(' === $this->data[$this->cursor]) { + $value .= $this->lexNestedExpression().')'; + } + + ++$this->cursor; + + if ($this->cursor === $this->end) { + throw $this->createFormatException('Missing closing parenthesis.'); + } } - if ($notQuoted && $currentValue == $value && preg_match('/\s+/', $value)) { - throw $this->createFormatException('A value containing spaces must be surrounded by quotes'); + if ("\n" === $this->data[$this->cursor]) { + throw $this->createFormatException('Missing closing parenthesis.'); } return $value; diff --git a/src/Symfony/Component/Dotenv/Tests/DotenvTest.php b/src/Symfony/Component/Dotenv/Tests/DotenvTest.php index c257b84f0f017..a7f211ecd6e37 100644 --- a/src/Symfony/Component/Dotenv/Tests/DotenvTest.php +++ b/src/Symfony/Component/Dotenv/Tests/DotenvTest.php @@ -85,7 +85,6 @@ public function getEnvData() array("FOO='bar'\n", array('FOO' => 'bar')), array("FOO='bar\"foo'\n", array('FOO' => 'bar"foo')), array("FOO=\"bar\\\"foo\"\n", array('FOO' => 'bar"foo')), - array("FOO='bar''foo'\n", array('FOO' => 'bar\'foo')), array('FOO="bar\nfoo"', array('FOO' => "bar\nfoo")), array('FOO="bar\rfoo"', array('FOO' => "bar\rfoo")), array('FOO=\'bar\nfoo\'', array('FOO' => 'bar\nfoo')), @@ -99,6 +98,10 @@ public function getEnvData() array('FOO=\\"BAR', array('FOO' => '"BAR')), // concatenated values + array("FOO='bar''foo'\n", array('FOO' => 'barfoo')), + array("FOO='bar '' baz'", array('FOO' => 'bar baz')), + array("FOO=bar\nBAR='baz'\"\$FOO\"", array('FOO' => 'bar', 'BAR' => 'bazbar')), + array("FOO='bar '\\'' baz'", array('FOO' => "bar ' baz")), // comments array("#FOO=bar\nBAR=foo", array('BAR' => 'foo')), From b576f46c26ea5801e889a04fac2fe181c40cee5c Mon Sep 17 00:00:00 2001 From: mcorteel Date: Mon, 3 Jul 2017 09:17:38 +0200 Subject: [PATCH 099/106] Misspelled word MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The French word "chaine" should be spelled "chaîne". --- .../Validator/Resources/translations/validators.fr.xlf | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.fr.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.fr.xlf index b50ecbc63a1b5..e28ea54b4512c 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.fr.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.fr.xlf @@ -76,7 +76,7 @@ This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. - Cette chaine est trop longue. Elle doit avoir au maximum {{ limit }} caractère.|Cette chaine est trop longue. Elle doit avoir au maximum {{ limit }} caractères. + Cette chaîne est trop longue. Elle doit avoir au maximum {{ limit }} caractère.|Cette chaîne est trop longue. Elle doit avoir au maximum {{ limit }} caractères. This value should be {{ limit }} or more. @@ -84,7 +84,7 @@ This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. - Cette chaine est trop courte. Elle doit avoir au minimum {{ limit }} caractère.|Cette chaine est trop courte. Elle doit avoir au minimum {{ limit }} caractères. + Cette chaîne est trop courte. Elle doit avoir au minimum {{ limit }} caractère.|Cette chaîne est trop courte. Elle doit avoir au minimum {{ limit }} caractères. This value should not be blank. @@ -180,7 +180,7 @@ This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters. - Cette chaine doit avoir exactement {{ limit }} caractère.|Cette chaine doit avoir exactement {{ limit }} caractères. + Cette chaîne doit avoir exactement {{ limit }} caractère.|Cette chaîne doit avoir exactement {{ limit }} caractères. The file was only partially uploaded. From ebdbecfb8b0a8cd136e9a92f9a2f65fd4f32a70d Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Mon, 3 Jul 2017 11:21:33 +0200 Subject: [PATCH 100/106] gracefully handle missing hinclude renderer --- .../DependencyInjection/Compiler/ExtensionPass.php | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/Symfony/Bundle/TwigBundle/DependencyInjection/Compiler/ExtensionPass.php b/src/Symfony/Bundle/TwigBundle/DependencyInjection/Compiler/ExtensionPass.php index 65f36edf205ee..96278822bf069 100644 --- a/src/Symfony/Bundle/TwigBundle/DependencyInjection/Compiler/ExtensionPass.php +++ b/src/Symfony/Bundle/TwigBundle/DependencyInjection/Compiler/ExtensionPass.php @@ -65,10 +65,7 @@ public function process(ContainerBuilder $container) $container->getDefinition('twig.extension.httpkernel')->addTag('twig.extension'); // inject Twig in the hinclude service if Twig is the only registered templating engine - if ( - !$container->hasParameter('templating.engines') - || array('twig') == $container->getParameter('templating.engines') - ) { + if ((!$container->hasParameter('templating.engines') || array('twig') == $container->getParameter('templating.engines')) && $container->hasDefinition('fragment.renderer.hinclude')) { $container->getDefinition('fragment.renderer.hinclude') ->addTag('kernel.fragment_renderer', array('alias' => 'hinclude')) ->replaceArgument(0, new Reference('twig')) From 3a529e3391ab526ba9ea776fbd887573921b4eb1 Mon Sep 17 00:00:00 2001 From: Thomas Perez Date: Mon, 3 Jul 2017 15:09:40 +0200 Subject: [PATCH 101/106] Improve CircularReferenceException message --- .../Component/Serializer/Normalizer/AbstractNormalizer.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/Serializer/Normalizer/AbstractNormalizer.php b/src/Symfony/Component/Serializer/Normalizer/AbstractNormalizer.php index 63bfb871e819d..5149d0dbc7d97 100644 --- a/src/Symfony/Component/Serializer/Normalizer/AbstractNormalizer.php +++ b/src/Symfony/Component/Serializer/Normalizer/AbstractNormalizer.php @@ -228,7 +228,7 @@ protected function handleCircularReference($object) return call_user_func($this->circularReferenceHandler, $object); } - throw new CircularReferenceException(sprintf('A circular reference has been detected (configured limit: %d).', $this->circularReferenceLimit)); + throw new CircularReferenceException(sprintf('A circular reference has been detected when serializing the object of class "%s" (configured limit: %d)', get_class($object), $this->circularReferenceLimit)); } /** From 3ddb6e6aade5ae2086d72a83ddde60aa75511e3e Mon Sep 17 00:00:00 2001 From: Robin Chalas Date: Mon, 3 Jul 2017 15:19:36 +0200 Subject: [PATCH 102/106] [Console] Fix descriptor tests --- .../Fixtures/input_argument_with_default_inf_value.md | 6 +++--- .../Tests/Fixtures/input_option_with_default_inf_value.md | 7 +++---- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/src/Symfony/Component/Console/Tests/Fixtures/input_argument_with_default_inf_value.md b/src/Symfony/Component/Console/Tests/Fixtures/input_argument_with_default_inf_value.md index 293d816201271..4f4d9b164a775 100644 --- a/src/Symfony/Component/Console/Tests/Fixtures/input_argument_with_default_inf_value.md +++ b/src/Symfony/Component/Console/Tests/Fixtures/input_argument_with_default_inf_value.md @@ -1,7 +1,7 @@ -**argument_name:** +#### `argument_name` + +argument description -* Name: argument_name * Is required: no * Is array: no -* Description: argument description * Default: `INF` diff --git a/src/Symfony/Component/Console/Tests/Fixtures/input_option_with_default_inf_value.md b/src/Symfony/Component/Console/Tests/Fixtures/input_option_with_default_inf_value.md index b57bd04bf9993..c27e30a0a3291 100644 --- a/src/Symfony/Component/Console/Tests/Fixtures/input_option_with_default_inf_value.md +++ b/src/Symfony/Component/Console/Tests/Fixtures/input_option_with_default_inf_value.md @@ -1,9 +1,8 @@ -**option_name:** +#### `--option_name|-o` + +option description -* Name: `--option_name` -* Shortcut: `-o` * Accept value: yes * Is value required: no * Is multiple: no -* Description: option description * Default: `INF` From 1d07a28beda7b2e9f2c18e13502ba8b293780f21 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Tue, 20 Jun 2017 19:01:50 +0200 Subject: [PATCH 103/106] call setContainer() for autowired controllers --- .../Controller/ControllerResolver.php | 14 +++- .../Controller/ControllerResolverTest.php | 69 +++++++++++++++++++ 2 files changed, 82 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/Controller/ControllerResolver.php b/src/Symfony/Bundle/FrameworkBundle/Controller/ControllerResolver.php index 355f526fdc950..3de157bd4ff3e 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Controller/ControllerResolver.php +++ b/src/Symfony/Bundle/FrameworkBundle/Controller/ControllerResolver.php @@ -49,7 +49,19 @@ protected function createController($controller) $controller = $this->parser->parse($controller); } - return parent::createController($controller); + $resolvedController = parent::createController($controller); + + if (1 === substr_count($controller, ':') && is_array($resolvedController)) { + if ($resolvedController[0] instanceof ContainerAwareInterface) { + $resolvedController[0]->setContainer($this->container); + } + + if ($resolvedController[0] instanceof AbstractController && null !== $previousContainer = $resolvedController[0]->setContainer($this->container)) { + $resolvedController[0]->setContainer($previousContainer); + } + } + + return $resolvedController; } /** diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/ControllerResolverTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/ControllerResolverTest.php index 7946a96e8d2c0..5880ee0186a18 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/ControllerResolverTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/ControllerResolverTest.php @@ -13,6 +13,7 @@ use Psr\Container\ContainerInterface as Psr11ContainerInterface; use Psr\Log\LoggerInterface; +use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Bundle\FrameworkBundle\Controller\ControllerNameParser; use Symfony\Bundle\FrameworkBundle\Controller\ControllerResolver; use Symfony\Component\DependencyInjection\Container; @@ -68,6 +69,24 @@ public function testGetControllerWithBundleNotation() $this->assertSame('testAction', $controller[1]); } + public function testContainerAwareControllerGetsContainerWhenNotSet() + { + class_exists(AbstractControllerTest::class); + + $controller = new ContainerAwareController(); + + $container = new Container(); + $container->set(TestAbstractController::class, $controller); + + $resolver = $this->createControllerResolver(null, $container); + + $request = Request::create('/'); + $request->attributes->set('_controller', TestAbstractController::class.':testAction'); + + $this->assertSame(array($controller, 'testAction'), $resolver->getController($request)); + $this->assertSame($container, $controller->getContainer()); + } + public function testAbstractControllerGetsContainerWhenNotSet() { class_exists(AbstractControllerTest::class); @@ -86,6 +105,24 @@ class_exists(AbstractControllerTest::class); $this->assertSame($container, $controller->setContainer($container)); } + public function testAbstractControllerServiceWithFcqnIdGetsContainerWhenNotSet() + { + class_exists(AbstractControllerTest::class); + + $controller = new DummyController(); + + $container = new Container(); + $container->set(DummyController::class, $controller); + + $resolver = $this->createControllerResolver(null, $container); + + $request = Request::create('/'); + $request->attributes->set('_controller', DummyController::class.':fooAction'); + + $this->assertSame(array($controller, 'fooAction'), $resolver->getController($request)); + $this->assertSame($container, $controller->getContainer()); + } + public function testAbstractControllerGetsNoContainerWhenSet() { class_exists(AbstractControllerTest::class); @@ -106,6 +143,26 @@ class_exists(AbstractControllerTest::class); $this->assertSame($controllerContainer, $controller->setContainer($container)); } + public function testAbstractControllerServiceWithFcqnIdGetsNoContainerWhenSet() + { + class_exists(AbstractControllerTest::class); + + $controller = new DummyController(); + $controllerContainer = new Container(); + $controller->setContainer($controllerContainer); + + $container = new Container(); + $container->set(DummyController::class, $controller); + + $resolver = $this->createControllerResolver(null, $container); + + $request = Request::create('/'); + $request->attributes->set('_controller', DummyController::class.':fooAction'); + + $this->assertSame(array($controller, 'fooAction'), $resolver->getController($request)); + $this->assertSame($controllerContainer, $controller->getContainer()); + } + protected function createControllerResolver(LoggerInterface $logger = null, Psr11ContainerInterface $container = null, ControllerNameParser $parser = null) { if (!$parser) { @@ -152,3 +209,15 @@ public function __invoke() { } } + +class DummyController extends AbstractController +{ + public function getContainer() + { + return $this->container; + } + + public function fooAction() + { + } +} From 08a6178e77e1fd5bc44a39215861dc4ffd48388b Mon Sep 17 00:00:00 2001 From: Robin Chalas Date: Tue, 4 Jul 2017 00:07:18 +0200 Subject: [PATCH 104/106] Don't access private services from container aware commands (deprecated) --- .../Command/RouterDebugCommand.php | 3 +- .../Tests/Command/RouterDebugCommandTest.php | 31 +++++++++----- .../Tests/Command/RouterMatchCommandTest.php | 42 +++++++++++-------- 3 files changed, 47 insertions(+), 29 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/RouterDebugCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/RouterDebugCommand.php index 97707e8798b59..a08c1a352197f 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/RouterDebugCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/RouterDebugCommand.php @@ -12,6 +12,7 @@ namespace Symfony\Bundle\FrameworkBundle\Command; use Symfony\Bundle\FrameworkBundle\Console\Helper\DescriptorHelper; +use Symfony\Bundle\FrameworkBundle\Controller\ControllerNameParser; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; @@ -109,7 +110,7 @@ protected function execute(InputInterface $input, OutputInterface $output) private function convertController(Route $route) { - $nameParser = $this->getContainer()->get('controller_name_converter'); + $nameParser = new ControllerNameParser($this->getApplication()->getKernel()); if ($route->hasDefault('_controller')) { try { $route->setDefault('_controller', $nameParser->build($route->getDefault('_controller'))); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/RouterDebugCommandTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/RouterDebugCommandTest.php index 6d32a37fd0ec9..597082485a0b6 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/RouterDebugCommandTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/RouterDebugCommandTest.php @@ -12,9 +12,10 @@ namespace Symfony\Bundle\FrameworkBundle\Tests\Command; use PHPUnit\Framework\TestCase; -use Symfony\Component\Console\Application; +use Symfony\Bundle\FrameworkBundle\Console\Application; use Symfony\Component\Console\Tester\CommandTester; use Symfony\Bundle\FrameworkBundle\Command\RouterDebugCommand; +use Symfony\Component\HttpKernel\KernelInterface; use Symfony\Component\Routing\Route; use Symfony\Component\Routing\RouteCollection; @@ -51,16 +52,15 @@ public function testDebugInvalidRoute() */ private function createCommandTester() { - $application = new Application(); + $application = new Application($this->getKernel()); $command = new RouterDebugCommand(); - $command->setContainer($this->getContainer()); $application->add($command); return new CommandTester($application->find('debug:router')); } - private function getContainer() + private function getKernel() { $routeCollection = new RouteCollection(); $routeCollection->add('foo', new Route('foo')); @@ -82,14 +82,25 @@ private function getContainer() ->with('router') ->will($this->returnValue(true)) ; - $container + ->expects($this->any()) ->method('get') - ->will($this->returnValueMap(array( - array('router', 1, $router), - array('controller_name_converter', 1, $loader), - ))); + ->with('router') + ->willReturn($router) + ; + + $kernel = $this->getMockBuilder(KernelInterface::class)->getMock(); + $kernel + ->expects($this->any()) + ->method('getContainer') + ->willReturn($container) + ; + $kernel + ->expects($this->once()) + ->method('getBundles') + ->willReturn(array()) + ; - return $container; + return $kernel; } } diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/RouterMatchCommandTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/RouterMatchCommandTest.php index cd15b8c5e82fc..384bd7ca53079 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/RouterMatchCommandTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/RouterMatchCommandTest.php @@ -12,10 +12,11 @@ namespace Symfony\Bundle\FrameworkBundle\Tests\Command; use PHPUnit\Framework\TestCase; -use Symfony\Component\Console\Application; +use Symfony\Bundle\FrameworkBundle\Console\Application; use Symfony\Component\Console\Tester\CommandTester; use Symfony\Bundle\FrameworkBundle\Command\RouterMatchCommand; use Symfony\Bundle\FrameworkBundle\Command\RouterDebugCommand; +use Symfony\Component\HttpKernel\KernelInterface; use Symfony\Component\Routing\Route; use Symfony\Component\Routing\RouteCollection; use Symfony\Component\Routing\RequestContext; @@ -45,20 +46,14 @@ public function testWithNotMatchPath() */ private function createCommandTester() { - $application = new Application(); - - $command = new RouterMatchCommand(); - $command->setContainer($this->getContainer()); - $application->add($command); - - $command = new RouterDebugCommand(); - $command->setContainer($this->getContainer()); - $application->add($command); + $application = new Application($this->getKernel()); + $application->add(new RouterMatchCommand()); + $application->add(new RouterDebugCommand()); return new CommandTester($application->find('router:match')); } - private function getContainer() + private function getKernel() { $routeCollection = new RouteCollection(); $routeCollection->add('foo', new Route('foo')); @@ -81,16 +76,27 @@ private function getContainer() $container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerInterface')->getMock(); $container - ->expects($this->once()) + ->expects($this->atLeastOnce()) ->method('has') ->with('router') ->will($this->returnValue(true)); - $container->method('get') - ->will($this->returnValueMap(array( - array('router', 1, $router), - array('controller_name_converter', 1, $loader), - ))); + $container + ->expects($this->any()) + ->method('get') + ->willReturn($router); + + $kernel = $this->getMockBuilder(KernelInterface::class)->getMock(); + $kernel + ->expects($this->any()) + ->method('getContainer') + ->willReturn($container) + ; + $kernel + ->expects($this->once()) + ->method('getBundles') + ->willReturn(array()) + ; - return $container; + return $kernel; } } From fcb6171d9ef8161cb1dbd02eb0f98182848a2c5c Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Tue, 4 Jul 2017 09:02:47 +0300 Subject: [PATCH 105/106] updated CHANGELOG for 3.3.3 --- CHANGELOG-3.3.md | 66 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) diff --git a/CHANGELOG-3.3.md b/CHANGELOG-3.3.md index 6c3cb3540ff0c..1817eff60299e 100644 --- a/CHANGELOG-3.3.md +++ b/CHANGELOG-3.3.md @@ -7,6 +7,72 @@ in 3.3 minor versions. To get the diff for a specific change, go to https://github.com/symfony/symfony/commit/XXX where XXX is the change hash To get the diff between two versions, go to https://github.com/symfony/symfony/compare/v3.3.0...v3.3.1 +* 3.3.3 (2017-07-04) + + * bug #23366 [FrameworkBundle] Don't get() private services from debug:router (chalasr) + * bug #23239 [FrameworkBundle] call setContainer() for autowired controllers (xabbuh) + * bug #23351 [Dotenv] parse concatenated variable values (xabbuh) + * bug #23341 [DoctrineBridge][Security][Validator] do not validate empty values (xabbuh) + * bug #23274 Display a better error design when the toolbar cannot be displayed (yceruto) + * bug #23342 [Dotenv] parse escaped quotes in unquoted env var values (xabbuh) + * bug #23291 [Security] Fix Firewall ExceptionListener priority (chalasr) + * bug #23296 [WebProfilerBundle] Fix css trick used for offsetting html anchor from fixed header (ogizanagi) + * bug #23333 [PropertyAccess] Fix TypeError discard (dunglas) + * bug #23326 [Cache] fix cleanup of expired items for PdoAdapter (dmaicher) + * bug #23345 [Console] fix description of INF default values (xabbuh) + * bug #23328 [FrameworkBundle] Display a proper warning on cache:clear without the --no-warmup option (ogizanagi) + * bug #23299 [Workflow] Added more events to the announce function (Nyholm) + * bug #23279 Don't call count on non countable object (pierredup) + * bug #23283 [TwigBundle] add back exception check (xabbuh) + * bug #23268 Show exception is checked twice in ExceptionController of twig (gmponos) + * bug #23266 Display a better error message when the toolbar cannot be displayed (javiereguiluz) + * bug #23271 [FrameworkBundle] allow SSI fragments configuration in XML files (xabbuh) + * bug #23254 [Form][TwigBridge] render hidden _method field in form_rest() (xabbuh) + * bug #23250 [Translation] return fallback locales whenever possible (xabbuh) + * bug #23237 [Cache] Fix Predis client cluster with pipeline (flolivaud) + * bug #23240 [Console] Fix catching exception type in QuestionHelper (voronkovich) + * bug #23218 [DI] Dedup tags when using instanceof/autoconfigure (ogizanagi) + * bug #23231 Improved the exception page when there is no message (javiereguiluz) + * bug #23229 [WebProfilerBundle] Eliminate line wrap on count column (routing) (e-moe) + * bug #22732 [Security] fix switch user _exit without having current token (dmaicher) + * bug #23226 [Validator] replace hardcoded service id (xabbuh) + * bug #22730 [FrameworkBundle] Sessions: configurable "use_strict_mode" option for NativeSessionStorage (MacDada) + * bug #23195 [FrameworkBundle] [Command] Clean bundle directory, fixes #23177 (NicolasPion) + * bug #23213 Fixed composer resources between web/cli (iltar) + * bug #23160 [WebProfilerBundle] Fix the icon for the Cache panel (javiereguiluz) + * bug #23052 [TwigBundle] Add Content-Type header for exception response (rchoquet) + * bug #23173 [WebServerBundle] Fix router script option BC (1ed) + * bug #23199 Reset redirectCount when throwing exception (hvanoch) + * bug #23180 [FrameworkBundle] Expose the AbstractController's container to its subclasses (BPScott) + * bug #23186 [TwigBundle] Move template.xml loading to a compiler pass (ogizanagi) + * bug #23130 Keep s-maxage when expiry and validation are used in combination (mpdude) + * bug #23129 Fix two edge cases in ResponseCacheStrategy (mpdude) + * feature #22636 [Routing] Expose request in route conditions, if needed and possible (ro0NL) + * bug #22636 [Routing] Expose request in route conditions, if needed and possible (ro0NL) + * bug #22943 [SecurityBundle] Move cache of the firewall context into the request parameters (GromNaN) + * bug #23088 [FrameworkBundle] Dont set pre-defined esi/ssi services (ro0NL) + * bug #23057 [Translation][FrameworkBundle] Fix resource loading order inconsistency reported in #23034 (mpdude) + * bug #23092 [Filesystem] added workaround in Filesystem::rename for PHP bug (VolCh) + * bug #23074 [HttpFoundation] add back support for legacy constant values (xabbuh) + * bug #23128 [HttpFoundation] fix for Support for new 7.1 session options (vincentaubert) + * bug #23176 [VarDumper] fixes (nicolas-grekas) + * bug #23100 [PropertyAccess] Do not silence TypeErrors from client code. (tsufeki) + * bug #23156 [PropertyAccess] Fix Usage with anonymous classes (mablae) + * bug #23168 [Config] Fix ** GlobResource on Windows (nicolas-grekas) + * bug #23171 [Yaml] Fix linting yaml with constants as keys (chalasr) + * bug #23121 [Routing] Revert the change in [#b42018] with respect to Routing/Route.php (Dan Wilga) + * bug #23141 [DI] Fix keys resolution in ResolveParameterPlaceHoldersPass (nicolas-grekas) + * bug #23145 Fix the conditional definition of the SymfonyTestsListener (stof) + * bug #23091 [Cache] ApcuAdapter::isSupported() should return true when apc.enable_cli=Off (nicolas-grekas) + * bug #22953 #22839 - changed debug toolbar dump section to relative and use full window width (mkurzeja) + * bug #23086 [FrameworkBundle] Fix perf issue in CacheClearCommand::warmup() (nicolas-grekas) + * bug #23090 [SecurityBundle] Made 2 service aliases private (nicolas-grekas) + * bug #23108 [Yaml] Remove line number in deprecation notices (nicolas-grekas) + * bug #23098 Cache ipCheck (2.7) (gonzalovilaseca) + * bug #23082 [MonologBridge] Do not silence errors in ServerLogHandler::formatRecord (lyrixx) + * bug #23007 [HttpKernel][Debug] Fix missing trace on deprecations collected during bootstrapping & silenced errors (ogizanagi) + * bug #23069 [SecurityBundle] Show unique Inherited roles in profile panel (yceruto) + * 3.3.2 (2017-06-06) * bug #23073 [TwigBridge] Fix namespaced classes (ogizanagi) From 5d8d746a100d9eff0500a058fde8b06189155f11 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Tue, 4 Jul 2017 09:02:59 +0300 Subject: [PATCH 106/106] updated VERSION for 3.3.3 --- src/Symfony/Component/HttpKernel/Kernel.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/HttpKernel/Kernel.php b/src/Symfony/Component/HttpKernel/Kernel.php index a89e4d50bb866..955be15e9ea12 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -61,12 +61,12 @@ abstract class Kernel implements KernelInterface, TerminableInterface private $projectDir; - const VERSION = '3.3.3-DEV'; + const VERSION = '3.3.3'; const VERSION_ID = 30303; const MAJOR_VERSION = 3; const MINOR_VERSION = 3; const RELEASE_VERSION = 3; - const EXTRA_VERSION = 'DEV'; + const EXTRA_VERSION = ''; const END_OF_MAINTENANCE = '01/2018'; const END_OF_LIFE = '07/2018';