mirror of
https://github.com/symfony/debug.git
synced 2026-03-25 09:42:20 +01:00
Compare commits
106 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
43ce8ab34c | ||
|
|
adbdd5d663 | ||
|
|
94eda15aa1 | ||
|
|
a5961253fa | ||
|
|
26bccc04be | ||
|
|
878d05a2eb | ||
|
|
83e5508e9d | ||
|
|
d5f9980171 | ||
|
|
de73f48977 | ||
|
|
8d8a9e877b | ||
|
|
9359ad70a1 | ||
|
|
1fe36a98e2 | ||
|
|
945530598e | ||
|
|
8b8b8b7e57 | ||
|
|
cf9b2e33f7 | ||
|
|
caf0f3fa57 | ||
|
|
667a26c4dd | ||
|
|
7ae7883ea2 | ||
|
|
4174d02351 | ||
|
|
b624515da8 | ||
|
|
970d9da53e | ||
|
|
2e1483cd0d | ||
|
|
f6bdc0a7df | ||
|
|
00db8f8b37 | ||
|
|
45c6e7759f | ||
|
|
d1815d4beb | ||
|
|
8747fd01a7 | ||
|
|
2574a83be3 | ||
|
|
4d92150508 | ||
|
|
1a53cddc50 | ||
|
|
ab51c79f5e | ||
|
|
5ca61fb12e | ||
|
|
ce763d24ed | ||
|
|
64cb33c81e | ||
|
|
3ba0dfd9af | ||
|
|
26d7f23b9b | ||
|
|
c8e078dd18 | ||
|
|
e9c81d5231 | ||
|
|
6eb115e3a5 | ||
|
|
26bd579e62 | ||
|
|
e0a2b92ee0 | ||
|
|
533c656e12 | ||
|
|
a2233f555d | ||
|
|
7a8a60421b | ||
|
|
0aae90af4e | ||
|
|
f9eea0cff9 | ||
|
|
2016b3eec2 | ||
|
|
74251c8d50 | ||
|
|
85c1365d7a | ||
|
|
19090917b8 | ||
|
|
fe9793af00 | ||
|
|
6a198c52b6 | ||
|
|
e72d01486a | ||
|
|
e3f76ce619 | ||
|
|
0a612e9dfb | ||
|
|
087890e02f | ||
|
|
65d41d1696 | ||
|
|
92320d007e | ||
|
|
b4a0b67dee | ||
|
|
b70cfaae39 | ||
|
|
0a6c85e5c6 | ||
|
|
8f69eb64e4 | ||
|
|
acb9e69323 | ||
|
|
a037ae518a | ||
|
|
d7b459ba7b | ||
|
|
4fd77efcd4 | ||
|
|
9374383ad2 | ||
|
|
ede2c4b8fd | ||
|
|
87cecce74b | ||
|
|
42bdc01d61 | ||
|
|
e2b31a5a23 | ||
|
|
47ead688f1 | ||
|
|
c4625e7534 | ||
|
|
cbb8a5f212 | ||
|
|
c16ccd52db | ||
|
|
9316545571 | ||
|
|
8d5462cfbc | ||
|
|
d5a058ff6e | ||
|
|
d985c8546d | ||
|
|
32023e0ffa | ||
|
|
38b2f7a11a | ||
|
|
eba30e3a78 | ||
|
|
13041d84e3 | ||
|
|
2f42aa269a | ||
|
|
056f617413 | ||
|
|
fa0b714b55 | ||
|
|
fce13776fb | ||
|
|
34bdb1c801 | ||
|
|
d070fc2e64 | ||
|
|
d49a626c51 | ||
|
|
a1f2118ced | ||
|
|
1970189082 | ||
|
|
46f848122e | ||
|
|
8c2d96aff8 | ||
|
|
0e3ca9cbde | ||
|
|
47e6788c5b | ||
|
|
a26ddce7fe | ||
|
|
ef8bd62973 | ||
|
|
dbe0fad880 | ||
|
|
ef0abb7ca3 | ||
|
|
a7e8068943 | ||
|
|
5d48e9c0f8 | ||
|
|
09f5c0938b | ||
|
|
b28fd73fef | ||
|
|
c7d48cc12e | ||
|
|
feb747f95f |
@@ -20,17 +20,17 @@ use Psr\Log\AbstractLogger;
|
||||
*/
|
||||
class BufferingLogger extends AbstractLogger
|
||||
{
|
||||
private $logs = array();
|
||||
private $logs = [];
|
||||
|
||||
public function log($level, $message, array $context = array())
|
||||
public function log($level, $message, array $context = [])
|
||||
{
|
||||
$this->logs[] = array($level, $message, $context);
|
||||
$this->logs[] = [$level, $message, $context];
|
||||
}
|
||||
|
||||
public function cleanLogs()
|
||||
{
|
||||
$logs = $this->logs;
|
||||
$this->logs = array();
|
||||
$this->logs = [];
|
||||
|
||||
return $logs;
|
||||
}
|
||||
|
||||
@@ -42,10 +42,10 @@ class Debug
|
||||
error_reporting(E_ALL);
|
||||
}
|
||||
|
||||
if (!\in_array(PHP_SAPI, array('cli', 'phpdbg'), true)) {
|
||||
if (!\in_array(\PHP_SAPI, ['cli', 'phpdbg'], true)) {
|
||||
ini_set('display_errors', 0);
|
||||
ExceptionHandler::register();
|
||||
} elseif ($displayErrors && (!ini_get('log_errors') || ini_get('error_log'))) {
|
||||
} elseif ($displayErrors && (!filter_var(ini_get('log_errors'), FILTER_VALIDATE_BOOLEAN) || ini_get('error_log'))) {
|
||||
// CLI - display errors only if they're not already logged to STDERR
|
||||
ini_set('display_errors', 1);
|
||||
}
|
||||
|
||||
@@ -11,6 +11,8 @@
|
||||
|
||||
namespace Symfony\Component\Debug;
|
||||
|
||||
use PHPUnit\Framework\MockObject\Matcher\StatelessInvocation;
|
||||
|
||||
/**
|
||||
* Autoloader checking if the class is really defined in the file found.
|
||||
*
|
||||
@@ -21,29 +23,31 @@ namespace Symfony\Component\Debug;
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
* @author Christophe Coevoet <stof@notk.org>
|
||||
* @author Nicolas Grekas <p@tchwork.com>
|
||||
* @author Guilhem Niot <guilhem.niot@gmail.com>
|
||||
*/
|
||||
class DebugClassLoader
|
||||
{
|
||||
private $classLoader;
|
||||
private $isFinder;
|
||||
private $loaded = array();
|
||||
private $loaded = [];
|
||||
private static $caseCheck;
|
||||
private static $checkedClasses = array();
|
||||
private static $final = array();
|
||||
private static $finalMethods = array();
|
||||
private static $deprecated = array();
|
||||
private static $internal = array();
|
||||
private static $internalMethods = array();
|
||||
private static $darwinCache = array('/' => array('/', array()));
|
||||
private static $checkedClasses = [];
|
||||
private static $final = [];
|
||||
private static $finalMethods = [];
|
||||
private static $deprecated = [];
|
||||
private static $internal = [];
|
||||
private static $internalMethods = [];
|
||||
private static $annotatedParameters = [];
|
||||
private static $darwinCache = ['/' => ['/', []]];
|
||||
|
||||
public function __construct(callable $classLoader)
|
||||
{
|
||||
$this->classLoader = $classLoader;
|
||||
$this->isFinder = is_array($classLoader) && method_exists($classLoader[0], 'findFile');
|
||||
$this->isFinder = \is_array($classLoader) && method_exists($classLoader[0], 'findFile');
|
||||
|
||||
if (!isset(self::$caseCheck)) {
|
||||
$file = file_exists(__FILE__) ? __FILE__ : rtrim(realpath('.'), DIRECTORY_SEPARATOR);
|
||||
$i = strrpos($file, DIRECTORY_SEPARATOR);
|
||||
$file = file_exists(__FILE__) ? __FILE__ : rtrim(realpath('.'), \DIRECTORY_SEPARATOR);
|
||||
$i = strrpos($file, \DIRECTORY_SEPARATOR);
|
||||
$dir = substr($file, 0, 1 + $i);
|
||||
$file = substr($file, 1 + $i);
|
||||
$test = strtoupper($file) === $file ? strtolower($file) : strtoupper($file);
|
||||
@@ -52,7 +56,7 @@ class DebugClassLoader
|
||||
if (false === $test || false === $i) {
|
||||
// filesystem is case sensitive
|
||||
self::$caseCheck = 0;
|
||||
} elseif (substr($test, -strlen($file)) === $file) {
|
||||
} elseif (substr($test, -\strlen($file)) === $file) {
|
||||
// filesystem is case insensitive and realpath() normalizes the case of characters
|
||||
self::$caseCheck = 1;
|
||||
} elseif (false !== stripos(PHP_OS, 'darwin')) {
|
||||
@@ -84,7 +88,7 @@ class DebugClassLoader
|
||||
class_exists('Symfony\Component\Debug\ErrorHandler');
|
||||
class_exists('Psr\Log\LogLevel');
|
||||
|
||||
if (!is_array($functions = spl_autoload_functions())) {
|
||||
if (!\is_array($functions = spl_autoload_functions())) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -93,8 +97,8 @@ class DebugClassLoader
|
||||
}
|
||||
|
||||
foreach ($functions as $function) {
|
||||
if (!is_array($function) || !$function[0] instanceof self) {
|
||||
$function = array(new static($function), 'loadClass');
|
||||
if (!\is_array($function) || !$function[0] instanceof self) {
|
||||
$function = [new static($function), 'loadClass'];
|
||||
}
|
||||
|
||||
spl_autoload_register($function);
|
||||
@@ -106,7 +110,7 @@ class DebugClassLoader
|
||||
*/
|
||||
public static function disable()
|
||||
{
|
||||
if (!is_array($functions = spl_autoload_functions())) {
|
||||
if (!\is_array($functions = spl_autoload_functions())) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -115,7 +119,7 @@ class DebugClassLoader
|
||||
}
|
||||
|
||||
foreach ($functions as $function) {
|
||||
if (is_array($function) && $function[0] instanceof self) {
|
||||
if (\is_array($function) && $function[0] instanceof self) {
|
||||
$function = $function[0]->getClassLoader();
|
||||
}
|
||||
|
||||
@@ -123,13 +127,19 @@ class DebugClassLoader
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string|null
|
||||
*/
|
||||
public function findFile($class)
|
||||
{
|
||||
return $this->isFinder ? $this->classLoader[0]->findFile($class) ?: null : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the given class or interface.
|
||||
*
|
||||
* @param string $class The name of the class
|
||||
*
|
||||
* @return bool|null True, if loaded
|
||||
*
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function loadClass($class)
|
||||
@@ -139,17 +149,17 @@ class DebugClassLoader
|
||||
try {
|
||||
if ($this->isFinder && !isset($this->loaded[$class])) {
|
||||
$this->loaded[$class] = true;
|
||||
if ($file = $this->classLoader[0]->findFile($class) ?: false) {
|
||||
$wasCached = \function_exists('opcache_is_script_cached') && @opcache_is_script_cached($file);
|
||||
|
||||
if (!$file = $this->classLoader[0]->findFile($class) ?: false) {
|
||||
// no-op
|
||||
} elseif (\function_exists('opcache_is_script_cached') && @opcache_is_script_cached($file)) {
|
||||
require $file;
|
||||
|
||||
if ($wasCached) {
|
||||
return;
|
||||
}
|
||||
return;
|
||||
} else {
|
||||
require $file;
|
||||
}
|
||||
} else {
|
||||
call_user_func($this->classLoader, $class);
|
||||
($this->classLoader)($class);
|
||||
$file = false;
|
||||
}
|
||||
} finally {
|
||||
@@ -183,196 +193,266 @@ class DebugClassLoader
|
||||
throw new \RuntimeException(sprintf('Case mismatch between loaded and declared class names: "%s" vs "%s".', $class, $name));
|
||||
}
|
||||
|
||||
// Don't trigger deprecations for classes in the same vendor
|
||||
if (2 > $len = 1 + (\strpos($name, '\\') ?: \strpos($name, '_'))) {
|
||||
$len = 0;
|
||||
$ns = '';
|
||||
$deprecations = $this->checkAnnotations($refl, $name);
|
||||
|
||||
foreach ($deprecations as $message) {
|
||||
@trigger_error($message, E_USER_DEPRECATED);
|
||||
}
|
||||
}
|
||||
|
||||
if (!$file) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!$exists) {
|
||||
if (false !== strpos($class, '/')) {
|
||||
throw new \RuntimeException(sprintf('Trying to autoload a class with an invalid name "%s". Be careful that the namespace separator is "\" in PHP, not "/".', $class));
|
||||
}
|
||||
|
||||
throw new \RuntimeException(sprintf('The autoloader expected class "%s" to be defined in file "%s". The file was found but the class was not in it, the class name or namespace probably has a typo.', $class, $file));
|
||||
}
|
||||
|
||||
if (self::$caseCheck && $message = $this->checkCase($refl, $file, $class)) {
|
||||
throw new \RuntimeException(sprintf('Case mismatch between class and real file names: "%s" vs "%s" in "%s".', $message[0], $message[1], $message[2]));
|
||||
}
|
||||
}
|
||||
|
||||
public function checkAnnotations(\ReflectionClass $refl, $class)
|
||||
{
|
||||
$deprecations = [];
|
||||
|
||||
// Don't trigger deprecations for classes in the same vendor
|
||||
if (2 > $len = 1 + (\strpos($class, '\\') ?: \strpos($class, '_'))) {
|
||||
$len = 0;
|
||||
$ns = '';
|
||||
} else {
|
||||
$ns = \str_replace('_', '\\', \substr($class, 0, $len));
|
||||
}
|
||||
|
||||
// Detect annotations on the class
|
||||
if (false !== $doc = $refl->getDocComment()) {
|
||||
foreach (['final', 'deprecated', 'internal'] as $annotation) {
|
||||
if (false !== \strpos($doc, $annotation) && preg_match('#\n\s+\* @'.$annotation.'(?:( .+?)\.?)?\r?\n\s+\*(?: @|/$|\r?\n)#s', $doc, $notice)) {
|
||||
self::${$annotation}[$class] = isset($notice[1]) ? preg_replace('#\.?\r?\n( \*)? *(?= |\r?\n|$)#', '', $notice[1]) : '';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$parent = \get_parent_class($class);
|
||||
$parentAndOwnInterfaces = $this->getOwnInterfaces($class, $parent);
|
||||
if ($parent) {
|
||||
$parentAndOwnInterfaces[$parent] = $parent;
|
||||
|
||||
if (!isset(self::$checkedClasses[$parent])) {
|
||||
$this->checkClass($parent);
|
||||
}
|
||||
|
||||
if (isset(self::$final[$parent])) {
|
||||
$deprecations[] = sprintf('The "%s" class is considered final%s. It may change without further notice as of its next major version. You should not extend it from "%s".', $parent, self::$final[$parent], $class);
|
||||
}
|
||||
}
|
||||
|
||||
// Detect if the parent is annotated
|
||||
foreach ($parentAndOwnInterfaces + \class_uses($class, false) as $use) {
|
||||
if (!isset(self::$checkedClasses[$use])) {
|
||||
$this->checkClass($use);
|
||||
}
|
||||
if (isset(self::$deprecated[$use]) && \strncmp($ns, \str_replace('_', '\\', $use), $len) && !isset(self::$deprecated[$class])) {
|
||||
$type = class_exists($class, false) ? 'class' : (interface_exists($class, false) ? 'interface' : 'trait');
|
||||
$verb = class_exists($use, false) || interface_exists($class, false) ? 'extends' : (interface_exists($use, false) ? 'implements' : 'uses');
|
||||
|
||||
$deprecations[] = sprintf('The "%s" %s %s "%s" that is deprecated%s.', $class, $type, $verb, $use, self::$deprecated[$use]);
|
||||
}
|
||||
if (isset(self::$internal[$use]) && \strncmp($ns, \str_replace('_', '\\', $use), $len)) {
|
||||
$deprecations[] = sprintf('The "%s" %s is considered internal%s. It may change without further notice. You should not use it from "%s".', $use, class_exists($use, false) ? 'class' : (interface_exists($use, false) ? 'interface' : 'trait'), self::$internal[$use], $class);
|
||||
}
|
||||
}
|
||||
|
||||
if (\trait_exists($class)) {
|
||||
return $deprecations;
|
||||
}
|
||||
|
||||
// Inherit @final, @internal and @param annotations for methods
|
||||
self::$finalMethods[$class] = [];
|
||||
self::$internalMethods[$class] = [];
|
||||
self::$annotatedParameters[$class] = [];
|
||||
foreach ($parentAndOwnInterfaces as $use) {
|
||||
foreach (['finalMethods', 'internalMethods', 'annotatedParameters'] as $property) {
|
||||
if (isset(self::${$property}[$use])) {
|
||||
self::${$property}[$class] = self::${$property}[$class] ? self::${$property}[$use] + self::${$property}[$class] : self::${$property}[$use];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($refl->getMethods(\ReflectionMethod::IS_PUBLIC | \ReflectionMethod::IS_PROTECTED) as $method) {
|
||||
if ($method->class !== $class) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($parent && isset(self::$finalMethods[$parent][$method->name])) {
|
||||
list($declaringClass, $message) = self::$finalMethods[$parent][$method->name];
|
||||
$deprecations[] = sprintf('The "%s::%s()" method is considered final%s. It may change without further notice as of its next major version. You should not extend it from "%s".', $declaringClass, $method->name, $message, $class);
|
||||
}
|
||||
|
||||
if (isset(self::$internalMethods[$class][$method->name])) {
|
||||
list($declaringClass, $message) = self::$internalMethods[$class][$method->name];
|
||||
if (\strncmp($ns, $declaringClass, $len)) {
|
||||
$deprecations[] = sprintf('The "%s::%s()" method is considered internal%s. It may change without further notice. You should not extend it from "%s".', $declaringClass, $method->name, $message, $class);
|
||||
}
|
||||
}
|
||||
|
||||
// To read method annotations
|
||||
$doc = $method->getDocComment();
|
||||
|
||||
if (isset(self::$annotatedParameters[$class][$method->name])) {
|
||||
$definedParameters = [];
|
||||
foreach ($method->getParameters() as $parameter) {
|
||||
$definedParameters[$parameter->name] = true;
|
||||
}
|
||||
|
||||
foreach (self::$annotatedParameters[$class][$method->name] as $parameterName => $deprecation) {
|
||||
if (!isset($definedParameters[$parameterName]) && !($doc && preg_match("/\\n\\s+\\* @param (.*?)(?<= )\\\${$parameterName}\\b/", $doc))) {
|
||||
$deprecations[] = sprintf($deprecation, $class);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!$doc) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$finalOrInternal = false;
|
||||
|
||||
foreach (['final', 'internal'] as $annotation) {
|
||||
if (false !== \strpos($doc, $annotation) && preg_match('#\n\s+\* @'.$annotation.'(?:( .+?)\.?)?\r?\n\s+\*(?: @|/$|\r?\n)#s', $doc, $notice)) {
|
||||
$message = isset($notice[1]) ? preg_replace('#\.?\r?\n( \*)? *(?= |\r?\n|$)#', '', $notice[1]) : '';
|
||||
self::${$annotation.'Methods'}[$class][$method->name] = [$class, $message];
|
||||
$finalOrInternal = true;
|
||||
}
|
||||
}
|
||||
|
||||
if ($finalOrInternal || $method->isConstructor() || false === \strpos($doc, '@param') || StatelessInvocation::class === $class) {
|
||||
continue;
|
||||
}
|
||||
if (!preg_match_all('#\n\s+\* @param (.*?)(?<= )\$([a-zA-Z0-9_\x7f-\xff]++)#', $doc, $matches, PREG_SET_ORDER)) {
|
||||
continue;
|
||||
}
|
||||
if (!isset(self::$annotatedParameters[$class][$method->name])) {
|
||||
$definedParameters = [];
|
||||
foreach ($method->getParameters() as $parameter) {
|
||||
$definedParameters[$parameter->name] = true;
|
||||
}
|
||||
}
|
||||
foreach ($matches as list(, $parameterType, $parameterName)) {
|
||||
if (!isset($definedParameters[$parameterName])) {
|
||||
$parameterType = trim($parameterType);
|
||||
self::$annotatedParameters[$class][$method->name][$parameterName] = sprintf('The "%%s::%s()" method will require a new "%s$%s" argument in the next major version of its parent class "%s", not defining it is deprecated.', $method->name, $parameterType ? $parameterType.' ' : '', $parameterName, $method->class);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $deprecations;
|
||||
}
|
||||
|
||||
public function checkCase(\ReflectionClass $refl, $file, $class)
|
||||
{
|
||||
$real = explode('\\', $class.strrchr($file, '.'));
|
||||
$tail = explode(\DIRECTORY_SEPARATOR, str_replace('/', \DIRECTORY_SEPARATOR, $file));
|
||||
|
||||
$i = \count($tail) - 1;
|
||||
$j = \count($real) - 1;
|
||||
|
||||
while (isset($tail[$i], $real[$j]) && $tail[$i] === $real[$j]) {
|
||||
--$i;
|
||||
--$j;
|
||||
}
|
||||
|
||||
array_splice($tail, 0, $i + 1);
|
||||
|
||||
if (!$tail) {
|
||||
return;
|
||||
}
|
||||
|
||||
$tail = \DIRECTORY_SEPARATOR.implode(\DIRECTORY_SEPARATOR, $tail);
|
||||
$tailLen = \strlen($tail);
|
||||
$real = $refl->getFileName();
|
||||
|
||||
if (2 === self::$caseCheck) {
|
||||
$real = $this->darwinRealpath($real);
|
||||
}
|
||||
|
||||
if (0 === substr_compare($real, $tail, -$tailLen, $tailLen, true)
|
||||
&& 0 !== substr_compare($real, $tail, -$tailLen, $tailLen, false)
|
||||
) {
|
||||
return [substr($tail, -$tailLen + 1), substr($real, -$tailLen + 1), substr($real, 0, -$tailLen + 1)];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* `realpath` on MacOSX doesn't normalize the case of characters.
|
||||
*/
|
||||
private function darwinRealpath($real)
|
||||
{
|
||||
$i = 1 + strrpos($real, '/');
|
||||
$file = substr($real, $i);
|
||||
$real = substr($real, 0, $i);
|
||||
|
||||
if (isset(self::$darwinCache[$real])) {
|
||||
$kDir = $real;
|
||||
} else {
|
||||
$kDir = strtolower($real);
|
||||
|
||||
if (isset(self::$darwinCache[$kDir])) {
|
||||
$real = self::$darwinCache[$kDir][0];
|
||||
} else {
|
||||
$ns = \substr($name, 0, $len);
|
||||
}
|
||||
$dir = getcwd();
|
||||
chdir($real);
|
||||
$real = getcwd().'/';
|
||||
chdir($dir);
|
||||
|
||||
// Detect annotations on the class
|
||||
if (false !== $doc = $refl->getDocComment()) {
|
||||
foreach (array('final', 'deprecated', 'internal') as $annotation) {
|
||||
if (false !== \strpos($doc, $annotation) && preg_match('#\n \* @'.$annotation.'(?:( .+?)\.?)?\r?\n \*(?: @|/$)#s', $doc, $notice)) {
|
||||
self::${$annotation}[$name] = isset($notice[1]) ? preg_replace('#\s*\r?\n \* +#', ' ', $notice[1]) : '';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$parentAndTraits = \class_uses($name, false);
|
||||
if ($parent = \get_parent_class($class)) {
|
||||
$parentAndTraits[] = $parent;
|
||||
|
||||
if (!isset(self::$checkedClasses[$parent])) {
|
||||
$this->checkClass($parent);
|
||||
}
|
||||
|
||||
if (isset(self::$final[$parent])) {
|
||||
@trigger_error(sprintf('The "%s" class is considered final%s. It may change without further notice as of its next major version. You should not extend it from "%s".', $parent, self::$final[$parent], $name), E_USER_DEPRECATED);
|
||||
}
|
||||
}
|
||||
|
||||
// Detect if the parent is annotated
|
||||
foreach ($parentAndTraits + $this->getOwnInterfaces($name, $parent) as $use) {
|
||||
if (!isset(self::$checkedClasses[$use])) {
|
||||
$this->checkClass($use);
|
||||
}
|
||||
if (isset(self::$deprecated[$use]) && \strncmp($ns, $use, $len)) {
|
||||
$type = class_exists($name, false) ? 'class' : (interface_exists($name, false) ? 'interface' : 'trait');
|
||||
$verb = class_exists($use, false) || interface_exists($name, false) ? 'extends' : (interface_exists($use, false) ? 'implements' : 'uses');
|
||||
|
||||
@trigger_error(sprintf('The "%s" %s %s "%s" that is deprecated%s.', $name, $type, $verb, $use, self::$deprecated[$use]), E_USER_DEPRECATED);
|
||||
}
|
||||
if (isset(self::$internal[$use]) && \strncmp($ns, $use, $len)) {
|
||||
@trigger_error(sprintf('The "%s" %s is considered internal%s. It may change without further notice. You should not use it from "%s".', $use, class_exists($use, false) ? 'class' : (interface_exists($use, false) ? 'interface' : 'trait'), self::$internal[$use], $name), E_USER_DEPRECATED);
|
||||
}
|
||||
}
|
||||
|
||||
// Inherit @final and @internal annotations for methods
|
||||
self::$finalMethods[$name] = array();
|
||||
self::$internalMethods[$name] = array();
|
||||
foreach ($parentAndTraits as $use) {
|
||||
foreach (array('finalMethods', 'internalMethods') as $property) {
|
||||
if (isset(self::${$property}[$use])) {
|
||||
self::${$property}[$name] = self::${$property}[$name] ? self::${$property}[$use] + self::${$property}[$name] : self::${$property}[$use];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$isClass = \class_exists($name, false);
|
||||
foreach ($refl->getMethods(\ReflectionMethod::IS_PUBLIC | \ReflectionMethod::IS_PROTECTED) as $method) {
|
||||
if ($method->class !== $name) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Method from a trait
|
||||
if ($method->getFilename() !== $refl->getFileName()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($isClass && $parent && isset(self::$finalMethods[$parent][$method->name])) {
|
||||
list($declaringClass, $message) = self::$finalMethods[$parent][$method->name];
|
||||
@trigger_error(sprintf('The "%s::%s()" method is considered final%s. It may change without further notice as of its next major version. You should not extend it from "%s".', $declaringClass, $method->name, $message, $name), E_USER_DEPRECATED);
|
||||
}
|
||||
|
||||
foreach ($parentAndTraits as $use) {
|
||||
if (isset(self::$internalMethods[$use][$method->name])) {
|
||||
list($declaringClass, $message) = self::$internalMethods[$use][$method->name];
|
||||
if (\strncmp($ns, $declaringClass, $len)) {
|
||||
@trigger_error(sprintf('The "%s::%s()" method is considered internal%s. It may change without further notice. You should not extend it from "%s".', $declaringClass, $method->name, $message, $name), E_USER_DEPRECATED);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Detect method annotations
|
||||
if (false === $doc = $method->getDocComment()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach (array('final', 'internal') as $annotation) {
|
||||
if (false !== \strpos($doc, $annotation) && preg_match('#\n\s+\* @'.$annotation.'(?:( .+?)\.?)?\r?\n\s+\*(?: @|/$)#s', $doc, $notice)) {
|
||||
$message = isset($notice[1]) ? preg_replace('#\s*\r?\n \* +#', ' ', $notice[1]) : '';
|
||||
self::${$annotation.'Methods'}[$name][$method->name] = array($name, $message);
|
||||
$dir = $real;
|
||||
$k = $kDir;
|
||||
$i = \strlen($dir) - 1;
|
||||
while (!isset(self::$darwinCache[$k])) {
|
||||
self::$darwinCache[$k] = [$dir, []];
|
||||
self::$darwinCache[$dir] = &self::$darwinCache[$k];
|
||||
|
||||
while ('/' !== $dir[--$i]) {
|
||||
}
|
||||
$k = substr($k, 0, ++$i);
|
||||
$dir = substr($dir, 0, $i--);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($file) {
|
||||
if (!$exists) {
|
||||
if (false !== strpos($class, '/')) {
|
||||
throw new \RuntimeException(sprintf('Trying to autoload a class with an invalid name "%s". Be careful that the namespace separator is "\" in PHP, not "/".', $class));
|
||||
}
|
||||
$dirFiles = self::$darwinCache[$kDir][1];
|
||||
|
||||
throw new \RuntimeException(sprintf('The autoloader expected class "%s" to be defined in file "%s". The file was found but the class was not in it, the class name or namespace probably has a typo.', $class, $file));
|
||||
}
|
||||
if (self::$caseCheck) {
|
||||
$real = explode('\\', $class.strrchr($file, '.'));
|
||||
$tail = explode(DIRECTORY_SEPARATOR, str_replace('/', DIRECTORY_SEPARATOR, $file));
|
||||
|
||||
$i = count($tail) - 1;
|
||||
$j = count($real) - 1;
|
||||
|
||||
while (isset($tail[$i], $real[$j]) && $tail[$i] === $real[$j]) {
|
||||
--$i;
|
||||
--$j;
|
||||
}
|
||||
|
||||
array_splice($tail, 0, $i + 1);
|
||||
}
|
||||
if (self::$caseCheck && $tail) {
|
||||
$tail = DIRECTORY_SEPARATOR.implode(DIRECTORY_SEPARATOR, $tail);
|
||||
$tailLen = strlen($tail);
|
||||
$real = $refl->getFileName();
|
||||
|
||||
if (2 === self::$caseCheck) {
|
||||
// realpath() on MacOSX doesn't normalize the case of characters
|
||||
|
||||
$i = 1 + strrpos($real, '/');
|
||||
$file = substr($real, $i);
|
||||
$real = substr($real, 0, $i);
|
||||
|
||||
if (isset(self::$darwinCache[$real])) {
|
||||
$kDir = $real;
|
||||
} else {
|
||||
$kDir = strtolower($real);
|
||||
|
||||
if (isset(self::$darwinCache[$kDir])) {
|
||||
$real = self::$darwinCache[$kDir][0];
|
||||
} else {
|
||||
$dir = getcwd();
|
||||
chdir($real);
|
||||
$real = getcwd().'/';
|
||||
chdir($dir);
|
||||
|
||||
$dir = $real;
|
||||
$k = $kDir;
|
||||
$i = strlen($dir) - 1;
|
||||
while (!isset(self::$darwinCache[$k])) {
|
||||
self::$darwinCache[$k] = array($dir, array());
|
||||
self::$darwinCache[$dir] = &self::$darwinCache[$k];
|
||||
|
||||
while ('/' !== $dir[--$i]) {
|
||||
}
|
||||
$k = substr($k, 0, ++$i);
|
||||
$dir = substr($dir, 0, $i--);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$dirFiles = self::$darwinCache[$kDir][1];
|
||||
|
||||
if (isset($dirFiles[$file])) {
|
||||
$kFile = $file;
|
||||
} else {
|
||||
$kFile = strtolower($file);
|
||||
|
||||
if (!isset($dirFiles[$kFile])) {
|
||||
foreach (scandir($real, 2) as $f) {
|
||||
if ('.' !== $f[0]) {
|
||||
$dirFiles[$f] = $f;
|
||||
if ($f === $file) {
|
||||
$kFile = $k = $file;
|
||||
} elseif ($f !== $k = strtolower($f)) {
|
||||
$dirFiles[$k] = $f;
|
||||
}
|
||||
}
|
||||
}
|
||||
self::$darwinCache[$kDir][1] = $dirFiles;
|
||||
}
|
||||
}
|
||||
|
||||
$real .= $dirFiles[$kFile];
|
||||
}
|
||||
|
||||
if (0 === substr_compare($real, $tail, -$tailLen, $tailLen, true)
|
||||
&& 0 !== substr_compare($real, $tail, -$tailLen, $tailLen, false)
|
||||
) {
|
||||
throw new \RuntimeException(sprintf('Case mismatch between class and real file names: "%s" vs "%s" in "%s".', substr($tail, -$tailLen + 1), substr($real, -$tailLen + 1), substr($real, 0, -$tailLen + 1)));
|
||||
}
|
||||
}
|
||||
if (!isset($dirFiles[$file]) && ') : eval()\'d code' === substr($file, -17)) {
|
||||
// Get the file name from "file_name.php(123) : eval()'d code"
|
||||
$file = substr($file, 0, strrpos($file, '(', -17));
|
||||
}
|
||||
|
||||
if (isset($dirFiles[$file])) {
|
||||
return $real .= $dirFiles[$file];
|
||||
}
|
||||
|
||||
$kFile = strtolower($file);
|
||||
|
||||
if (!isset($dirFiles[$kFile])) {
|
||||
foreach (scandir($real, 2) as $f) {
|
||||
if ('.' !== $f[0]) {
|
||||
$dirFiles[$f] = $f;
|
||||
if ($f === $file) {
|
||||
$kFile = $k = $file;
|
||||
} elseif ($f !== $k = strtolower($f)) {
|
||||
$dirFiles[$k] = $f;
|
||||
}
|
||||
}
|
||||
}
|
||||
self::$darwinCache[$kDir][1] = $dirFiles;
|
||||
}
|
||||
|
||||
return $real .= $dirFiles[$kFile];
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
156
ErrorHandler.php
156
ErrorHandler.php
@@ -11,16 +11,17 @@
|
||||
|
||||
namespace Symfony\Component\Debug;
|
||||
|
||||
use Psr\Log\LogLevel;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Psr\Log\LogLevel;
|
||||
use Symfony\Component\Debug\Exception\FatalErrorException;
|
||||
use Symfony\Component\Debug\Exception\FatalThrowableError;
|
||||
use Symfony\Component\Debug\Exception\FlattenException;
|
||||
use Symfony\Component\Debug\Exception\OutOfMemoryException;
|
||||
use Symfony\Component\Debug\Exception\SilencedErrorContext;
|
||||
use Symfony\Component\Debug\FatalErrorHandler\UndefinedFunctionFatalErrorHandler;
|
||||
use Symfony\Component\Debug\FatalErrorHandler\UndefinedMethodFatalErrorHandler;
|
||||
use Symfony\Component\Debug\FatalErrorHandler\ClassNotFoundFatalErrorHandler;
|
||||
use Symfony\Component\Debug\FatalErrorHandler\FatalErrorHandlerInterface;
|
||||
use Symfony\Component\Debug\FatalErrorHandler\UndefinedFunctionFatalErrorHandler;
|
||||
use Symfony\Component\Debug\FatalErrorHandler\UndefinedMethodFatalErrorHandler;
|
||||
|
||||
/**
|
||||
* A generic ErrorHandler for the PHP engine.
|
||||
@@ -47,7 +48,7 @@ use Symfony\Component\Debug\FatalErrorHandler\FatalErrorHandlerInterface;
|
||||
*/
|
||||
class ErrorHandler
|
||||
{
|
||||
private $levels = array(
|
||||
private $levels = [
|
||||
E_DEPRECATED => 'Deprecated',
|
||||
E_USER_DEPRECATED => 'User Deprecated',
|
||||
E_NOTICE => 'Notice',
|
||||
@@ -63,25 +64,25 @@ class ErrorHandler
|
||||
E_PARSE => 'Parse Error',
|
||||
E_ERROR => 'Error',
|
||||
E_CORE_ERROR => 'Core Error',
|
||||
);
|
||||
];
|
||||
|
||||
private $loggers = array(
|
||||
E_DEPRECATED => array(null, LogLevel::INFO),
|
||||
E_USER_DEPRECATED => array(null, LogLevel::INFO),
|
||||
E_NOTICE => array(null, LogLevel::WARNING),
|
||||
E_USER_NOTICE => array(null, LogLevel::WARNING),
|
||||
E_STRICT => array(null, LogLevel::WARNING),
|
||||
E_WARNING => array(null, LogLevel::WARNING),
|
||||
E_USER_WARNING => array(null, LogLevel::WARNING),
|
||||
E_COMPILE_WARNING => array(null, LogLevel::WARNING),
|
||||
E_CORE_WARNING => array(null, LogLevel::WARNING),
|
||||
E_USER_ERROR => array(null, LogLevel::CRITICAL),
|
||||
E_RECOVERABLE_ERROR => array(null, LogLevel::CRITICAL),
|
||||
E_COMPILE_ERROR => array(null, LogLevel::CRITICAL),
|
||||
E_PARSE => array(null, LogLevel::CRITICAL),
|
||||
E_ERROR => array(null, LogLevel::CRITICAL),
|
||||
E_CORE_ERROR => array(null, LogLevel::CRITICAL),
|
||||
);
|
||||
private $loggers = [
|
||||
E_DEPRECATED => [null, LogLevel::INFO],
|
||||
E_USER_DEPRECATED => [null, LogLevel::INFO],
|
||||
E_NOTICE => [null, LogLevel::WARNING],
|
||||
E_USER_NOTICE => [null, LogLevel::WARNING],
|
||||
E_STRICT => [null, LogLevel::WARNING],
|
||||
E_WARNING => [null, LogLevel::WARNING],
|
||||
E_USER_WARNING => [null, LogLevel::WARNING],
|
||||
E_COMPILE_WARNING => [null, LogLevel::WARNING],
|
||||
E_CORE_WARNING => [null, LogLevel::WARNING],
|
||||
E_USER_ERROR => [null, LogLevel::CRITICAL],
|
||||
E_RECOVERABLE_ERROR => [null, LogLevel::CRITICAL],
|
||||
E_COMPILE_ERROR => [null, LogLevel::CRITICAL],
|
||||
E_PARSE => [null, LogLevel::CRITICAL],
|
||||
E_ERROR => [null, LogLevel::CRITICAL],
|
||||
E_CORE_ERROR => [null, LogLevel::CRITICAL],
|
||||
];
|
||||
|
||||
private $thrownErrors = 0x1FFF; // E_ALL - E_DEPRECATED - E_USER_DEPRECATED
|
||||
private $scopedErrors = 0x1FFF; // E_ALL - E_DEPRECATED - E_USER_DEPRECATED
|
||||
@@ -97,7 +98,7 @@ class ErrorHandler
|
||||
|
||||
private static $reservedMemory;
|
||||
private static $toStringException = null;
|
||||
private static $silencedErrorCache = array();
|
||||
private static $silencedErrorCache = [];
|
||||
private static $silencedErrorCount = 0;
|
||||
private static $exitCode = 0;
|
||||
|
||||
@@ -120,29 +121,29 @@ class ErrorHandler
|
||||
$handler = new static();
|
||||
}
|
||||
|
||||
if (null === $prev = set_error_handler(array($handler, 'handleError'))) {
|
||||
if (null === $prev = set_error_handler([$handler, 'handleError'])) {
|
||||
restore_error_handler();
|
||||
// Specifying the error types earlier would expose us to https://bugs.php.net/63206
|
||||
set_error_handler(array($handler, 'handleError'), $handler->thrownErrors | $handler->loggedErrors);
|
||||
set_error_handler([$handler, 'handleError'], $handler->thrownErrors | $handler->loggedErrors);
|
||||
$handler->isRoot = true;
|
||||
}
|
||||
|
||||
if ($handlerIsNew && is_array($prev) && $prev[0] instanceof self) {
|
||||
if ($handlerIsNew && \is_array($prev) && $prev[0] instanceof self) {
|
||||
$handler = $prev[0];
|
||||
$replace = false;
|
||||
}
|
||||
if (!$replace && $prev) {
|
||||
restore_error_handler();
|
||||
$handlerIsRegistered = is_array($prev) && $handler === $prev[0];
|
||||
$handlerIsRegistered = \is_array($prev) && $handler === $prev[0];
|
||||
} else {
|
||||
$handlerIsRegistered = true;
|
||||
}
|
||||
if (is_array($prev = set_exception_handler(array($handler, 'handleException'))) && $prev[0] instanceof self) {
|
||||
if (\is_array($prev = set_exception_handler([$handler, 'handleException'])) && $prev[0] instanceof self) {
|
||||
restore_exception_handler();
|
||||
if (!$handlerIsRegistered) {
|
||||
$handler = $prev[0];
|
||||
} elseif ($handler !== $prev[0] && $replace) {
|
||||
set_exception_handler(array($handler, 'handleException'));
|
||||
set_exception_handler([$handler, 'handleException']);
|
||||
$p = $prev[0]->setExceptionHandler(null);
|
||||
$handler->setExceptionHandler($p);
|
||||
$prev[0]->setExceptionHandler($p);
|
||||
@@ -175,12 +176,12 @@ class ErrorHandler
|
||||
*/
|
||||
public function setDefaultLogger(LoggerInterface $logger, $levels = E_ALL, $replace = false)
|
||||
{
|
||||
$loggers = array();
|
||||
$loggers = [];
|
||||
|
||||
if (is_array($levels)) {
|
||||
if (\is_array($levels)) {
|
||||
foreach ($levels as $type => $logLevel) {
|
||||
if (empty($this->loggers[$type][0]) || $replace || $this->loggers[$type][0] === $this->bootstrappingLogger) {
|
||||
$loggers[$type] = array($logger, $logLevel);
|
||||
$loggers[$type] = [$logger, $logLevel];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -211,15 +212,15 @@ class ErrorHandler
|
||||
{
|
||||
$prevLogged = $this->loggedErrors;
|
||||
$prev = $this->loggers;
|
||||
$flush = array();
|
||||
$flush = [];
|
||||
|
||||
foreach ($loggers as $type => $log) {
|
||||
if (!isset($prev[$type])) {
|
||||
throw new \InvalidArgumentException('Unknown error type: '.$type);
|
||||
}
|
||||
if (!is_array($log)) {
|
||||
$log = array($log);
|
||||
} elseif (!array_key_exists(0, $log)) {
|
||||
if (!\is_array($log)) {
|
||||
$log = [$log];
|
||||
} elseif (!\array_key_exists(0, $log)) {
|
||||
throw new \InvalidArgumentException('No logger provided');
|
||||
}
|
||||
if (null === $log[0]) {
|
||||
@@ -350,14 +351,14 @@ class ErrorHandler
|
||||
{
|
||||
if ($prev !== $this->thrownErrors | $this->loggedErrors) {
|
||||
$handler = set_error_handler('var_dump');
|
||||
$handler = is_array($handler) ? $handler[0] : null;
|
||||
$handler = \is_array($handler) ? $handler[0] : null;
|
||||
restore_error_handler();
|
||||
if ($handler === $this) {
|
||||
restore_error_handler();
|
||||
if ($this->isRoot) {
|
||||
set_error_handler(array($this, 'handleError'), $this->thrownErrors | $this->loggedErrors);
|
||||
set_error_handler([$this, 'handleError'], $this->thrownErrors | $this->loggedErrors);
|
||||
} else {
|
||||
set_error_handler(array($this, 'handleError'));
|
||||
set_error_handler([$this, 'handleError']);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -393,10 +394,10 @@ class ErrorHandler
|
||||
}
|
||||
$scope = $this->scopedErrors & $type;
|
||||
|
||||
if (4 < $numArgs = func_num_args()) {
|
||||
$context = $scope ? (func_get_arg(4) ?: array()) : array();
|
||||
if (4 < $numArgs = \func_num_args()) {
|
||||
$context = $scope ? (func_get_arg(4) ?: []) : [];
|
||||
} else {
|
||||
$context = array();
|
||||
$context = [];
|
||||
}
|
||||
|
||||
if (isset($context['GLOBALS']) && $scope) {
|
||||
@@ -405,26 +406,30 @@ class ErrorHandler
|
||||
$context = $e;
|
||||
}
|
||||
|
||||
$logMessage = $this->levels[$type].': '.$message;
|
||||
if (false !== strpos($message, "class@anonymous\0")) {
|
||||
$logMessage = $this->levels[$type].': '.(new FlattenException())->setMessage($message)->getMessage();
|
||||
} else {
|
||||
$logMessage = $this->levels[$type].': '.$message;
|
||||
}
|
||||
|
||||
if (null !== self::$toStringException) {
|
||||
$errorAsException = self::$toStringException;
|
||||
self::$toStringException = null;
|
||||
} elseif (!$throw && !($type & $level)) {
|
||||
if (!isset(self::$silencedErrorCache[$id = $file.':'.$line])) {
|
||||
$lightTrace = $this->tracedErrors & $type ? $this->cleanTrace(debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 3), $type, $file, $line, false) : array();
|
||||
$errorAsException = new SilencedErrorContext($type, $file, $line, $lightTrace);
|
||||
$lightTrace = $this->tracedErrors & $type ? $this->cleanTrace(debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 5), $type, $file, $line, false) : [];
|
||||
$errorAsException = new SilencedErrorContext($type, $file, $line, isset($lightTrace[1]) ? [$lightTrace[0]] : $lightTrace);
|
||||
} elseif (isset(self::$silencedErrorCache[$id][$message])) {
|
||||
$lightTrace = null;
|
||||
$errorAsException = self::$silencedErrorCache[$id][$message];
|
||||
++$errorAsException->count;
|
||||
} else {
|
||||
$lightTrace = array();
|
||||
$lightTrace = [];
|
||||
$errorAsException = null;
|
||||
}
|
||||
|
||||
if (100 < ++self::$silencedErrorCount) {
|
||||
self::$silencedErrorCache = $lightTrace = array();
|
||||
self::$silencedErrorCache = $lightTrace = [];
|
||||
self::$silencedErrorCount = 1;
|
||||
}
|
||||
if ($errorAsException) {
|
||||
@@ -436,14 +441,13 @@ class ErrorHandler
|
||||
} else {
|
||||
$errorAsException = new \ErrorException($logMessage, 0, $type, $file, $line);
|
||||
|
||||
// Clean the trace by removing function arguments and the first frames added by the error handler itself.
|
||||
if ($throw || $this->tracedErrors & $type) {
|
||||
$backtrace = $errorAsException->getTrace();
|
||||
$lightTrace = $this->cleanTrace($backtrace, $type, $file, $line, $throw);
|
||||
$this->traceReflector->setValue($errorAsException, $lightTrace);
|
||||
} else {
|
||||
$this->traceReflector->setValue($errorAsException, array());
|
||||
$backtrace = array();
|
||||
$this->traceReflector->setValue($errorAsException, []);
|
||||
$backtrace = [];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -486,12 +490,21 @@ class ErrorHandler
|
||||
if ($this->isRecursive) {
|
||||
$log = 0;
|
||||
} else {
|
||||
if (!\defined('HHVM_VERSION')) {
|
||||
$currentErrorHandler = set_error_handler('var_dump');
|
||||
restore_error_handler();
|
||||
}
|
||||
|
||||
try {
|
||||
$this->isRecursive = true;
|
||||
$level = ($type & $level) ? $this->loggers[$type][1] : LogLevel::DEBUG;
|
||||
$this->loggers[$type][0]->log($level, $logMessage, $errorAsException ? array('exception' => $errorAsException) : array());
|
||||
$this->loggers[$type][0]->log($level, $logMessage, $errorAsException ? ['exception' => $errorAsException] : []);
|
||||
} finally {
|
||||
$this->isRecursive = false;
|
||||
|
||||
if (!\defined('HHVM_VERSION')) {
|
||||
set_error_handler($currentErrorHandler);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -518,26 +531,29 @@ class ErrorHandler
|
||||
$handlerException = null;
|
||||
|
||||
if (($this->loggedErrors & $type) || $exception instanceof FatalThrowableError) {
|
||||
if (false !== strpos($message = $exception->getMessage(), "class@anonymous\0")) {
|
||||
$message = (new FlattenException())->setMessage($message)->getMessage();
|
||||
}
|
||||
if ($exception instanceof FatalErrorException) {
|
||||
if ($exception instanceof FatalThrowableError) {
|
||||
$error = array(
|
||||
$error = [
|
||||
'type' => $type,
|
||||
'message' => $message = $exception->getMessage(),
|
||||
'message' => $message,
|
||||
'file' => $exception->getFile(),
|
||||
'line' => $exception->getLine(),
|
||||
);
|
||||
];
|
||||
} else {
|
||||
$message = 'Fatal '.$exception->getMessage();
|
||||
$message = 'Fatal '.$message;
|
||||
}
|
||||
} elseif ($exception instanceof \ErrorException) {
|
||||
$message = 'Uncaught '.$exception->getMessage();
|
||||
$message = 'Uncaught '.$message;
|
||||
} else {
|
||||
$message = 'Uncaught Exception: '.$exception->getMessage();
|
||||
$message = 'Uncaught Exception: '.$message;
|
||||
}
|
||||
}
|
||||
if ($this->loggedErrors & $type) {
|
||||
try {
|
||||
$this->loggers[$type][0]->log($this->loggers[$type][1], $message, array('exception' => $exception));
|
||||
$this->loggers[$type][0]->log($this->loggers[$type][1], $message, ['exception' => $exception]);
|
||||
} catch (\Throwable $handlerException) {
|
||||
}
|
||||
}
|
||||
@@ -553,7 +569,7 @@ class ErrorHandler
|
||||
$this->exceptionHandler = null;
|
||||
try {
|
||||
if (null !== $exceptionHandler) {
|
||||
return \call_user_func($exceptionHandler, $exception);
|
||||
return $exceptionHandler($exception);
|
||||
}
|
||||
$handlerException = $handlerException ?: $exception;
|
||||
} catch (\Throwable $handlerException) {
|
||||
@@ -579,11 +595,11 @@ class ErrorHandler
|
||||
}
|
||||
|
||||
$handler = self::$reservedMemory = null;
|
||||
$handlers = array();
|
||||
$handlers = [];
|
||||
$previousHandler = null;
|
||||
$sameHandlerLimit = 10;
|
||||
|
||||
while (!is_array($handler) || !$handler[0] instanceof self) {
|
||||
while (!\is_array($handler) || !$handler[0] instanceof self) {
|
||||
$handler = set_exception_handler('var_dump');
|
||||
restore_exception_handler();
|
||||
|
||||
@@ -610,7 +626,7 @@ class ErrorHandler
|
||||
$handler[0]->setExceptionHandler($h);
|
||||
}
|
||||
$handler = $handler[0];
|
||||
$handlers = array();
|
||||
$handlers = [];
|
||||
|
||||
if ($exit = null === $error) {
|
||||
$error = error_get_last();
|
||||
@@ -654,23 +670,33 @@ class ErrorHandler
|
||||
*/
|
||||
protected function getFatalErrorHandlers()
|
||||
{
|
||||
return array(
|
||||
return [
|
||||
new UndefinedFunctionFatalErrorHandler(),
|
||||
new UndefinedMethodFatalErrorHandler(),
|
||||
new ClassNotFoundFatalErrorHandler(),
|
||||
);
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Cleans the trace by removing function arguments and the frames added by the error handler and DebugClassLoader.
|
||||
*/
|
||||
private function cleanTrace($backtrace, $type, $file, $line, $throw)
|
||||
{
|
||||
$lightTrace = $backtrace;
|
||||
|
||||
for ($i = 0; isset($backtrace[$i]); ++$i) {
|
||||
if (isset($backtrace[$i]['file'], $backtrace[$i]['line']) && $backtrace[$i]['line'] === $line && $backtrace[$i]['file'] === $file) {
|
||||
$lightTrace = array_slice($lightTrace, 1 + $i);
|
||||
$lightTrace = \array_slice($lightTrace, 1 + $i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (class_exists(DebugClassLoader::class, false)) {
|
||||
for ($i = \count($lightTrace) - 2; 0 < $i; --$i) {
|
||||
if (DebugClassLoader::class === ($lightTrace[$i]['class'] ?? null)) {
|
||||
array_splice($lightTrace, --$i, 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!($throw || $this->scopedErrors & $type)) {
|
||||
for ($i = 0; isset($lightTrace[$i]); ++$i) {
|
||||
unset($lightTrace[$i]['args'], $lightTrace[$i]['object']);
|
||||
|
||||
@@ -26,6 +26,9 @@ class ClassNotFoundException extends FatalErrorException
|
||||
$previous->getSeverity(),
|
||||
$previous->getFile(),
|
||||
$previous->getLine(),
|
||||
null,
|
||||
true,
|
||||
null,
|
||||
$previous->getPrevious()
|
||||
);
|
||||
$this->setTrace($previous->getTrace());
|
||||
|
||||
@@ -18,9 +18,9 @@ namespace Symfony\Component\Debug\Exception;
|
||||
*/
|
||||
class FatalErrorException extends \ErrorException
|
||||
{
|
||||
public function __construct(string $message, int $code, int $severity, string $filename, int $lineno, int $traceOffset = null, bool $traceArgs = true, array $trace = null)
|
||||
public function __construct(string $message, int $code, int $severity, string $filename, int $lineno, int $traceOffset = null, bool $traceArgs = true, array $trace = null, \Throwable $previous = null)
|
||||
{
|
||||
parent::__construct($message, $code, $severity, $filename, $lineno);
|
||||
parent::__construct($message, $code, $severity, $filename, $lineno, $previous);
|
||||
|
||||
if (null !== $trace) {
|
||||
if (!$traceArgs) {
|
||||
@@ -31,7 +31,7 @@ class FatalErrorException extends \ErrorException
|
||||
|
||||
$this->setTrace($trace);
|
||||
} elseif (null !== $traceOffset) {
|
||||
if (function_exists('xdebug_get_function_stack')) {
|
||||
if (\function_exists('xdebug_get_function_stack')) {
|
||||
$trace = xdebug_get_function_stack();
|
||||
if (0 < $traceOffset) {
|
||||
array_splice($trace, -$traceOffset);
|
||||
@@ -61,7 +61,7 @@ class FatalErrorException extends \ErrorException
|
||||
unset($frame);
|
||||
$trace = array_reverse($trace);
|
||||
} else {
|
||||
$trace = array();
|
||||
$trace = [];
|
||||
}
|
||||
|
||||
$this->setTrace($trace);
|
||||
|
||||
@@ -33,12 +33,12 @@ class FlattenException
|
||||
private $file;
|
||||
private $line;
|
||||
|
||||
public static function create(\Exception $exception, $statusCode = null, array $headers = array())
|
||||
public static function create(\Exception $exception, $statusCode = null, array $headers = [])
|
||||
{
|
||||
return static::createFromThrowable($exception, $statusCode, $headers);
|
||||
}
|
||||
|
||||
public static function createFromThrowable(\Throwable $exception, ?int $statusCode = null, array $headers = array()): self
|
||||
public static function createFromThrowable(\Throwable $exception, ?int $statusCode = null, array $headers = []): self
|
||||
{
|
||||
$e = new static();
|
||||
$e->setMessage($exception->getMessage());
|
||||
@@ -73,13 +73,13 @@ class FlattenException
|
||||
|
||||
public function toArray()
|
||||
{
|
||||
$exceptions = array();
|
||||
foreach (array_merge(array($this), $this->getAllPrevious()) as $exception) {
|
||||
$exceptions[] = array(
|
||||
$exceptions = [];
|
||||
foreach (array_merge([$this], $this->getAllPrevious()) as $exception) {
|
||||
$exceptions[] = [
|
||||
'message' => $exception->getMessage(),
|
||||
'class' => $exception->getClass(),
|
||||
'trace' => $exception->getTrace(),
|
||||
);
|
||||
];
|
||||
}
|
||||
|
||||
return $exceptions;
|
||||
@@ -90,9 +90,14 @@ class FlattenException
|
||||
return $this->statusCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return $this
|
||||
*/
|
||||
public function setStatusCode($code)
|
||||
{
|
||||
$this->statusCode = $code;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getHeaders()
|
||||
@@ -100,9 +105,14 @@ class FlattenException
|
||||
return $this->headers;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return $this
|
||||
*/
|
||||
public function setHeaders(array $headers)
|
||||
{
|
||||
$this->headers = $headers;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getClass()
|
||||
@@ -110,9 +120,14 @@ class FlattenException
|
||||
return $this->class;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return $this
|
||||
*/
|
||||
public function setClass($class)
|
||||
{
|
||||
$this->class = $class;
|
||||
$this->class = 'c' === $class[0] && 0 === strpos($class, "class@anonymous\0") ? get_parent_class($class).'@anonymous' : $class;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getFile()
|
||||
@@ -120,9 +135,14 @@ class FlattenException
|
||||
return $this->file;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return $this
|
||||
*/
|
||||
public function setFile($file)
|
||||
{
|
||||
$this->file = $file;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getLine()
|
||||
@@ -130,9 +150,14 @@ class FlattenException
|
||||
return $this->line;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return $this
|
||||
*/
|
||||
public function setLine($line)
|
||||
{
|
||||
$this->line = $line;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getMessage()
|
||||
@@ -140,9 +165,20 @@ class FlattenException
|
||||
return $this->message;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return $this
|
||||
*/
|
||||
public function setMessage($message)
|
||||
{
|
||||
if (false !== strpos($message, "class@anonymous\0")) {
|
||||
$message = preg_replace_callback('/class@anonymous\x00.*?\.php0x?[0-9a-fA-F]++/', function ($m) {
|
||||
return \class_exists($m[0], false) ? get_parent_class($m[0]).'@anonymous' : $m[0];
|
||||
}, $message);
|
||||
}
|
||||
|
||||
$this->message = $message;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getCode()
|
||||
@@ -150,9 +186,14 @@ class FlattenException
|
||||
return $this->code;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return $this
|
||||
*/
|
||||
public function setCode($code)
|
||||
{
|
||||
$this->code = $code;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getPrevious()
|
||||
@@ -160,14 +201,19 @@ class FlattenException
|
||||
return $this->previous;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return $this
|
||||
*/
|
||||
public function setPrevious(self $previous)
|
||||
{
|
||||
$this->previous = $previous;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getAllPrevious()
|
||||
{
|
||||
$exceptions = array();
|
||||
$exceptions = [];
|
||||
$e = $this;
|
||||
while ($e = $e->getPrevious()) {
|
||||
$exceptions[] = $e;
|
||||
@@ -186,20 +232,23 @@ class FlattenException
|
||||
*/
|
||||
public function setTraceFromException(\Exception $exception)
|
||||
{
|
||||
@trigger_error(sprintf('"%s" is deprecated since Symfony 4.1, use "setTraceFromThrowable()" instead.', __METHOD__), E_USER_DEPRECATED);
|
||||
@trigger_error(sprintf('The "%s()" method is deprecated since Symfony 4.1, use "setTraceFromThrowable()" instead.', __METHOD__), E_USER_DEPRECATED);
|
||||
|
||||
$this->setTraceFromThrowable($exception);
|
||||
}
|
||||
|
||||
public function setTraceFromThrowable(\Throwable $throwable): void
|
||||
public function setTraceFromThrowable(\Throwable $throwable)
|
||||
{
|
||||
$this->setTrace($throwable->getTrace(), $throwable->getFile(), $throwable->getLine());
|
||||
return $this->setTrace($throwable->getTrace(), $throwable->getFile(), $throwable->getLine());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return $this
|
||||
*/
|
||||
public function setTrace($trace, $file, $line)
|
||||
{
|
||||
$this->trace = array();
|
||||
$this->trace[] = array(
|
||||
$this->trace = [];
|
||||
$this->trace[] = [
|
||||
'namespace' => '',
|
||||
'short_class' => '',
|
||||
'class' => '',
|
||||
@@ -207,8 +256,8 @@ class FlattenException
|
||||
'function' => '',
|
||||
'file' => $file,
|
||||
'line' => $line,
|
||||
'args' => array(),
|
||||
);
|
||||
'args' => [],
|
||||
];
|
||||
foreach ($trace as $entry) {
|
||||
$class = '';
|
||||
$namespace = '';
|
||||
@@ -218,7 +267,7 @@ class FlattenException
|
||||
$namespace = implode('\\', $parts);
|
||||
}
|
||||
|
||||
$this->trace[] = array(
|
||||
$this->trace[] = [
|
||||
'namespace' => $namespace,
|
||||
'short_class' => $class,
|
||||
'class' => isset($entry['class']) ? $entry['class'] : '',
|
||||
@@ -226,41 +275,43 @@ class FlattenException
|
||||
'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(),
|
||||
);
|
||||
'args' => isset($entry['args']) ? $this->flattenArgs($entry['args']) : [],
|
||||
];
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
private function flattenArgs($args, $level = 0, &$count = 0)
|
||||
{
|
||||
$result = array();
|
||||
$result = [];
|
||||
foreach ($args as $key => $value) {
|
||||
if (++$count > 1e4) {
|
||||
return array('array', '*SKIPPED over 10000 entries*');
|
||||
return ['array', '*SKIPPED over 10000 entries*'];
|
||||
}
|
||||
if ($value instanceof \__PHP_Incomplete_Class) {
|
||||
// is_object() returns false on PHP<=7.1
|
||||
$result[$key] = array('incomplete-object', $this->getClassNameFromIncomplete($value));
|
||||
} elseif (is_object($value)) {
|
||||
$result[$key] = array('object', get_class($value));
|
||||
} elseif (is_array($value)) {
|
||||
$result[$key] = ['incomplete-object', $this->getClassNameFromIncomplete($value)];
|
||||
} elseif (\is_object($value)) {
|
||||
$result[$key] = ['object', \get_class($value)];
|
||||
} elseif (\is_array($value)) {
|
||||
if ($level > 10) {
|
||||
$result[$key] = array('array', '*DEEP NESTED ARRAY*');
|
||||
$result[$key] = ['array', '*DEEP NESTED ARRAY*'];
|
||||
} else {
|
||||
$result[$key] = array('array', $this->flattenArgs($value, $level + 1, $count));
|
||||
$result[$key] = ['array', $this->flattenArgs($value, $level + 1, $count)];
|
||||
}
|
||||
} elseif (null === $value) {
|
||||
$result[$key] = array('null', null);
|
||||
} elseif (is_bool($value)) {
|
||||
$result[$key] = array('boolean', $value);
|
||||
} elseif (is_int($value)) {
|
||||
$result[$key] = array('integer', $value);
|
||||
} elseif (is_float($value)) {
|
||||
$result[$key] = array('float', $value);
|
||||
} elseif (is_resource($value)) {
|
||||
$result[$key] = array('resource', get_resource_type($value));
|
||||
$result[$key] = ['null', null];
|
||||
} elseif (\is_bool($value)) {
|
||||
$result[$key] = ['boolean', $value];
|
||||
} elseif (\is_int($value)) {
|
||||
$result[$key] = ['integer', $value];
|
||||
} elseif (\is_float($value)) {
|
||||
$result[$key] = ['float', $value];
|
||||
} elseif (\is_resource($value)) {
|
||||
$result[$key] = ['resource', get_resource_type($value)];
|
||||
} else {
|
||||
$result[$key] = array('string', (string) $value);
|
||||
$result[$key] = ['string', (string) $value];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ class SilencedErrorContext implements \JsonSerializable
|
||||
private $line;
|
||||
private $trace;
|
||||
|
||||
public function __construct(int $severity, string $file, int $line, array $trace = array(), int $count = 1)
|
||||
public function __construct(int $severity, string $file, int $line, array $trace = [], int $count = 1)
|
||||
{
|
||||
$this->severity = $severity;
|
||||
$this->file = $file;
|
||||
@@ -56,12 +56,12 @@ class SilencedErrorContext implements \JsonSerializable
|
||||
|
||||
public function JsonSerialize()
|
||||
{
|
||||
return array(
|
||||
return [
|
||||
'severity' => $this->severity,
|
||||
'file' => $this->file,
|
||||
'line' => $this->line,
|
||||
'trace' => $this->trace,
|
||||
'count' => $this->count,
|
||||
);
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,6 +26,9 @@ class UndefinedFunctionException extends FatalErrorException
|
||||
$previous->getSeverity(),
|
||||
$previous->getFile(),
|
||||
$previous->getLine(),
|
||||
null,
|
||||
true,
|
||||
null,
|
||||
$previous->getPrevious()
|
||||
);
|
||||
$this->setTrace($previous->getTrace());
|
||||
|
||||
@@ -26,6 +26,9 @@ class UndefinedMethodException extends FatalErrorException
|
||||
$previous->getSeverity(),
|
||||
$previous->getFile(),
|
||||
$previous->getLine(),
|
||||
null,
|
||||
true,
|
||||
null,
|
||||
$previous->getPrevious()
|
||||
);
|
||||
$this->setTrace($previous->getTrace());
|
||||
|
||||
@@ -56,10 +56,10 @@ class ExceptionHandler
|
||||
{
|
||||
$handler = new static($debug, $charset, $fileLinkFormat);
|
||||
|
||||
$prev = set_exception_handler(array($handler, 'handle'));
|
||||
if (is_array($prev) && $prev[0] instanceof ErrorHandler) {
|
||||
$prev = set_exception_handler([$handler, 'handle']);
|
||||
if (\is_array($prev) && $prev[0] instanceof ErrorHandler) {
|
||||
restore_exception_handler();
|
||||
$prev[0]->setExceptionHandler(array($handler, 'handle'));
|
||||
$prev[0]->setExceptionHandler([$handler, 'handle']);
|
||||
}
|
||||
|
||||
return $handler;
|
||||
@@ -142,7 +142,7 @@ class ExceptionHandler
|
||||
$this->caughtBuffer = null;
|
||||
|
||||
try {
|
||||
call_user_func($this->handler, $exception);
|
||||
($this->handler)($exception);
|
||||
$this->caughtLength = $caughtLength;
|
||||
} catch (\Exception $e) {
|
||||
if (!$caughtLength) {
|
||||
@@ -208,48 +208,55 @@ class ExceptionHandler
|
||||
$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->formatClass($e['class']);
|
||||
$message = nl2br($this->escapeHtml($e['message']));
|
||||
$content .= sprintf(<<<'EOF'
|
||||
<div class="trace trace-as-html">
|
||||
<table class="trace-details">
|
||||
<thead class="trace-head"><tr><th>
|
||||
<h3 class="trace-class">
|
||||
<span class="text-muted">(%d/%d)</span>
|
||||
<span class="exception_title">%s</span>
|
||||
</h3>
|
||||
<p class="break-long-words trace-message">%s</p>
|
||||
</th></tr></thead>
|
||||
<tbody>
|
||||
EOF
|
||||
, $ind, $total, $class, $message);
|
||||
foreach ($e['trace'] as $trace) {
|
||||
$content .= '<tr><td>';
|
||||
if ($trace['function']) {
|
||||
$content .= sprintf('at <span class="trace-class">%s</span><span class="trace-type">%s</span><span class="trace-method">%s</span>(<span class="trace-arguments">%s</span>)', $this->formatClass($trace['class']), $trace['type'], $trace['function'], $this->formatArgs($trace['args']));
|
||||
}
|
||||
if (isset($trace['file']) && isset($trace['line'])) {
|
||||
$content .= $this->formatPath($trace['file'], $trace['line']);
|
||||
}
|
||||
$content .= "</td></tr>\n";
|
||||
}
|
||||
if (!$this->debug) {
|
||||
return <<<EOF
|
||||
<div class="container">
|
||||
<h1>$title</h1>
|
||||
</div>
|
||||
EOF;
|
||||
}
|
||||
|
||||
$content .= "</tbody>\n</table>\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($e), $this->escapeHtml($e->getMessage()));
|
||||
} else {
|
||||
$title = 'Whoops, looks like something went wrong.';
|
||||
$content = '';
|
||||
try {
|
||||
$count = \count($exception->getAllPrevious());
|
||||
$total = $count + 1;
|
||||
foreach ($exception->toArray() as $position => $e) {
|
||||
$ind = $count - $position + 1;
|
||||
$class = $this->formatClass($e['class']);
|
||||
$message = nl2br($this->escapeHtml($e['message']));
|
||||
$content .= sprintf(<<<'EOF'
|
||||
<div class="trace trace-as-html">
|
||||
<table class="trace-details">
|
||||
<thead class="trace-head"><tr><th>
|
||||
<h3 class="trace-class">
|
||||
<span class="text-muted">(%d/%d)</span>
|
||||
<span class="exception_title">%s</span>
|
||||
</h3>
|
||||
<p class="break-long-words trace-message">%s</p>
|
||||
</th></tr></thead>
|
||||
<tbody>
|
||||
EOF
|
||||
, $ind, $total, $class, $message);
|
||||
foreach ($e['trace'] as $trace) {
|
||||
$content .= '<tr><td>';
|
||||
if ($trace['function']) {
|
||||
$content .= sprintf('at <span class="trace-class">%s</span><span class="trace-type">%s</span><span class="trace-method">%s</span>(<span class="trace-arguments">%s</span>)', $this->formatClass($trace['class']), $trace['type'], $trace['function'], $this->formatArgs($trace['args']));
|
||||
}
|
||||
if (isset($trace['file']) && isset($trace['line'])) {
|
||||
$content .= $this->formatPath($trace['file'], $trace['line']);
|
||||
}
|
||||
$content .= "</td></tr>\n";
|
||||
}
|
||||
|
||||
$content .= "</tbody>\n</table>\n</div>\n";
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
// something nasty happened and we cannot throw an exception anymore
|
||||
if ($this->debug) {
|
||||
$e = FlattenException::create($e);
|
||||
$title = sprintf('Exception thrown when handling an exception (%s: %s)', $e->getClass(), $this->escapeHtml($e->getMessage()));
|
||||
} else {
|
||||
$title = 'Whoops, looks like something went wrong.';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -278,6 +285,14 @@ EOF;
|
||||
*/
|
||||
public function getStylesheet(FlattenException $exception)
|
||||
{
|
||||
if (!$this->debug) {
|
||||
return <<<'EOF'
|
||||
body { background-color: #fff; color: #222; font: 16px/1.5 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif; margin: 0; }
|
||||
.container { margin: 30px; max-width: 600px; }
|
||||
h1 { color: #dc3545; font-size: 24px; }
|
||||
EOF;
|
||||
}
|
||||
|
||||
return <<<'EOF'
|
||||
body { background-color: #F9F9F9; color: #222; font: 14px/1.4 Helvetica, Arial, sans-serif; margin: 0; padding-bottom: 45px; }
|
||||
|
||||
@@ -362,17 +377,17 @@ EOF;
|
||||
}
|
||||
|
||||
if (\is_string($fmt)) {
|
||||
$i = strpos($f = $fmt, '&', max(strrpos($f, '%f'), strrpos($f, '%l'))) ?: strlen($f);
|
||||
$fmt = array(substr($f, 0, $i)) + preg_split('/&([^>]++)>/', substr($f, $i), -1, PREG_SPLIT_DELIM_CAPTURE);
|
||||
$i = strpos($f = $fmt, '&', max(strrpos($f, '%f'), strrpos($f, '%l'))) ?: \strlen($f);
|
||||
$fmt = [substr($f, 0, $i)] + preg_split('/&([^>]++)>/', substr($f, $i), -1, PREG_SPLIT_DELIM_CAPTURE);
|
||||
|
||||
for ($i = 1; isset($fmt[$i]); ++$i) {
|
||||
if (0 === strpos($path, $k = $fmt[$i++])) {
|
||||
$path = substr_replace($path, $fmt[$i], 0, strlen($k));
|
||||
$path = substr_replace($path, $fmt[$i], 0, \strlen($k));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$link = strtr($fmt[0], array('%f' => $path, '%l' => $line));
|
||||
$link = strtr($fmt[0], ['%f' => $path, '%l' => $line]);
|
||||
} else {
|
||||
$link = $fmt->format($path, $line);
|
||||
}
|
||||
@@ -389,12 +404,12 @@ EOF;
|
||||
*/
|
||||
private function formatArgs(array $args)
|
||||
{
|
||||
$result = array();
|
||||
$result = [];
|
||||
foreach ($args as $key => $item) {
|
||||
if ('object' === $item[0]) {
|
||||
$formattedValue = sprintf('<em>object</em>(%s)', $this->formatClass($item[1]));
|
||||
} elseif ('array' === $item[0]) {
|
||||
$formattedValue = sprintf('<em>array</em>(%s)', is_array($item[1]) ? $this->formatArgs($item[1]) : $item[1]);
|
||||
$formattedValue = sprintf('<em>array</em>(%s)', \is_array($item[1]) ? $this->formatArgs($item[1]) : $item[1]);
|
||||
} elseif ('null' === $item[0]) {
|
||||
$formattedValue = '<em>null</em>';
|
||||
} elseif ('boolean' === $item[0]) {
|
||||
@@ -405,7 +420,7 @@ EOF;
|
||||
$formattedValue = str_replace("\n", '', $this->escapeHtml(var_export($item[1], true)));
|
||||
}
|
||||
|
||||
$result[] = is_int($key) ? $formattedValue : sprintf("'%s' => %s", $this->escapeHtml($key), $formattedValue);
|
||||
$result[] = \is_int($key) ? $formattedValue : sprintf("'%s' => %s", $this->escapeHtml($key), $formattedValue);
|
||||
}
|
||||
|
||||
return implode(', ', $result);
|
||||
|
||||
@@ -11,11 +11,11 @@
|
||||
|
||||
namespace Symfony\Component\Debug\FatalErrorHandler;
|
||||
|
||||
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\ClassLoader as SymfonyClassLoader;
|
||||
use Symfony\Component\Debug\DebugClassLoader;
|
||||
use Symfony\Component\Debug\Exception\ClassNotFoundException;
|
||||
use Symfony\Component\Debug\Exception\FatalErrorException;
|
||||
|
||||
/**
|
||||
* ErrorHandler for classes that do not exist.
|
||||
@@ -29,9 +29,9 @@ class ClassNotFoundFatalErrorHandler implements FatalErrorHandlerInterface
|
||||
*/
|
||||
public function handleError(array $error, FatalErrorException $exception)
|
||||
{
|
||||
$messageLen = strlen($error['message']);
|
||||
$messageLen = \strlen($error['message']);
|
||||
$notFoundSuffix = '\' not found';
|
||||
$notFoundSuffixLen = strlen($notFoundSuffix);
|
||||
$notFoundSuffixLen = \strlen($notFoundSuffix);
|
||||
if ($notFoundSuffixLen > $messageLen) {
|
||||
return;
|
||||
}
|
||||
@@ -40,9 +40,9 @@ class ClassNotFoundFatalErrorHandler implements FatalErrorHandlerInterface
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (array('class', 'interface', 'trait') as $typeName) {
|
||||
foreach (['class', 'interface', 'trait'] as $typeName) {
|
||||
$prefix = ucfirst($typeName).' \'';
|
||||
$prefixLen = strlen($prefix);
|
||||
$prefixLen = \strlen($prefix);
|
||||
if (0 !== strpos($error['message'], $prefix)) {
|
||||
continue;
|
||||
}
|
||||
@@ -85,22 +85,22 @@ class ClassNotFoundFatalErrorHandler implements FatalErrorHandlerInterface
|
||||
*/
|
||||
private function getClassCandidates(string $class): array
|
||||
{
|
||||
if (!is_array($functions = spl_autoload_functions())) {
|
||||
return array();
|
||||
if (!\is_array($functions = spl_autoload_functions())) {
|
||||
return [];
|
||||
}
|
||||
|
||||
// find Symfony and Composer autoloaders
|
||||
$classes = array();
|
||||
$classes = [];
|
||||
|
||||
foreach ($functions as $function) {
|
||||
if (!is_array($function)) {
|
||||
if (!\is_array($function)) {
|
||||
continue;
|
||||
}
|
||||
// get class loaders wrapped by DebugClassLoader
|
||||
if ($function[0] instanceof DebugClassLoader) {
|
||||
$function = $function[0]->getClassLoader();
|
||||
|
||||
if (!is_array($function)) {
|
||||
if (!\is_array($function)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@@ -126,11 +126,11 @@ class ClassNotFoundFatalErrorHandler implements FatalErrorHandlerInterface
|
||||
|
||||
private function findClassInPath(string $path, string $class, string $prefix): array
|
||||
{
|
||||
if (!$path = realpath($path.'/'.strtr($prefix, '\\_', '//')) ?: realpath($path.'/'.dirname(strtr($prefix, '\\_', '//'))) ?: realpath($path)) {
|
||||
return array();
|
||||
if (!$path = realpath($path.'/'.strtr($prefix, '\\_', '//')) ?: realpath($path.'/'.\dirname(strtr($prefix, '\\_', '//'))) ?: realpath($path)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$classes = array();
|
||||
$classes = [];
|
||||
$filename = $class.'.php';
|
||||
foreach (new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($path, \RecursiveDirectoryIterator::SKIP_DOTS), \RecursiveIteratorIterator::LEAVES_ONLY) as $file) {
|
||||
if ($filename == $file->getFileName() && $class = $this->convertFileToClass($path, $file->getPathName(), $prefix)) {
|
||||
@@ -143,9 +143,9 @@ class ClassNotFoundFatalErrorHandler implements FatalErrorHandlerInterface
|
||||
|
||||
private function convertFileToClass(string $path, string $file, string $prefix): ?string
|
||||
{
|
||||
$candidates = array(
|
||||
$candidates = [
|
||||
// namespaced class
|
||||
$namespacedClass = str_replace(array($path.DIRECTORY_SEPARATOR, '.php', '/'), array('', '', '\\'), $file),
|
||||
$namespacedClass = str_replace([$path.\DIRECTORY_SEPARATOR, '.php', '/'], ['', '', '\\'], $file),
|
||||
// namespaced class (with target dir)
|
||||
$prefix.$namespacedClass,
|
||||
// namespaced class (with target dir and separator)
|
||||
@@ -156,7 +156,7 @@ class ClassNotFoundFatalErrorHandler implements FatalErrorHandlerInterface
|
||||
str_replace('\\', '_', $prefix.$namespacedClass),
|
||||
// PEAR class (with target dir and separator)
|
||||
str_replace('\\', '_', $prefix.'\\'.$namespacedClass),
|
||||
);
|
||||
];
|
||||
|
||||
if ($prefix) {
|
||||
$candidates = array_filter($candidates, function ($candidate) use ($prefix) { return 0 === strpos($candidate, $prefix); });
|
||||
|
||||
@@ -11,8 +11,8 @@
|
||||
|
||||
namespace Symfony\Component\Debug\FatalErrorHandler;
|
||||
|
||||
use Symfony\Component\Debug\Exception\UndefinedFunctionException;
|
||||
use Symfony\Component\Debug\Exception\FatalErrorException;
|
||||
use Symfony\Component\Debug\Exception\UndefinedFunctionException;
|
||||
|
||||
/**
|
||||
* ErrorHandler for undefined functions.
|
||||
@@ -26,9 +26,9 @@ class UndefinedFunctionFatalErrorHandler implements FatalErrorHandlerInterface
|
||||
*/
|
||||
public function handleError(array $error, FatalErrorException $exception)
|
||||
{
|
||||
$messageLen = strlen($error['message']);
|
||||
$messageLen = \strlen($error['message']);
|
||||
$notFoundSuffix = '()';
|
||||
$notFoundSuffixLen = strlen($notFoundSuffix);
|
||||
$notFoundSuffixLen = \strlen($notFoundSuffix);
|
||||
if ($notFoundSuffixLen > $messageLen) {
|
||||
return;
|
||||
}
|
||||
@@ -38,7 +38,7 @@ class UndefinedFunctionFatalErrorHandler implements FatalErrorHandlerInterface
|
||||
}
|
||||
|
||||
$prefix = 'Call to undefined function ';
|
||||
$prefixLen = strlen($prefix);
|
||||
$prefixLen = \strlen($prefix);
|
||||
if (0 !== strpos($error['message'], $prefix)) {
|
||||
return;
|
||||
}
|
||||
@@ -53,7 +53,7 @@ class UndefinedFunctionFatalErrorHandler implements FatalErrorHandlerInterface
|
||||
$message = sprintf('Attempted to call function "%s" from the global namespace.', $functionName);
|
||||
}
|
||||
|
||||
$candidates = array();
|
||||
$candidates = [];
|
||||
foreach (get_defined_functions() as $type => $definedFunctionNames) {
|
||||
foreach ($definedFunctionNames as $definedFunctionName) {
|
||||
if (false !== $namespaceSeparatorIndex = strrpos($definedFunctionName, '\\')) {
|
||||
|
||||
@@ -41,10 +41,10 @@ class UndefinedMethodFatalErrorHandler implements FatalErrorHandlerInterface
|
||||
return new UndefinedMethodException($message, $exception);
|
||||
}
|
||||
|
||||
$candidates = array();
|
||||
$candidates = [];
|
||||
foreach ($methods as $definedMethodName) {
|
||||
$lev = levenshtein($methodName, $definedMethodName);
|
||||
if ($lev <= strlen($methodName) / 3 || false !== strpos($definedMethodName, $methodName)) {
|
||||
if ($lev <= \strlen($methodName) / 3 || false !== strpos($definedMethodName, $methodName)) {
|
||||
$candidates[] = $definedMethodName;
|
||||
}
|
||||
}
|
||||
|
||||
2
LICENSE
2
LICENSE
@@ -1,4 +1,4 @@
|
||||
Copyright (c) 2004-2018 Fabien Potencier
|
||||
Copyright (c) 2004-2019 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
|
||||
|
||||
@@ -27,14 +27,14 @@ class DebugClassLoaderTest extends TestCase
|
||||
{
|
||||
$this->errorReporting = error_reporting(E_ALL);
|
||||
$this->loader = new ClassLoader();
|
||||
spl_autoload_register(array($this->loader, 'loadClass'), true, true);
|
||||
spl_autoload_register([$this->loader, 'loadClass'], true, true);
|
||||
DebugClassLoader::enable();
|
||||
}
|
||||
|
||||
protected function tearDown()
|
||||
{
|
||||
DebugClassLoader::disable();
|
||||
spl_autoload_unregister(array($this->loader, 'loadClass'));
|
||||
spl_autoload_unregister([$this->loader, 'loadClass']);
|
||||
error_reporting($this->errorReporting);
|
||||
}
|
||||
|
||||
@@ -44,7 +44,7 @@ class DebugClassLoaderTest extends TestCase
|
||||
|
||||
$functions = spl_autoload_functions();
|
||||
foreach ($functions as $function) {
|
||||
if (is_array($function) && $function[0] instanceof DebugClassLoader) {
|
||||
if (\is_array($function) && $function[0] instanceof DebugClassLoader) {
|
||||
$reflClass = new \ReflectionClass($function[0]);
|
||||
$reflProp = $reflClass->getProperty('classLoader');
|
||||
$reflProp->setAccessible(true);
|
||||
@@ -136,20 +136,20 @@ class DebugClassLoaderTest extends TestCase
|
||||
$lastError = error_get_last();
|
||||
unset($lastError['file'], $lastError['line']);
|
||||
|
||||
$xError = array(
|
||||
$xError = [
|
||||
'type' => E_USER_DEPRECATED,
|
||||
'message' => 'The "Test\Symfony\Component\Debug\Tests\\'.$class.'" class '.$type.' "Symfony\Component\Debug\Tests\Fixtures\\'.$super.'" that is deprecated but this is a test deprecation notice.',
|
||||
);
|
||||
];
|
||||
|
||||
$this->assertSame($xError, $lastError);
|
||||
}
|
||||
|
||||
public function provideDeprecatedSuper()
|
||||
{
|
||||
return array(
|
||||
array('DeprecatedInterfaceClass', 'DeprecatedInterface', 'implements'),
|
||||
array('DeprecatedParentClass', 'DeprecatedClass', 'extends'),
|
||||
);
|
||||
return [
|
||||
['DeprecatedInterfaceClass', 'DeprecatedInterface', 'implements'],
|
||||
['DeprecatedParentClass', 'DeprecatedClass', 'extends'],
|
||||
];
|
||||
}
|
||||
|
||||
public function testInterfaceExtendsDeprecatedInterface()
|
||||
@@ -166,10 +166,10 @@ class DebugClassLoaderTest extends TestCase
|
||||
$lastError = error_get_last();
|
||||
unset($lastError['file'], $lastError['line']);
|
||||
|
||||
$xError = array(
|
||||
$xError = [
|
||||
'type' => E_USER_NOTICE,
|
||||
'message' => '',
|
||||
);
|
||||
];
|
||||
|
||||
$this->assertSame($xError, $lastError);
|
||||
}
|
||||
@@ -188,56 +188,60 @@ class DebugClassLoaderTest extends TestCase
|
||||
$lastError = error_get_last();
|
||||
unset($lastError['file'], $lastError['line']);
|
||||
|
||||
$xError = array(
|
||||
$xError = [
|
||||
'type' => E_USER_NOTICE,
|
||||
'message' => '',
|
||||
);
|
||||
];
|
||||
|
||||
$this->assertSame($xError, $lastError);
|
||||
}
|
||||
|
||||
public function testExtendedFinalClass()
|
||||
{
|
||||
set_error_handler(function () { return false; });
|
||||
$e = error_reporting(0);
|
||||
trigger_error('', E_USER_NOTICE);
|
||||
$deprecations = [];
|
||||
set_error_handler(function ($type, $msg) use (&$deprecations) { $deprecations[] = $msg; });
|
||||
$e = error_reporting(E_USER_DEPRECATED);
|
||||
|
||||
class_exists('Test\\'.__NAMESPACE__.'\\ExtendsFinalClass', true);
|
||||
require __DIR__.'/Fixtures/FinalClasses.php';
|
||||
|
||||
$i = 1;
|
||||
while (class_exists($finalClass = __NAMESPACE__.'\\Fixtures\\FinalClass'.$i++, false)) {
|
||||
spl_autoload_call($finalClass);
|
||||
class_exists('Test\\'.__NAMESPACE__.'\\Extends'.substr($finalClass, strrpos($finalClass, '\\') + 1), true);
|
||||
}
|
||||
|
||||
error_reporting($e);
|
||||
restore_error_handler();
|
||||
|
||||
$lastError = error_get_last();
|
||||
unset($lastError['file'], $lastError['line']);
|
||||
|
||||
$xError = array(
|
||||
'type' => E_USER_DEPRECATED,
|
||||
'message' => 'The "Symfony\Component\Debug\Tests\Fixtures\FinalClass" class is considered final. It may change without further notice as of its next major version. You should not extend it from "Test\Symfony\Component\Debug\Tests\ExtendsFinalClass".',
|
||||
);
|
||||
|
||||
$this->assertSame($xError, $lastError);
|
||||
$this->assertSame([
|
||||
'The "Symfony\Component\Debug\Tests\Fixtures\FinalClass1" class is considered final since version 3.3. It may change without further notice as of its next major version. You should not extend it from "Test\Symfony\Component\Debug\Tests\ExtendsFinalClass1".',
|
||||
'The "Symfony\Component\Debug\Tests\Fixtures\FinalClass2" class is considered final. It may change without further notice as of its next major version. You should not extend it from "Test\Symfony\Component\Debug\Tests\ExtendsFinalClass2".',
|
||||
'The "Symfony\Component\Debug\Tests\Fixtures\FinalClass3" class is considered final comment with @@@ and ***. It may change without further notice as of its next major version. You should not extend it from "Test\Symfony\Component\Debug\Tests\ExtendsFinalClass3".',
|
||||
'The "Symfony\Component\Debug\Tests\Fixtures\FinalClass4" class is considered final. It may change without further notice as of its next major version. You should not extend it from "Test\Symfony\Component\Debug\Tests\ExtendsFinalClass4".',
|
||||
'The "Symfony\Component\Debug\Tests\Fixtures\FinalClass5" class is considered final multiline comment. It may change without further notice as of its next major version. You should not extend it from "Test\Symfony\Component\Debug\Tests\ExtendsFinalClass5".',
|
||||
'The "Symfony\Component\Debug\Tests\Fixtures\FinalClass6" class is considered final. It may change without further notice as of its next major version. You should not extend it from "Test\Symfony\Component\Debug\Tests\ExtendsFinalClass6".',
|
||||
'The "Symfony\Component\Debug\Tests\Fixtures\FinalClass7" class is considered final another multiline comment... It may change without further notice as of its next major version. You should not extend it from "Test\Symfony\Component\Debug\Tests\ExtendsFinalClass7".',
|
||||
'The "Symfony\Component\Debug\Tests\Fixtures\FinalClass8" class is considered final. It may change without further notice as of its next major version. You should not extend it from "Test\Symfony\Component\Debug\Tests\ExtendsFinalClass8".',
|
||||
], $deprecations);
|
||||
}
|
||||
|
||||
public function testExtendedFinalMethod()
|
||||
{
|
||||
set_error_handler(function () { return false; });
|
||||
$e = error_reporting(0);
|
||||
trigger_error('', E_USER_NOTICE);
|
||||
$deprecations = [];
|
||||
set_error_handler(function ($type, $msg) use (&$deprecations) { $deprecations[] = $msg; });
|
||||
$e = error_reporting(E_USER_DEPRECATED);
|
||||
|
||||
class_exists(__NAMESPACE__.'\\Fixtures\\ExtendedFinalMethod', true);
|
||||
|
||||
error_reporting($e);
|
||||
restore_error_handler();
|
||||
|
||||
$lastError = error_get_last();
|
||||
unset($lastError['file'], $lastError['line']);
|
||||
$xError = [
|
||||
'The "Symfony\Component\Debug\Tests\Fixtures\FinalMethod::finalMethod()" method is considered final. It may change without further notice as of its next major version. You should not extend it from "Symfony\Component\Debug\Tests\Fixtures\ExtendedFinalMethod".',
|
||||
'The "Symfony\Component\Debug\Tests\Fixtures\FinalMethod::finalMethod2()" method is considered final. It may change without further notice as of its next major version. You should not extend it from "Symfony\Component\Debug\Tests\Fixtures\ExtendedFinalMethod".',
|
||||
];
|
||||
|
||||
$xError = array(
|
||||
'type' => E_USER_DEPRECATED,
|
||||
'message' => 'The "Symfony\Component\Debug\Tests\Fixtures\FinalMethod::finalMethod()" method is considered final. It may change without further notice as of its next major version. You should not extend it from "Symfony\Component\Debug\Tests\Fixtures\ExtendedFinalMethod".',
|
||||
);
|
||||
|
||||
$this->assertSame($xError, $lastError);
|
||||
$this->assertSame($xError, $deprecations);
|
||||
}
|
||||
|
||||
public function testExtendedDeprecatedMethodDoesntTriggerAnyNotice()
|
||||
@@ -254,12 +258,12 @@ class DebugClassLoaderTest extends TestCase
|
||||
$lastError = error_get_last();
|
||||
unset($lastError['file'], $lastError['line']);
|
||||
|
||||
$this->assertSame(array('type' => E_USER_NOTICE, 'message' => ''), $lastError);
|
||||
$this->assertSame(['type' => E_USER_NOTICE, 'message' => ''], $lastError);
|
||||
}
|
||||
|
||||
public function testInternalsUse()
|
||||
{
|
||||
$deprecations = array();
|
||||
$deprecations = [];
|
||||
set_error_handler(function ($type, $msg) use (&$deprecations) { $deprecations[] = $msg; });
|
||||
$e = error_reporting(E_USER_DEPRECATED);
|
||||
|
||||
@@ -268,12 +272,49 @@ class DebugClassLoaderTest extends TestCase
|
||||
error_reporting($e);
|
||||
restore_error_handler();
|
||||
|
||||
$this->assertSame($deprecations, array(
|
||||
'The "Symfony\Component\Debug\Tests\Fixtures\InternalClass" class is considered internal. It may change without further notice. You should not use it from "Test\Symfony\Component\Debug\Tests\ExtendsInternalsParent".',
|
||||
$this->assertSame($deprecations, [
|
||||
'The "Symfony\Component\Debug\Tests\Fixtures\InternalInterface" interface is considered internal. It may change without further notice. You should not use it from "Test\Symfony\Component\Debug\Tests\ExtendsInternalsParent".',
|
||||
'The "Symfony\Component\Debug\Tests\Fixtures\InternalClass" class is considered internal. It may change without further notice. You should not use it from "Test\Symfony\Component\Debug\Tests\ExtendsInternalsParent".',
|
||||
'The "Symfony\Component\Debug\Tests\Fixtures\InternalTrait" trait is considered internal. It may change without further notice. You should not use it from "Test\Symfony\Component\Debug\Tests\ExtendsInternals".',
|
||||
'The "Symfony\Component\Debug\Tests\Fixtures\InternalTrait2::internalMethod()" method is considered internal. It may change without further notice. You should not extend it from "Test\Symfony\Component\Debug\Tests\ExtendsInternals".',
|
||||
));
|
||||
'The "Symfony\Component\Debug\Tests\Fixtures\InternalClass::internalMethod()" method is considered internal. It may change without further notice. You should not extend it from "Test\Symfony\Component\Debug\Tests\ExtendsInternals".',
|
||||
]);
|
||||
}
|
||||
|
||||
public function testExtendedMethodDefinesNewParameters()
|
||||
{
|
||||
$deprecations = [];
|
||||
set_error_handler(function ($type, $msg) use (&$deprecations) { $deprecations[] = $msg; });
|
||||
$e = error_reporting(E_USER_DEPRECATED);
|
||||
|
||||
class_exists(__NAMESPACE__.'\\Fixtures\SubClassWithAnnotatedParameters', true);
|
||||
|
||||
error_reporting($e);
|
||||
restore_error_handler();
|
||||
|
||||
$this->assertSame([
|
||||
'The "Symfony\Component\Debug\Tests\Fixtures\SubClassWithAnnotatedParameters::quzMethod()" method will require a new "Quz $quz" argument in the next major version of its parent class "Symfony\Component\Debug\Tests\Fixtures\ClassWithAnnotatedParameters", not defining it is deprecated.',
|
||||
'The "Symfony\Component\Debug\Tests\Fixtures\SubClassWithAnnotatedParameters::whereAmI()" method will require a new "bool $matrix" argument in the next major version of its parent class "Symfony\Component\Debug\Tests\Fixtures\InterfaceWithAnnotatedParameters", not defining it is deprecated.',
|
||||
'The "Symfony\Component\Debug\Tests\Fixtures\SubClassWithAnnotatedParameters::isSymfony()" method will require a new "true $yes" argument in the next major version of its parent class "Symfony\Component\Debug\Tests\Fixtures\ClassWithAnnotatedParameters", not defining it is deprecated.',
|
||||
], $deprecations);
|
||||
}
|
||||
|
||||
public function testUseTraitWithInternalMethod()
|
||||
{
|
||||
$deprecations = [];
|
||||
set_error_handler(function ($type, $msg) use (&$deprecations) { $deprecations[] = $msg; });
|
||||
$e = error_reporting(E_USER_DEPRECATED);
|
||||
|
||||
class_exists('Test\\'.__NAMESPACE__.'\\UseTraitWithInternalMethod', true);
|
||||
|
||||
error_reporting($e);
|
||||
restore_error_handler();
|
||||
|
||||
$this->assertSame([], $deprecations);
|
||||
}
|
||||
|
||||
public function testEvaluatedCode()
|
||||
{
|
||||
$this->assertTrue(class_exists(__NAMESPACE__.'\Fixtures\DefinitionInEvaluatedCode', true));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -285,12 +326,12 @@ class ClassLoader
|
||||
|
||||
public function getClassMap()
|
||||
{
|
||||
return array(__NAMESPACE__.'\Fixtures\NotPSR0bis' => __DIR__.'/Fixtures/notPsr0Bis.php');
|
||||
return [__NAMESPACE__.'\Fixtures\NotPSR0bis' => __DIR__.'/Fixtures/notPsr0Bis.php'];
|
||||
}
|
||||
|
||||
public function findFile($class)
|
||||
{
|
||||
$fixtureDir = __DIR__.DIRECTORY_SEPARATOR.'Fixtures'.DIRECTORY_SEPARATOR;
|
||||
$fixtureDir = __DIR__.\DIRECTORY_SEPARATOR.'Fixtures'.\DIRECTORY_SEPARATOR;
|
||||
|
||||
if (__NAMESPACE__.'\TestingUnsilencing' === $class) {
|
||||
eval('-- parse error --');
|
||||
@@ -299,7 +340,7 @@ class ClassLoader
|
||||
} elseif (__NAMESPACE__.'\TestingCaseMismatch' === $class) {
|
||||
eval('namespace '.__NAMESPACE__.'; class TestingCaseMisMatch {}');
|
||||
} elseif (__NAMESPACE__.'\Fixtures\Psr4CaseMismatch' === $class) {
|
||||
return $fixtureDir.'psr4'.DIRECTORY_SEPARATOR.'Psr4CaseMismatch.php';
|
||||
return $fixtureDir.'psr4'.\DIRECTORY_SEPARATOR.'Psr4CaseMismatch.php';
|
||||
} elseif (__NAMESPACE__.'\Fixtures\NotPSR0' === $class) {
|
||||
return $fixtureDir.'reallyNotPsr0.php';
|
||||
} elseif (__NAMESPACE__.'\Fixtures\NotPSR0bis' === $class) {
|
||||
@@ -314,8 +355,9 @@ class ClassLoader
|
||||
eval('namespace Test\\'.__NAMESPACE__.'; class NonDeprecatedInterfaceClass implements \\'.__NAMESPACE__.'\Fixtures\NonDeprecatedInterface {}');
|
||||
} elseif ('Test\\'.__NAMESPACE__.'\Float' === $class) {
|
||||
eval('namespace Test\\'.__NAMESPACE__.'; class Float {}');
|
||||
} elseif ('Test\\'.__NAMESPACE__.'\ExtendsFinalClass' === $class) {
|
||||
eval('namespace Test\\'.__NAMESPACE__.'; class ExtendsFinalClass extends \\'.__NAMESPACE__.'\Fixtures\FinalClass {}');
|
||||
} elseif (0 === strpos($class, 'Test\\'.__NAMESPACE__.'\ExtendsFinalClass')) {
|
||||
$classShortName = substr($class, strrpos($class, '\\') + 1);
|
||||
eval('namespace Test\\'.__NAMESPACE__.'; class '.$classShortName.' extends \\'.__NAMESPACE__.'\Fixtures\\'.substr($classShortName, 7).' {}');
|
||||
} elseif ('Test\\'.__NAMESPACE__.'\ExtendsAnnotatedClass' === $class) {
|
||||
eval('namespace Test\\'.__NAMESPACE__.'; class ExtendsAnnotatedClass extends \\'.__NAMESPACE__.'\Fixtures\AnnotatedClass {
|
||||
public function deprecatedMethod() { }
|
||||
@@ -328,6 +370,8 @@ class ClassLoader
|
||||
}');
|
||||
} elseif ('Test\\'.__NAMESPACE__.'\ExtendsInternalsParent' === $class) {
|
||||
eval('namespace Test\\'.__NAMESPACE__.'; class ExtendsInternalsParent extends \\'.__NAMESPACE__.'\Fixtures\InternalClass implements \\'.__NAMESPACE__.'\Fixtures\InternalInterface { }');
|
||||
} elseif ('Test\\'.__NAMESPACE__.'\UseTraitWithInternalMethod' === $class) {
|
||||
eval('namespace Test\\'.__NAMESPACE__.'; class UseTraitWithInternalMethod { use \\'.__NAMESPACE__.'\Fixtures\TraitWithInternalMethod; }');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,9 +13,12 @@ namespace Symfony\Component\Debug\Tests;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Psr\Log\LogLevel;
|
||||
use Psr\Log\NullLogger;
|
||||
use Symfony\Component\Debug\BufferingLogger;
|
||||
use Symfony\Component\Debug\ErrorHandler;
|
||||
use Symfony\Component\Debug\Exception\SilencedErrorContext;
|
||||
use Symfony\Component\Debug\Tests\Fixtures\ErrorHandlerThatUsesThePreviousOne;
|
||||
use Symfony\Component\Debug\Tests\Fixtures\LoggerThatSetAnErrorHandler;
|
||||
|
||||
/**
|
||||
* ErrorHandlerTest.
|
||||
@@ -38,13 +41,13 @@ class ErrorHandlerTest extends TestCase
|
||||
$this->assertSame($handler, ErrorHandler::register($newHandler, false));
|
||||
$h = set_error_handler('var_dump');
|
||||
restore_error_handler();
|
||||
$this->assertSame(array($handler, 'handleError'), $h);
|
||||
$this->assertSame([$handler, 'handleError'], $h);
|
||||
|
||||
try {
|
||||
$this->assertSame($newHandler, ErrorHandler::register($newHandler, true));
|
||||
$h = set_error_handler('var_dump');
|
||||
restore_error_handler();
|
||||
$this->assertSame(array($newHandler, 'handleError'), $h);
|
||||
$this->assertSame([$newHandler, 'handleError'], $h);
|
||||
} catch (\Exception $e) {
|
||||
}
|
||||
|
||||
@@ -74,12 +77,12 @@ class ErrorHandlerTest extends TestCase
|
||||
|
||||
try {
|
||||
@trigger_error('Hello', E_USER_WARNING);
|
||||
$expected = array(
|
||||
$expected = [
|
||||
'type' => E_USER_WARNING,
|
||||
'message' => 'Hello',
|
||||
'file' => __FILE__,
|
||||
'line' => __LINE__ - 5,
|
||||
);
|
||||
];
|
||||
$this->assertSame($expected, error_get_last());
|
||||
} catch (\Exception $e) {
|
||||
restore_error_handler();
|
||||
@@ -145,26 +148,26 @@ class ErrorHandlerTest extends TestCase
|
||||
$logger = $this->getMockBuilder('Psr\Log\LoggerInterface')->getMock();
|
||||
|
||||
$handler->setDefaultLogger($logger, E_NOTICE);
|
||||
$handler->setDefaultLogger($logger, array(E_USER_NOTICE => LogLevel::CRITICAL));
|
||||
$handler->setDefaultLogger($logger, [E_USER_NOTICE => LogLevel::CRITICAL]);
|
||||
|
||||
$loggers = array(
|
||||
E_DEPRECATED => array(null, LogLevel::INFO),
|
||||
E_USER_DEPRECATED => array(null, LogLevel::INFO),
|
||||
E_NOTICE => array($logger, LogLevel::WARNING),
|
||||
E_USER_NOTICE => array($logger, LogLevel::CRITICAL),
|
||||
E_STRICT => array(null, LogLevel::WARNING),
|
||||
E_WARNING => array(null, LogLevel::WARNING),
|
||||
E_USER_WARNING => array(null, LogLevel::WARNING),
|
||||
E_COMPILE_WARNING => array(null, LogLevel::WARNING),
|
||||
E_CORE_WARNING => array(null, LogLevel::WARNING),
|
||||
E_USER_ERROR => array(null, LogLevel::CRITICAL),
|
||||
E_RECOVERABLE_ERROR => array(null, LogLevel::CRITICAL),
|
||||
E_COMPILE_ERROR => array(null, LogLevel::CRITICAL),
|
||||
E_PARSE => array(null, LogLevel::CRITICAL),
|
||||
E_ERROR => array(null, LogLevel::CRITICAL),
|
||||
E_CORE_ERROR => array(null, LogLevel::CRITICAL),
|
||||
);
|
||||
$this->assertSame($loggers, $handler->setLoggers(array()));
|
||||
$loggers = [
|
||||
E_DEPRECATED => [null, LogLevel::INFO],
|
||||
E_USER_DEPRECATED => [null, LogLevel::INFO],
|
||||
E_NOTICE => [$logger, LogLevel::WARNING],
|
||||
E_USER_NOTICE => [$logger, LogLevel::CRITICAL],
|
||||
E_STRICT => [null, LogLevel::WARNING],
|
||||
E_WARNING => [null, LogLevel::WARNING],
|
||||
E_USER_WARNING => [null, LogLevel::WARNING],
|
||||
E_COMPILE_WARNING => [null, LogLevel::WARNING],
|
||||
E_CORE_WARNING => [null, LogLevel::WARNING],
|
||||
E_USER_ERROR => [null, LogLevel::CRITICAL],
|
||||
E_RECOVERABLE_ERROR => [null, LogLevel::CRITICAL],
|
||||
E_COMPILE_ERROR => [null, LogLevel::CRITICAL],
|
||||
E_PARSE => [null, LogLevel::CRITICAL],
|
||||
E_ERROR => [null, LogLevel::CRITICAL],
|
||||
E_CORE_ERROR => [null, LogLevel::CRITICAL],
|
||||
];
|
||||
$this->assertSame($loggers, $handler->setLoggers([]));
|
||||
} finally {
|
||||
restore_error_handler();
|
||||
restore_exception_handler();
|
||||
@@ -176,14 +179,14 @@ class ErrorHandlerTest extends TestCase
|
||||
try {
|
||||
$handler = ErrorHandler::register();
|
||||
$handler->throwAt(0, true);
|
||||
$this->assertFalse($handler->handleError(0, 'foo', 'foo.php', 12, array()));
|
||||
$this->assertFalse($handler->handleError(0, 'foo', 'foo.php', 12, []));
|
||||
|
||||
restore_error_handler();
|
||||
restore_exception_handler();
|
||||
|
||||
$handler = ErrorHandler::register();
|
||||
$handler->throwAt(3, true);
|
||||
$this->assertFalse($handler->handleError(4, 'foo', 'foo.php', 12, array()));
|
||||
$this->assertFalse($handler->handleError(4, 'foo', 'foo.php', 12, []));
|
||||
|
||||
restore_error_handler();
|
||||
restore_exception_handler();
|
||||
@@ -191,7 +194,7 @@ class ErrorHandlerTest extends TestCase
|
||||
$handler = ErrorHandler::register();
|
||||
$handler->throwAt(3, true);
|
||||
try {
|
||||
$handler->handleError(4, 'foo', 'foo.php', 12, array());
|
||||
$handler->handleError(4, 'foo', 'foo.php', 12, []);
|
||||
} catch (\ErrorException $e) {
|
||||
$this->assertSame('Parse Error: foo', $e->getMessage());
|
||||
$this->assertSame(4, $e->getSeverity());
|
||||
@@ -204,14 +207,14 @@ class ErrorHandlerTest extends TestCase
|
||||
|
||||
$handler = ErrorHandler::register();
|
||||
$handler->throwAt(E_USER_DEPRECATED, true);
|
||||
$this->assertFalse($handler->handleError(E_USER_DEPRECATED, 'foo', 'foo.php', 12, array()));
|
||||
$this->assertFalse($handler->handleError(E_USER_DEPRECATED, 'foo', 'foo.php', 12, []));
|
||||
|
||||
restore_error_handler();
|
||||
restore_exception_handler();
|
||||
|
||||
$handler = ErrorHandler::register();
|
||||
$handler->throwAt(E_DEPRECATED, true);
|
||||
$this->assertFalse($handler->handleError(E_DEPRECATED, 'foo', 'foo.php', 12, array()));
|
||||
$this->assertFalse($handler->handleError(E_DEPRECATED, 'foo', 'foo.php', 12, []));
|
||||
|
||||
restore_error_handler();
|
||||
restore_exception_handler();
|
||||
@@ -236,7 +239,7 @@ class ErrorHandlerTest extends TestCase
|
||||
|
||||
$handler = ErrorHandler::register();
|
||||
$handler->setDefaultLogger($logger, E_USER_DEPRECATED);
|
||||
$this->assertTrue($handler->handleError(E_USER_DEPRECATED, 'foo', 'foo.php', 12, array()));
|
||||
$this->assertTrue($handler->handleError(E_USER_DEPRECATED, 'foo', 'foo.php', 12, []));
|
||||
|
||||
restore_error_handler();
|
||||
restore_exception_handler();
|
||||
@@ -320,7 +323,9 @@ class ErrorHandlerTest extends TestCase
|
||||
|
||||
$handler = new ErrorHandler();
|
||||
$handler->setDefaultLogger($logger);
|
||||
@$handler->handleError(E_USER_DEPRECATED, 'Foo deprecation', __FILE__, __LINE__, array());
|
||||
@$handler->handleError(E_USER_DEPRECATED, 'Foo deprecation', __FILE__, __LINE__, []);
|
||||
|
||||
restore_error_handler();
|
||||
}
|
||||
|
||||
public function testHandleException()
|
||||
@@ -369,27 +374,27 @@ class ErrorHandlerTest extends TestCase
|
||||
$bootLogger = new BufferingLogger();
|
||||
$handler = new ErrorHandler($bootLogger);
|
||||
|
||||
$loggers = array(
|
||||
E_DEPRECATED => array($bootLogger, LogLevel::INFO),
|
||||
E_USER_DEPRECATED => array($bootLogger, LogLevel::INFO),
|
||||
E_NOTICE => array($bootLogger, LogLevel::WARNING),
|
||||
E_USER_NOTICE => array($bootLogger, LogLevel::WARNING),
|
||||
E_STRICT => array($bootLogger, LogLevel::WARNING),
|
||||
E_WARNING => array($bootLogger, LogLevel::WARNING),
|
||||
E_USER_WARNING => array($bootLogger, LogLevel::WARNING),
|
||||
E_COMPILE_WARNING => array($bootLogger, LogLevel::WARNING),
|
||||
E_CORE_WARNING => array($bootLogger, LogLevel::WARNING),
|
||||
E_USER_ERROR => array($bootLogger, LogLevel::CRITICAL),
|
||||
E_RECOVERABLE_ERROR => array($bootLogger, LogLevel::CRITICAL),
|
||||
E_COMPILE_ERROR => array($bootLogger, LogLevel::CRITICAL),
|
||||
E_PARSE => array($bootLogger, LogLevel::CRITICAL),
|
||||
E_ERROR => array($bootLogger, LogLevel::CRITICAL),
|
||||
E_CORE_ERROR => array($bootLogger, LogLevel::CRITICAL),
|
||||
);
|
||||
$loggers = [
|
||||
E_DEPRECATED => [$bootLogger, LogLevel::INFO],
|
||||
E_USER_DEPRECATED => [$bootLogger, LogLevel::INFO],
|
||||
E_NOTICE => [$bootLogger, LogLevel::WARNING],
|
||||
E_USER_NOTICE => [$bootLogger, LogLevel::WARNING],
|
||||
E_STRICT => [$bootLogger, LogLevel::WARNING],
|
||||
E_WARNING => [$bootLogger, LogLevel::WARNING],
|
||||
E_USER_WARNING => [$bootLogger, LogLevel::WARNING],
|
||||
E_COMPILE_WARNING => [$bootLogger, LogLevel::WARNING],
|
||||
E_CORE_WARNING => [$bootLogger, LogLevel::WARNING],
|
||||
E_USER_ERROR => [$bootLogger, LogLevel::CRITICAL],
|
||||
E_RECOVERABLE_ERROR => [$bootLogger, LogLevel::CRITICAL],
|
||||
E_COMPILE_ERROR => [$bootLogger, LogLevel::CRITICAL],
|
||||
E_PARSE => [$bootLogger, LogLevel::CRITICAL],
|
||||
E_ERROR => [$bootLogger, LogLevel::CRITICAL],
|
||||
E_CORE_ERROR => [$bootLogger, LogLevel::CRITICAL],
|
||||
];
|
||||
|
||||
$this->assertSame($loggers, $handler->setLoggers(array()));
|
||||
$this->assertSame($loggers, $handler->setLoggers([]));
|
||||
|
||||
$handler->handleError(E_DEPRECATED, 'Foo message', __FILE__, 123, array());
|
||||
$handler->handleError(E_DEPRECATED, 'Foo message', __FILE__, 123, []);
|
||||
|
||||
$logs = $bootLogger->cleanLogs();
|
||||
|
||||
@@ -405,14 +410,14 @@ class ErrorHandlerTest extends TestCase
|
||||
$this->assertSame(123, $exception->getLine());
|
||||
$this->assertSame(E_DEPRECATED, $exception->getSeverity());
|
||||
|
||||
$bootLogger->log(LogLevel::WARNING, 'Foo message', array('exception' => $exception));
|
||||
$bootLogger->log(LogLevel::WARNING, 'Foo message', ['exception' => $exception]);
|
||||
|
||||
$mockLogger = $this->getMockBuilder('Psr\Log\LoggerInterface')->getMock();
|
||||
$mockLogger->expects($this->once())
|
||||
->method('log')
|
||||
->with(LogLevel::WARNING, 'Foo message', array('exception' => $exception));
|
||||
->with(LogLevel::WARNING, 'Foo message', ['exception' => $exception]);
|
||||
|
||||
$handler->setLoggers(array(E_DEPRECATED => array($mockLogger, LogLevel::WARNING)));
|
||||
$handler->setLoggers([E_DEPRECATED => [$mockLogger, LogLevel::WARNING]]);
|
||||
}
|
||||
|
||||
public function testSettingLoggerWhenExceptionIsBuffered()
|
||||
@@ -425,7 +430,7 @@ class ErrorHandlerTest extends TestCase
|
||||
$mockLogger = $this->getMockBuilder('Psr\Log\LoggerInterface')->getMock();
|
||||
$mockLogger->expects($this->once())
|
||||
->method('log')
|
||||
->with(LogLevel::CRITICAL, 'Uncaught Exception: Foo message', array('exception' => $exception));
|
||||
->with(LogLevel::CRITICAL, 'Uncaught Exception: Foo message', ['exception' => $exception]);
|
||||
|
||||
$handler->setExceptionHandler(function () use ($handler, $mockLogger) {
|
||||
$handler->setDefaultLogger($mockLogger);
|
||||
@@ -439,12 +444,12 @@ class ErrorHandlerTest extends TestCase
|
||||
try {
|
||||
$handler = ErrorHandler::register();
|
||||
|
||||
$error = array(
|
||||
$error = [
|
||||
'type' => E_PARSE,
|
||||
'message' => 'foo',
|
||||
'file' => 'bar',
|
||||
'line' => 123,
|
||||
);
|
||||
];
|
||||
|
||||
$logger = $this->getMockBuilder('Psr\Log\LoggerInterface')->getMock();
|
||||
|
||||
@@ -480,7 +485,7 @@ class ErrorHandlerTest extends TestCase
|
||||
|
||||
$handler = new ErrorHandler();
|
||||
$handler->setExceptionHandler(function () use (&$args) {
|
||||
$args = func_get_args();
|
||||
$args = \func_get_args();
|
||||
});
|
||||
|
||||
$handler->handleException($exception);
|
||||
@@ -501,4 +506,58 @@ class ErrorHandlerTest extends TestCase
|
||||
|
||||
$handler->handleException(new \Exception());
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider errorHandlerWhenLoggingProvider
|
||||
*/
|
||||
public function testErrorHandlerWhenLogging($previousHandlerWasDefined, $loggerSetsAnotherHandler, $nextHandlerIsDefined)
|
||||
{
|
||||
try {
|
||||
if ($previousHandlerWasDefined) {
|
||||
set_error_handler('count');
|
||||
}
|
||||
|
||||
$logger = $loggerSetsAnotherHandler ? new LoggerThatSetAnErrorHandler() : new NullLogger();
|
||||
|
||||
$handler = ErrorHandler::register();
|
||||
$handler->setDefaultLogger($logger);
|
||||
|
||||
if ($nextHandlerIsDefined) {
|
||||
$handler = ErrorHandlerThatUsesThePreviousOne::register();
|
||||
}
|
||||
|
||||
@trigger_error('foo', E_USER_DEPRECATED);
|
||||
@trigger_error('bar', E_USER_DEPRECATED);
|
||||
|
||||
$this->assertSame([$handler, 'handleError'], set_error_handler('var_dump'));
|
||||
|
||||
if ($logger instanceof LoggerThatSetAnErrorHandler) {
|
||||
$this->assertCount(2, $logger->cleanLogs());
|
||||
}
|
||||
|
||||
restore_error_handler();
|
||||
|
||||
if ($previousHandlerWasDefined) {
|
||||
restore_error_handler();
|
||||
}
|
||||
|
||||
if ($nextHandlerIsDefined) {
|
||||
restore_error_handler();
|
||||
}
|
||||
} finally {
|
||||
restore_error_handler();
|
||||
restore_exception_handler();
|
||||
}
|
||||
}
|
||||
|
||||
public function errorHandlerWhenLoggingProvider()
|
||||
{
|
||||
foreach ([false, true] as $previousHandlerWasDefined) {
|
||||
foreach ([false, true] as $loggerSetsAnotherHandler) {
|
||||
foreach ([false, true] as $nextHandlerIsDefined) {
|
||||
yield [$previousHandlerWasDefined, $loggerSetsAnotherHandler, $nextHandlerIsDefined];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,19 +15,19 @@ use PHPUnit\Framework\TestCase;
|
||||
use Symfony\Component\Debug\Exception\FatalThrowableError;
|
||||
use Symfony\Component\Debug\Exception\FlattenException;
|
||||
use Symfony\Component\HttpFoundation\Exception\SuspiciousOperationException;
|
||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
use Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException;
|
||||
use Symfony\Component\HttpKernel\Exception\UnauthorizedHttpException;
|
||||
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
|
||||
use Symfony\Component\HttpKernel\Exception\NotAcceptableHttpException;
|
||||
use Symfony\Component\HttpKernel\Exception\ConflictHttpException;
|
||||
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
|
||||
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
|
||||
use Symfony\Component\HttpKernel\Exception\ConflictHttpException;
|
||||
use Symfony\Component\HttpKernel\Exception\GoneHttpException;
|
||||
use Symfony\Component\HttpKernel\Exception\LengthRequiredHttpException;
|
||||
use Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException;
|
||||
use Symfony\Component\HttpKernel\Exception\NotAcceptableHttpException;
|
||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
use Symfony\Component\HttpKernel\Exception\PreconditionFailedHttpException;
|
||||
use Symfony\Component\HttpKernel\Exception\PreconditionRequiredHttpException;
|
||||
use Symfony\Component\HttpKernel\Exception\ServiceUnavailableHttpException;
|
||||
use Symfony\Component\HttpKernel\Exception\TooManyRequestsHttpException;
|
||||
use Symfony\Component\HttpKernel\Exception\UnauthorizedHttpException;
|
||||
use Symfony\Component\HttpKernel\Exception\UnsupportedMediaTypeHttpException;
|
||||
|
||||
class FlattenExceptionTest extends TestCase
|
||||
@@ -61,7 +61,7 @@ class FlattenExceptionTest extends TestCase
|
||||
$flattened = FlattenException::create(new ConflictHttpException());
|
||||
$this->assertEquals('409', $flattened->getStatusCode());
|
||||
|
||||
$flattened = FlattenException::create(new MethodNotAllowedHttpException(array('POST')));
|
||||
$flattened = FlattenException::create(new MethodNotAllowedHttpException(['POST']));
|
||||
$this->assertEquals('405', $flattened->getStatusCode());
|
||||
|
||||
$flattened = FlattenException::create(new AccessDeniedHttpException());
|
||||
@@ -96,23 +96,23 @@ class FlattenExceptionTest extends TestCase
|
||||
|
||||
public function testHeadersForHttpException()
|
||||
{
|
||||
$flattened = FlattenException::create(new MethodNotAllowedHttpException(array('POST')));
|
||||
$this->assertEquals(array('Allow' => 'POST'), $flattened->getHeaders());
|
||||
$flattened = FlattenException::create(new MethodNotAllowedHttpException(['POST']));
|
||||
$this->assertEquals(['Allow' => 'POST'], $flattened->getHeaders());
|
||||
|
||||
$flattened = FlattenException::create(new UnauthorizedHttpException('Basic realm="My Realm"'));
|
||||
$this->assertEquals(array('WWW-Authenticate' => 'Basic realm="My Realm"'), $flattened->getHeaders());
|
||||
$this->assertEquals(['WWW-Authenticate' => 'Basic realm="My Realm"'], $flattened->getHeaders());
|
||||
|
||||
$flattened = FlattenException::create(new ServiceUnavailableHttpException('Fri, 31 Dec 1999 23:59:59 GMT'));
|
||||
$this->assertEquals(array('Retry-After' => 'Fri, 31 Dec 1999 23:59:59 GMT'), $flattened->getHeaders());
|
||||
$this->assertEquals(['Retry-After' => 'Fri, 31 Dec 1999 23:59:59 GMT'], $flattened->getHeaders());
|
||||
|
||||
$flattened = FlattenException::create(new ServiceUnavailableHttpException(120));
|
||||
$this->assertEquals(array('Retry-After' => 120), $flattened->getHeaders());
|
||||
$this->assertEquals(['Retry-After' => 120], $flattened->getHeaders());
|
||||
|
||||
$flattened = FlattenException::create(new TooManyRequestsHttpException('Fri, 31 Dec 1999 23:59:59 GMT'));
|
||||
$this->assertEquals(array('Retry-After' => 'Fri, 31 Dec 1999 23:59:59 GMT'), $flattened->getHeaders());
|
||||
$this->assertEquals(['Retry-After' => 'Fri, 31 Dec 1999 23:59:59 GMT'], $flattened->getHeaders());
|
||||
|
||||
$flattened = FlattenException::create(new TooManyRequestsHttpException(120));
|
||||
$this->assertEquals(array('Retry-After' => 120), $flattened->getHeaders());
|
||||
$this->assertEquals(['Retry-After' => 120], $flattened->getHeaders());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -162,7 +162,7 @@ class FlattenExceptionTest extends TestCase
|
||||
|
||||
$this->assertSame($flattened2, $flattened->getPrevious());
|
||||
|
||||
$this->assertSame(array($flattened2), $flattened->getAllPrevious());
|
||||
$this->assertSame([$flattened2], $flattened->getAllPrevious());
|
||||
}
|
||||
|
||||
public function testPreviousError()
|
||||
@@ -200,18 +200,18 @@ class FlattenExceptionTest extends TestCase
|
||||
public function testToArray(\Throwable $exception, string $expectedClass)
|
||||
{
|
||||
$flattened = FlattenException::createFromThrowable($exception);
|
||||
$flattened->setTrace(array(), 'foo.php', 123);
|
||||
$flattened->setTrace([], 'foo.php', 123);
|
||||
|
||||
$this->assertEquals(array(
|
||||
array(
|
||||
$this->assertEquals([
|
||||
[
|
||||
'message' => 'test',
|
||||
'class' => $expectedClass,
|
||||
'trace' => array(array(
|
||||
'trace' => [[
|
||||
'namespace' => '', 'short_class' => '', 'class' => '', 'type' => '', 'function' => '', 'file' => 'foo.php', 'line' => 123,
|
||||
'args' => array(),
|
||||
)),
|
||||
),
|
||||
), $flattened->toArray());
|
||||
'args' => [],
|
||||
]],
|
||||
],
|
||||
], $flattened->toArray());
|
||||
}
|
||||
|
||||
public function testCreate()
|
||||
@@ -229,10 +229,10 @@ class FlattenExceptionTest extends TestCase
|
||||
|
||||
public function flattenDataProvider()
|
||||
{
|
||||
return array(
|
||||
array(new \Exception('test', 123), 'Exception'),
|
||||
array(new \Error('test', 123), 'Error'),
|
||||
);
|
||||
return [
|
||||
[new \Exception('test', 123), 'Exception'],
|
||||
[new \Error('test', 123), 'Error'],
|
||||
];
|
||||
}
|
||||
|
||||
public function testArguments()
|
||||
@@ -242,15 +242,15 @@ class FlattenExceptionTest extends TestCase
|
||||
|
||||
$incomplete = unserialize('O:14:"BogusTestClass":0:{}');
|
||||
|
||||
$exception = $this->createException(array(
|
||||
(object) array('foo' => 1),
|
||||
$exception = $this->createException([
|
||||
(object) ['foo' => 1],
|
||||
new NotFoundHttpException(),
|
||||
$incomplete,
|
||||
$dh,
|
||||
$fh,
|
||||
function () {},
|
||||
array(1, 2),
|
||||
array('foo' => 123),
|
||||
[1, 2],
|
||||
['foo' => 123],
|
||||
null,
|
||||
true,
|
||||
false,
|
||||
@@ -260,7 +260,7 @@ class FlattenExceptionTest extends TestCase
|
||||
'',
|
||||
INF,
|
||||
NAN,
|
||||
));
|
||||
]);
|
||||
|
||||
$flattened = FlattenException::create($exception);
|
||||
$trace = $flattened->getTrace();
|
||||
@@ -271,26 +271,26 @@ class FlattenExceptionTest extends TestCase
|
||||
fclose($fh);
|
||||
|
||||
$i = 0;
|
||||
$this->assertSame(array('object', 'stdClass'), $array[$i++]);
|
||||
$this->assertSame(array('object', 'Symfony\Component\HttpKernel\Exception\NotFoundHttpException'), $array[$i++]);
|
||||
$this->assertSame(array('incomplete-object', 'BogusTestClass'), $array[$i++]);
|
||||
$this->assertSame(array('resource', 'stream'), $array[$i++]);
|
||||
$this->assertSame(array('resource', 'stream'), $array[$i++]);
|
||||
$this->assertSame(['object', 'stdClass'], $array[$i++]);
|
||||
$this->assertSame(['object', 'Symfony\Component\HttpKernel\Exception\NotFoundHttpException'], $array[$i++]);
|
||||
$this->assertSame(['incomplete-object', 'BogusTestClass'], $array[$i++]);
|
||||
$this->assertSame(['resource', 'stream'], $array[$i++]);
|
||||
$this->assertSame(['resource', 'stream'], $array[$i++]);
|
||||
|
||||
$args = $array[$i++];
|
||||
$this->assertSame($args[0], 'object');
|
||||
$this->assertTrue('Closure' === $args[1] || is_subclass_of($args[1], '\Closure'), 'Expect object class name to be Closure or a subclass of Closure.');
|
||||
|
||||
$this->assertSame(array('array', array(array('integer', 1), array('integer', 2))), $array[$i++]);
|
||||
$this->assertSame(array('array', array('foo' => array('integer', 123))), $array[$i++]);
|
||||
$this->assertSame(array('null', null), $array[$i++]);
|
||||
$this->assertSame(array('boolean', true), $array[$i++]);
|
||||
$this->assertSame(array('boolean', false), $array[$i++]);
|
||||
$this->assertSame(array('integer', 0), $array[$i++]);
|
||||
$this->assertSame(array('float', 0.0), $array[$i++]);
|
||||
$this->assertSame(array('string', '0'), $array[$i++]);
|
||||
$this->assertSame(array('string', ''), $array[$i++]);
|
||||
$this->assertSame(array('float', INF), $array[$i++]);
|
||||
$this->assertSame(['array', [['integer', 1], ['integer', 2]]], $array[$i++]);
|
||||
$this->assertSame(['array', ['foo' => ['integer', 123]]], $array[$i++]);
|
||||
$this->assertSame(['null', null], $array[$i++]);
|
||||
$this->assertSame(['boolean', true], $array[$i++]);
|
||||
$this->assertSame(['boolean', false], $array[$i++]);
|
||||
$this->assertSame(['integer', 0], $array[$i++]);
|
||||
$this->assertSame(['float', 0.0], $array[$i++]);
|
||||
$this->assertSame(['string', '0'], $array[$i++]);
|
||||
$this->assertSame(['string', ''], $array[$i++]);
|
||||
$this->assertSame(['float', INF], $array[$i++]);
|
||||
|
||||
// assertEquals() does not like NAN values.
|
||||
$this->assertEquals($array[$i][0], 'float');
|
||||
@@ -300,7 +300,7 @@ class FlattenExceptionTest extends TestCase
|
||||
public function testRecursionInArguments()
|
||||
{
|
||||
$a = null;
|
||||
$a = array('foo', array(2, &$a));
|
||||
$a = ['foo', [2, &$a]];
|
||||
$exception = $this->createException($a);
|
||||
|
||||
$flattened = FlattenException::create($exception);
|
||||
@@ -310,7 +310,7 @@ class FlattenExceptionTest extends TestCase
|
||||
|
||||
public function testTooBigArray()
|
||||
{
|
||||
$a = array();
|
||||
$a = [];
|
||||
for ($i = 0; $i < 20; ++$i) {
|
||||
for ($j = 0; $j < 50; ++$j) {
|
||||
for ($k = 0; $k < 10; ++$k) {
|
||||
@@ -325,7 +325,7 @@ class FlattenExceptionTest extends TestCase
|
||||
$flattened = FlattenException::create($exception);
|
||||
$trace = $flattened->getTrace();
|
||||
|
||||
$this->assertSame($trace[1]['args'][0], array('array', array('array', '*SKIPPED over 10000 entries*')));
|
||||
$this->assertSame($trace[1]['args'][0], ['array', ['array', '*SKIPPED over 10000 entries*']]);
|
||||
|
||||
$serializeTrace = serialize($trace);
|
||||
|
||||
@@ -333,6 +333,19 @@ class FlattenExceptionTest extends TestCase
|
||||
$this->assertNotContains('*value1*', $serializeTrace);
|
||||
}
|
||||
|
||||
public function testAnonymousClass()
|
||||
{
|
||||
$flattened = FlattenException::create(new class() extends \RuntimeException {
|
||||
});
|
||||
|
||||
$this->assertSame('RuntimeException@anonymous', $flattened->getClass());
|
||||
|
||||
$flattened = FlattenException::create(new \Exception(sprintf('Class "%s" blah.', \get_class(new class() extends \RuntimeException {
|
||||
}))));
|
||||
|
||||
$this->assertSame('Class "RuntimeException@anonymous" blah.', $flattened->getMessage());
|
||||
}
|
||||
|
||||
private function createException($foo)
|
||||
{
|
||||
return new \Exception();
|
||||
|
||||
@@ -12,10 +12,10 @@
|
||||
namespace Symfony\Component\Debug\Tests;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Symfony\Component\Debug\ExceptionHandler;
|
||||
use Symfony\Component\Debug\Exception\OutOfMemoryException;
|
||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
use Symfony\Component\Debug\ExceptionHandler;
|
||||
use Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException;
|
||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
|
||||
require_once __DIR__.'/HeaderMock.php';
|
||||
|
||||
@@ -62,10 +62,10 @@ class ExceptionHandlerTest extends TestCase
|
||||
|
||||
$this->assertContains('Sorry, the page you are looking for could not be found.', $response);
|
||||
|
||||
$expectedHeaders = array(
|
||||
array('HTTP/1.0 404', true, null),
|
||||
array('Content-Type: text/html; charset=iso8859-1', true, null),
|
||||
);
|
||||
$expectedHeaders = [
|
||||
['HTTP/1.0 404', true, null],
|
||||
['Content-Type: text/html; charset=iso8859-1', true, null],
|
||||
];
|
||||
|
||||
$this->assertSame($expectedHeaders, testHeader());
|
||||
}
|
||||
@@ -75,14 +75,14 @@ class ExceptionHandlerTest extends TestCase
|
||||
$handler = new ExceptionHandler(false, 'iso8859-1');
|
||||
|
||||
ob_start();
|
||||
$handler->sendPhpResponse(new MethodNotAllowedHttpException(array('POST')));
|
||||
$handler->sendPhpResponse(new MethodNotAllowedHttpException(['POST']));
|
||||
$response = ob_get_clean();
|
||||
|
||||
$expectedHeaders = array(
|
||||
array('HTTP/1.0 405', true, null),
|
||||
array('Allow: POST', false, null),
|
||||
array('Content-Type: text/html; charset=iso8859-1', true, null),
|
||||
);
|
||||
$expectedHeaders = [
|
||||
['HTTP/1.0 405', true, null],
|
||||
['Allow: POST', false, null],
|
||||
['Content-Type: text/html; charset=iso8859-1', true, null],
|
||||
];
|
||||
|
||||
$this->assertSame($expectedHeaders, testHeader());
|
||||
}
|
||||
@@ -101,7 +101,7 @@ class ExceptionHandlerTest extends TestCase
|
||||
{
|
||||
$exception = new \Exception('foo');
|
||||
|
||||
$handler = $this->getMockBuilder('Symfony\Component\Debug\ExceptionHandler')->setMethods(array('sendPhpResponse'))->getMock();
|
||||
$handler = $this->getMockBuilder('Symfony\Component\Debug\ExceptionHandler')->setMethods(['sendPhpResponse'])->getMock();
|
||||
$handler
|
||||
->expects($this->exactly(2))
|
||||
->method('sendPhpResponse');
|
||||
@@ -119,7 +119,7 @@ class ExceptionHandlerTest extends TestCase
|
||||
{
|
||||
$exception = new OutOfMemoryException('foo', 0, E_ERROR, __FILE__, __LINE__);
|
||||
|
||||
$handler = $this->getMockBuilder('Symfony\Component\Debug\ExceptionHandler')->setMethods(array('sendPhpResponse'))->getMock();
|
||||
$handler = $this->getMockBuilder('Symfony\Component\Debug\ExceptionHandler')->setMethods(['sendPhpResponse'])->getMock();
|
||||
$handler
|
||||
->expects($this->once())
|
||||
->method('sendPhpResponse');
|
||||
|
||||
@@ -11,18 +11,18 @@
|
||||
|
||||
namespace Symfony\Component\Debug\Tests\FatalErrorHandler;
|
||||
|
||||
use Composer\Autoload\ClassLoader as ComposerClassLoader;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Symfony\Component\Debug\DebugClassLoader;
|
||||
use Symfony\Component\Debug\Exception\FatalErrorException;
|
||||
use Symfony\Component\Debug\FatalErrorHandler\ClassNotFoundFatalErrorHandler;
|
||||
use Symfony\Component\Debug\DebugClassLoader;
|
||||
use Composer\Autoload\ClassLoader as ComposerClassLoader;
|
||||
|
||||
class ClassNotFoundFatalErrorHandlerTest extends TestCase
|
||||
{
|
||||
public static function setUpBeforeClass()
|
||||
{
|
||||
foreach (spl_autoload_functions() as $function) {
|
||||
if (!is_array($function)) {
|
||||
if (!\is_array($function)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ class ClassNotFoundFatalErrorHandlerTest extends TestCase
|
||||
}
|
||||
|
||||
if ($function[0] instanceof ComposerClassLoader) {
|
||||
$function[0]->add('Symfony_Component_Debug_Tests_Fixtures', dirname(dirname(dirname(dirname(dirname(__DIR__))))));
|
||||
$function[0]->add('Symfony_Component_Debug_Tests_Fixtures', \dirname(\dirname(\dirname(\dirname(\dirname(__DIR__))))));
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -72,85 +72,85 @@ class ClassNotFoundFatalErrorHandlerTest extends TestCase
|
||||
$autoloader = new ComposerClassLoader();
|
||||
$autoloader->add('Symfony\Component\Debug\Exception\\', realpath(__DIR__.'/../../Exception'));
|
||||
|
||||
$debugClassLoader = new DebugClassLoader(array($autoloader, 'loadClass'));
|
||||
$debugClassLoader = new DebugClassLoader([$autoloader, 'loadClass']);
|
||||
|
||||
return array(
|
||||
array(
|
||||
array(
|
||||
return [
|
||||
[
|
||||
[
|
||||
'type' => 1,
|
||||
'line' => 12,
|
||||
'file' => 'foo.php',
|
||||
'message' => 'Class \'WhizBangFactory\' not found',
|
||||
),
|
||||
],
|
||||
"Attempted to load class \"WhizBangFactory\" from the global namespace.\nDid you forget a \"use\" statement?",
|
||||
),
|
||||
array(
|
||||
array(
|
||||
],
|
||||
[
|
||||
[
|
||||
'type' => 1,
|
||||
'line' => 12,
|
||||
'file' => 'foo.php',
|
||||
'message' => 'Class \'Foo\\Bar\\WhizBangFactory\' not found',
|
||||
),
|
||||
],
|
||||
"Attempted to load class \"WhizBangFactory\" from namespace \"Foo\\Bar\".\nDid you forget a \"use\" statement for another namespace?",
|
||||
),
|
||||
array(
|
||||
array(
|
||||
],
|
||||
[
|
||||
[
|
||||
'type' => 1,
|
||||
'line' => 12,
|
||||
'file' => 'foo.php',
|
||||
'message' => 'Class \'UndefinedFunctionException\' not found',
|
||||
),
|
||||
],
|
||||
"Attempted to load class \"UndefinedFunctionException\" from the global namespace.\nDid you forget a \"use\" statement for \"Symfony\Component\Debug\Exception\UndefinedFunctionException\"?",
|
||||
),
|
||||
array(
|
||||
array(
|
||||
],
|
||||
[
|
||||
[
|
||||
'type' => 1,
|
||||
'line' => 12,
|
||||
'file' => 'foo.php',
|
||||
'message' => 'Class \'PEARClass\' not found',
|
||||
),
|
||||
],
|
||||
"Attempted to load class \"PEARClass\" from the global namespace.\nDid you forget a \"use\" statement for \"Symfony_Component_Debug_Tests_Fixtures_PEARClass\"?",
|
||||
),
|
||||
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\".\nDid you forget a \"use\" statement for \"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\".\nDid you forget a \"use\" statement for \"Symfony\Component\Debug\Exception\UndefinedFunctionException\"?",
|
||||
array($autoloader, 'loadClass'),
|
||||
),
|
||||
array(
|
||||
array(
|
||||
[$autoloader, 'loadClass'],
|
||||
],
|
||||
[
|
||||
[
|
||||
'type' => 1,
|
||||
'line' => 12,
|
||||
'file' => 'foo.php',
|
||||
'message' => 'Class \'Foo\\Bar\\UndefinedFunctionException\' not found',
|
||||
),
|
||||
],
|
||||
"Attempted to load class \"UndefinedFunctionException\" from namespace \"Foo\Bar\".\nDid you forget a \"use\" statement for \"Symfony\Component\Debug\Exception\UndefinedFunctionException\"?",
|
||||
array($debugClassLoader, 'loadClass'),
|
||||
),
|
||||
array(
|
||||
array(
|
||||
[$debugClassLoader, 'loadClass'],
|
||||
],
|
||||
[
|
||||
[
|
||||
'type' => 1,
|
||||
'line' => 12,
|
||||
'file' => 'foo.php',
|
||||
'message' => 'Class \'Foo\\Bar\\UndefinedFunctionException\' not found',
|
||||
),
|
||||
],
|
||||
"Attempted to load class \"UndefinedFunctionException\" from namespace \"Foo\\Bar\".\nDid you forget a \"use\" statement for another namespace?",
|
||||
function ($className) { /* do nothing here */ },
|
||||
),
|
||||
);
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
public function testCannotRedeclareClass()
|
||||
@@ -161,12 +161,12 @@ class ClassNotFoundFatalErrorHandlerTest extends TestCase
|
||||
|
||||
require_once __DIR__.'/../FIXTURES2/REQUIREDTWICE.PHP';
|
||||
|
||||
$error = array(
|
||||
$error = [
|
||||
'type' => 1,
|
||||
'line' => 12,
|
||||
'file' => 'foo.php',
|
||||
'message' => 'Class \'Foo\\Bar\\RequiredTwice\' not found',
|
||||
);
|
||||
];
|
||||
|
||||
$handler = new ClassNotFoundFatalErrorHandler();
|
||||
$exception = $handler->handleError($error, new FatalErrorException('', 0, $error['type'], $error['file'], $error['line']));
|
||||
|
||||
@@ -35,44 +35,44 @@ class UndefinedFunctionFatalErrorHandlerTest extends TestCase
|
||||
|
||||
public function provideUndefinedFunctionData()
|
||||
{
|
||||
return array(
|
||||
array(
|
||||
array(
|
||||
return [
|
||||
[
|
||||
[
|
||||
'type' => 1,
|
||||
'line' => 12,
|
||||
'file' => 'foo.php',
|
||||
'message' => 'Call to undefined function test_namespaced_function()',
|
||||
),
|
||||
],
|
||||
"Attempted to call function \"test_namespaced_function\" from the global namespace.\nDid you mean to call \"\\symfony\\component\\debug\\tests\\fatalerrorhandler\\test_namespaced_function\"?",
|
||||
),
|
||||
array(
|
||||
array(
|
||||
],
|
||||
[
|
||||
[
|
||||
'type' => 1,
|
||||
'line' => 12,
|
||||
'file' => 'foo.php',
|
||||
'message' => 'Call to undefined function Foo\\Bar\\Baz\\test_namespaced_function()',
|
||||
),
|
||||
],
|
||||
"Attempted to call function \"test_namespaced_function\" from namespace \"Foo\\Bar\\Baz\".\nDid you mean to call \"\\symfony\\component\\debug\\tests\\fatalerrorhandler\\test_namespaced_function\"?",
|
||||
),
|
||||
array(
|
||||
array(
|
||||
],
|
||||
[
|
||||
[
|
||||
'type' => 1,
|
||||
'line' => 12,
|
||||
'file' => 'foo.php',
|
||||
'message' => 'Call to undefined function foo()',
|
||||
),
|
||||
],
|
||||
'Attempted to call function "foo" from the global namespace.',
|
||||
),
|
||||
array(
|
||||
array(
|
||||
],
|
||||
[
|
||||
[
|
||||
'type' => 1,
|
||||
'line' => 12,
|
||||
'file' => 'foo.php',
|
||||
'message' => 'Call to undefined function Foo\\Bar\\Baz\\foo()',
|
||||
),
|
||||
],
|
||||
'Attempted to call function "foo" from namespace "Foo\Bar\Baz".',
|
||||
),
|
||||
);
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -34,43 +34,43 @@ class UndefinedMethodFatalErrorHandlerTest extends TestCase
|
||||
|
||||
public function provideUndefinedMethodData()
|
||||
{
|
||||
return array(
|
||||
array(
|
||||
array(
|
||||
return [
|
||||
[
|
||||
[
|
||||
'type' => 1,
|
||||
'line' => 12,
|
||||
'file' => 'foo.php',
|
||||
'message' => 'Call to undefined method SplObjectStorage::what()',
|
||||
),
|
||||
],
|
||||
'Attempted to call an undefined method named "what" of class "SplObjectStorage".',
|
||||
),
|
||||
array(
|
||||
array(
|
||||
],
|
||||
[
|
||||
[
|
||||
'type' => 1,
|
||||
'line' => 12,
|
||||
'file' => 'foo.php',
|
||||
'message' => 'Call to undefined method SplObjectStorage::walid()',
|
||||
),
|
||||
],
|
||||
"Attempted to call an undefined method named \"walid\" of class \"SplObjectStorage\".\nDid you mean to call \"valid\"?",
|
||||
),
|
||||
array(
|
||||
array(
|
||||
],
|
||||
[
|
||||
[
|
||||
'type' => 1,
|
||||
'line' => 12,
|
||||
'file' => 'foo.php',
|
||||
'message' => 'Call to undefined method SplObjectStorage::offsetFet()',
|
||||
),
|
||||
],
|
||||
"Attempted to call an undefined method named \"offsetFet\" of class \"SplObjectStorage\".\nDid you mean to call e.g. \"offsetGet\", \"offsetSet\" or \"offsetUnset\"?",
|
||||
),
|
||||
array(
|
||||
array(
|
||||
'type' => 1,
|
||||
'message' => 'Call to undefined method class@anonymous::test()',
|
||||
'file' => '/home/possum/work/symfony/test.php',
|
||||
'line' => 11,
|
||||
),
|
||||
],
|
||||
[
|
||||
[
|
||||
'type' => 1,
|
||||
'message' => 'Call to undefined method class@anonymous::test()',
|
||||
'file' => '/home/possum/work/symfony/test.php',
|
||||
'line' => 11,
|
||||
],
|
||||
'Attempted to call an undefined method named "test" of class "class@anonymous".',
|
||||
),
|
||||
);
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
34
Tests/Fixtures/ClassWithAnnotatedParameters.php
Normal file
34
Tests/Fixtures/ClassWithAnnotatedParameters.php
Normal file
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
namespace Symfony\Component\Debug\Tests\Fixtures;
|
||||
|
||||
class ClassWithAnnotatedParameters
|
||||
{
|
||||
/**
|
||||
* @param string $foo this is a foo parameter
|
||||
*/
|
||||
public function fooMethod(string $foo)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $bar parameter not implemented yet
|
||||
*/
|
||||
public function barMethod(/* string $bar = null */)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Quz $quz parameter not implemented yet
|
||||
*/
|
||||
public function quzMethod(/* Quz $quz = null */)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @param true $yes
|
||||
*/
|
||||
public function isSymfony()
|
||||
{
|
||||
}
|
||||
}
|
||||
11
Tests/Fixtures/DefinitionInEvaluatedCode.php
Normal file
11
Tests/Fixtures/DefinitionInEvaluatedCode.php
Normal file
@@ -0,0 +1,11 @@
|
||||
<?php
|
||||
|
||||
namespace Symfony\Component\Debug\Tests\Fixtures;
|
||||
|
||||
eval('
|
||||
namespace Symfony\Component\Debug\Tests\Fixtures;
|
||||
|
||||
class DefinitionInEvaluatedCode
|
||||
{
|
||||
}
|
||||
');
|
||||
22
Tests/Fixtures/ErrorHandlerThatUsesThePreviousOne.php
Normal file
22
Tests/Fixtures/ErrorHandlerThatUsesThePreviousOne.php
Normal file
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
namespace Symfony\Component\Debug\Tests\Fixtures;
|
||||
|
||||
class ErrorHandlerThatUsesThePreviousOne
|
||||
{
|
||||
private static $previous;
|
||||
|
||||
public static function register()
|
||||
{
|
||||
$handler = new static();
|
||||
|
||||
self::$previous = set_error_handler([$handler, 'handleError']);
|
||||
|
||||
return $handler;
|
||||
}
|
||||
|
||||
public function handleError($type, $message, $file, $line, $context)
|
||||
{
|
||||
return \call_user_func(self::$previous, $type, $message, $file, $line, $context);
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,8 @@ namespace Symfony\Component\Debug\Tests\Fixtures;
|
||||
|
||||
class ExtendedFinalMethod extends FinalMethod
|
||||
{
|
||||
use FinalMethod2Trait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Symfony\Component\Debug\Tests\Fixtures;
|
||||
|
||||
/**
|
||||
* @final
|
||||
*/
|
||||
class FinalClass
|
||||
{
|
||||
}
|
||||
85
Tests/Fixtures/FinalClasses.php
Normal file
85
Tests/Fixtures/FinalClasses.php
Normal file
@@ -0,0 +1,85 @@
|
||||
<?php
|
||||
|
||||
namespace Symfony\Component\Debug\Tests\Fixtures;
|
||||
|
||||
/**
|
||||
* @final since version 3.3.
|
||||
*/
|
||||
class FinalClass1
|
||||
{
|
||||
// simple comment
|
||||
}
|
||||
|
||||
/**
|
||||
* @final
|
||||
*/
|
||||
class FinalClass2
|
||||
{
|
||||
// no comment
|
||||
}
|
||||
|
||||
/**
|
||||
* @final comment with @@@ and ***
|
||||
*
|
||||
* @author John Doe
|
||||
*/
|
||||
class FinalClass3
|
||||
{
|
||||
// with comment and a tag after
|
||||
}
|
||||
|
||||
/**
|
||||
* @final
|
||||
*
|
||||
* @author John Doe
|
||||
*/
|
||||
class FinalClass4
|
||||
{
|
||||
// without comment and a tag after
|
||||
}
|
||||
|
||||
/**
|
||||
* @author John Doe
|
||||
*
|
||||
*
|
||||
* @final multiline
|
||||
* comment
|
||||
*/
|
||||
class FinalClass5
|
||||
{
|
||||
// with comment and a tag before
|
||||
}
|
||||
|
||||
/**
|
||||
* @author John Doe
|
||||
*
|
||||
* @final
|
||||
*/
|
||||
class FinalClass6
|
||||
{
|
||||
// without comment and a tag before
|
||||
}
|
||||
|
||||
/**
|
||||
* @author John Doe
|
||||
*
|
||||
* @final another
|
||||
* multiline comment...
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
class FinalClass7
|
||||
{
|
||||
// with comment and a tag before and after
|
||||
}
|
||||
|
||||
/**
|
||||
* @author John Doe
|
||||
* @final
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
class FinalClass8
|
||||
{
|
||||
// without comment and a tag before and after
|
||||
}
|
||||
@@ -11,6 +11,15 @@ class FinalMethod
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @final
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function finalMethod2()
|
||||
{
|
||||
}
|
||||
|
||||
public function anotherMethod()
|
||||
{
|
||||
}
|
||||
|
||||
10
Tests/Fixtures/FinalMethod2Trait.php
Normal file
10
Tests/Fixtures/FinalMethod2Trait.php
Normal file
@@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
namespace Symfony\Component\Debug\Tests\Fixtures;
|
||||
|
||||
trait FinalMethod2Trait
|
||||
{
|
||||
public function finalMethod2()
|
||||
{
|
||||
}
|
||||
}
|
||||
14
Tests/Fixtures/InterfaceWithAnnotatedParameters.php
Normal file
14
Tests/Fixtures/InterfaceWithAnnotatedParameters.php
Normal file
@@ -0,0 +1,14 @@
|
||||
<?php
|
||||
|
||||
namespace Symfony\Component\Debug\Tests\Fixtures;
|
||||
|
||||
/**
|
||||
* Ensures a deprecation is triggered when a new parameter is not declared in child classes.
|
||||
*/
|
||||
interface InterfaceWithAnnotatedParameters
|
||||
{
|
||||
/**
|
||||
* @param bool $matrix
|
||||
*/
|
||||
public function whereAmI();
|
||||
}
|
||||
15
Tests/Fixtures/LoggerThatSetAnErrorHandler.php
Normal file
15
Tests/Fixtures/LoggerThatSetAnErrorHandler.php
Normal file
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
namespace Symfony\Component\Debug\Tests\Fixtures;
|
||||
|
||||
use Symfony\Component\Debug\BufferingLogger;
|
||||
|
||||
class LoggerThatSetAnErrorHandler extends BufferingLogger
|
||||
{
|
||||
public function log($level, $message, array $context = [])
|
||||
{
|
||||
set_error_handler('is_string');
|
||||
parent::log($level, $message, $context);
|
||||
restore_error_handler();
|
||||
}
|
||||
}
|
||||
24
Tests/Fixtures/SubClassWithAnnotatedParameters.php
Normal file
24
Tests/Fixtures/SubClassWithAnnotatedParameters.php
Normal file
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
namespace Symfony\Component\Debug\Tests\Fixtures;
|
||||
|
||||
class SubClassWithAnnotatedParameters extends ClassWithAnnotatedParameters implements InterfaceWithAnnotatedParameters
|
||||
{
|
||||
use TraitWithAnnotatedParameters;
|
||||
|
||||
public function fooMethod(string $foo)
|
||||
{
|
||||
}
|
||||
|
||||
public function barMethod($bar = null)
|
||||
{
|
||||
}
|
||||
|
||||
public function quzMethod()
|
||||
{
|
||||
}
|
||||
|
||||
public function whereAmI()
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -18,7 +18,7 @@ class ToStringThrower
|
||||
} catch (\Exception $e) {
|
||||
// Using user_error() here is on purpose so we do not forget
|
||||
// that this alias also should work alongside with trigger_error().
|
||||
return user_error($e, E_USER_ERROR);
|
||||
return trigger_error($e, E_USER_ERROR);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
13
Tests/Fixtures/TraitWithAnnotatedParameters.php
Normal file
13
Tests/Fixtures/TraitWithAnnotatedParameters.php
Normal file
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
namespace Symfony\Component\Debug\Tests\Fixtures;
|
||||
|
||||
trait TraitWithAnnotatedParameters
|
||||
{
|
||||
/**
|
||||
* `@param` annotations in traits are not parsed.
|
||||
*/
|
||||
public function isSymfony()
|
||||
{
|
||||
}
|
||||
}
|
||||
13
Tests/Fixtures/TraitWithInternalMethod.php
Normal file
13
Tests/Fixtures/TraitWithInternalMethod.php
Normal file
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
namespace Symfony\Component\Debug\Tests\Fixtures;
|
||||
|
||||
trait TraitWithInternalMethod
|
||||
{
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
public function foo()
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -25,14 +25,14 @@ namespace Symfony\Component\Debug\Tests;
|
||||
|
||||
function testHeader()
|
||||
{
|
||||
static $headers = array();
|
||||
static $headers = [];
|
||||
|
||||
if (!$h = func_get_args()) {
|
||||
if (!$h = \func_get_args()) {
|
||||
$h = $headers;
|
||||
$headers = array();
|
||||
$headers = [];
|
||||
|
||||
return $h;
|
||||
}
|
||||
|
||||
$headers[] = func_get_args();
|
||||
$headers[] = \func_get_args();
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ use Symfony\Component\Debug\DebugClassLoader;
|
||||
|
||||
$vendor = __DIR__;
|
||||
while (!file_exists($vendor.'/vendor')) {
|
||||
$vendor = dirname($vendor);
|
||||
$vendor = \dirname($vendor);
|
||||
}
|
||||
require $vendor.'/vendor/autoload.php';
|
||||
|
||||
@@ -24,3 +24,4 @@ class_exists(ExtendedFinalMethod::class);
|
||||
?>
|
||||
--EXPECTF--
|
||||
The "Symfony\Component\Debug\Tests\Fixtures\FinalMethod::finalMethod()" method is considered final. It may change without further notice as of its next major version. You should not extend it from "Symfony\Component\Debug\Tests\Fixtures\ExtendedFinalMethod".
|
||||
The "Symfony\Component\Debug\Tests\Fixtures\FinalMethod::finalMethod2()" method is considered final. It may change without further notice as of its next major version. You should not extend it from "Symfony\Component\Debug\Tests\Fixtures\ExtendedFinalMethod".
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
--TEST--
|
||||
Test catching fatal errors when handlers are nested
|
||||
--INI--
|
||||
display_errors=0
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
@@ -7,7 +9,7 @@ namespace Symfony\Component\Debug;
|
||||
|
||||
$vendor = __DIR__;
|
||||
while (!file_exists($vendor.'/vendor')) {
|
||||
$vendor = dirname($vendor);
|
||||
$vendor = \dirname($vendor);
|
||||
}
|
||||
require $vendor.'/vendor/autoload.php';
|
||||
|
||||
@@ -24,7 +26,6 @@ if (true) {
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
Fatal error: Class 'Symfony\Component\Debug\missing' not found in %s on line %d
|
||||
object(Symfony\Component\Debug\Exception\ClassNotFoundException)#%d (8) {
|
||||
["message":protected]=>
|
||||
string(131) "Attempted to load class "missing" from namespace "Symfony\Component\Debug".
|
||||
@@ -38,8 +39,7 @@ Did you forget a "use" statement for another namespace?"
|
||||
["line":protected]=>
|
||||
int(%d)
|
||||
["trace":"Exception":private]=>
|
||||
array(0) {
|
||||
}
|
||||
array(%d) {%A}
|
||||
["previous":"Exception":private]=>
|
||||
NULL
|
||||
["severity":protected]=>
|
||||
|
||||
@@ -7,14 +7,14 @@ namespace Symfony\Component\Debug;
|
||||
|
||||
$vendor = __DIR__;
|
||||
while (!file_exists($vendor.'/vendor')) {
|
||||
$vendor = dirname($vendor);
|
||||
$vendor = \dirname($vendor);
|
||||
}
|
||||
require $vendor.'/vendor/autoload.php';
|
||||
|
||||
if (true) {
|
||||
class TestLogger extends \Psr\Log\AbstractLogger
|
||||
{
|
||||
public function log($level, $message, array $context = array())
|
||||
public function log($level, $message, array $context = [])
|
||||
{
|
||||
echo $message, "\n";
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ namespace Symfony\Component\Debug;
|
||||
|
||||
$vendor = __DIR__;
|
||||
while (!file_exists($vendor.'/vendor')) {
|
||||
$vendor = dirname($vendor);
|
||||
$vendor = \dirname($vendor);
|
||||
}
|
||||
require $vendor.'/vendor/autoload.php';
|
||||
|
||||
@@ -17,9 +17,9 @@ ini_set('display_errors', 0);
|
||||
$eHandler = set_error_handler('var_dump');
|
||||
$xHandler = set_exception_handler('var_dump');
|
||||
|
||||
var_dump(array(
|
||||
var_dump([
|
||||
$eHandler[0] === $xHandler[0] ? 'Error and exception handlers do match' : 'Error and exception handlers are different',
|
||||
));
|
||||
]);
|
||||
|
||||
$eHandler[0]->setExceptionHandler('print_r');
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
"minimum-stability": "dev",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "4.1-dev"
|
||||
"dev-master": "4.2-dev"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:noNamespaceSchemaLocation="http://schema.phpunit.de/4.1/phpunit.xsd"
|
||||
xsi:noNamespaceSchemaLocation="http://schema.phpunit.de/5.2/phpunit.xsd"
|
||||
backupGlobals="false"
|
||||
colors="true"
|
||||
bootstrap="vendor/autoload.php"
|
||||
|
||||
Reference in New Issue
Block a user