Skip to content
Browse files

merged branch fabpot/debug-component (PR #7441)

This PR was merged into the master branch.

Discussion
----------

[Debug] added the component (closes #6828, closes #6834, closes #7330)

| Q             | A
| ------------- | ---
| Bug fix?      | no
| New feature?  | yes
| BC breaks?    | no
| Deprecations? | yes
| Tests pass?   | yes
| Fixed tickets | #6828, #6834, #7330
| License       | MIT
| Doc PR        | symfony/symfony-docs#2479

You can use the individual tools, or register them all:

```php
use Symfony\Component\Debug\Debug;

Debug::enable();
```

Changes in Symfony SE: symfony/symfony-standard#523

Commits
-------

f693128 fixed typos
1ab1146 [Debug] fixed minor bugs
daa3a3c [Debug] changed composer to accept more versions
e455269 [Debug] ensured that the Debug tools can only be registered once
946bfb2 [Debug] made the exception handler independant of HttpFoundation
2b305c2 added a main Debug class to ease integration
2ff0927 [Debug] added the component (closes #6828, closes #6834, closes #7330)
  • Loading branch information...
2 parents 22adfdf + f693128 commit 6d552c956e478a7772a04efbc5cd683a48ef88fc @fabpot fabpot committed Apr 7, 2013
View
14 UPGRADE-3.0.md
@@ -3,8 +3,8 @@ UPGRADE FROM 2.x to 3.0
### ClassLoader
- * The `UniversalClassLoader` class has been removed in favor of `ClassLoader`. The only difference is that some method
- names are different:
+ * The `UniversalClassLoader` class has been removed in favor of
+ `ClassLoader`. The only difference is that some method names are different:
* `registerNamespaces()` -> `addPrefixes()`
* `registerPrefixes()` -> `addPrefixes()`
@@ -34,6 +34,16 @@ UPGRADE FROM 2.x to 3.0
* `Symfony\Bridge\Monolog\Logger`
* `Symfony\Component\HttpKernel\Log\NullLogger`
+ * The `Symfony\Component\HttpKernel\Kernel::init()` method has been removed.
+
+ * The following classes have been renamed as they have been moved to the
+ Debug component:
+
+ * `Symfony\Component\HttpKernel\Debug\ErrorHandler` -> `Symfony\Component\Debug\ErrorHandler`
+ * `Symfony\Component\HttpKernel\Debug\ExceptionHandler` -> `Symfony\Component\Debug\ExceptionHandler`
+ * `Symfony\Component\HttpKernel\Exception\FatalErrorException` -> `Symfony\Component\Debug\Exception\FatalErrorException`
+ * `Symfony\Component\HttpKernel\Exception\FlattenException` -> `Symfony\Component\Debug\Exception\FlattenException`
+
### Routing
* Some route settings have been renamed:
View
3 src/Symfony/Component/Debug/.gitignore
@@ -0,0 +1,3 @@
+vendor/
+composer.lock
+phpunit.xml
View
7 src/Symfony/Component/Debug/CHANGELOG.md
@@ -0,0 +1,7 @@
+CHANGELOG
+=========
+
+2.3.0
+-----
+
+ * added the component
View
56 src/Symfony/Component/Debug/Debug.php
@@ -0,0 +1,56 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Debug;
+
+use Symfony\Component\ClassLoader\DebugClassLoader;
+
+/**
+ * Registers all the debug tools.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+class Debug
+{
+ private static $enabled = false;
+
+ /**
+ * Enables the debug tools.
+ *
+ * This method registers an error handler and an exception handler.
+ *
+ * If the Symfony ClassLoader component is available, a special
+ * class loader is also registered.
+ *
+ * @param integer $errorReportingLevel The level of error reporting you want
+ */
+ public static function enable($errorReportingLevel = null)
+ {
+ if (static::$enabled) {
+ return;
+ }
+
+ static::$enabled = true;
+
+ error_reporting(-1);
+
+ ErrorHandler::register($errorReportingLevel);
+ if ('cli' !== php_sapi_name()) {
+ ExceptionHandler::register();
+ } elseif (!ini_get('log_errors') || ini_get('error_log')) {
+ ini_set('display_errors', 1);
+ }
+
+ if (class_exists('Symfony\Component\ClassLoader\DebugClassLoader')) {
+ DebugClassLoader::enable();
+ }
+ }
+}
View
128 src/Symfony/Component/Debug/ErrorHandler.php
@@ -0,0 +1,128 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Debug;
+
+use Symfony\Component\Debug\Exception\FatalErrorException;
+use Psr\Log\LoggerInterface;
+
+/**
+ * ErrorHandler.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+class ErrorHandler
+{
+ const TYPE_DEPRECATION = -100;
+
+ private $levels = array(
+ E_WARNING => 'Warning',
+ E_NOTICE => 'Notice',
+ E_USER_ERROR => 'User Error',
+ E_USER_WARNING => 'User Warning',
+ E_USER_NOTICE => 'User Notice',
+ E_STRICT => 'Runtime Notice',
+ E_RECOVERABLE_ERROR => 'Catchable Fatal Error',
+ E_DEPRECATED => 'Deprecated',
+ E_USER_DEPRECATED => 'User Deprecated',
+ E_ERROR => 'Error',
+ E_CORE_ERROR => 'Core Error',
+ E_COMPILE_ERROR => 'Compile Error',
+ E_PARSE => 'Parse',
+ );
+
+ private $level;
+
+ private $reservedMemory;
+
+ /** @var LoggerInterface */
+ private static $logger;
+
+ /**
+ * Registers the error handler.
+ *
+ * @param integer $level The level at which the conversion to Exception is done (null to use the error_reporting() value and 0 to disable)
+ *
+ * @return The registered error handler
+ */
+ public static function register($level = null)
+ {
+ $handler = new static();
+ $handler->setLevel($level);
+
+ ini_set('display_errors', 0);
+ set_error_handler(array($handler, 'handle'));
+ register_shutdown_function(array($handler, 'handleFatal'));
+ $handler->reservedMemory = str_repeat('x', 10240);
+
+ return $handler;
+ }
+
+ public function setLevel($level)
+ {
+ $this->level = null === $level ? error_reporting() : $level;
+ }
+
+ public static function setLogger(LoggerInterface $logger)
+ {
+ self::$logger = $logger;
+ }
+
+ /**
+ * @throws \ErrorException When error_reporting returns error
+ */
+ public function handle($level, $message, $file, $line, $context)
+ {
+ if (0 === $this->level) {
+ return false;
+ }
+
+ if ($level & (E_USER_DEPRECATED | E_DEPRECATED)) {
+ if (null !== self::$logger) {
+ $stack = version_compare(PHP_VERSION, '5.4', '<') ? array_slice(debug_backtrace(false), 0, 10) : debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 10);
+
+ self::$logger->warning($message, array('type' => self::TYPE_DEPRECATION, 'stack' => $stack));
+ }
+
+ return true;
+ }
+
+ if (error_reporting() & $level && $this->level & $level) {
+ throw new \ErrorException(sprintf('%s: %s in %s line %d', isset($this->levels[$level]) ? $this->levels[$level] : $level, $message, $file, $line), 0, $level, $file, $line);
+ }
+
+ return false;
+ }
+
+ public function handleFatal()
+ {
+ if (null === $error = error_get_last()) {
+ return;
+ }
+
+ unset($this->reservedMemory);
+ $type = $error['type'];
+ if (0 === $this->level || !in_array($type, array(E_ERROR, E_CORE_ERROR, E_COMPILE_ERROR, E_PARSE))) {
+ return;
+ }
+
+ // get current exception handler
+ $exceptionHandler = set_exception_handler(function() {});
+ restore_exception_handler();
+
+ if (is_array($exceptionHandler) && $exceptionHandler[0] instanceof ExceptionHandler) {
+ $level = isset($this->levels[$type]) ? $this->levels[$type] : $type;
+ $message = sprintf('%s: %s in %s line %d', $level, $error['message'], $error['file'], $error['line']);
+ $exception = new FatalErrorException($message, 0, $type, $error['file'], $error['line']);
+ $exceptionHandler[0]->handle($exception);
+ }
+ }
+}
View
21 src/Symfony/Component/Debug/Exception/FatalErrorException.php
@@ -0,0 +1,21 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Debug\Exception;
+
+/**
+ * Fatal Error Exception.
+ *
+ * @author Konstanton Myakshin <koc-dp@yandex.ru>
+ */
+class FatalErrorException extends \ErrorException
+{
+}
View
277 src/Symfony/Component/Debug/Exception/FlattenException.php
@@ -0,0 +1,277 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Debug\Exception;
+
+use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface;
+
+/**
+ * FlattenException wraps a PHP Exception to be able to serialize it.
+ *
+ * Basically, this class removes all objects from the trace.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+class FlattenException
+{
+ private $message;
+ private $code;
+ private $previous;
+ private $trace;
+ private $class;
+ private $statusCode;
+ private $headers;
+ private $file;
+ private $line;
+
+ public static function create(\Exception $exception, $statusCode = null, array $headers = array())
+ {
+ $e = new static();
+ $e->setMessage($exception->getMessage());
+ $e->setCode($exception->getCode());
+
+ if ($exception instanceof HttpExceptionInterface) {
+ $statusCode = $exception->getStatusCode();
+ $headers = array_merge($headers, $exception->getHeaders());
+ }
+
+ if (null === $statusCode) {
+ $statusCode = 500;
+ }
+
+ $e->setStatusCode($statusCode);
+ $e->setHeaders($headers);
+ $e->setTraceFromException($exception);
+ $e->setClass(get_class($exception));
+ $e->setFile($exception->getFile());
+ $e->setLine($exception->getLine());
+ if ($exception->getPrevious()) {
+ $e->setPrevious(static::create($exception->getPrevious()));
+ }
+
+ return $e;
+ }
+
+ public function toArray()
+ {
+ $exceptions = array();
+ foreach (array_merge(array($this), $this->getAllPrevious()) as $exception) {
+ $exceptions[] = array(
+ 'message' => $exception->getMessage(),
+ 'class' => $exception->getClass(),
+ 'trace' => $exception->getTrace(),
+ );
+ }
+
+ return $exceptions;
+ }
+
+ public function getStatusCode()
+ {
+ return $this->statusCode;
+ }
+
+ public function setStatusCode($code)
+ {
+ $this->statusCode = $code;
+ }
+
+ public function getHeaders()
+ {
+ return $this->headers;
+ }
+
+ public function setHeaders(array $headers)
+ {
+ $this->headers = $headers;
+ }
+
+ public function getClass()
+ {
+ return $this->class;
+ }
+
+ public function setClass($class)
+ {
+ $this->class = $class;
+ }
+
+ public function getFile()
+ {
+ return $this->file;
+ }
+
+ public function setFile($file)
+ {
+ $this->file = $file;
+ }
+
+ public function getLine()
+ {
+ return $this->line;
+ }
+
+ public function setLine($line)
+ {
+ $this->line = $line;
+ }
+
+ public function getMessage()
+ {
+ return $this->message;
+ }
+
+ public function setMessage($message)
+ {
+ $this->message = $message;
+ }
+
+ public function getCode()
+ {
+ return $this->code;
+ }
+
+ public function setCode($code)
+ {
+ $this->code = $code;
+ }
+
+ public function getPrevious()
+ {
+ return $this->previous;
+ }
+
+ public function setPrevious(FlattenException $previous)
+ {
+ $this->previous = $previous;
+ }
+
+ public function getAllPrevious()
+ {
+ $exceptions = array();
+ $e = $this;
+ while ($e = $e->getPrevious()) {
+ $exceptions[] = $e;
+ }
+
+ return $exceptions;
+ }
+
+ public function getTrace()
+ {
+ return $this->trace;
+ }
+
+ public function setTraceFromException(\Exception $exception)
+ {
+ $trace = $exception->getTrace();
+
+ if ($exception instanceof FatalErrorException) {
+ if (function_exists('xdebug_get_function_stack')) {
+ $trace = array_slice(array_reverse(xdebug_get_function_stack()), 4);
+
+ foreach ($trace as $i => $frame) {
+ // XDebug pre 2.1.1 doesn't currently set the call type key http://bugs.xdebug.org/view.php?id=695
+ if (!isset($frame['type'])) {
+ $trace[$i]['type'] = '??';
+ }
+
+ if ('dynamic' === $trace[$i]['type']) {
+ $trace[$i]['type'] = '->';
+ } elseif ('static' === $trace[$i]['type']) {
+ $trace[$i]['type'] = '::';
+ }
+
+ // XDebug also has a different name for the parameters array
+ if (isset($frame['params']) && !isset($frame['args'])) {
+ $trace[$i]['args'] = $frame['params'];
+ unset($trace[$i]['params']);
+ }
+ }
+ } else {
+ $trace = array_slice(array_reverse($trace), 1);
+ }
+ }
+
+ $this->setTrace($trace, $exception->getFile(), $exception->getLine());
+ }
+
+ public function setTrace($trace, $file, $line)
+ {
+ $this->trace = array();
+ $this->trace[] = array(
+ 'namespace' => '',
+ 'short_class' => '',
+ 'class' => '',
+ 'type' => '',
+ 'function' => '',
+ 'file' => $file,
+ 'line' => $line,
+ 'args' => array(),
+ );
+ foreach ($trace as $entry) {
+ $class = '';
+ $namespace = '';
+ if (isset($entry['class'])) {
+ $parts = explode('\\', $entry['class']);
+ $class = array_pop($parts);
+ $namespace = implode('\\', $parts);
+ }
+
+ $this->trace[] = array(
+ 'namespace' => $namespace,
+ 'short_class' => $class,
+ 'class' => isset($entry['class']) ? $entry['class'] : '',
+ 'type' => isset($entry['type']) ? $entry['type'] : '',
+ 'function' => isset($entry['function']) ? $entry['function'] : null,
+ 'file' => isset($entry['file']) ? $entry['file'] : null,
+ 'line' => isset($entry['line']) ? $entry['line'] : null,
+ 'args' => isset($entry['args']) ? $this->flattenArgs($entry['args']) : array(),
+ );
+ }
+ }
+
+ private function flattenArgs($args, $level = 0)
+ {
+ $result = array();
+ foreach ($args as $key => $value) {
+ if (is_object($value)) {
+ $result[$key] = array('object', get_class($value));
+ } elseif (is_array($value)) {
+ if ($level > 10) {
+ $result[$key] = array('array', '*DEEP NESTED ARRAY*');
+ } else {
+ $result[$key] = array('array', $this->flattenArgs($value, ++$level));
+ }
+ } elseif (null === $value) {
+ $result[$key] = array('null', null);
+ } elseif (is_bool($value)) {
+ $result[$key] = array('boolean', $value);
+ } elseif (is_resource($value)) {
+ $result[$key] = array('resource', get_resource_type($value));
+ } elseif ($value instanceof \__PHP_Incomplete_Class) {
+ // Special case of object, is_object will return false
+ $result[$key] = array('incomplete-object', $this->getClassNameFromIncomplete($value));
+ } else {
+ $result[$key] = array('string', (string) $value);
+ }
+ }
+
+ return $result;
+ }
+
+ private function getClassNameFromIncomplete(\__PHP_Incomplete_Class $value)
+ {
+ $array = new \ArrayObject($value);
+
+ return $array['__PHP_Incomplete_Class_Name'];
+ }
+}
View
316 src/Symfony/Component/Debug/ExceptionHandler.php
@@ -0,0 +1,316 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Debug;
+
+use Symfony\Component\HttpFoundation\Response;
+use Symfony\Component\Debug\Exception\FlattenException;
+
+if (!defined('ENT_SUBSTITUTE')) {
+ define('ENT_SUBSTITUTE', 8);
+}
+
+/**
+ * ExceptionHandler converts an exception to a Response object.
+ *
+ * It is mostly useful in debug mode to replace the default PHP/XDebug
+ * output with something prettier and more useful.
+ *
+ * As this class is mainly used during Kernel boot, where nothing is yet
+ * available, the Response content is always HTML.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+class ExceptionHandler
+{
+ private $debug;
+ private $charset;
+
+ public function __construct($debug = true, $charset = 'UTF-8')
+ {
+ $this->debug = $debug;
+ $this->charset = $charset;
+ }
+
+ /**
+ * Registers the exception handler.
+ *
+ * @param Boolean $debug
+ *
+ * @return ExceptionHandler The registered exception handler
+ */
+ public static function register($debug = true)
+ {
+ $handler = new static($debug);
+
+ set_exception_handler(array($handler, 'handle'));
+
+ return $handler;
+ }
+
+ /**
+ * Sends a response for the given Exception.
+ *
+ * If you have the Symfony HttpFoundation component installed,
+ * this method will use it to create and send the response. If not,
+ * it will fallback to plain PHP functions.
+ *
+ * @param \Exception $exception An \Exception instance
+ *
+ * @see sendPhpResponse
+ * @see createResponse
+ */
+ public function handle(\Exception $exception)
+ {
+ if (class_exists('Symfony\Component\HttpFoundation\Response')) {
+ $this->createResponse($exception)->send();
+ } else {
+ $this->sendPhpResponse($exception);
+ }
+ }
+
+ /**
+ * Sends the error associated with the given Exception as a plain PHP response.
+ *
+ * This method uses plain PHP functions like header() and echo to output
+ * the response.
+ *
+ * @param \Exception|FlattenException $exception An \Exception instance
+ */
+ public function sendPhpResponse($exception)
+ {
+ if (!$exception instanceof FlattenException) {
+ $exception = FlattenException::create($exception);
+ }
+
+ header(sprintf('HTTP/1.0 %s', $exception->getStatusCode()));
+ foreach ($exception->getHeaders() as $name => $value) {
+ header($name.': '.$value, false);
+ }
+
+ echo $this->decorate($this->getContent($exception), $this->getStylesheet($exception));
+ }
+
+ /**
+ * Creates the error Response associated with the given Exception.
+ *
+ * @param \Exception|FlattenException $exception An \Exception instance
+ *
+ * @return Response A Response instance
+ */
+ public function createResponse($exception)
+ {
+ if (!$exception instanceof FlattenException) {
+ $exception = FlattenException::create($exception);
+ }
+
+ return new Response($this->decorate($this->getContent($exception), $this->getStylesheet($exception)), $exception->getStatusCode(), $exception->getHeaders());
+ }
+
+ /**
+ * Gets the HTML content associated with the given exception.
+ *
+ * @param FlattenException $exception A FlattenException instance
+ *
+ * @return string The content as a string
+ */
+ public function getContent(FlattenException $exception)
+ {
+ switch ($exception->getStatusCode()) {
+ case 404:
+ $title = 'Sorry, the page you are looking for could not be found.';
+ break;
+ default:
+ $title = 'Whoops, looks like something went wrong.';
+ }
+
+ $content = '';
+ if ($this->debug) {
+ try {
+ $count = count($exception->getAllPrevious());
+ $total = $count + 1;
+ foreach ($exception->toArray() as $position => $e) {
+ $ind = $count - $position + 1;
+ $class = $this->abbrClass($e['class']);
+ $message = nl2br($e['message']);
+ $content .= sprintf(<<<EOF
+ <div class="block_exception clear_fix">
+ <h2><span>%d/%d</span> %s: %s</h2>
+ </div>
+ <div class="block">
+ <ol class="traces list_exception">
+
+EOF
+ , $ind, $total, $class, $message);
+ foreach ($e['trace'] as $trace) {
+ $content .= ' <li>';
+ if ($trace['function']) {
+ $content .= sprintf('at %s%s%s(%s)', $this->abbrClass($trace['class']), $trace['type'], $trace['function'], $this->formatArgs($trace['args']));
+ }
+ if (isset($trace['file']) && isset($trace['line'])) {
+ if ($linkFormat = ini_get('xdebug.file_link_format')) {
+ $link = str_replace(array('%f', '%l'), array($trace['file'], $trace['line']), $linkFormat);
+ $content .= sprintf(' in <a href="%s" title="Go to source">%s line %s</a>', $link, $trace['file'], $trace['line']);
+ } else {
+ $content .= sprintf(' in %s line %s', $trace['file'], $trace['line']);
+ }
+ }
+ $content .= "</li>\n";
+ }
+
+ $content .= " </ol>\n</div>\n";
+ }
+ } catch (\Exception $e) {
+ // something nasty happened and we cannot throw an exception anymore
+ if ($this->debug) {
+ $title = sprintf('Exception thrown when handling an exception (%s: %s)', get_class($exception), $exception->getMessage());
+ } else {
+ $title = 'Whoops, looks like something went wrong.';
+ }
+ }
+ }
+
+ return <<<EOF
+ <div id="sf-resetcontent" class="sf-reset">
+ <h1>$title</h1>
+ $content
+ </div>
+EOF;
+ }
+
+ /**
+ * Gets the stylesheet associated with the given exception.
+ *
+ * @param FlattenException $exception A FlattenException instance
+ *
+ * @return string The stylesheet as a string
+ */
+ public function getStylesheet(FlattenException $exception)
+ {
+ return <<<EOF
+ .sf-reset { font: 11px Verdana, Arial, sans-serif; color: #333 }
+ .sf-reset .clear { clear:both; height:0; font-size:0; line-height:0; }
+ .sf-reset .clear_fix:after { display:block; height:0; clear:both; visibility:hidden; }
+ .sf-reset .clear_fix { display:inline-block; }
+ .sf-reset * html .clear_fix { height:1%; }
+ .sf-reset .clear_fix { display:block; }
+ .sf-reset, .sf-reset .block { margin: auto }
+ .sf-reset abbr { border-bottom: 1px dotted #000; cursor: help; }
+ .sf-reset p { font-size:14px; line-height:20px; color:#868686; padding-bottom:20px }
+ .sf-reset strong { font-weight:bold; }
+ .sf-reset a { color:#6c6159; }
+ .sf-reset a img { border:none; }
+ .sf-reset a:hover { text-decoration:underline; }
+ .sf-reset em { font-style:italic; }
+ .sf-reset h1, .sf-reset h2 { font: 20px Georgia, "Times New Roman", Times, serif }
+ .sf-reset h2 span { background-color: #fff; color: #333; padding: 6px; float: left; margin-right: 10px; }
+ .sf-reset .traces li { font-size:12px; padding: 2px 4px; list-style-type:decimal; margin-left:20px; }
+ .sf-reset .block { background-color:#FFFFFF; padding:10px 28px; margin-bottom:20px;
+ -webkit-border-bottom-right-radius: 16px;
+ -webkit-border-bottom-left-radius: 16px;
+ -moz-border-radius-bottomright: 16px;
+ -moz-border-radius-bottomleft: 16px;
+ border-bottom-right-radius: 16px;
+ border-bottom-left-radius: 16px;
+ border-bottom:1px solid #ccc;
+ border-right:1px solid #ccc;
+ border-left:1px solid #ccc;
+ }
+ .sf-reset .block_exception { background-color:#ddd; color: #333; padding:20px;
+ -webkit-border-top-left-radius: 16px;
+ -webkit-border-top-right-radius: 16px;
+ -moz-border-radius-topleft: 16px;
+ -moz-border-radius-topright: 16px;
+ border-top-left-radius: 16px;
+ border-top-right-radius: 16px;
+ border-top:1px solid #ccc;
+ border-right:1px solid #ccc;
+ border-left:1px solid #ccc;
+ overflow: hidden;
+ word-wrap: break-word;
+ }
+ .sf-reset li a { background:none; color:#868686; text-decoration:none; }
+ .sf-reset li a:hover { background:none; color:#313131; text-decoration:underline; }
+ .sf-reset ol { padding: 10px 0; }
+ .sf-reset h1 { background-color:#FFFFFF; padding: 15px 28px; margin-bottom: 20px;
+ -webkit-border-radius: 10px;
+ -moz-border-radius: 10px;
+ border-radius: 10px;
+ border: 1px solid #ccc;
+ }
+EOF;
+ }
+
+ private function decorate($content, $css)
+ {
+ return <<<EOF
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+ <meta name="robots" content="noindex,nofollow" />
+ <style>
+ /* Copyright (c) 2010, Yahoo! Inc. All rights reserved. Code licensed under the BSD License: http://developer.yahoo.com/yui/license.html */
+ html{color:#000;background:#FFF;}body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,code,form,fieldset,legend,input,textarea,p,blockquote,th,td{margin:0;padding:0;}table{border-collapse:collapse;border-spacing:0;}fieldset,img{border:0;}address,caption,cite,code,dfn,em,strong,th,var{font-style:normal;font-weight:normal;}li{list-style:none;}caption,th{text-align:left;}h1,h2,h3,h4,h5,h6{font-size:100%;font-weight:normal;}q:before,q:after{content:'';}abbr,acronym{border:0;font-variant:normal;}sup{vertical-align:text-top;}sub{vertical-align:text-bottom;}input,textarea,select{font-family:inherit;font-size:inherit;font-weight:inherit;}input,textarea,select{*font-size:100%;}legend{color:#000;}
+
+ html { background: #eee; padding: 10px }
+ img { border: 0; }
+ #sf-resetcontent { width:970px; margin:0 auto; }
+ $css
+ </style>
+ </head>
+ <body>
+ $content
+ </body>
+</html>
+EOF;
+ }
+
+ private function abbrClass($class)
+ {
+ $parts = explode('\\', $class);
+
+ return sprintf("<abbr title=\"%s\">%s</abbr>", $class, array_pop($parts));
+ }
+
+ /**
+ * Formats an array as a string.
+ *
+ * @param array $args The argument array
+ *
+ * @return string
+ */
+ private function formatArgs(array $args)
+ {
+ $result = array();
+ foreach ($args as $key => $item) {
+ if ('object' === $item[0]) {
+ $formattedValue = sprintf("<em>object</em>(%s)", $this->abbrClass($item[1]));
+ } elseif ('array' === $item[0]) {
+ $formattedValue = sprintf("<em>array</em>(%s)", is_array($item[1]) ? $this->formatArgs($item[1]) : $item[1]);
+ } elseif ('string' === $item[0]) {
+ $formattedValue = sprintf("'%s'", htmlspecialchars($item[1], ENT_QUOTES | ENT_SUBSTITUTE, $this->charset));
+ } elseif ('null' === $item[0]) {
+ $formattedValue = '<em>null</em>';
+ } elseif ('boolean' === $item[0]) {
+ $formattedValue = '<em>'.strtolower(var_export($item[1], true)).'</em>';
+ } elseif ('resource' === $item[0]) {
+ $formattedValue = '<em>resource</em>';
+ } else {
+ $formattedValue = str_replace("\n", '', var_export(htmlspecialchars((string) $item[1], ENT_QUOTES | ENT_SUBSTITUTE, $this->charset), true));
+ }
+
+ $result[] = is_int($key) ? $formattedValue : sprintf("'%s' => %s", $key, $formattedValue);
+ }
+
+ return implode(', ', $result);
+ }
+}
View
19 src/Symfony/Component/Debug/LICENSE
@@ -0,0 +1,19 @@
+Copyright (c) 2004-2013 Fabien Potencier
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is furnished
+to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
View
40 src/Symfony/Component/Debug/README.md
@@ -0,0 +1,40 @@
+Debug Component
+===============
+
+Debug provides tools to make debugging easier.
+
+Enabling all debug tools is as easy as calling the `enable()` method on the
+main `Debug` class:
+
+ use Symfony\Component\Debug\Debug;
+
+ Debug::enable();
+
+You can also use the tools individually:
+
+ use Symfony\Component\Debug\ErrorHandler;
+ use Symfony\Component\Debug\ExceptionHandler;
+
+ error_reporting(-1);
+
+ ErrorHandler::register($errorReportingLevel);
+ if ('cli' !== php_sapi_name()) {
+ ExceptionHandler::register();
+ } elseif (!ini_get('log_errors') || ini_get('error_log')) {
+ ini_set('display_errors', 1);
+ }
+
+Note that the `Debug::enable()` call also registers the debug class loader
+from the Symfony ClassLoader component when available.
+
+This component can optionally take advantage of the features of the HttpKernel
+and HttpFoundation components.
+
+Resources
+---------
+
+You can run the unit tests with the following command:
+
+ $ cd path/to/Symfony/Component/Debug/
+ $ composer.phar install --dev
+ $ phpunit
View
4 ...tpKernel/Tests/Debug/ErrorHandlerTest.php → ...omponent/Debug/Tests/ErrorHandlerTest.php
@@ -9,9 +9,9 @@
* file that was distributed with this source code.
*/
-namespace Symfony\Component\HttpKernel\Tests\Debug;
+namespace Symfony\Component\Debug\Tests;
-use Symfony\Component\HttpKernel\Debug\ErrorHandler;
+use Symfony\Component\Debug\ErrorHandler;
/**
* ErrorHandlerTest
View
4 .../Tests/Exception/FlattenExceptionTest.php → .../Tests/Exception/FlattenExceptionTest.php
@@ -9,9 +9,9 @@
* file that was distributed with this source code.
*/
-namespace Symfony\Component\HttpKernel\Tests\Exception;
+namespace Symfony\Component\Debug\Tests\Exception;
-use Symfony\Component\HttpKernel\Exception\FlattenException;
+use Symfony\Component\Debug\Exception\FlattenException;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException;
use Symfony\Component\HttpKernel\Exception\UnauthorizedHttpException;
View
4 ...rnel/Tests/Debug/ExceptionHandlerTest.php → ...nent/Debug/Tests/ExceptionHandlerTest.php
@@ -9,9 +9,9 @@
* file that was distributed with this source code.
*/
-namespace Symfony\Component\HttpKernel\Tests\Debug;
+namespace Symfony\Component\Debug\Tests;
-use Symfony\Component\HttpKernel\Debug\ExceptionHandler;
+use Symfony\Component\Debug\ExceptionHandler;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException;
View
40 src/Symfony/Component/Debug/composer.json
@@ -0,0 +1,40 @@
+{
+ "name": "symfony/debug",
+ "type": "library",
+ "description": "Symfony Debug Component",
+ "keywords": [],
+ "homepage": "http://symfony.com",
+ "license": "MIT",
+ "authors": [
+ {
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "http://symfony.com/contributors"
+ }
+ ],
+ "require": {
+ "php": ">=5.3.3"
+ },
+ "require-dev": {
+ "symfony/http-kernel": "~2.1",
+ "symfony/http-foundation": "~2.1"
+ },
+ "suggest": {
+ "symfony/http-foundation": "~2.1",
+ "symfony/http-kernel": "~2.1",
+ "symfony/class-loader": "~2.1"
+ },
+ "autoload": {
+ "psr-0": { "Symfony\\Component\\Debug\\": "" }
+ },
+ "target-dir": "Symfony/Component/Debug",
+ "minimum-stability": "dev",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.3-dev"
+ }
+ }
+}
View
29 src/Symfony/Component/Debug/phpunit.xml.dist
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<phpunit backupGlobals="false"
+ backupStaticAttributes="false"
+ colors="true"
+ convertErrorsToExceptions="true"
+ convertNoticesToExceptions="true"
+ convertWarningsToExceptions="true"
+ processIsolation="false"
+ stopOnFailure="false"
+ syntaxCheck="false"
+ bootstrap="vendor/autoload.php"
+>
+ <testsuites>
+ <testsuite name="Symfony Debug Component Test Suite">
+ <directory>./Tests/</directory>
+ </testsuite>
+ </testsuites>
+
+ <filter>
+ <whitelist>
+ <directory>./</directory>
+ <exclude>
+ <directory>./Tests</directory>
+ <directory>./vendor</directory>
+ </exclude>
+ </whitelist>
+ </filter>
+</phpunit>
View
3 src/Symfony/Component/HttpKernel/CHANGELOG.md
@@ -4,6 +4,9 @@ CHANGELOG
2.3.0
-----
+ * deprecated `Symfony\Component\HttpKernel\Debug\ErrorHandler`, `Symfony\Component\HttpKernel\Debug\ExceptionHandler`,
+ `Symfony\Component\HttpKernel\Exception\FatalErrorException`, and `Symfony\Component\HttpKernel\Exception\FlattenException`
+ * deprecated `Symfony\Component\HttpKernel\Kernel::init()``
* added the possibility to specify an id an extra attributes to hinclude tags
* added the collect of data if a controller is a Closure in the Request collector
View
111 src/Symfony/Component/HttpKernel/Debug/ErrorHandler.php
@@ -11,118 +11,15 @@
namespace Symfony\Component\HttpKernel\Debug;
-use Symfony\Component\HttpKernel\Exception\FatalErrorException;
-use Psr\Log\LoggerInterface;
+use Symfony\Component\Debug\ErrorHandler as DebugErrorHandler;
/**
* ErrorHandler.
*
* @author Fabien Potencier <fabien@symfony.com>
+ *
+ * @deprecated Deprecated in 2.3, to be removed in 3.0. Use the same class from the Debug component instead.
*/
-class ErrorHandler
+class ErrorHandler extends DebugErrorHandler
{
- const TYPE_DEPRECATION = -100;
-
- private $levels = array(
- E_WARNING => 'Warning',
- E_NOTICE => 'Notice',
- E_USER_ERROR => 'User Error',
- E_USER_WARNING => 'User Warning',
- E_USER_NOTICE => 'User Notice',
- E_STRICT => 'Runtime Notice',
- E_RECOVERABLE_ERROR => 'Catchable Fatal Error',
- E_DEPRECATED => 'Deprecated',
- E_USER_DEPRECATED => 'User Deprecated',
- E_ERROR => 'Error',
- E_CORE_ERROR => 'Core Error',
- E_COMPILE_ERROR => 'Compile Error',
- E_PARSE => 'Parse',
- );
-
- private $level;
-
- private $reservedMemory;
-
- /** @var LoggerInterface */
- private static $logger;
-
- /**
- * Register the error handler.
- *
- * @param integer $level The level at which the conversion to Exception is done (null to use the error_reporting() value and 0 to disable)
- *
- * @return The registered error handler
- */
- public static function register($level = null)
- {
- $handler = new static();
- $handler->setLevel($level);
-
- ini_set('display_errors', 0);
- set_error_handler(array($handler, 'handle'));
- register_shutdown_function(array($handler, 'handleFatal'));
- $handler->reservedMemory = str_repeat('x', 10240);
-
- return $handler;
- }
-
- public function setLevel($level)
- {
- $this->level = null === $level ? error_reporting() : $level;
- }
-
- public static function setLogger(LoggerInterface $logger)
- {
- self::$logger = $logger;
- }
-
- /**
- * @throws \ErrorException When error_reporting returns error
- */
- public function handle($level, $message, $file, $line, $context)
- {
- if (0 === $this->level) {
- return false;
- }
-
- if ($level & (E_USER_DEPRECATED | E_DEPRECATED)) {
- if (null !== self::$logger) {
- $stack = version_compare(PHP_VERSION, '5.4', '<') ? array_slice(debug_backtrace(false), 0, 10) : debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 10);
-
- self::$logger->warning($message, array('type' => self::TYPE_DEPRECATION, 'stack' => $stack));
- }
-
- return true;
- }
-
- if (error_reporting() & $level && $this->level & $level) {
- throw new \ErrorException(sprintf('%s: %s in %s line %d', isset($this->levels[$level]) ? $this->levels[$level] : $level, $message, $file, $line), 0, $level, $file, $line);
- }
-
- return false;
- }
-
- public function handleFatal()
- {
- if (null === $error = error_get_last()) {
- return;
- }
-
- unset($this->reservedMemory);
- $type = $error['type'];
- if (0 === $this->level || !in_array($type, array(E_ERROR, E_CORE_ERROR, E_COMPILE_ERROR, E_PARSE))) {
- return;
- }
-
- // get current exception handler
- $exceptionHandler = set_exception_handler(function() {});
- restore_exception_handler();
-
- if (is_array($exceptionHandler) && $exceptionHandler[0] instanceof ExceptionHandler) {
- $level = isset($this->levels[$type]) ? $this->levels[$type] : $type;
- $message = sprintf('%s: %s in %s line %d', $level, $error['message'], $error['file'], $error['line']);
- $exception = new FatalErrorException($message, 0, $type, $error['file'], $error['line']);
- $exceptionHandler[0]->handle($exception);
- }
- }
}
View
266 src/Symfony/Component/HttpKernel/Debug/ExceptionHandler.php
@@ -11,273 +11,15 @@
namespace Symfony\Component\HttpKernel\Debug;
-use Symfony\Component\HttpFoundation\Response;
-use Symfony\Component\HttpKernel\Exception\FlattenException;
-
-if (!defined('ENT_SUBSTITUTE')) {
- define('ENT_SUBSTITUTE', 8);
-}
+use Symfony\Component\Debug\ExceptionHandler as DebugExceptionHandler;
/**
* ExceptionHandler converts an exception to a Response object.
*
- * It is mostly useful in debug mode to replace the default PHP/XDebug
- * output with something prettier and more useful.
- *
- * As this class is mainly used during Kernel boot, where nothing is yet
- * available, the Response content is always HTML.
- *
* @author Fabien Potencier <fabien@symfony.com>
+ *
+ * @deprecated Deprecated in 2.3, to be removed in 3.0. Use the same class from the Debug component instead.
*/
-class ExceptionHandler
+class ExceptionHandler extends DebugExceptionHandler
{
- private $debug;
- private $charset;
-
- public function __construct($debug = true, $charset = 'UTF-8')
- {
- $this->debug = $debug;
- $this->charset = $charset;
- }
-
- /**
- * Register the exception handler.
- *
- * @param Boolean $debug
- *
- * @return ExceptionHandler The registered exception handler
- */
- public static function register($debug = true)
- {
- $handler = new static($debug);
-
- set_exception_handler(array($handler, 'handle'));
-
- return $handler;
- }
-
- /**
- * Sends a Response for the given Exception.
- *
- * @param \Exception $exception An \Exception instance
- */
- public function handle(\Exception $exception)
- {
- $this->createResponse($exception)->send();
- }
-
- /**
- * Creates the error Response associated with the given Exception.
- *
- * @param \Exception|FlattenException $exception An \Exception instance
- *
- * @return Response A Response instance
- */
- public function createResponse($exception)
- {
- if (!$exception instanceof FlattenException) {
- $exception = FlattenException::create($exception);
- }
-
- return new Response($this->decorate($this->getContent($exception), $this->getStylesheet($exception)), $exception->getStatusCode(), $exception->getHeaders());
- }
-
- /**
- * Gets the HTML content associated with the given exception.
- *
- * @param FlattenException $exception A FlattenException instance
- *
- * @return string The content as a string
- */
- public function getContent(FlattenException $exception)
- {
- switch ($exception->getStatusCode()) {
- case 404:
- $title = 'Sorry, the page you are looking for could not be found.';
- break;
- default:
- $title = 'Whoops, looks like something went wrong.';
- }
-
- $content = '';
- if ($this->debug) {
- try {
- $count = count($exception->getAllPrevious());
- $total = $count + 1;
- foreach ($exception->toArray() as $position => $e) {
- $ind = $count - $position + 1;
- $class = $this->abbrClass($e['class']);
- $message = nl2br($e['message']);
- $content .= sprintf(<<<EOF
- <div class="block_exception clear_fix">
- <h2><span>%d/%d</span> %s: %s</h2>
- </div>
- <div class="block">
- <ol class="traces list_exception">
-
-EOF
- , $ind, $total, $class, $message);
- foreach ($e['trace'] as $trace) {
- $content .= ' <li>';
- if ($trace['function']) {
- $content .= sprintf('at %s%s%s(%s)', $this->abbrClass($trace['class']), $trace['type'], $trace['function'], $this->formatArgs($trace['args']));
- }
- if (isset($trace['file']) && isset($trace['line'])) {
- if ($linkFormat = ini_get('xdebug.file_link_format')) {
- $link = str_replace(array('%f', '%l'), array($trace['file'], $trace['line']), $linkFormat);
- $content .= sprintf(' in <a href="%s" title="Go to source">%s line %s</a>', $link, $trace['file'], $trace['line']);
- } else {
- $content .= sprintf(' in %s line %s', $trace['file'], $trace['line']);
- }
- }
- $content .= "</li>\n";
- }
-
- $content .= " </ol>\n</div>\n";
- }
- } catch (\Exception $e) {
- // something nasty happened and we cannot throw an exception anymore
- if ($this->debug) {
- $title = sprintf('Exception thrown when handling an exception (%s: %s)', get_class($exception), $exception->getMessage());
- } else {
- $title = 'Whoops, looks like something went wrong.';
- }
- }
- }
-
- return <<<EOF
- <div id="sf-resetcontent" class="sf-reset">
- <h1>$title</h1>
- $content
- </div>
-EOF;
- }
-
- /**
- * Gets the stylesheet associated with the given exception.
- *
- * @param FlattenException $exception A FlattenException instance
- *
- * @return string The stylesheet as a string
- */
- public function getStylesheet(FlattenException $exception)
- {
- return <<<EOF
- .sf-reset { font: 11px Verdana, Arial, sans-serif; color: #333 }
- .sf-reset .clear { clear:both; height:0; font-size:0; line-height:0; }
- .sf-reset .clear_fix:after { display:block; height:0; clear:both; visibility:hidden; }
- .sf-reset .clear_fix { display:inline-block; }
- .sf-reset * html .clear_fix { height:1%; }
- .sf-reset .clear_fix { display:block; }
- .sf-reset, .sf-reset .block { margin: auto }
- .sf-reset abbr { border-bottom: 1px dotted #000; cursor: help; }
- .sf-reset p { font-size:14px; line-height:20px; color:#868686; padding-bottom:20px }
- .sf-reset strong { font-weight:bold; }
- .sf-reset a { color:#6c6159; }
- .sf-reset a img { border:none; }
- .sf-reset a:hover { text-decoration:underline; }
- .sf-reset em { font-style:italic; }
- .sf-reset h1, .sf-reset h2 { font: 20px Georgia, "Times New Roman", Times, serif }
- .sf-reset h2 span { background-color: #fff; color: #333; padding: 6px; float: left; margin-right: 10px; }
- .sf-reset .traces li { font-size:12px; padding: 2px 4px; list-style-type:decimal; margin-left:20px; }
- .sf-reset .block { background-color:#FFFFFF; padding:10px 28px; margin-bottom:20px;
- -webkit-border-bottom-right-radius: 16px;
- -webkit-border-bottom-left-radius: 16px;
- -moz-border-radius-bottomright: 16px;
- -moz-border-radius-bottomleft: 16px;
- border-bottom-right-radius: 16px;
- border-bottom-left-radius: 16px;
- border-bottom:1px solid #ccc;
- border-right:1px solid #ccc;
- border-left:1px solid #ccc;
- }
- .sf-reset .block_exception { background-color:#ddd; color: #333; padding:20px;
- -webkit-border-top-left-radius: 16px;
- -webkit-border-top-right-radius: 16px;
- -moz-border-radius-topleft: 16px;
- -moz-border-radius-topright: 16px;
- border-top-left-radius: 16px;
- border-top-right-radius: 16px;
- border-top:1px solid #ccc;
- border-right:1px solid #ccc;
- border-left:1px solid #ccc;
- overflow: hidden;
- word-wrap: break-word;
- }
- .sf-reset li a { background:none; color:#868686; text-decoration:none; }
- .sf-reset li a:hover { background:none; color:#313131; text-decoration:underline; }
- .sf-reset ol { padding: 10px 0; }
- .sf-reset h1 { background-color:#FFFFFF; padding: 15px 28px; margin-bottom: 20px;
- -webkit-border-radius: 10px;
- -moz-border-radius: 10px;
- border-radius: 10px;
- border: 1px solid #ccc;
- }
-EOF;
- }
-
- private function decorate($content, $css)
- {
- return <<<EOF
-<!DOCTYPE html>
-<html>
- <head>
- <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
- <meta name="robots" content="noindex,nofollow" />
- <style>
- /* Copyright (c) 2010, Yahoo! Inc. All rights reserved. Code licensed under the BSD License: http://developer.yahoo.com/yui/license.html */
- html{color:#000;background:#FFF;}body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,code,form,fieldset,legend,input,textarea,p,blockquote,th,td{margin:0;padding:0;}table{border-collapse:collapse;border-spacing:0;}fieldset,img{border:0;}address,caption,cite,code,dfn,em,strong,th,var{font-style:normal;font-weight:normal;}li{list-style:none;}caption,th{text-align:left;}h1,h2,h3,h4,h5,h6{font-size:100%;font-weight:normal;}q:before,q:after{content:'';}abbr,acronym{border:0;font-variant:normal;}sup{vertical-align:text-top;}sub{vertical-align:text-bottom;}input,textarea,select{font-family:inherit;font-size:inherit;font-weight:inherit;}input,textarea,select{*font-size:100%;}legend{color:#000;}
-
- html { background: #eee; padding: 10px }
- img { border: 0; }
- #sf-resetcontent { width:970px; margin:0 auto; }
- $css
- </style>
- </head>
- <body>
- $content
- </body>
-</html>
-EOF;
- }
-
- private function abbrClass($class)
- {
- $parts = explode('\\', $class);
-
- return sprintf("<abbr title=\"%s\">%s</abbr>", $class, array_pop($parts));
- }
-
- /**
- * Formats an array as a string.
- *
- * @param array $args The argument array
- *
- * @return string
- */
- private function formatArgs(array $args)
- {
- $result = array();
- foreach ($args as $key => $item) {
- if ('object' === $item[0]) {
- $formattedValue = sprintf("<em>object</em>(%s)", $this->abbrClass($item[1]));
- } elseif ('array' === $item[0]) {
- $formattedValue = sprintf("<em>array</em>(%s)", is_array($item[1]) ? $this->formatArgs($item[1]) : $item[1]);
- } elseif ('string' === $item[0]) {
- $formattedValue = sprintf("'%s'", htmlspecialchars($item[1], ENT_QUOTES | ENT_SUBSTITUTE, $this->charset));
- } elseif ('null' === $item[0]) {
- $formattedValue = '<em>null</em>';
- } elseif ('boolean' === $item[0]) {
- $formattedValue = '<em>'.strtolower(var_export($item[1], true)).'</em>';
- } elseif ('resource' === $item[0]) {
- $formattedValue = '<em>resource</em>';
- } else {
- $formattedValue = str_replace("\n", '', var_export(htmlspecialchars((string) $item[1], ENT_QUOTES | ENT_SUBSTITUTE, $this->charset), true));
- }
-
- $result[] = is_int($key) ? $formattedValue : sprintf("'%s' => %s", $key, $formattedValue);
- }
-
- return implode(', ', $result);
- }
}
View
7 src/Symfony/Component/HttpKernel/Exception/FatalErrorException.php
@@ -11,12 +11,15 @@
namespace Symfony\Component\HttpKernel\Exception;
+use Symfony\Component\Debug\Exception\FatalErrorException as DebugFatalErrorException;
+
/**
* Fatal Error Exception.
*
* @author Konstanton Myakshin <koc-dp@yandex.ru>
+ *
+ * @deprecated Deprecated in 2.3, to be removed in 3.0. Use the same class from the Debug component instead.
*/
-class FatalErrorException extends \ErrorException
+class FatalErrorException extends DebugFatalErrorException
{
-
}
View
258 src/Symfony/Component/HttpKernel/Exception/FlattenException.php
@@ -11,265 +11,17 @@
namespace Symfony\Component\HttpKernel\Exception;
+use Symfony\Component\Debug\Exception\FlattenException as DebugFlattenException;
+
/**
* FlattenException wraps a PHP Exception to be able to serialize it.
*
* Basically, this class removes all objects from the trace.
*
* @author Fabien Potencier <fabien@symfony.com>
+ *
+ * @deprecated Deprecated in 2.3, to be removed in 3.0. Use the same class from the Debug component instead.
*/
-class FlattenException
+class FlattenException extends DebugFlattenException
{
- private $message;
- private $code;
- private $previous;
- private $trace;
- private $class;
- private $statusCode;
- private $headers;
- private $file;
- private $line;
-
- public static function create(\Exception $exception, $statusCode = null, array $headers = array())
- {
- $e = new static();
- $e->setMessage($exception->getMessage());
- $e->setCode($exception->getCode());
-
- if ($exception instanceof HttpExceptionInterface) {
- $statusCode = $exception->getStatusCode();
- $headers = array_merge($headers, $exception->getHeaders());
- }
-
- if (null === $statusCode) {
- $statusCode = 500;
- }
-
- $e->setStatusCode($statusCode);
- $e->setHeaders($headers);
- $e->setTraceFromException($exception);
- $e->setClass(get_class($exception));
- $e->setFile($exception->getFile());
- $e->setLine($exception->getLine());
- if ($exception->getPrevious()) {
- $e->setPrevious(static::create($exception->getPrevious()));
- }
-
- return $e;
- }
-
- public function toArray()
- {
- $exceptions = array();
- foreach (array_merge(array($this), $this->getAllPrevious()) as $exception) {
- $exceptions[] = array(
- 'message' => $exception->getMessage(),
- 'class' => $exception->getClass(),
- 'trace' => $exception->getTrace(),
- );
- }
-
- return $exceptions;
- }
-
- public function getStatusCode()
- {
- return $this->statusCode;
- }
-
- public function setStatusCode($code)
- {
- $this->statusCode = $code;
- }
-
- public function getHeaders()
- {
- return $this->headers;
- }
-
- public function setHeaders(array $headers)
- {
- $this->headers = $headers;
- }
-
- public function getClass()
- {
- return $this->class;
- }
-
- public function setClass($class)
- {
- $this->class = $class;
- }
-
- public function getFile()
- {
- return $this->file;
- }
-
- public function setFile($file)
- {
- $this->file = $file;
- }
-
- public function getLine()
- {
- return $this->line;
- }
-
- public function setLine($line)
- {
- $this->line = $line;
- }
-
- public function getMessage()
- {
- return $this->message;
- }
-
- public function setMessage($message)
- {
- $this->message = $message;
- }
-
- public function getCode()
- {
- return $this->code;
- }
-
- public function setCode($code)
- {
- $this->code = $code;
- }
-
- public function getPrevious()
- {
- return $this->previous;
- }
-
- public function setPrevious(FlattenException $previous)
- {
- $this->previous = $previous;
- }
-
- public function getAllPrevious()
- {
- $exceptions = array();
- $e = $this;
- while ($e = $e->getPrevious()) {
- $exceptions[] = $e;
- }
-
- return $exceptions;
- }
-
- public function getTrace()
- {
- return $this->trace;
- }
-
- public function setTraceFromException(\Exception $exception)
- {
- $trace = $exception->getTrace();
-
- if ($exception instanceof FatalErrorException) {
- if (function_exists('xdebug_get_function_stack')) {
- $trace = array_slice(array_reverse(xdebug_get_function_stack()), 4);
-
- foreach ($trace as $i => $frame) {
- // XDebug pre 2.1.1 doesn't currently set the call type key http://bugs.xdebug.org/view.php?id=695
- if (!isset($frame['type'])) {
- $trace[$i]['type'] = '??';
- }
-
- if ('dynamic' === $trace[$i]['type']) {
- $trace[$i]['type'] = '->';
- } elseif ('static' === $trace[$i]['type']) {
- $trace[$i]['type'] = '::';
- }
-
- // XDebug also has a different name for the parameters array
- if (isset($frame['params']) && !isset($frame['args'])) {
- $trace[$i]['args'] = $frame['params'];
- unset($trace[$i]['params']);
- }
- }
- } else {
- $trace = array_slice(array_reverse($trace), 1);
- }
- }
-
- $this->setTrace($trace, $exception->getFile(), $exception->getLine());
- }
-
- public function setTrace($trace, $file, $line)
- {
- $this->trace = array();
- $this->trace[] = array(
- 'namespace' => '',
- 'short_class' => '',
- 'class' => '',
- 'type' => '',
- 'function' => '',
- 'file' => $file,
- 'line' => $line,
- 'args' => array(),
- );
- foreach ($trace as $entry) {
- $class = '';
- $namespace = '';
- if (isset($entry['class'])) {
- $parts = explode('\\', $entry['class']);
- $class = array_pop($parts);
- $namespace = implode('\\', $parts);
- }
-
- $this->trace[] = array(
- 'namespace' => $namespace,
- 'short_class' => $class,
- 'class' => isset($entry['class']) ? $entry['class'] : '',
- 'type' => isset($entry['type']) ? $entry['type'] : '',
- 'function' => isset($entry['function']) ? $entry['function'] : null,
- 'file' => isset($entry['file']) ? $entry['file'] : null,
- 'line' => isset($entry['line']) ? $entry['line'] : null,
- 'args' => isset($entry['args']) ? $this->flattenArgs($entry['args']) : array(),
- );
- }
- }
-
- private function flattenArgs($args, $level = 0)
- {
- $result = array();
- foreach ($args as $key => $value) {
- if (is_object($value)) {
- $result[$key] = array('object', get_class($value));
- } elseif (is_array($value)) {
- if ($level > 10) {
- $result[$key] = array('array', '*DEEP NESTED ARRAY*');
- } else {
- $result[$key] = array('array', $this->flattenArgs($value, ++$level));
- }
- } elseif (null === $value) {
- $result[$key] = array('null', null);
- } elseif (is_bool($value)) {
- $result[$key] = array('boolean', $value);
- } elseif (is_resource($value)) {
- $result[$key] = array('resource', get_resource_type($value));
- } elseif ($value instanceof \__PHP_Incomplete_Class) {
- // Special case of object, is_object will return false
- $result[$key] = array('incomplete-object', $this->getClassNameFromIncomplete($value));
- } else {
- $result[$key] = array('string', (string) $value);
- }
- }
-
- return $result;
- }
-
- private function getClassNameFromIncomplete(\__PHP_Incomplete_Class $value)
- {
- $array = new \ArrayObject($value);
-
- return $array['__PHP_Incomplete_Class_Name'];
- }
}
View
20 src/Symfony/Component/HttpKernel/Kernel.php
@@ -27,13 +27,10 @@
use Symfony\Component\HttpKernel\Config\FileLocator;
use Symfony\Component\HttpKernel\DependencyInjection\MergeExtensionConfigurationPass;
use Symfony\Component\HttpKernel\DependencyInjection\AddClassesToCachePass;
-use Symfony\Component\HttpKernel\Debug\ErrorHandler;
-use Symfony\Component\HttpKernel\Debug\ExceptionHandler;
use Symfony\Component\Config\Loader\LoaderResolver;
use Symfony\Component\Config\Loader\DelegatingLoader;
use Symfony\Component\Config\ConfigCache;
use Symfony\Component\ClassLoader\ClassCollectionLoader;
-use Symfony\Component\ClassLoader\DebugClassLoader;
/**
* The Kernel is the heart of the Symfony system.
@@ -60,7 +57,6 @@
protected $name;
protected $startTime;
protected $classes;
- protected $errorReportingLevel;
const VERSION = '2.3.0-DEV';
const VERSION_ID = '20300';
@@ -94,21 +90,11 @@ public function __construct($environment, $debug)
$this->init();
}
+ /**
+ * @deprecated Deprecated since version 2.3, to be removed in 3.0. Move your logic in the constructor instead.
+ */
public function init()
{
- ini_set('display_errors', 0);
-
- if ($this->debug) {
- error_reporting(-1);
-
- DebugClassLoader::enable();
- ErrorHandler::register($this->errorReportingLevel);
- if ('cli' !== php_sapi_name()) {
- ExceptionHandler::register();
- } elseif (!ini_get('log_errors') || ini_get('error_log')) {
- ini_set('display_errors', 1);
- }
- }
}
public function __clone()

0 comments on commit 6d552c9

Please sign in to comment.
Something went wrong with that request. Please try again.