Skip to content

Commit dfa8ff8

Browse files
[Debug] cleanup interfaces before 2.5-final
1 parent b2855a5 commit dfa8ff8

File tree

8 files changed

+156
-173
lines changed

8 files changed

+156
-173
lines changed

src/Symfony/Bundle/FrameworkBundle/Resources/config/debug.xml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
<parameter key="debug.stopwatch.class">Symfony\Component\Stopwatch\Stopwatch</parameter>
1010
<parameter key="debug.container.dump">%kernel.cache_dir%/%kernel.container_class%.xml</parameter>
1111
<parameter key="debug.controller_resolver.class">Symfony\Component\HttpKernel\Controller\TraceableControllerResolver</parameter>
12-
<parameter key="debug.fatal_error_exceptions_listener.class">Symfony\Component\HttpKernel\EventListener\FatalErrorExceptionsListener</parameter>
12+
<parameter key="debug.debug_handlers_listener.class">Symfony\Component\HttpKernel\EventListener\DebugHandlersListener</parameter>
1313
</parameters>
1414

1515
<services>
@@ -41,11 +41,11 @@
4141
<argument type="service" id="logger" on-invalid="null" />
4242
</service>
4343

44-
<service id="debug.fatal_error_exceptions_listener" class="%debug.fatal_error_exceptions_listener.class%">
44+
<service id="debug.debug_handlers_listener" class="%debug.debug_handlers_listener.class%">
4545
<tag name="kernel.event_subscriber" />
4646
<argument type="collection">
4747
<argument type="service" id="http_kernel" on-invalid="null" />
48-
<argument>handleFatalErrorException</argument>
48+
<argument>terminateWithException</argument>
4949
</argument>
5050
</service>
5151
</services>

src/Symfony/Component/Debug/CHANGELOG.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,8 @@ CHANGELOG
44
2.5.0
55
-----
66

7-
* added ErrorHandler::setFatalErrorExceptionHandler()
7+
* added ExceptionHandler::setHandler()
88
* added UndefinedMethodFatalErrorHandler
9-
* deprecated ExceptionHandlerInterface
109
* deprecated DummyException
1110

1211
2.4.0

src/Symfony/Component/Debug/ErrorHandler.php

Lines changed: 7 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,6 @@ class ErrorHandler
5353

5454
private $displayErrors;
5555

56-
private $caughtOutput = 0;
57-
5856
/**
5957
* @var LoggerInterface[] Loggers for channels
6058
*/
@@ -64,8 +62,6 @@ class ErrorHandler
6462

6563
private static $stackedErrorLevels = array();
6664

67-
private static $fatalHandler = false;
68-
6965
/**
7066
* Registers the error handler.
7167
*
@@ -119,16 +115,6 @@ public static function setLogger(LoggerInterface $logger, $channel = 'deprecatio
119115
self::$loggers[$channel] = $logger;
120116
}
121117

122-
/**
123-
* Sets a fatal error exception handler.
124-
*
125-
* @param callable $handler An handler that will be called on FatalErrorException
126-
*/
127-
public static function setFatalErrorExceptionHandler($handler)
128-
{
129-
self::$fatalHandler = $handler;
130-
}
131-
132118
/**
133119
* @throws ContextErrorException When error_reporting returns error
134120
*/
@@ -284,7 +270,7 @@ public function handleFatal()
284270
throw $exception;
285271
}
286272

287-
if (!$error || !$this->level || !in_array($error['type'], array(E_ERROR, E_CORE_ERROR, E_COMPILE_ERROR, E_PARSE))) {
273+
if (!$error || !$this->level || !($error['type'] & (E_ERROR | E_CORE_ERROR | E_COMPILE_ERROR | E_PARSE))) {
288274
return;
289275
}
290276

@@ -298,7 +284,7 @@ public function handleFatal()
298284
self::$loggers['emergency']->emergency($error['message'], $fatal);
299285
}
300286

301-
if ($this->displayErrors && ($exceptionHandler || self::$fatalHandler)) {
287+
if ($this->displayErrors && $exceptionHandler) {
302288
$this->handleFatalError($exceptionHandler, $error);
303289
}
304290
}
@@ -336,73 +322,12 @@ private function handleFatalError($exceptionHandler, array $error)
336322
}
337323
}
338324

339-
// To be as fail-safe as possible, the FatalErrorException is first handled
340-
// by the exception handler, then by the fatal error handler. The latter takes
341-
// precedence and any output from the former is cancelled, if and only if
342-
// nothing bad happens in this handling path.
343-
344-
$caughtOutput = 0;
345-
346-
if ($exceptionHandler) {
347-
$this->caughtOutput = false;
348-
ob_start(array($this, 'catchOutput'));
349-
try {
350-
call_user_func($exceptionHandler, $exception);
351-
} catch (\Exception $e) {
352-
// Ignore this exception, we have to deal with the fatal error
353-
}
354-
if (false === $this->caughtOutput) {
355-
ob_end_clean();
356-
}
357-
if (isset($this->caughtOutput[0])) {
358-
ob_start(array($this, 'cleanOutput'));
359-
echo $this->caughtOutput;
360-
$caughtOutput = ob_get_length();
361-
}
362-
$this->caughtOutput = 0;
363-
}
364-
365-
if (self::$fatalHandler) {
366-
try {
367-
call_user_func(self::$fatalHandler, $exception);
368-
369-
if ($caughtOutput) {
370-
$this->caughtOutput = $caughtOutput;
371-
}
372-
} catch (\Exception $e) {
373-
if (!$caughtOutput) {
374-
// Neither the exception nor the fatal handler succeeded.
375-
// Let PHP handle that now.
376-
throw $exception;
377-
}
378-
}
379-
}
380-
}
381-
382-
/**
383-
* @internal
384-
*/
385-
public function catchOutput($buffer)
386-
{
387-
$this->caughtOutput = $buffer;
388-
389-
return '';
390-
}
391-
392-
/**
393-
* @internal
394-
*/
395-
public function cleanOutput($buffer)
396-
{
397-
if ($this->caughtOutput) {
398-
// use substr_replace() instead of substr() for mbstring overloading resistance
399-
$cleanBuffer = substr_replace($buffer, '', 0, $this->caughtOutput);
400-
if (isset($cleanBuffer[0])) {
401-
$buffer = $cleanBuffer;
402-
}
325+
try {
326+
call_user_func($exceptionHandler, $exception);
327+
} catch (\Exception $e) {
328+
// The handler failed. Let PHP handle that now.
329+
throw $exception;
403330
}
404-
405-
return $buffer;
406331
}
407332
}
408333

src/Symfony/Component/Debug/ExceptionHandler.php

Lines changed: 88 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,12 @@
2929
*
3030
* @author Fabien Potencier <fabien@symfony.com>
3131
*/
32-
class ExceptionHandler implements ExceptionHandlerInterface
32+
class ExceptionHandler
3333
{
3434
private $debug;
3535
private $charset;
36+
private $handler;
37+
private $caughtOutput = 0;
3638

3739
public function __construct($debug = true, $charset = 'UTF-8')
3840
{
@@ -56,6 +58,22 @@ public static function register($debug = true)
5658
return $handler;
5759
}
5860

61+
/**
62+
* Sets a user exception handler.
63+
*
64+
* @param callable $handler An handler that will be called on Exception
65+
*/
66+
public function setHandler($handler)
67+
{
68+
if (isset($handler) && !is_callable($handler)) {
69+
throw new \LogicException('The exception handler must be a valid PHP callable.');
70+
}
71+
$old = $this->handler;
72+
$this->handler = $handler;
73+
74+
return $old;
75+
}
76+
5977
/**
6078
* {@inheritdoc}
6179
*
@@ -70,12 +88,49 @@ public static function register($debug = true)
7088
*/
7189
public function handle(\Exception $exception)
7290
{
73-
if (class_exists('Symfony\Component\HttpFoundation\Response')) {
74-
$response = $this->createResponse($exception);
75-
$response->sendHeaders();
76-
$response->sendContent();
77-
} else {
78-
$this->sendPhpResponse($exception);
91+
// To be as fail-safe as possible, the exception is first handled
92+
// by our simple exception handler, then by the user exception handler.
93+
// The latter takes precedence and any output from the former is cancelled,
94+
// if and only if nothing bad happens in this handling path.
95+
96+
$caughtOutput = 0;
97+
98+
$this->caughtOutput = false;
99+
ob_start(array($this, 'catchOutput'));
100+
try {
101+
if (class_exists('Symfony\Component\HttpFoundation\Response')) {
102+
$response = $this->createResponse($exception);
103+
$response->sendHeaders();
104+
$response->sendContent();
105+
} else {
106+
$this->sendPhpResponse($exception);
107+
}
108+
} catch (\Exception $e) {
109+
// Ignore this $e exception, we have to deal with $exception
110+
}
111+
if (false === $this->caughtOutput) {
112+
ob_end_clean();
113+
}
114+
if (isset($this->caughtOutput[0])) {
115+
ob_start(array($this, 'cleanOutput'));
116+
echo $this->caughtOutput;
117+
$caughtOutput = ob_get_length();
118+
}
119+
$this->caughtOutput = 0;
120+
121+
if (!empty($this->handler)) {
122+
try {
123+
call_user_func($this->handler, $exception);
124+
125+
if ($caughtOutput) {
126+
$this->caughtOutput = $caughtOutput;
127+
}
128+
} catch (\Exception $e) {
129+
if (!$caughtOutput) {
130+
// All handlers failed. Let PHP handle that now.
131+
throw $exception;
132+
}
133+
}
79134
}
80135
}
81136

@@ -317,4 +372,30 @@ private function formatArgs(array $args)
317372

318373
return implode(', ', $result);
319374
}
375+
376+
/**
377+
* @internal
378+
*/
379+
public function catchOutput($buffer)
380+
{
381+
$this->caughtOutput = $buffer;
382+
383+
return '';
384+
}
385+
386+
/**
387+
* @internal
388+
*/
389+
public function cleanOutput($buffer)
390+
{
391+
if ($this->caughtOutput) {
392+
// use substr_replace() instead of substr() for mbstring overloading resistance
393+
$cleanBuffer = substr_replace($buffer, '', 0, $this->caughtOutput);
394+
if (isset($cleanBuffer[0])) {
395+
$buffer = $cleanBuffer;
396+
}
397+
}
398+
399+
return $buffer;
400+
}
320401
}

src/Symfony/Component/Debug/ExceptionHandlerInterface.php

Lines changed: 0 additions & 29 deletions
This file was deleted.
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
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\EventListener;
13+
14+
use Symfony\Component\Debug\ExceptionHandler;
15+
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
16+
use Symfony\Component\HttpKernel\KernelEvents;
17+
18+
/**
19+
* Configures the ExceptionHandler.
20+
*
21+
* @author Nicolas Grekas <p@tchwork.com>
22+
*/
23+
class DebugHandlersListener implements EventSubscriberInterface
24+
{
25+
private $exceptionHandler;
26+
27+
public function __construct($exceptionHandler)
28+
{
29+
if (is_callable($exceptionHandler)) {
30+
$this->exceptionHandler = $exceptionHandler;
31+
}
32+
}
33+
34+
public function configure()
35+
{
36+
if ($this->exceptionHandler) {
37+
$mainHandler = set_exception_handler('var_dump');
38+
restore_exception_handler();
39+
if ($mainHandler instanceof ExceptionHandler) {
40+
$mainHandler->setHandler($this->exceptionHandler);
41+
}
42+
$this->exceptionHandler = null;
43+
}
44+
}
45+
46+
public static function getSubscribedEvents()
47+
{
48+
return array(KernelEvents::REQUEST => array('configure', 2048));
49+
}
50+
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy