diff --git a/HttpKernel.php b/HttpKernel.php index f84a39e5a2..22f7ef5430 100644 --- a/HttpKernel.php +++ b/HttpKernel.php @@ -106,7 +106,17 @@ public function terminateWithException(\Throwable $exception, Request $request = throw $exception; } - $response = $this->handleThrowable($exception, $request, self::MAIN_REQUEST); + if ($pop = $request !== $this->requestStack->getMainRequest()) { + $this->requestStack->push($request); + } + + try { + $response = $this->handleThrowable($exception, $request, self::MAIN_REQUEST); + } finally { + if ($pop) { + $this->requestStack->pop(); + } + } $response->sendHeaders(); $response->sendContent(); diff --git a/Kernel.php b/Kernel.php index 3c8c4068dc..78193d31c6 100644 --- a/Kernel.php +++ b/Kernel.php @@ -78,11 +78,11 @@ abstract class Kernel implements KernelInterface, RebootableInterface, Terminabl */ private static array $freshCache = []; - public const VERSION = '6.1.6'; - public const VERSION_ID = 60106; + public const VERSION = '6.1.7'; + public const VERSION_ID = 60107; public const MAJOR_VERSION = 6; public const MINOR_VERSION = 1; - public const RELEASE_VERSION = 6; + public const RELEASE_VERSION = 7; public const EXTRA_VERSION = ''; public const END_OF_MAINTENANCE = '01/2023'; diff --git a/Log/Logger.php b/Log/Logger.php index 1b3f977379..370069e517 100644 --- a/Log/Logger.php +++ b/Log/Logger.php @@ -49,10 +49,14 @@ public function __construct(string $minLevel = null, $output = null, callable $f if (isset($_ENV['SHELL_VERBOSITY']) || isset($_SERVER['SHELL_VERBOSITY'])) { switch ((int) ($_ENV['SHELL_VERBOSITY'] ?? $_SERVER['SHELL_VERBOSITY'])) { - case -1: $minLevel = LogLevel::ERROR; break; - case 1: $minLevel = LogLevel::NOTICE; break; - case 2: $minLevel = LogLevel::INFO; break; - case 3: $minLevel = LogLevel::DEBUG; break; + case -1: $minLevel = LogLevel::ERROR; + break; + case 1: $minLevel = LogLevel::NOTICE; + break; + case 2: $minLevel = LogLevel::INFO; + break; + case 3: $minLevel = LogLevel::DEBUG; + break; } } } @@ -83,7 +87,7 @@ public function log($level, $message, array $context = []): void $formatter = $this->formatter; if ($this->handle) { - @fwrite($this->handle, $formatter($level, $message, $context)); + @fwrite($this->handle, $formatter($level, $message, $context).\PHP_EOL); } else { error_log($formatter($level, $message, $context, false)); } @@ -108,7 +112,7 @@ private function format(string $level, string $message, array $context, bool $pr $message = strtr($message, $replacements); } - $log = sprintf('[%s] %s', $level, $message).\PHP_EOL; + $log = sprintf('[%s] %s', $level, $message); if ($prefixDate) { $log = date(\DateTime::RFC3339).' '.$log; } diff --git a/Tests/HttpCache/HttpCacheTest.php b/Tests/HttpCache/HttpCacheTest.php index 42b009fc00..1915d0d4dc 100644 --- a/Tests/HttpCache/HttpCacheTest.php +++ b/Tests/HttpCache/HttpCacheTest.php @@ -590,7 +590,7 @@ public function testDegradationWhenCacheLocked() $this->cacheConfig['stale_while_revalidate'] = 10; - // The prescence of Last-Modified makes this cacheable (because Response::isValidateable() then). + // The presence of Last-Modified makes this cacheable (because Response::isValidateable() then). $this->setNextResponse(200, ['Cache-Control' => 'public, s-maxage=5', 'Last-Modified' => 'some while ago'], 'Old response'); $this->request('GET', '/'); // warm the cache diff --git a/Tests/HttpKernelTest.php b/Tests/HttpKernelTest.php index 182b524e98..38a09ef2d2 100644 --- a/Tests/HttpKernelTest.php +++ b/Tests/HttpKernelTest.php @@ -341,6 +341,22 @@ public function testTerminate() $this->assertEquals($response, $capturedResponse); } + public function testTerminateWithException() + { + $dispatcher = new EventDispatcher(); + $requestStack = new RequestStack(); + $kernel = $this->getHttpKernel($dispatcher, null, $requestStack); + + $dispatcher->addListener(KernelEvents::EXCEPTION, function (ExceptionEvent $event) use (&$capturedRequest, $requestStack) { + $capturedRequest = $requestStack->getCurrentRequest(); + $event->setResponse(new Response()); + }); + + $kernel->terminateWithException(new \Exception('boo'), $request = Request::create('/')); + $this->assertSame($request, $capturedRequest); + $this->assertNull($requestStack->getCurrentRequest()); + } + public function testVerifyRequestStackPushPopDuringHandle() { $request = new Request(); diff --git a/Tests/Log/LoggerTest.php b/Tests/Log/LoggerTest.php index fb2b43cc82..5996e6e72a 100644 --- a/Tests/Log/LoggerTest.php +++ b/Tests/Log/LoggerTest.php @@ -48,7 +48,7 @@ protected function tearDown(): void public static function assertLogsMatch(array $expected, array $given) { foreach ($given as $k => $line) { - self::assertThat(1 === preg_match('/[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}[\+-][0-9]{2}:[0-9]{2} '.preg_quote($expected[$k]).'/', $line), self::isTrue(), "\"$line\" do not match expected pattern \"$expected[$k]\""); + self::assertSame(1, preg_match('/[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}[\+-][0-9]{2}:[0-9]{2} '.preg_quote($expected[$k]).'/', $line), "\"$line\" do not match expected pattern \"$expected[$k]\""); } } @@ -186,7 +186,7 @@ public function testContextExceptionKeyCanBeExceptionOrOtherValues() public function testFormatter() { $this->logger = new Logger(LogLevel::DEBUG, $this->tmpFile, function ($level, $message, $context) { - return json_encode(['level' => $level, 'message' => $message, 'context' => $context]).\PHP_EOL; + return json_encode(['level' => $level, 'message' => $message, 'context' => $context]); }); $this->logger->error('An error', ['foo' => 'bar']); @@ -196,6 +196,26 @@ public function testFormatter() '{"level":"warning","message":"A warning","context":{"baz":"bar"}}', ], $this->getLogs()); } + + public function testLogsWithoutOutput() + { + $oldErrorLog = ini_set('error_log', $this->tmpFile); + + $logger = new Logger(); + $logger->error('test'); + $logger->critical('test'); + + $expected = [ + '[error] test', + '[critical] test', + ]; + + foreach ($this->getLogs() as $k => $line) { + $this->assertSame(1, preg_match('/\[[\w\/\-: ]+\] '.preg_quote($expected[$k]).'/', $line), "\"$line\" do not match expected pattern \"$expected[$k]\""); + } + + ini_set('error_log', $oldErrorLog); + } } class DummyTest