8000 [FrameworkBundle][HttpKernel] Configure ErrorHandler on boot · symfony/symfony@21b00ce · GitHub
[go: up one dir, main page]

Skip to content

Commit 21b00ce

Browse files
committed
[FrameworkBundle][HttpKernel] Configure ErrorHandler on boot
1 parent e16aea4 commit 21b00ce

File tree

10 files changed

+243
-191
lines changed

10 files changed

+243
-191
lines changed

src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ CHANGELOG
1313
* Deprecate the `notifier.logger_notification_listener` service, use the `notifier.notification_logger_listener` service instead
1414
* Allow setting private services with the test container
1515
* Register alias for argument for workflow services with workflow name only
16+
* Configure the `ErrorHandler` on `FrameworkBundle::boot()`
1617

1718
6.2
1819
---

src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1095,12 +1095,12 @@ private function registerDebugConfiguration(array $config, ContainerBuilder $con
10951095
$loader->load('debug.php');
10961096
}
10971097

1098-
$definition = $container->findDefinition('debug.debug_handlers_listener');
1098+
$definition = $container->findDefinition('debug.error_handler_configurator');
10991099

11001100
if (false === $config['log']) {
1101-
$definition->replaceArgument(1, null);
1101+
$definition->replaceArgument(0, null);
11021102
} elseif (true !== $config['log']) {
1103-
$definition->replaceArgument(2, $config['log']);
1103+
$definition->replaceArgument(1, $config['log']);
11041104
}
11051105

11061106
if (!$config['throw']) {

src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,8 @@ class FrameworkBundle extends Bundle
9494
*/
9595
public function boot()
9696
{
97-
ErrorHandler::register(null, false)->throwAt($this->container->getParameter('debug.error_handler.throw_at'), true);
97+
$handler = ErrorHandler::register(null, false);
98+
$this->container->get('debug.error_handler_configurator')->configure($handler);
9899

99100
if ($this->container->getParameter('kernel.http_method_override')) {
100101
Request::enableHttpMethodParameterOverride();

src/Symfony/Bundle/FrameworkBundle/Resources/config/debug_prod.php

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,26 +11,32 @@
1111

1212
namespace Symfony\Component\DependencyInjection\Loader\Configurator;
1313

14+
use Symfony\Component\HttpKernel\Debug\ErrorHandlerConfigurator;
1415
use Symfony\Component\HttpKernel\Debug\FileLinkFormatter;
1516
use Symfony\Component\HttpKernel\EventListener\DebugHandlersListener;
1617

1718
return static function (ContainerConfigurator $container) {
1819
$container->parameters()->set('debug.error_handler.throw_at', -1);
1920

2021
$container->services()
21-
->set('debug.debug_handlers_listener', DebugHandlersListener::class)
22+
->set('debug.error_handler_configurator', ErrorHandlerConfigurator::class)
23+
->public()
2224
->args([
23-
null, // Exception handler
2425
service('monolog.logger.php')->nullOnInvalid(),
2526
null, // Log levels map for enabled error levels
2627
param('debug.error_handler.throw_at'),
2728
param('kernel.debug'),
2829
param('kernel.debug'),
2930
service('monolog.logger.deprecation')->nullOnInvalid(),
3031
])
31-
->tag('kernel.event_subscriber')
3232
->tag('monolog.logger', ['channel' => 'php'])
3333

34+
->set('debug.debug_handlers_listener', DebugHandlersListener::class)
35+
->args([
36+
null, // Exception handler
37+
])
38+
->tag('kernel.event_subscriber')
39+
3440
->set('debug.file_link_formatter', FileLinkFormatter::class)
3541
->args([param('debug.file_link_format')])
3642

src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTestCase.php

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -541,41 +541,41 @@ public function testEnabledPhpErrorsConfig()
541541
{
542542
$container = $this->createContainerFromFile('php_errors_enabled');
543543

544-
$definition = $container->getDefinition('debug.debug_handlers_listener');
545-
$this->assertEquals(new Reference('monolog.logger.php', ContainerInterface::NULL_ON_INVALID_REFERENCE), $definition->getArgument(1));
546-
$this->assertNull($definition->getArgument(2));
544+
$definition = $container->getDefinition('debug.error_handler_configurator');
545+
$this->assertEquals(new Reference('monolog.logger.php', ContainerInterface::NULL_ON_INVALID_REFERENCE), $definition->getArgument(0));
546+
$this->assertNull($definition->getArgument(1));
547547
$this->assertSame(-1, $container->getParameter('debug.error_handler.throw_at'));
548548
}
549549

550550
public function testDisabledPhpErrorsConfig()
551551
{
552552
$container = $this->createContainerFromFile('php_errors_disabled');
553553

554-
$definition = $container->getDefinition('debug.debug_handlers_listener');
554+
$definition = $container->getDefinition('debug.error_handler_configurator');
555+
$this->assertNull($definition->getArgument(0));
555556
$this->assertNull($definition->getArgument(1));
556-
$this->assertNull($definition->getArgument(2));
557557
$this->assertSame(0, $container->getParameter('debug.error_handler.throw_at'));
558558
}
559559

560560
public function testPhpErrorsWithLogLevel()
561561
{
562562
$container = $this->createContainerFromFile('php_errors_log_level');
563563

564-
$definition = $container->getDefinition('debug.debug_handlers_listener');
565-
$this->assertEquals(new Reference('monolog.logger.php', ContainerInterface::NULL_ON_INVALID_REFERENCE), $definition->getArgument(1));
566-
$this->assertSame(8, $definition->getArgument(2));
564+
$definition = $container->getDefinition('debug.error_handler_configurator');
565+
$this->assertEquals(new Reference('monolog.logger.php', ContainerInterface::NULL_ON_INVALID_REFERENCE), $definition->getArgument(0));
566+
$this->assertSame(8, $definition->getArgument(1));
567567
}
568568

569569
public function testPhpErrorsWithLogLevels()
570570
{
571571
$container = $this->createContainerFromFile('php_errors_log_levels');
572572

573-
$definition = $container->getDefinition('debug.debug_handlers_listener');
574-
$this->assertEquals(new Reference('monolog.logger.php', ContainerInterface::NULL_ON_INVALID_REFERENCE), $definition->getArgument(1));
573+
$definition = $container->getDefinition('debug.error_handler_configurator');
574+
$this->assertEquals(new Reference('monolog.logger.php', ContainerInterface::NULL_ON_INVALID_REFERENCE), $definition->getArgument(0));
575575
$this->assertSame([
576576
\E_NOTICE => \Psr\Log\LogLevel::ERROR,
577577
\E_WARNING => \Psr\Log\LogLevel::ERROR,
578-
], $definition->getArgument(2));
578+
], $definition->getArgument(1));
579579
}
580580

581581
public function testExceptionsConfig()

src/Symfony/Bundle/FrameworkBundle/composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
"symfony/error-handler": "^6.1",
2727
"symfony/event-dispatcher": "^5.4|^6.0",
2828
"symfony/http-foundation": "^6.2",
29-
"symfony/http-kernel": "^6.2.1",
29+
"symfony/http-kernel": "^6.3",
3030
"symfony/polyfill-mbstring": "~1.0",
3131
"symfony/filesystem": "^5.4|^6.0",
3232
"symfony/finder": "^5.4|^6.0",
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\HttpKernel\Debug;
13+
14+
use Psr\Log\LoggerInterface;
15+
use Symfony\Component\ErrorHandler\ErrorHandler;
16+
17+
/**
18+
* Configures the error handler.
19+
*
20+
* @final
21+
*
22+
* @internal
23+
*/
24+
class ErrorHandlerConfigurator
25+
{
26+
private ?LoggerInterface $logger;
27+
private ?LoggerInterface $deprecationLogger;
28+
private array|int|null $levels;
29+
private ?int $throwAt;
30+
private bool $scream;
31+
private bool $scope;
32+
33+
/**
34+
* @param array|int|null $levels An array map of E_* to LogLevel::* or an integer bit field of E_* constants
35+
* @param int|null $throwAt Thrown errors in a bit field of E_* constants, or null to keep the current value
36+
* @param bool $scream Enables/disables screaming mode, where even silenced errors are logged
37+
* @param bool $scope Enables/disables scoping mode
38+
*/
39+
public function __construct(LoggerInterface $logger = null, array|int|null $levels = \E_ALL, ?int $throwAt = \E_ALL, bool $scream = true, bool $scope = true, LoggerInterface $deprecationLogger = null)
40+
{
41+
$this->logger = $logger;
42+
$this->levels = $levels ?? \E_ALL;
43+
$this->throwAt = \is_int($throwAt) ? $throwAt : (null === $throwAt ? null : ($throwAt ? \E_ALL : null));
44+
$this->scream = $scream;
45+
$this->scope = $scope;
46+
$this->deprecationLogger = $deprecationLogger;
47+
}
48+
49+
/**
50+
* Configures the error handler.
51+
*/
52+
public function configure(ErrorHandler $handler): void
53+
{
54+
if ($this->logger || $this->deprecationLogger) {
55+
$this->setDefaultLoggers($handler);
56+
if (\is_array($this->levels)) {
57+
$levels = 0;
58+
foreach ($this->levels as $type => $log) {
59+
$levels |= $type;
60+
}
61+
} else {
62+
$levels = $this->levels;
63+
}
64+
65+
if ($this->scream) {
66+
$handler->screamAt($levels);
67+
}
68+
if ($this->scope) {
69+
$handler->scopeAt($levels & ~\E_USER_DEPRECATED & ~\E_DEPRECATED);
70+
} else {
71+
$handler->scopeAt(0, true);
72+
}
73+
$this->logger = $this->deprecationLogger = $this->levels = null;
74+
}
75+
if (null !== $this->throwAt) {
76+
$handler->throwAt($this->throwAt, true);
77+
}
78+
}
79+
80+
private function setDefaultLoggers(ErrorHandler $handler): void
81+
{
82+
if (\is_array($this->levels)) {
83+
$levelsDeprecatedOnly = [];
84+
$levelsWithoutDeprecated = [];
85+
foreach ($this->levels as $type => $log) {
86+
if (\E_DEPRECATED == $type || \E_USER_DEPRECATED == $type) {
87+
$levelsDeprecatedOnly[$type] = $log;
88+
} else {
89+
$levelsWithoutDeprecated[$type] = $log;
90+
}
91+
}
92+
} else {
93+
$levelsDeprecatedOnly = $this->levels & (\E_DEPRECATED | \E_USER_DEPRECATED);
94+
$levelsWithoutDeprecated = $this->levels & ~\E_DEPRECATED & ~\E_USER_DEPRECATED;
95+
}
96+
97+
$defaultLoggerLevels = $this->levels;
98+
if ($this->deprecationLogger && $levelsDeprecatedOnly) {
99+
$handler->setDefaultLogger($this->deprecationLogger, $levelsDeprecatedOnly);
100+
$defaultLoggerLevels = $levelsWithoutDeprecated;
101+
}
102+
103+
if ($this->logger && $defaultLoggerLevels) {
104+
$handler->setDefaultLogger($this->logger, $defaultLoggerLevels);
105+
}
106+
}
107+
}

src/Symfony/Component/HttpKernel/EventListener/DebugHandlersListener.php

Lines changed: 11 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111

1212
namespace Symfony\Component\HttpKernel\EventListener;
1313

14-
use Psr\Log\LoggerInterface;
1514
use Symfony\Component\Console\ConsoleEvents;
1615
use Symfony\Component\Console\Event\ConsoleEvent;
1716
use Symfony\Component\Console\Output\ConsoleOutputInterface;
@@ -21,7 +20,7 @@
2120
use Symfony\Component\HttpKernel\KernelEvents;
2221

2322
/**
24-
* Configures errors and exceptions handlers.
23+
* Sets an exception handler.
2524
*
2625
* @author Nicolas Grekas <p@tchwork.com>
2726
*
@@ -33,35 +32,19 @@ class DebugHandlersListener implements EventSubscriberInterface
3332
{
3433
private string|object|null $earlyHandler;
3534
private ?\Closure $exceptionHandler;
36-
private ?LoggerInterface $logger;
37-
private ?LoggerInterface $deprecationLogger;
38-
private array|int|null $levels;
39-
private ?int $throwAt;
40-
private bool $scream;
41-
private bool $scope;
4235
private bool $firstCall = true;
4336
private bool $hasTerminatedWithException = false;
4437

4538
/**
46-
* @param callable|null $exceptionHandler A handler that must support \Throwable instances that will be called on Exception
47-
* @param array|int|null $levels An array map of E_* to LogLevel::* or an integer bit field of E_* constants
48-
* @param int|null $throwAt Thrown errors in a bit field of E_* constants, or null to keep the current value
49-
* @param bool $scream Enables/disables screaming mode, where even silenced errors are logged
50-
* @param bool $scope Enables/disables scoping mode
39+
* @param callable|null $exceptionHandler A handler that must support \Throwable instances that will be called on Exception
5140
*/
52-
public function __construct(callable $exceptionHandler = null, LoggerInterface $logger = null, array|int|null $levels = \E_ALL, ?int $throwAt = \E_ALL, bool $scream = true, bool $scope = true, LoggerInterface $deprecationLogger = null)
41+
public function __construct(callable $exceptionHandler = null)
5342
{
5443
$handler = set_exception_handler('is_int');
5544
$this->earlyHandler = \is_array($handler) ? $handler[0] : null;
5645
restore_exception_handler();
5746

5847
$this->exceptionHandler = null === $exceptionHandler ? null : $exceptionHandler(...);
59-
$this->logger = $logger;
60-
$this->levels = $levels ?? \E_ALL;
61-
$this->throwAt = \is_int($throwAt) ? $throwAt : (null === $throwAt ? null : ($throwAt ? \E_ALL : null));
62-
$this->scream = $scream;
63-
$this->scope = $scope;
64-
$this->deprecationLogger = $deprecationLogger;
6548
}
6649

6750
/**
@@ -77,40 +60,6 @@ public function configure(object $event = null): void
7760
}
7861
$this->firstCall = $this->hasTerminatedWithException = false;
7962

80-
$handler = set_exception_handler('is_int');
81-
$handler = \is_array($handler) ? $handler[0] : null;
82-
restore_exception_handler();
83-
84-
if (!$handler instanceof ErrorHandler) {
85-
$handler = $this->earlyHandler;
86-
}
87-
88-
if ($handler instanceof ErrorHandler) {
89-
if ($this->logger || $this->deprecationLogger) {
90-
$this->setDefaultLoggers($handler);
91-
if (\is_array($this->levels)) {
92-
$levels = 0;
93-
foreach ($this->levels as $type => $log) {
94-
$levels |= $type;
95-
}
96-
} else {
97-
$levels = $this->levels;
98-
}
99-
100-
if ($this->scream) {
101-
$handler->screamAt($levels);
102-
}
103-
if ($this->scope) {
104-
$handler->scopeAt($levels & ~\E_USER_DEPRECATED & ~\E_DEPRECATED);
105-
} else {
106-
$handler->scopeAt(0, true);
107-
}
108-
$this->logger = $this->deprecationLogger = $this->levels = null;
109-
}
110-
if (null !== $this->throwAt) {
111-
$handler->throwAt($this->throwAt, true);
112-
}
113-
}
11463
if (!$this->exceptionHandler) {
11564
if ($event instanceof KernelEvent) {
11665
if (method_exists($kernel = $event->getKernel(), 'terminateWithException')) {
@@ -136,41 +85,21 @@ public function configure(object $event = null): void
13685
}
13786
}
13887
if ($this->exceptionHandler) {
88+
$handler = set_exception_handler('is_int');
89+
$handler = \is_array($handler) ? $handler[0] : null;
90+
restore_exception_handler();
91+
92+
if (!$handler instanceof ErrorHandler) {
93+
$handler = $this->earlyHandler;
94+
}
95+
13996
if ($handler instanceof ErrorHandler) {
14097
$handler->setExceptionHandler($this->exceptionHandler);
14198
}
14299
$this->exceptionHandler = null;
143100
}
144101
}
145102

146-
private function setDefaultLoggers(ErrorHandler $handler): void
147-
{
148-
if (\is_array($this->levels)) {
149-
$levelsDeprecatedOnly = [];
150-
$levelsWithoutDeprecated = [];
151-
foreach ($this->levels as $type => $log) {
152-
if (\E_DEPRECATED == $type || \E_USER_DEPRECATED == $type) {
153-
$levelsDeprecatedOnly[$type] = $log;
154-
} else {
155-
$levelsWithoutDeprecated[$type] = $log;
156-
}
157-
}
158-
} else {
159-
$levelsDeprecatedOnly = $this->levels & (\E_DEPRECATED | \E_USER_DEPRECATED);
160-
$levelsWithoutDeprecated = $this->levels & ~\E_DEPRECATED & ~\E_USER_DEPRECATED;
161-
}
162-
163-
$defaultLoggerLevels = $this->levels;
164-
if ($this->deprecationLogger && $levelsDeprecatedOnly) {
165-
$handler->setDefaultLogger($this->deprecationLogger, $levelsDeprecatedOnly);
166-
$defaultLoggerLevels = $levelsWithoutDeprecated;
167-
}
168-
169-
if ($this->logger && $defaultLoggerLevels) {
170-
$handler->setDefaultLogger($this->logger, $defaultLoggerLevels);
171-
}
172-
}
173-
174103
public static function getSubscribedEvents(): array
175104
{
176105
$events = [KernelEvents::REQUEST => ['configure', 2048]];

0 commit comments

Comments
 (0)
0