mirror of
https://github.com/symfony/debug.git
synced 2026-03-25 09:42:20 +01:00
Compare commits
22 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
672a71e723 | ||
|
|
dcd43ab175 | ||
|
|
bc5a43ca7c | ||
|
|
0021c1d0d2 | ||
|
|
783848f50f | ||
|
|
86497902eb | ||
|
|
fe37874581 | ||
|
|
e6c079c4c1 | ||
|
|
62ebdfc7d6 | ||
|
|
7a2e2e7580 | ||
|
|
213f2cf05e | ||
|
|
cfd2c55384 | ||
|
|
3db261c0bd | ||
|
|
b65a554e0a | ||
|
|
c80c19c531 | ||
|
|
de91f9cf14 | ||
|
|
a331253db6 | ||
|
|
1164432942 | ||
|
|
610797d590 | ||
|
|
1c5c246195 | ||
|
|
d99bc72746 | ||
|
|
2394e45f56 |
@@ -65,11 +65,7 @@ class DebugClassLoader
|
||||
*/
|
||||
public function getClassLoader()
|
||||
{
|
||||
if ($this->wasFinder) {
|
||||
return $this->classLoader[0];
|
||||
} else {
|
||||
return $this->classLoader;
|
||||
}
|
||||
return $this->wasFinder ? $this->classLoader[0] : $this->classLoader;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -140,7 +136,7 @@ class DebugClassLoader
|
||||
*
|
||||
* @param string $class The name of the class
|
||||
*
|
||||
* @return bool|null True, if loaded
|
||||
* @return bool|null True, if loaded
|
||||
*
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
@@ -213,7 +209,7 @@ class DebugClassLoader
|
||||
chdir($cwd);
|
||||
}
|
||||
|
||||
if ( 0 === substr_compare($real, $tail, -strlen($tail), strlen($tail), true)
|
||||
if (0 === substr_compare($real, $tail, -strlen($tail), strlen($tail), true)
|
||||
&& 0 !== substr_compare($real, $tail, -strlen($tail), strlen($tail), false)
|
||||
) {
|
||||
throw new \RuntimeException(sprintf('Case mismatch between class and source file names: %s vs %s', $class, $real));
|
||||
|
||||
@@ -88,7 +88,7 @@ class ErrorHandler
|
||||
/**
|
||||
* Sets the level at which the conversion to Exception is done.
|
||||
*
|
||||
* @param int|null $level The level (null to use the error_reporting() value and 0 to disable)
|
||||
* @param int|null $level The level (null to use the error_reporting() value and 0 to disable)
|
||||
*/
|
||||
public function setLevel($level)
|
||||
{
|
||||
@@ -98,7 +98,7 @@ class ErrorHandler
|
||||
/**
|
||||
* Sets the display_errors flag value.
|
||||
*
|
||||
* @param int $displayErrors The display_errors flag value
|
||||
* @param int $displayErrors The display_errors flag value
|
||||
*/
|
||||
public function setDisplayErrors($displayErrors)
|
||||
{
|
||||
|
||||
@@ -11,6 +11,8 @@
|
||||
|
||||
namespace Symfony\Component\Debug\Exception;
|
||||
|
||||
use Symfony\Component\HttpKernel\Exception\FatalErrorException as LegacyFatalErrorException;
|
||||
|
||||
/**
|
||||
* Fatal Error Exception.
|
||||
*
|
||||
@@ -18,6 +20,19 @@ namespace Symfony\Component\Debug\Exception;
|
||||
* @author Konstanton Myakshin <koc-dp@yandex.ru>
|
||||
* @author Nicolas Grekas <p@tchwork.com>
|
||||
*/
|
||||
class FatalErrorException extends LegacyFatalErrorException
|
||||
{
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
public function __construct($message, $code, $severity, $filename, $lineno, $traceOffset = null, $traceArgs = true)
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
|
||||
namespace Symfony\Component\Debug\Exception;
|
||||
|
||||
use Symfony\Component\HttpKernel\Exception\FlattenException as LegacyFlattenException;
|
||||
use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface;
|
||||
|
||||
/**
|
||||
@@ -20,7 +21,7 @@ use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface;
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
class FlattenException
|
||||
class FlattenException extends LegacyFlattenException
|
||||
{
|
||||
private $message;
|
||||
private $code;
|
||||
@@ -210,17 +211,20 @@ class FlattenException
|
||||
}
|
||||
}
|
||||
|
||||
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 + 1));
|
||||
$result[$key] = array('array', $this->flattenArgs($value, $level + 1, $count));
|
||||
}
|
||||
} elseif (null === $value) {
|
||||
$result[$key] = array('null', null);
|
||||
@@ -246,3 +250,35 @@ class FlattenException
|
||||
return $array['__PHP_Incomplete_Class_Name'];
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
return forward_static_call_array(array('Symfony\Component\Debug\Exception\FlattenException', $method), $args);
|
||||
}
|
||||
|
||||
public function __call($method, $args)
|
||||
{
|
||||
if (!isset($this->handler)) {
|
||||
$this->handler = new DebugFlattenException();
|
||||
}
|
||||
|
||||
return call_user_func_array(array($this->handler, $method), $args);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -123,8 +123,10 @@ class ExceptionHandler
|
||||
* this method will use it to create and send the response. If not,
|
||||
* it will fallback to plain PHP functions.
|
||||
*
|
||||
* @see sendPhpResponse
|
||||
* @see createResponse
|
||||
* @param \Exception $exception An \Exception instance
|
||||
*
|
||||
* @see sendPhpResponse()
|
||||
* @see createResponse()
|
||||
*/
|
||||
private function failSafeHandle(\Exception $exception)
|
||||
{
|
||||
|
||||
@@ -15,7 +15,8 @@ use Symfony\Component\Debug\Exception\ClassNotFoundException;
|
||||
use Symfony\Component\Debug\Exception\FatalErrorException;
|
||||
use Symfony\Component\Debug\DebugClassLoader;
|
||||
use Composer\Autoload\ClassLoader as ComposerClassLoader;
|
||||
use Symfony\Component\ClassLoader as SymfonyClassLoader;
|
||||
use Symfony\Component\ClassLoader\ClassLoader as SymfonyClassLoader;
|
||||
use Symfony\Component\ClassLoader\UniversalClassLoader as SymfonyUniversalClassLoader;
|
||||
|
||||
/**
|
||||
* ErrorHandler for classes that do not exist.
|
||||
@@ -97,11 +98,11 @@ class ClassNotFoundFatalErrorHandler implements FatalErrorHandlerInterface
|
||||
|
||||
// find Symfony and Composer autoloaders
|
||||
$classes = array();
|
||||
|
||||
foreach ($functions as $function) {
|
||||
if (!is_array($function)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// get class loaders wrapped by DebugClassLoader
|
||||
if ($function[0] instanceof DebugClassLoader) {
|
||||
$function = $function[0]->getClassLoader();
|
||||
@@ -116,7 +117,7 @@ class ClassNotFoundFatalErrorHandler implements FatalErrorHandlerInterface
|
||||
}
|
||||
}
|
||||
|
||||
if ($function[0] instanceof ComposerClassLoader || $function[0] instanceof SymfonyClassLoader) {
|
||||
if ($function[0] instanceof ComposerClassLoader || $function[0] instanceof SymfonyClassLoader || $function[0] instanceof SymfonyUniversalClassLoader) {
|
||||
foreach ($function[0]->getPrefixes() as $prefix => $paths) {
|
||||
foreach ($paths as $path) {
|
||||
$classes = array_merge($classes, $this->findClassInPath($path, $class, $prefix));
|
||||
@@ -125,7 +126,7 @@ class ClassNotFoundFatalErrorHandler implements FatalErrorHandlerInterface
|
||||
}
|
||||
}
|
||||
|
||||
return $classes;
|
||||
return array_unique($classes);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
2
LICENSE
2
LICENSE
@@ -1,4 +1,4 @@
|
||||
Copyright (c) 2004-2014 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
|
||||
|
||||
@@ -62,17 +62,14 @@ class DebugClassLoaderTest extends \PHPUnit_Framework_TestCase
|
||||
public function testUnsilencing()
|
||||
{
|
||||
ob_start();
|
||||
$bak = array(
|
||||
ini_set('log_errors', 0),
|
||||
ini_set('display_errors', 1),
|
||||
);
|
||||
|
||||
$this->iniSet('log_errors', 0);
|
||||
$this->iniSet('display_errors', 1);
|
||||
|
||||
// See below: this will fail with parse error
|
||||
// but this should not be @-silenced.
|
||||
@class_exists(__NAMESPACE__.'\TestingUnsilencing', true);
|
||||
|
||||
ini_set('log_errors', $bak[0]);
|
||||
ini_set('display_errors', $bak[1]);
|
||||
$output = ob_get_clean();
|
||||
|
||||
$this->assertStringMatchesFormat('%aParse error%a', $output);
|
||||
|
||||
@@ -15,7 +15,7 @@ use Symfony\Component\Debug\ErrorHandler;
|
||||
use Symfony\Component\Debug\Exception\ContextErrorException;
|
||||
|
||||
/**
|
||||
* ErrorHandlerTest
|
||||
* ErrorHandlerTest.
|
||||
*
|
||||
* @author Robert Schönthal <seroscho@googlemail.com>
|
||||
*/
|
||||
@@ -26,21 +26,14 @@ class ErrorHandlerTest extends \PHPUnit_Framework_TestCase
|
||||
*/
|
||||
protected $errorReporting;
|
||||
|
||||
/**
|
||||
* @var string Display errors setting before running tests.
|
||||
*/
|
||||
protected $displayErrors;
|
||||
|
||||
public function setUp()
|
||||
{
|
||||
$this->errorReporting = error_reporting(E_ALL | E_STRICT);
|
||||
$this->displayErrors = ini_get('display_errors');
|
||||
ini_set('display_errors', '1');
|
||||
$this->iniSet('display_errors', '1');
|
||||
}
|
||||
|
||||
public function tearDown()
|
||||
{
|
||||
ini_set('display_errors', $this->displayErrors);
|
||||
error_reporting($this->errorReporting);
|
||||
}
|
||||
|
||||
|
||||
@@ -186,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();
|
||||
|
||||
@@ -11,6 +11,8 @@
|
||||
|
||||
namespace Symfony\Component\Debug\Tests\FatalErrorHandler;
|
||||
|
||||
use Symfony\Component\ClassLoader\ClassLoader as SymfonyClassLoader;
|
||||
use Symfony\Component\ClassLoader\UniversalClassLoader as SymfonyUniversalClassLoader;
|
||||
use Symfony\Component\Debug\Exception\FatalErrorException;
|
||||
use Symfony\Component\Debug\FatalErrorHandler\ClassNotFoundFatalErrorHandler;
|
||||
|
||||
@@ -19,11 +21,25 @@ class ClassNotFoundFatalErrorHandlerTest extends \PHPUnit_Framework_TestCase
|
||||
/**
|
||||
* @dataProvider provideClassNotFoundData
|
||||
*/
|
||||
public function testClassNotFound($error, $translatedMessage)
|
||||
public function testHandleClassNotFound($error, $translatedMessage, $autoloader = null)
|
||||
{
|
||||
if ($autoloader) {
|
||||
// Unregister all autoloaders to ensure the custom provided
|
||||
// autoloader is the only one to be used during the test run.
|
||||
$autoloaders = spl_autoload_functions();
|
||||
array_map('spl_autoload_unregister', $autoloaders);
|
||||
spl_autoload_register($autoloader);
|
||||
}
|
||||
|
||||
$handler = new ClassNotFoundFatalErrorHandler();
|
||||
|
||||
$exception = $handler->handleError($error, new FatalErrorException('', 0, $error['type'], $error['file'], $error['line']));
|
||||
|
||||
if ($autoloader) {
|
||||
spl_autoload_unregister($autoloader);
|
||||
array_map('spl_autoload_register', $autoloaders);
|
||||
}
|
||||
|
||||
$this->assertInstanceof('Symfony\Component\Debug\Exception\ClassNotFoundException', $exception);
|
||||
$this->assertSame($translatedMessage, $exception->getMessage());
|
||||
$this->assertSame($error['type'], $exception->getSeverity());
|
||||
@@ -33,6 +49,14 @@ class ClassNotFoundFatalErrorHandlerTest extends \PHPUnit_Framework_TestCase
|
||||
|
||||
public function provideClassNotFoundData()
|
||||
{
|
||||
$prefixes = array('Symfony\Component\Debug\Exception\\' => realpath(__DIR__.'/../../Exception'));
|
||||
|
||||
$symfonyAutoloader = new SymfonyClassLoader();
|
||||
$symfonyAutoloader->addPrefixes($prefixes);
|
||||
|
||||
$symfonyUniversalClassLoader = new SymfonyUniversalClassLoader();
|
||||
$symfonyUniversalClassLoader->registerPrefixes($prefixes);
|
||||
|
||||
return array(
|
||||
array(
|
||||
array(
|
||||
@@ -79,6 +103,36 @@ class ClassNotFoundFatalErrorHandlerTest extends \PHPUnit_Framework_TestCase
|
||||
),
|
||||
'Attempted to load class "UndefinedFunctionException" from namespace "Foo\Bar" in foo.php line 12. Do you need to "use" it from another namespace? Perhaps you need to add a use statement for one of the following: Symfony\Component\Debug\Exception\UndefinedFunctionException.',
|
||||
),
|
||||
array(
|
||||
array(
|
||||
'type' => 1,
|
||||
'line' => 12,
|
||||
'file' => 'foo.php',
|
||||
'message' => 'Class \'Foo\\Bar\\UndefinedFunctionException\' not found',
|
||||
),
|
||||
'Attempted to load class "UndefinedFunctionException" from namespace "Foo\Bar" in foo.php line 12. Do you need to "use" it from another namespace? Perhaps you need to add a use statement for one of the following: Symfony\Component\Debug\Exception\UndefinedFunctionException.',
|
||||
array($symfonyAutoloader, 'loadClass'),
|
||||
),
|
||||
array(
|
||||
array(
|
||||
'type' => 1,
|
||||
'line' => 12,
|
||||
'file' => 'foo.php',
|
||||
'message' => 'Class \'Foo\\Bar\\UndefinedFunctionException\' not found',
|
||||
),
|
||||
'Attempted to load class "UndefinedFunctionException" from namespace "Foo\Bar" in foo.php line 12. Do you need to "use" it from another namespace? Perhaps you need to add a use statement for one of the following: Symfony\Component\Debug\Exception\UndefinedFunctionException.',
|
||||
array($symfonyUniversalClassLoader, 'loadClass'),
|
||||
),
|
||||
array(
|
||||
array(
|
||||
'type' => 1,
|
||||
'line' => 12,
|
||||
'file' => 'foo.php',
|
||||
'message' => 'Class \'Foo\\Bar\\UndefinedFunctionException\' not found',
|
||||
),
|
||||
'Attempted to load class "UndefinedFunctionException" from namespace "Foo\Bar" in foo.php line 12. Do you need to "use" it from another namespace?',
|
||||
function ($className) { /* do nothing here */ },
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -19,7 +19,8 @@
|
||||
"php": ">=5.3.3"
|
||||
},
|
||||
"require-dev": {
|
||||
"symfony/http-kernel": "~2.1",
|
||||
"symfony/class-loader": "~2.2",
|
||||
"symfony/http-kernel": "~2.3.24|~2.5.9|~2.6,>=2.6.2",
|
||||
"symfony/http-foundation": "~2.1"
|
||||
},
|
||||
"suggest": {
|
||||
|
||||
@@ -6,6 +6,10 @@
|
||||
colors="true"
|
||||
bootstrap="vendor/autoload.php"
|
||||
>
|
||||
<php>
|
||||
<!-- Silence E_USER_DEPRECATED (-16385 == -1 & ~E_USER_DEPRECATED) -->
|
||||
<ini name="error_reporting" value="-16385"/>
|
||||
</php>
|
||||
<testsuites>
|
||||
<testsuite name="Symfony Debug Component Test Suite">
|
||||
<directory>./Tests/</directory>
|
||||
|
||||
Reference in New Issue
Block a user