Compare commits

..

57 Commits

Author SHA1 Message Date
Nicolas Grekas
8bc9390ba3 [Debug 2.3] Fix test for PHP7 2015-05-06 12:13:27 +02:00
Christian Flothmann
95a5aa2b72 link to https://symfony.com where possible 2015-05-01 16:06:45 +02:00
Dariusz Ruminski
9cd1287f00 CS fixes 2015-04-16 09:01:03 +02:00
Dariusz Ruminski
796dd4cd11 CS: Convert double quotes to single quotes 2015-03-21 12:11:30 +01:00
Fabien Potencier
3e889e0489 bug #13901 [Bundle] Fix charset config (nicolas-grekas, bamarni)
This PR was merged into the 2.3 branch.

Discussion
----------

[Bundle] Fix charset config

| Q             | A
| ------------- | ---
| Bug fix?      | yes
| New feature?  | no
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | #13715, #7617, #7532
| License       | MIT
| Doc PR        | -

This reverts #13715 and resurrects #7532, which was fine.

Commits
-------

ef41059 [WebProfilerBundle] Set debug+charset on the ExceptionHandler fallback
cbd0525 used HTML5 meta charset tag and removed hardcoded ones
6ca7fc9 Revert "bug #13715 Enforce UTF-8 charset for core controllers (WouterJ)"
2015-03-12 15:23:35 +01:00
sarah khalil
dfb9bf2e04 Changed visibility of setUp() and tearDown to protected 2015-03-11 19:52:02 +01:00
Nicolas Grekas
29a6fd38f3 [WebProfilerBundle] Set debug+charset on the ExceptionHandler fallback 2015-03-11 17:56:24 +01:00
Fabien Potencier
712c58246b fixed XSS in the exception handler 2015-03-10 14:08:39 +01:00
Nicolas Grekas
4ba2bda995 [2.3] require-dev PHPUnit bridge 2015-02-24 11:24:26 +01:00
Fabien Potencier
24170a0eb7 renamed composer.phar to composer to be consistent with the Symfony docs 2015-02-08 08:41:14 +01:00
Fabien Potencier
b7c4104ea0 removed composer --dev option everywhere 2015-02-08 08:33:54 +01:00
Nicolas Grekas
ee29381719 [Debug] fix loading order for legacy classes 2015-01-15 13:58:08 +01:00
Nicolas Grekas
028a28b024 [Debug] add missing conflict dep rules 2015-01-13 10:04:07 +01:00
Nicolas Grekas
6e5c2b9e1f [2.3] Fix lowest deps 2015-01-03 19:20:28 +01:00
Fabien Potencier
bc5a43ca7c minor #13206 [2.3] Cleanup deprecations (nicolas-grekas)
This PR was merged into the 2.3 branch.

Discussion
----------

[2.3] Cleanup deprecations

| Q             | A
| ------------- | ---
| Bug fix?      | no
| New feature?  | no
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | let's see
| Fixed tickets | -
| License       | MIT
| Doc PR        | -

Commits
-------

d649bef [2.3] Remove useless tests skips
1d68ad3 [2.3] Cleanup deprecations
2015-01-03 15:49:25 +01:00
Nicolas Grekas
0021c1d0d2 [2.3] Remove useless tests skips 2015-01-03 14:14:51 +01:00
Nicolas Grekas
86497902eb [2.3] Cleanup deprecations 2015-01-03 10:22:29 +01:00
Mikael Pajunen
e6c079c4c1 Use PHPUnit ini_set wrapper in tests
PHPUnit ini_set wrapper is now used in tests to automatically reset
ini settings after the test is run. This avoids possible side effects
and test skipping.

Native ini_set is still used in DefaultCsrfProviderTest, but its
tests are run in isolation.
2015-01-02 18:15:09 +02:00
Hugo Hamon
62ebdfc7d6 Fixes various phpdoc and coding standards. 2015-01-02 09:58:20 +01:00
Saro0h
7a2e2e7580 Updated copyright to 2015 2015-01-01 13:56:52 +01:00
Graham Campbell
3db261c0bd [2.3] CS And DocBlock Fixes 2014-12-22 16:58:09 +01:00
sarah khalil
de91f9cf14 [Tests] Silenced all deprecations in tests for 2.3 2014-12-18 20:00:19 +01:00
Fabien Potencier
a331253db6 fixed CS 2014-12-17 22:41:08 +01:00
Daniel Wehner
1164432942 add a limit and a test to FlattenExceptionTest. 2014-12-17 22:36:26 +01:00
Nicolas Grekas
1c5c246195 Test components using their lowest possible deps 2014-12-15 11:45:17 +01:00
Graham Campbell
49c9cb8adc PSR-2 fixes 2014-12-02 19:42:47 +00:00
Graham Campbell
542c721438 Docblock fixes 2014-11-30 13:33:44 +00:00
Nicolas Grekas
d492ff8385 [Debug] fix error message on double exception 2014-11-28 10:40:13 +01:00
Christian Flothmann
5a7ebac6ac compare version using PHP_VERSION_ID
To let opcode caches optimize cached code, the `PHP_VERSION_ID`
constant is used to detect the current PHP version instead of calling
`version_compare()` with `PHP_VERSION`.
2014-11-17 17:27:42 +01:00
Christian Flothmann
d854bf96fe don't override internal PHP constants 2014-11-16 18:59:41 +01:00
Disquedur
342b4e4a8e Remove aligned '=>' and '=' 2014-10-26 08:30:58 +01:00
Tobias Schultze
883f847ad1 use meta charset in layouts without legacy http-equiv 2014-10-09 18:42:17 +02:00
Laurent Ghirardotti
9760bae845 [Doc] Use Markdown syntax highlighting 2014-10-01 07:38:33 +02:00
Fabien Potencier
993f4c9cfc fixed CS 2014-09-22 10:32:35 +02:00
Christian Raue
91e3a1480c removed defaults from PHPUnit configuration 2014-07-07 12:13:42 +02:00
Christian Raue
732b41060b added XSD to PHPUnit configuration 2014-07-07 11:57:21 +02:00
Nicolas Grekas
ca764f8af9 [Debug] fix #10313: FlattenException not found because of https://bugs.php.net/42098 2014-04-29 21:42:43 +02:00
Nicolas Grekas
9fb191fa62 [Debug] fix ErrorHandlerTest when context is not an array 2014-04-28 20:50:14 +02:00
Nicolas Grekas
b2e922174d [Debug] ErrorHandler: remove $GLOBALS from context in PHP5.3 fix #10292 2014-04-28 18:43:50 +02:00
Fabien Potencier
bdfb718a6c made phpdoc types consistent with those defined in Hack 2014-04-15 07:41:45 +02:00
Jerome TAMARELLE
3c1b5f218d Check headers sent before sending PHP response
If the response contents has been sent before an error occurs, PHP
triggers the warning "Cannot modify header information - headers already sent"

This change ensure that the error message is echoed, while it's impossible
to change the HTTP status code and headers.
2014-03-26 19:06:50 +01:00
Fabien Potencier
78dc94dce6 changed some PHPUnit assertions to more specific ones 2014-03-01 18:25:29 +01:00
Fabien Potencier
4885c636af fixed various inconsistencies 2014-02-11 11:29:24 +01:00
sun
6a55635898 Fixed recursion level incrementing in FlattenException::flattenArgs(). 2014-02-04 08:06:39 +01:00
Luis Cordova
7f875d2aae update year on licenses 2014-01-07 08:19:25 -05:00
Pascal Borreli
13d5fe432f Fixed typo 2013-12-28 12:31:17 +01:00
Fabien Potencier
89151cc3fe fixed CS for lambdas 2013-12-28 08:46:05 +01:00
Fabien Potencier
93f26330c7 fixed CS 2013-12-12 17:08:59 +01:00
Fabien Potencier
b4ea949b41 [Debug] ensured that a fatal PHP error is actually fatal after being handled by our error handler 2013-11-28 17:41:31 +01:00
Fabien Potencier
264eb40f8d [Debug] fixed unit tests 2013-11-28 11:16:43 +01:00
Christian Schmidt
ff1f1fc483 Avoid notice from being *eaten* by fatal error. 2013-11-28 11:16:19 +01:00
Fabien Potencier
5da7e8c937 fixed typos 2013-11-25 16:00:46 +01:00
Fabien Potencier
085d4fd990 fixed CS 2013-10-30 09:30:20 +01:00
Fabien Potencier
7f671456b9 fixed phpdoc 2013-09-19 11:47:13 +02:00
Fabien Potencier
234f31cd20 Merge branch '2.2' into 2.3
* 2.2:
  [FrameworkBundle][Security] Replaced void return type with null for consistency
  fixed CS
  NativeSessionStorage regenerate
  removed unneeded comment
  Use setTimeZone if this method exists.
  Fix FileResource test
  fixed wrong usage of unset()
  [HttpFoundation] Fixed the way path to directory is trimmed.
  [Console] Fixed argument parsing when a single dash is passed.

Conflicts:
	src/Symfony/Component/HttpKernel/Debug/ErrorHandler.php
2013-09-13 14:20:37 +02:00
ShiraNai7
729f6d19cf Make sure ContextErrorException is loaded during compile time errors 2013-08-08 16:16:10 +02:00
Fabien Potencier
947e8d434b fixed CS 2013-07-01 14:24:43 +02:00
14 changed files with 401 additions and 128 deletions

View File

@@ -30,8 +30,8 @@ class Debug
* If the Symfony ClassLoader component is available, a special
* class loader is also registered.
*
* @param integer $errorReportingLevel The level of error reporting you want
* @param Boolean $displayErrors Whether to display errors (for development) or just log them (for production)
* @param int $errorReportingLevel The level of error reporting you want
* @param bool $displayErrors Whether to display errors (for development) or just log them (for production)
*/
public static function enable($errorReportingLevel = null, $displayErrors = true)
{

View File

@@ -13,6 +13,7 @@ namespace Symfony\Component\Debug;
use Symfony\Component\Debug\Exception\FatalErrorException;
use Symfony\Component\Debug\Exception\ContextErrorException;
use Symfony\Component\Debug\Exception\DummyException;
use Psr\Log\LoggerInterface;
/**
@@ -26,19 +27,19 @@ 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_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',
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;
@@ -55,10 +56,10 @@ class ErrorHandler
/**
* 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)
* @param Boolean $displayErrors Display errors (for dev environment) or just log they (production usage)
* @param int $level The level at which the conversion to Exception is done (null to use the error_reporting() value and 0 to disable)
* @param bool $displayErrors Display errors (for dev environment) or just log they (production usage)
*
* @return The registered error handler
* @return ErrorHandler The registered error handler
*/
public static function register($level = null, $displayErrors = true)
{
@@ -100,10 +101,11 @@ class ErrorHandler
if ($level & (E_USER_DEPRECATED | E_DEPRECATED)) {
if (isset(self::$loggers['deprecation'])) {
if (version_compare(PHP_VERSION, '5.4', '<')) {
if (PHP_VERSION_ID < 50400) {
$stack = array_map(
function ($row) {
unset($row['args']);
return $row;
},
array_slice(debug_backtrace(false), 0, 10)
@@ -119,7 +121,46 @@ class ErrorHandler
}
if ($this->displayErrors && error_reporting() & $level && $this->level & $level) {
throw new ContextErrorException(sprintf('%s: %s in %s line %d', isset($this->levels[$level]) ? $this->levels[$level] : $level, $message, $file, $line), 0, $level, $file, $line, $context);
// make sure the ContextErrorException class is loaded (https://bugs.php.net/bug.php?id=65322)
if (!class_exists('Symfony\Component\Debug\Exception\ContextErrorException')) {
require __DIR__.'/Exception/ContextErrorException.php';
}
if (!class_exists('Symfony\Component\Debug\Exception\FlattenException')) {
require __DIR__.'/Exception/FlattenException.php';
}
if (PHP_VERSION_ID < 50400 && isset($context['GLOBALS']) && is_array($context)) {
unset($context['GLOBALS']);
}
$exception = new ContextErrorException(sprintf('%s: %s in %s line %d', isset($this->levels[$level]) ? $this->levels[$level] : $level, $message, $file, $line), 0, $level, $file, $line, $context);
// Exceptions thrown from error handlers are sometimes not caught by the exception
// handler, so we invoke it directly (https://bugs.php.net/bug.php?id=54275)
$exceptionHandler = set_exception_handler(function () {});
restore_exception_handler();
if (is_array($exceptionHandler) && $exceptionHandler[0] instanceof ExceptionHandler) {
$exceptionHandler[0]->handle($exception);
if (!class_exists('Symfony\Component\Debug\Exception\DummyException')) {
require __DIR__.'/Exception/DummyException.php';
}
// we must stop the PHP script execution, as the exception has
// already been dealt with, so, let's throw an exception that
// will be caught by a dummy exception handler
set_exception_handler(function (\Exception $e) use ($exceptionHandler) {
if (!$e instanceof DummyException) {
// happens if our dummy exception is caught by a
// catch-all from user code, in which case, let's the
// current handler handle this "new" exception
call_user_func($exceptionHandler, $e);
}
});
throw new DummyException();
}
}
return false;
@@ -131,7 +172,7 @@ class ErrorHandler
return;
}
unset($this->reservedMemory);
$this->reservedMemory = '';
$type = $error['type'];
if (0 === $this->level || !in_array($type, array(E_ERROR, E_CORE_ERROR, E_COMPILE_ERROR, E_PARSE))) {
return;
@@ -152,7 +193,7 @@ class ErrorHandler
}
// get current exception handler
$exceptionHandler = set_exception_handler(function() {});
$exceptionHandler = set_exception_handler(function () {});
restore_exception_handler();
if (is_array($exceptionHandler) && $exceptionHandler[0] instanceof ExceptionHandler) {

View File

@@ -19,18 +19,18 @@ namespace Symfony\Component\Debug\Exception;
class ContextErrorException extends \ErrorException
{
private $context = array();
public function __construct($message, $code, $severity, $filename, $lineno, $context = array())
{
parent::__construct($message, $code, $severity, $filename, $lineno);
$this->context = $context;
}
/**
* @return array Array of variables that existed when the exception occured
* @return array Array of variables that existed when the exception occurred
*/
public function getContext()
{
return $this->context;
}
}
}

View File

@@ -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;
/**
* Used to stop execution of a PHP script after handling a fatal error.
*
* @author Fabien Potencier <fabien@symfony.com>
*/
class DummyException extends \ErrorException
{
}

View File

@@ -9,13 +9,28 @@
* file that was distributed with this source code.
*/
namespace Symfony\Component\HttpKernel\Exception;
/**
* 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
{
}
namespace Symfony\Component\Debug\Exception;
use Symfony\Component\HttpKernel\Exception\FatalErrorException as LegacyFatalErrorException;
/**
* Fatal Error Exception.
*
* @author Konstanton Myakshin <koc-dp@yandex.ru>
*/
class FatalErrorException extends \ErrorException
class FatalErrorException extends LegacyFatalErrorException
{
}

View File

@@ -9,8 +9,49 @@
* file that was distributed with this source code.
*/
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
{
private $handler;
public static function __callStatic($method, $args)
{
if (!method_exists('Symfony\Component\Debug\Exception\FlattenException', $method)) {
throw new \BadMethodCallException(sprintf('Call to undefined method %s::%s()', get_called_class(), $method));
}
return call_user_func_array(array('Symfony\Component\Debug\Exception\FlattenException', $method), $args);
}
public function __call($method, $args)
{
if (!isset($this->handler)) {
$this->handler = new DebugFlattenException();
}
if (!method_exists($this->handler, $method)) {
throw new \BadMethodCallException(sprintf('Call to undefined method %s::%s()', get_class($this), $method));
}
return call_user_func_array(array($this->handler, $method), $args);
}
}
namespace Symfony\Component\Debug\Exception;
use Symfony\Component\HttpKernel\Exception\FlattenException as LegacyFlattenException;
use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface;
/**
@@ -20,7 +61,7 @@ use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface;
*
* @author Fabien Potencier <fabien@symfony.com>
*/
class FlattenException
class FlattenException extends LegacyFlattenException
{
private $message;
private $code;
@@ -66,8 +107,8 @@ class FlattenException
foreach (array_merge(array($this), $this->getAllPrevious()) as $exception) {
$exceptions[] = array(
'message' => $exception->getMessage(),
'class' => $exception->getClass(),
'trace' => $exception->getTrace(),
'class' => $exception->getClass(),
'trace' => $exception->getTrace(),
);
}
@@ -208,14 +249,14 @@ class FlattenException
{
$this->trace = array();
$this->trace[] = array(
'namespace' => '',
'namespace' => '',
'short_class' => '',
'class' => '',
'type' => '',
'function' => '',
'file' => $file,
'line' => $line,
'args' => array(),
'class' => '',
'type' => '',
'function' => '',
'file' => $file,
'line' => $line,
'args' => array(),
);
foreach ($trace as $entry) {
$class = '';
@@ -227,29 +268,32 @@ class FlattenException
}
$this->trace[] = array(
'namespace' => $namespace,
'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(),
'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)
private function flattenArgs($args, $level = 0, &$count = 0)
{
$result = array();
foreach ($args as $key => $value) {
if (++$count > 1e4) {
return array('array', '*SKIPPED over 10000 entries*');
}
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));
$result[$key] = array('array', $this->flattenArgs($value, $level + 1, $count));
}
} elseif (null === $value) {
$result[$key] = array('null', null);

View File

@@ -14,10 +14,6 @@ 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.
*
@@ -43,7 +39,7 @@ class ExceptionHandler
/**
* Registers the exception handler.
*
* @param Boolean $debug
* @param bool $debug
*
* @return ExceptionHandler The registered exception handler
*/
@@ -65,8 +61,8 @@ class ExceptionHandler
*
* @param \Exception $exception An \Exception instance
*
* @see sendPhpResponse
* @see createResponse
* @see sendPhpResponse()
* @see createResponse()
*/
public function handle(\Exception $exception)
{
@@ -91,9 +87,12 @@ class ExceptionHandler
$exception = FlattenException::create($exception);
}
header(sprintf('HTTP/1.0 %s', $exception->getStatusCode()));
foreach ($exception->getHeaders() as $name => $value) {
header($name.': '.$value, false);
if (!headers_sent()) {
header(sprintf('HTTP/1.0 %s', $exception->getStatusCode()));
foreach ($exception->getHeaders() as $name => $value) {
header($name.': '.$value, false);
}
header('Content-Type: text/html; charset='.$this->charset);
}
echo $this->decorate($this->getContent($exception), $this->getStylesheet($exception));
@@ -112,7 +111,7 @@ class ExceptionHandler
$exception = FlattenException::create($exception);
}
return new Response($this->decorate($this->getContent($exception), $this->getStylesheet($exception)), $exception->getStatusCode(), $exception->getHeaders());
return Response::create($this->decorate($this->getContent($exception), $this->getStylesheet($exception)), $exception->getStatusCode(), $exception->getHeaders())->setCharset($this->charset);
}
/**
@@ -133,6 +132,7 @@ class ExceptionHandler
}
$content = '';
$flags = PHP_VERSION_ID >= 50400 ? ENT_QUOTES | ENT_SUBSTITUTE : ENT_QUOTES;
if ($this->debug) {
try {
$count = count($exception->getAllPrevious());
@@ -140,7 +140,7 @@ class ExceptionHandler
foreach ($exception->toArray() as $position => $e) {
$ind = $count - $position + 1;
$class = $this->abbrClass($e['class']);
$message = nl2br($e['message']);
$message = nl2br(htmlspecialchars($e['message'], $flags, $this->charset));
$content .= sprintf(<<<EOF
<div class="block_exception clear_fix">
<h2><span>%d/%d</span> %s: %s</h2>
@@ -171,7 +171,7 @@ EOF
} 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());
$title = sprintf('Exception thrown when handling an exception (%s: %s)', get_class($e), htmlspecialchars($e->getMessage(), $flags, $this->charset));
} else {
$title = 'Whoops, looks like something went wrong.';
}
@@ -255,7 +255,7 @@ EOF;
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<meta 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 */
@@ -278,7 +278,7 @@ EOF;
{
$parts = explode('\\', $class);
return sprintf("<abbr title=\"%s\">%s</abbr>", $class, array_pop($parts));
return sprintf('<abbr title="%s">%s</abbr>', $class, array_pop($parts));
}
/**
@@ -290,14 +290,19 @@ EOF;
*/
private function formatArgs(array $args)
{
if (PHP_VERSION_ID >= 50400) {
$flags = ENT_QUOTES | ENT_SUBSTITUTE;
} else {
$flags = ENT_QUOTES;
}
$result = array();
foreach ($args as $key => $item) {
if ('object' === $item[0]) {
$formattedValue = sprintf("<em>object</em>(%s)", $this->abbrClass($item[1]));
$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));
$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], $flags, $this->charset));
} elseif ('null' === $item[0]) {
$formattedValue = '<em>null</em>';
} elseif ('boolean' === $item[0]) {
@@ -305,7 +310,7 @@ EOF;
} 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));
$formattedValue = str_replace("\n", '', var_export(htmlspecialchars((string) $item[1], $flags, $this->charset), true));
}
$result[] = is_int($key) ? $formattedValue : sprintf("'%s' => %s", $key, $formattedValue);

View File

@@ -1,4 +1,4 @@
Copyright (c) 2004-2013 Fabien Potencier
Copyright (c) 2004-2015 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

View File

@@ -6,23 +6,27 @@ 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;
```php
use Symfony\Component\Debug\Debug;
Debug::enable();
Debug::enable();
```
You can also use the tools individually:
use Symfony\Component\Debug\ErrorHandler;
use Symfony\Component\Debug\ExceptionHandler;
```php
use Symfony\Component\Debug\ErrorHandler;
use Symfony\Component\Debug\ExceptionHandler;
error_reporting(-1);
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);
}
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.
@@ -36,5 +40,5 @@ Resources
You can run the unit tests with the following command:
$ cd path/to/Symfony/Component/Debug/
$ composer.phar install --dev
$ composer install
$ phpunit

View File

@@ -12,14 +12,141 @@
namespace Symfony\Component\Debug\Tests;
use Symfony\Component\Debug\ErrorHandler;
use Symfony\Component\Debug\Exception\DummyException;
/**
* ErrorHandlerTest
* ErrorHandlerTest.
*
* @author Robert Schönthal <seroscho@googlemail.com>
*/
class ErrorHandlerTest extends \PHPUnit_Framework_TestCase
{
/**
* @var int Error reporting level before running tests.
*/
protected $errorReporting;
protected function setUp()
{
$this->errorReporting = error_reporting(E_ALL | E_STRICT);
$this->iniSet('display_errors', '1');
}
protected function tearDown()
{
error_reporting($this->errorReporting);
}
public function testCompileTimeError()
{
// the ContextErrorException must not be loaded to test the workaround
// for https://bugs.php.net/bug.php?id=65322.
if (class_exists('Symfony\Component\Debug\Exception\ContextErrorException', false)) {
$this->markTestSkipped('The ContextErrorException class is already loaded.');
}
$exceptionHandler = $this->getMock('Symfony\Component\Debug\ExceptionHandler', array('handle'));
// the following code forces some PHPUnit classes to be loaded
// so that they will be available in the exception handler
// as they won't be autoloaded by PHP
class_exists('PHPUnit_Framework_MockObject_Invocation_Object');
$this->assertInstanceOf('stdClass', new \stdClass());
$this->assertEquals(1, 1);
$this->assertStringStartsWith('foo', 'foobar');
$this->assertArrayHasKey('bar', array('bar' => 'foo'));
$that = $this;
$exceptionCheck = function ($exception) use ($that) {
$that->assertInstanceOf('Symfony\Component\Debug\Exception\ContextErrorException', $exception);
$that->assertEquals(2, $exception->getLine());
if (PHP_VERSION_ID < 70000) {
$that->assertEquals(E_STRICT, $exception->getSeverity());
$that->assertStringStartsWith('Runtime Notice: Declaration of _CompileTimeError::foo() should be compatible with', $exception->getMessage());
} else {
$that->assertEquals(E_WARNING, $exception->getSeverity());
$that->assertStringStartsWith('Warning: Declaration of _CompileTimeError::foo() should be compatible with', $exception->getMessage());
}
$that->assertArrayHasKey('bar', $exception->getContext());
};
$exceptionHandler->expects($this->once())
->method('handle')
->will($this->returnCallback($exceptionCheck))
;
ErrorHandler::register();
set_exception_handler(array($exceptionHandler, 'handle'));
// dummy variable to check for in error handler.
$bar = 123;
// trigger compile time error
try {
eval(<<<'PHP'
class _BaseCompileTimeError { function foo() {} }
class _CompileTimeError extends _BaseCompileTimeError { function foo($invalid) {} }
PHP
);
} catch (DummyException $e) {
// if an exception is thrown, the test passed
}
restore_error_handler();
restore_exception_handler();
}
public function testNotice()
{
$exceptionHandler = $this->getMock('Symfony\Component\Debug\ExceptionHandler', array('handle'));
set_exception_handler(array($exceptionHandler, 'handle'));
$that = $this;
$exceptionCheck = function ($exception) use ($that) {
$that->assertInstanceOf('Symfony\Component\Debug\Exception\ContextErrorException', $exception);
$that->assertEquals(E_NOTICE, $exception->getSeverity());
$that->assertEquals(__LINE__ + 40, $exception->getLine());
$that->assertEquals(__FILE__, $exception->getFile());
$that->assertRegexp('/^Notice: Undefined variable: (foo|bar)/', $exception->getMessage());
$that->assertArrayHasKey('foobar', $exception->getContext());
$trace = $exception->getTrace();
$that->assertEquals(__FILE__, $trace[0]['file']);
$that->assertEquals('Symfony\Component\Debug\ErrorHandler', $trace[0]['class']);
$that->assertEquals('handle', $trace[0]['function']);
$that->assertEquals('->', $trace[0]['type']);
$that->assertEquals(__FILE__, $trace[1]['file']);
$that->assertEquals(__CLASS__, $trace[1]['class']);
$that->assertEquals('triggerNotice', $trace[1]['function']);
$that->assertEquals('::', $trace[1]['type']);
$that->assertEquals(__CLASS__, $trace[2]['class']);
$that->assertEquals('testNotice', $trace[2]['function']);
$that->assertEquals('->', $trace[2]['type']);
};
$exceptionHandler->expects($this->once())
->method('handle')
->will($this->returnCallback($exceptionCheck));
ErrorHandler::register();
try {
self::triggerNotice($this);
} catch (DummyException $e) {
// if an exception is thrown, the test passed
}
restore_error_handler();
}
// dummy function to test trace in error handler.
private static function triggerNotice($that)
{
// dummy variable to check for in error handler.
$foobar = 123;
$that->assertSame('', $foo.$foo.$bar);
}
public function testConstruct()
{
@@ -36,18 +163,18 @@ class ErrorHandlerTest extends \PHPUnit_Framework_TestCase
public function testHandle()
{
$handler = ErrorHandler::register(0);
$this->assertFalse($handler->handle(0, 'foo', 'foo.php', 12, 'foo'));
$this->assertFalse($handler->handle(0, 'foo', 'foo.php', 12, array()));
restore_error_handler();
$handler = ErrorHandler::register(3);
$this->assertFalse($handler->handle(4, 'foo', 'foo.php', 12, 'foo'));
$this->assertFalse($handler->handle(4, 'foo', 'foo.php', 12, array()));
restore_error_handler();
$handler = ErrorHandler::register(3);
try {
$handler->handle(111, 'foo', 'foo.php', 12, 'foo');
$handler->handle(111, 'foo', 'foo.php', 12, array());
} catch (\ErrorException $e) {
$this->assertSame('111: foo in foo.php line 12', $e->getMessage());
$this->assertSame(111, $e->getSeverity());
@@ -58,19 +185,19 @@ class ErrorHandlerTest extends \PHPUnit_Framework_TestCase
restore_error_handler();
$handler = ErrorHandler::register(E_USER_DEPRECATED);
$this->assertTrue($handler->handle(E_USER_DEPRECATED, 'foo', 'foo.php', 12, 'foo'));
$this->assertTrue($handler->handle(E_USER_DEPRECATED, 'foo', 'foo.php', 12, array()));
restore_error_handler();
$handler = ErrorHandler::register(E_DEPRECATED);
$this->assertTrue($handler->handle(E_DEPRECATED, 'foo', 'foo.php', 12, 'foo'));
$this->assertTrue($handler->handle(E_DEPRECATED, 'foo', 'foo.php', 12, array()));
restore_error_handler();
$logger = $this->getMock('Psr\Log\LoggerInterface');
$that = $this;
$warnArgCheck = function($message, $context) use ($that) {
$warnArgCheck = function ($message, $context) use ($that) {
$that->assertEquals('foo', $message);
$that->assertArrayHasKey('type', $context);
$that->assertEquals($context['type'], ErrorHandler::TYPE_DEPRECATION);
@@ -86,7 +213,7 @@ class ErrorHandlerTest extends \PHPUnit_Framework_TestCase
$handler = ErrorHandler::register(E_USER_DEPRECATED);
$handler->setLogger($logger);
$handler->handle(E_USER_DEPRECATED, 'foo', 'foo.php', 12, 'foo');
$handler->handle(E_USER_DEPRECATED, 'foo', 'foo.php', 12, array());
restore_error_handler();
}

View File

@@ -113,8 +113,7 @@ class FlattenExceptionTest extends \PHPUnit_Framework_TestCase
$this->assertEquals($exception->getMessage(), $flattened->getMessage(), 'The message is copied from the original exception.');
$this->assertEquals($exception->getCode(), $flattened->getCode(), 'The code is copied from the original exception.');
$this->assertEquals(get_class($exception), $flattened->getClass(), 'The class is set to the class of the original exception');
$this->assertInstanceOf($flattened->getClass(), $exception, 'The class is set to the class of the original exception');
}
/**
@@ -127,9 +126,9 @@ class FlattenExceptionTest extends \PHPUnit_Framework_TestCase
$flattened->setPrevious($flattened2);
$this->assertSame($flattened2,$flattened->getPrevious());
$this->assertSame($flattened2, $flattened->getPrevious());
$this->assertSame(array($flattened2),$flattened->getAllPrevious());
$this->assertSame(array($flattened2), $flattened->getAllPrevious());
}
/**
@@ -160,13 +159,13 @@ class FlattenExceptionTest extends \PHPUnit_Framework_TestCase
$this->assertEquals(array(
array(
'message'=> 'test',
'class'=>'Exception',
'trace'=>array(array(
'namespace' => '', 'short_class' => '', 'class' => '','type' => '','function' => '', 'file' => 'foo.php', 'line' => 123,
'args' => array()
'message' => 'test',
'class' => 'Exception',
'trace' => array(array(
'namespace' => '', 'short_class' => '', 'class' => '', 'type' => '', 'function' => '', 'file' => 'foo.php', 'line' => 123,
'args' => array(),
)),
)
),
), $flattened->toArray());
}
@@ -187,6 +186,28 @@ class FlattenExceptionTest extends \PHPUnit_Framework_TestCase
$this->assertContains('*DEEP NESTED ARRAY*', serialize($trace));
}
public function testTooBigArray()
{
$a = array();
for ($i = 0; $i < 20; $i++) {
for ($j = 0; $j < 50; $j++) {
for ($k = 0; $k < 10; $k++) {
$a[$i][$j][$k] = 'value';
}
}
}
$a[20] = 'value';
$a[21] = 'value1';
$exception = $this->createException($a);
$flattened = FlattenException::create($exception);
$trace = $flattened->getTrace();
$serializeTrace = serialize($trace);
$this->assertContains('*SKIPPED over 10000 entries*', $serializeTrace);
$this->assertNotContains('*value1*', $serializeTrace);
}
private function createException($foo)
{
return new \Exception();
@@ -202,7 +223,7 @@ class FlattenExceptionTest extends \PHPUnit_Framework_TestCase
'line' => 123,
'function' => 'test',
'args' => array(
unserialize('O:14:"BogusTestClass":0:{}')
unserialize('O:14:"BogusTestClass":0:{}'),
),
),
),
@@ -211,25 +232,25 @@ class FlattenExceptionTest extends \PHPUnit_Framework_TestCase
$this->assertEquals(array(
array(
'message'=> 'test',
'class'=>'Exception',
'trace'=>array(
'message' => 'test',
'class' => 'Exception',
'trace' => array(
array(
'namespace' => '', 'short_class' => '', 'class' => '','type' => '','function' => '',
'file' => 'foo.php', 'line' => 123,
'args' => array(),
'namespace' => '', 'short_class' => '', 'class' => '', 'type' => '', 'function' => '',
'file' => 'foo.php', 'line' => 123,
'args' => array(),
),
array(
'namespace' => '', 'short_class' => '', 'class' => '','type' => '','function' => 'test',
'file' => __FILE__, 'line' => 123,
'args' => array(
'namespace' => '', 'short_class' => '', 'class' => '', 'type' => '', 'function' => 'test',
'file' => __FILE__, 'line' => 123,
'args' => array(
array(
'incomplete-object', 'BogusTestClass'
'incomplete-object', 'BogusTestClass',
),
),
)
),
),
)
),
), $flattened->toArray());
}
}

View File

@@ -17,13 +17,6 @@ use Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException;
class ExceptionHandlerTest extends \PHPUnit_Framework_TestCase
{
protected function setUp()
{
if (!class_exists('Symfony\Component\HttpFoundation\Request')) {
$this->markTestSkipped('The "HttpFoundation" component is not available');
}
}
public function testDebug()
{
$handler = new ExceptionHandler(false);
@@ -64,6 +57,6 @@ class ExceptionHandlerTest extends \PHPUnit_Framework_TestCase
public function testNestedExceptions()
{
$handler = new ExceptionHandler(true);
$response = $handler->createResponse(new \RuntimeException('Foo', null, new \RuntimeException('Bar')));
$response = $handler->createResponse(new \RuntimeException('Foo', 0, new \RuntimeException('Bar')));
}
}

View File

@@ -3,7 +3,7 @@
"type": "library",
"description": "Symfony Debug Component",
"keywords": [],
"homepage": "http://symfony.com",
"homepage": "https://symfony.com",
"license": "MIT",
"authors": [
{
@@ -12,14 +12,18 @@
},
{
"name": "Symfony Community",
"homepage": "http://symfony.com/contributors"
"homepage": "https://symfony.com/contributors"
}
],
"require": {
"php": ">=5.3.3"
},
"conflict": {
"symfony/http-kernel": ">=2.3,<2.3.24|~2.4.0|>=2.5,<2.5.9|>=2.6,<2.6.2"
},
"require-dev": {
"symfony/http-kernel": "~2.1",
"symfony/phpunit-bridge": "~2.7",
"symfony/http-kernel": "~2.3.24|~2.5.9|~2.6,>=2.6.2",
"symfony/http-foundation": "~2.1"
},
"suggest": {

View File

@@ -1,16 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit backupGlobals="false"
backupStaticAttributes="false"
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://schema.phpunit.de/4.1/phpunit.xsd"
backupGlobals="false"
colors="true"
convertErrorsToExceptions="true"
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
processIsolation="false"
stopOnFailure="false"
syntaxCheck="false"
bootstrap="vendor/autoload.php"
>
<php>
<ini name="error_reporting" value="-1" />
</php>
<testsuites>
<testsuite name="Symfony Debug Component Test Suite">
<directory>./Tests/</directory>