package and depencies

This commit is contained in:
RafficMohammed
2023-01-08 02:57:24 +05:30
parent d5332eb421
commit 1d54b8bc7f
4309 changed files with 193331 additions and 172289 deletions

View File

@@ -20,7 +20,7 @@ use Psr\Log\AbstractLogger;
*/
class BufferingLogger extends AbstractLogger
{
private $logs = [];
private array $logs = [];
public function log($level, $message, array $context = []): void
{
@@ -35,10 +35,7 @@ class BufferingLogger extends AbstractLogger
return $logs;
}
/**
* @return array
*/
public function __sleep()
public function __sleep(): array
{
throw new \BadMethodCallException('Cannot serialize '.__CLASS__);
}
@@ -51,21 +48,21 @@ class BufferingLogger extends AbstractLogger
public function __destruct()
{
foreach ($this->logs as [$level, $message, $context]) {
if (false !== strpos($message, '{')) {
if (str_contains($message, '{')) {
foreach ($context as $key => $val) {
if (null === $val || \is_scalar($val) || (\is_object($val) && \is_callable([$val, '__toString']))) {
$message = str_replace("{{$key}}", $val, $message);
} elseif ($val instanceof \DateTimeInterface) {
$message = str_replace("{{$key}}", $val->format(\DateTime::RFC3339), $message);
$message = str_replace("{{$key}}", $val->format(\DateTimeInterface::RFC3339), $message);
} elseif (\is_object($val)) {
$message = str_replace("{{$key}}", '[object '.\get_class($val).']', $message);
$message = str_replace("{{$key}}", '[object '.get_debug_type($val).']', $message);
} else {
$message = str_replace("{{$key}}", '['.\gettype($val).']', $message);
}
}
}
error_log(sprintf('%s [%s] %s', date(\DateTime::RFC3339), $level, $message));
error_log(sprintf('%s [%s] %s', date(\DateTimeInterface::RFC3339), $level, $message));
}
}
}

View File

@@ -1,6 +1,12 @@
CHANGELOG
=========
6.1
---
* Report overridden `@final` constants and properties
* Read environment variable `SYMFONY_IDE` to configure file link format
5.4
---

View File

@@ -24,7 +24,7 @@ class Debug
if (!\in_array(\PHP_SAPI, ['cli', 'phpdbg'], true)) {
ini_set('display_errors', 0);
} elseif (!filter_var(\ini_get('log_errors'), \FILTER_VALIDATE_BOOLEAN) || \ini_get('error_log')) {
} elseif (!filter_var(\ini_get('log_errors'), \FILTER_VALIDATE_BOOL) || \ini_get('error_log')) {
// CLI - display errors only if they're not already logged to STDERR
ini_set('display_errors', 1);
}

View File

@@ -21,6 +21,7 @@ use PHPUnit\Framework\MockObject\MockObject;
use Prophecy\Prophecy\ProphecySubjectInterface;
use ProxyManager\Proxy\ProxyInterface;
use Symfony\Component\ErrorHandler\Internal\TentativeTypes;
use Symfony\Component\VarExporter\LazyObjectInterface;
/**
* Autoloader checking if the class is really defined in the file found.
@@ -105,24 +106,29 @@ class DebugClassLoader
'__serialize' => 'array',
];
/**
* @var callable
*/
private $classLoader;
private $isFinder;
private $loaded = [];
private $patchTypes;
private bool $isFinder;
private array $loaded = [];
private array $patchTypes = [];
private static $caseCheck;
private static $checkedClasses = [];
private static $final = [];
private static $finalMethods = [];
private static $deprecated = [];
private static $internal = [];
private static $internalMethods = [];
private static $annotatedParameters = [];
private static $darwinCache = ['/' => ['/', []]];
private static $method = [];
private static $returnTypes = [];
private static $methodTraits = [];
private static $fileOffsets = [];
private static int $caseCheck;
private static array $checkedClasses = [];
private static array $final = [];
private static array $finalMethods = [];
private static array $finalProperties = [];
private static array $finalConstants = [];
private static array $deprecated = [];
private static array $internal = [];
private static array $internalMethods = [];
private static array $annotatedParameters = [];
private static array $darwinCache = ['/' => ['/', []]];
private static array $method = [];
private static array $returnTypes = [];
private static array $methodTraits = [];
private static array $fileOffsets = [];
public function __construct(callable $classLoader)
{
@@ -132,7 +138,7 @@ class DebugClassLoader
$this->patchTypes += [
'force' => null,
'php' => \PHP_MAJOR_VERSION.'.'.\PHP_MINOR_VERSION,
'deprecations' => \PHP_VERSION_ID >= 70400,
'deprecations' => true,
];
if ('phpdoc' === $this->patchTypes['force']) {
@@ -150,7 +156,7 @@ class DebugClassLoader
if (false === $test || false === $i) {
// filesystem is case sensitive
self::$caseCheck = 0;
} elseif (substr($test, -\strlen($file)) === $file) {
} elseif (str_ends_with($test, $file)) {
// filesystem is case insensitive and realpath() normalizes the case of characters
self::$caseCheck = 1;
} elseif ('Darwin' === \PHP_OS_FAMILY) {
@@ -249,6 +255,7 @@ class DebugClassLoader
&& !is_subclass_of($symbols[$i], ProphecySubjectInterface::class)
&& !is_subclass_of($symbols[$i], Proxy::class)
&& !is_subclass_of($symbols[$i], ProxyInterface::class)
&& !is_subclass_of($symbols[$i], LazyObjectInterface::class)
&& !is_subclass_of($symbols[$i], LegacyProxy::class)
&& !is_subclass_of($symbols[$i], MockInterface::class)
&& !is_subclass_of($symbols[$i], IMock::class)
@@ -336,7 +343,7 @@ class DebugClassLoader
}
if (!$exists) {
if (false !== strpos($class, '/')) {
if (str_contains($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));
}
@@ -358,7 +365,7 @@ class DebugClassLoader
}
$deprecations = [];
$className = false !== strpos($class, "@anonymous\0") ? (get_parent_class($class) ?: key(class_implements($class)) ?: 'class').'@anonymous' : $class;
$className = str_contains($class, "@anonymous\0") ? (get_parent_class($class) ?: key(class_implements($class)) ?: 'class').'@anonymous' : $class;
// Don't trigger deprecations for classes in the same vendor
if ($class !== $className) {
@@ -432,7 +439,7 @@ class DebugClassLoader
}
} elseif (!$refl->isInterface()) {
if (!strncmp($vendor, str_replace('_', '\\', $use), $vendorLen)
&& 0 === strpos($className, 'Symfony\\')
&& str_starts_with($className, 'Symfony\\')
&& (!class_exists(InstalledVersions::class)
|| 'symfony/symfony' !== InstalledVersions::getRootPackage()['name'])
) {
@@ -470,8 +477,10 @@ class DebugClassLoader
self::$finalMethods[$class] = [];
self::$internalMethods[$class] = [];
self::$annotatedParameters[$class] = [];
self::$finalProperties[$class] = [];
self::$finalConstants[$class] = [];
foreach ($parentAndOwnInterfaces as $use) {
foreach (['finalMethods', 'internalMethods', 'annotatedParameters', 'returnTypes'] as $property) {
foreach (['finalMethods', 'internalMethods', 'annotatedParameters', 'returnTypes', 'finalProperties', 'finalConstants'] as $property) {
if (isset(self::${$property}[$use])) {
self::${$property}[$class] = self::${$property}[$class] ? self::${$property}[$use] + self::${$property}[$class] : self::${$property}[$use];
}
@@ -487,7 +496,7 @@ class DebugClassLoader
}
$returnType = implode('|', $returnType);
self::$returnTypes[$class] += [$method => [$returnType, 0 === strpos($returnType, '?') ? substr($returnType, 1).'|null' : $returnType, $use, '']];
self::$returnTypes[$class] += [$method => [$returnType, str_starts_with($returnType, '?') ? substr($returnType, 1).'|null' : $returnType, $use, '']];
}
}
}
@@ -541,7 +550,7 @@ class DebugClassLoader
$forcePatchTypes = $this->patchTypes['force'];
if ($canAddReturnType = null !== $forcePatchTypes && false === strpos($method->getFileName(), \DIRECTORY_SEPARATOR.'vendor'.\DIRECTORY_SEPARATOR)) {
if ($canAddReturnType = null !== $forcePatchTypes && !str_contains($method->getFileName(), \DIRECTORY_SEPARATOR.'vendor'.\DIRECTORY_SEPARATOR)) {
if ('void' !== (self::MAGIC_METHODS[$method->name] ?? 'void')) {
$this->patchTypes['force'] = $forcePatchTypes ?: 'docblock';
}
@@ -562,7 +571,7 @@ class DebugClassLoader
$this->patchReturnTypeWillChange($method);
}
if (null !== ($returnType ?? $returnType = self::MAGIC_METHODS[$method->name] ?? null) && !$method->hasReturnType() && !isset($doc['return'])) {
if (null !== ($returnType ??= self::MAGIC_METHODS[$method->name] ?? null) && !$method->hasReturnType() && !isset($doc['return'])) {
[$normalizedType, $returnType, $declaringClass, $declaringFile] = \is_string($returnType) ? [$returnType, $returnType, '', ''] : $returnType;
if ($canAddReturnType && 'docblock' !== $this->patchTypes['force']) {
@@ -626,6 +635,31 @@ class DebugClassLoader
}
}
$finals = isset(self::$final[$class]) || $refl->isFinal() ? [] : [
'finalConstants' => $refl->getReflectionConstants(\ReflectionClassConstant::IS_PUBLIC | \ReflectionClassConstant::IS_PROTECTED),
'finalProperties' => $refl->getProperties(\ReflectionProperty::IS_PUBLIC | \ReflectionProperty::IS_PROTECTED),
];
foreach ($finals as $type => $reflectors) {
foreach ($reflectors as $r) {
if ($r->class !== $class) {
continue;
}
$doc = $this->parsePhpDoc($r);
foreach ($parentAndOwnInterfaces as $use) {
if (isset(self::${$type}[$use][$r->name]) && !isset($doc['deprecated']) && ('finalConstants' === $type || substr($use, 0, strrpos($use, '\\')) !== substr($use, 0, strrpos($class, '\\')))) {
$msg = 'finalConstants' === $type ? '%s" constant' : '$%s" property';
$deprecations[] = sprintf('The "%s::'.$msg.' is considered final. You should not override it in "%s".', self::${$type}[$use][$r->name], $r->name, $class);
}
}
if (isset($doc['final']) || ('finalProperties' === $type && str_starts_with($class, 'Symfony\\') && !$r->hasType())) {
self::${$type}[$class][$r->name] = $class;
}
}
}
return $deprecations;
}
@@ -708,7 +742,7 @@ class DebugClassLoader
$dirFiles = self::$darwinCache[$kDir][1];
if (!isset($dirFiles[$file]) && ') : eval()\'d code' === substr($file, -17)) {
if (!isset($dirFiles[$file]) && str_ends_with($file, ') : eval()\'d code')) {
// Get the file name from "file_name.php(123) : eval()'d code"
$file = substr($file, 0, strrpos($file, '(', -17));
}
@@ -772,14 +806,14 @@ class DebugClassLoader
return;
}
if ($nullable = 0 === strpos($types, 'null|')) {
if ($nullable = str_starts_with($types, 'null|')) {
$types = substr($types, 5);
} elseif ($nullable = '|null' === substr($types, -5)) {
} elseif ($nullable = str_ends_with($types, '|null')) {
$types = substr($types, 0, -5);
}
$arrayType = ['array' => 'array'];
$typesMap = [];
$glue = false !== strpos($types, '&') ? '&' : '|';
$glue = str_contains($types, '&') ? '&' : '|';
foreach (explode($glue, $types) as $t) {
$t = self::SPECIAL_RETURN_TYPES[strtolower($t)] ?? $t;
$typesMap[$this->normalizeType($t, $class, $parent, $returnType)][$t] = $t;
@@ -804,7 +838,7 @@ class DebugClassLoader
$iterable = $object = true;
foreach ($typesMap as $n => $t) {
if ('null' !== $n) {
$iterable = $iterable && (\in_array($n, ['array', 'iterable']) || false !== strpos($n, 'Iterator'));
$iterable = $iterable && (\in_array($n, ['array', 'iterable']) || str_contains($n, 'Iterator'));
$object = $object && (\in_array($n, ['callable', 'object', '$this', 'static']) || !isset(self::SPECIAL_RETURN_TYPES[$n]));
}
}
@@ -831,6 +865,11 @@ class DebugClassLoader
return;
}
if (!preg_match('/^(?:\\\\?[a-zA-Z_\x80-\xff][a-zA-Z0-9_\x80-\xff]*)+$/', $n)) {
// exclude any invalid PHP class name (e.g. `Cookie::SAMESITE_*`)
continue;
}
if (!isset($phpTypes[''])) {
$phpTypes[] = $n;
}
@@ -873,7 +912,7 @@ class DebugClassLoader
// We could resolve "use" statements to return the FQDN
// but this would be too expensive for a runtime checker
if ('[]' !== substr($type, -2)) {
if (!str_ends_with($type, '[]')) {
return $type;
}
@@ -893,7 +932,7 @@ class DebugClassLoader
*/
private function patchReturnTypeWillChange(\ReflectionMethod $method)
{
if (\PHP_VERSION_ID >= 80000 && \count($method->getAttributes(\ReturnTypeWillChange::class))) {
if (\count($method->getAttributes(\ReturnTypeWillChange::class))) {
return;
}
@@ -931,10 +970,10 @@ class DebugClassLoader
$patchedMethods[$file][$startLine] = true;
$fileOffset = self::$fileOffsets[$file] ?? 0;
$startLine += $fileOffset - 2;
if ($nullable = '|null' === substr($returnType, -5)) {
if ($nullable = str_ends_with($returnType, '|null')) {
$returnType = substr($returnType, 0, -5);
}
$glue = false !== strpos($returnType, '&') ? '&' : '|';
$glue = str_contains($returnType, '&') ? '&' : '|';
$returnType = explode($glue, $returnType);
$code = file($file);
@@ -950,10 +989,10 @@ class DebugClassLoader
continue;
}
[$namespace, $useOffset, $useMap] = $useStatements[$file] ?? $useStatements[$file] = self::getUseStatements($file);
[$namespace, $useOffset, $useMap] = $useStatements[$file] ??= self::getUseStatements($file);
if ('\\' !== $type[0]) {
[$declaringNamespace, , $declaringUseMap] = $useStatements[$declaringFile] ?? $useStatements[$declaringFile] = self::getUseStatements($declaringFile);
[$declaringNamespace, , $declaringUseMap] = $useStatements[$declaringFile] ??= self::getUseStatements($declaringFile);
$p = strpos($type, '\\', 1);
$alias = $p ? substr($type, 0, $p) : $type;
@@ -991,7 +1030,7 @@ class DebugClassLoader
if ('docblock' === $this->patchTypes['force'] || ('object' === $normalizedType && '7.1' === $this->patchTypes['php'])) {
$returnType = implode($glue, $returnType).($nullable ? '|null' : '');
if (false !== strpos($code[$startLine], '#[')) {
if (str_contains($code[$startLine], '#[')) {
--$startLine;
}
@@ -1032,15 +1071,15 @@ EOTXT;
break;
}
if (0 === strpos($file[$i], 'namespace ')) {
if (str_starts_with($file[$i], 'namespace ')) {
$namespace = substr($file[$i], \strlen('namespace '), -2).'\\';
$useOffset = $i + 2;
}
if (0 === strpos($file[$i], 'use ')) {
if (str_starts_with($file[$i], 'use ')) {
$useOffset = $i;
for (; 0 === strpos($file[$i], 'use '); ++$i) {
for (; str_starts_with($file[$i], 'use '); ++$i) {
$u = explode(' as ', substr($file[$i], 4, -2), 2);
if (1 === \count($u)) {
@@ -1069,11 +1108,11 @@ EOTXT;
return;
}
if ('8.0' > $this->patchTypes['php'] && (false !== strpos($returnType, '|') || \in_array($returnType, ['mixed', 'static'], true))) {
if ('8.0' > $this->patchTypes['php'] && (str_contains($returnType, '|') || \in_array($returnType, ['mixed', 'static'], true))) {
return;
}
if ('8.1' > $this->patchTypes['php'] && false !== strpos($returnType, '&')) {
if ('8.1' > $this->patchTypes['php'] && str_contains($returnType, '&')) {
return;
}
}

View File

@@ -13,9 +13,6 @@ namespace Symfony\Component\ErrorHandler\Error;
class ClassNotFoundError extends \Error
{
/**
* {@inheritdoc}
*/
public function __construct(string $message, \Throwable $previous)
{
parent::__construct($message, $previous->getCode(), $previous->getPrevious());
@@ -26,7 +23,6 @@ class ClassNotFoundError extends \Error
'trace' => $previous->getTrace(),
] as $property => $value) {
$refl = new \ReflectionProperty(\Error::class, $property);
$refl->setAccessible(true);
$refl->setValue($this, $value);
}
}

View File

@@ -13,11 +13,9 @@ namespace Symfony\Component\ErrorHandler\Error;
class FatalError extends \Error
{
private $error;
private array $error;
/**
* {@inheritdoc}
*
* @param array $error An array as returned by error_get_last()
*/
public function __construct(string $message, int $code, array $error, int $traceOffset = null, bool $traceArgs = true, array $trace = null)
@@ -73,15 +71,11 @@ class FatalError extends \Error
] as $property => $value) {
if (null !== $value) {
$refl = new \ReflectionProperty(\Error::class, $property);
$refl->setAccessible(true);
$refl->setValue($this, $value);
}
}
}
/**
* {@inheritdoc}
*/
public function getError(): array
{
return $this->error;

View File

@@ -13,9 +13,6 @@ namespace Symfony\Component\ErrorHandler\Error;
class UndefinedFunctionError extends \Error
{
/**
* {@inheritdoc}
*/
public function __construct(string $message, \Throwable $previous)
{
parent::__construct($message, $previous->getCode(), $previous->getPrevious());
@@ -26,7 +23,6 @@ class UndefinedFunctionError extends \Error
'trace' => $previous->getTrace(),
] as $property => $value) {
$refl = new \ReflectionProperty(\Error::class, $property);
$refl->setAccessible(true);
$refl->setValue($this, $value);
}
}

View File

@@ -13,9 +13,6 @@ namespace Symfony\Component\ErrorHandler\Error;
class UndefinedMethodError extends \Error
{
/**
* {@inheritdoc}
*/
public function __construct(string $message, \Throwable $previous)
{
parent::__construct($message, $previous->getCode(), $previous->getPrevious());
@@ -26,7 +23,6 @@ class UndefinedMethodError extends \Error
'trace' => $previous->getTrace(),
] as $property => $value) {
$refl = new \ReflectionProperty(\Error::class, $property);
$refl->setAccessible(true);
$refl->setValue($this, $value);
}
}

View File

@@ -21,9 +21,6 @@ use Symfony\Component\ErrorHandler\Error\FatalError;
*/
class ClassNotFoundErrorEnhancer implements ErrorEnhancerInterface
{
/**
* {@inheritdoc}
*/
public function enhance(\Throwable $error): ?\Throwable
{
// Some specific versions of PHP produce a fatal error when extending a not found class.
@@ -143,7 +140,7 @@ class ClassNotFoundErrorEnhancer implements ErrorEnhancerInterface
];
if ($prefix) {
$candidates = array_filter($candidates, function ($candidate) use ($prefix) { return 0 === strpos($candidate, $prefix); });
$candidates = array_filter($candidates, function ($candidate) use ($prefix) { return str_starts_with($candidate, $prefix); });
}
// We cannot use the autoloader here as most of them use require; but if the class
@@ -157,7 +154,7 @@ class ClassNotFoundErrorEnhancer implements ErrorEnhancerInterface
try {
require_once $file;
} catch (\Throwable $e) {
} catch (\Throwable) {
return null;
}

View File

@@ -19,9 +19,6 @@ use Symfony\Component\ErrorHandler\Error\UndefinedFunctionError;
*/
class UndefinedFunctionErrorEnhancer implements ErrorEnhancerInterface
{
/**
* {@inheritdoc}
*/
public function enhance(\Throwable $error): ?\Throwable
{
if ($error instanceof FatalError) {
@@ -42,7 +39,7 @@ class UndefinedFunctionErrorEnhancer implements ErrorEnhancerInterface
$prefix = 'Call to undefined function ';
$prefixLen = \strlen($prefix);
if (0 !== strpos($message, $prefix)) {
if (!str_starts_with($message, $prefix)) {
return null;
}

View File

@@ -19,9 +19,6 @@ use Symfony\Component\ErrorHandler\Error\UndefinedMethodError;
*/
class UndefinedMethodErrorEnhancer implements ErrorEnhancerInterface
{
/**
* {@inheritdoc}
*/
public function enhance(\Throwable $error): ?\Throwable
{
if ($error instanceof FatalError) {
@@ -47,7 +44,7 @@ class UndefinedMethodErrorEnhancer implements ErrorEnhancerInterface
$candidates = [];
foreach ($methods as $definedMethodName) {
$lev = levenshtein($methodName, $definedMethodName);
if ($lev <= \strlen($methodName) / 3 || false !== strpos($definedMethodName, $methodName)) {
if ($lev <= \strlen($methodName) / 3 || str_contains($definedMethodName, $methodName)) {
$candidates[] = $definedMethodName;
}
}

View File

@@ -50,7 +50,7 @@ use Symfony\Component\ErrorHandler\Exception\SilencedErrorContext;
*/
class ErrorHandler
{
private $levels = [
private array $levels = [
\E_DEPRECATED => 'Deprecated',
\E_USER_DEPRECATED => 'User Deprecated',
\E_NOTICE => 'Notice',
@@ -68,7 +68,7 @@ class ErrorHandler
\E_CORE_ERROR => 'Core Error',
];
private $loggers = [
private array $loggers = [
\E_DEPRECATED => [null, LogLevel::INFO],
\E_USER_DEPRECATED => [null, LogLevel::INFO],
\E_NOTICE => [null, LogLevel::WARNING],
@@ -86,24 +86,23 @@ class ErrorHandler
\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
private $tracedErrors = 0x77FB; // E_ALL - E_STRICT - E_PARSE
private $screamedErrors = 0x55; // E_ERROR + E_CORE_ERROR + E_COMPILE_ERROR + E_PARSE
private $loggedErrors = 0;
private $configureException;
private $debug;
private int $thrownErrors = 0x1FFF; // E_ALL - E_DEPRECATED - E_USER_DEPRECATED
private int $scopedErrors = 0x1FFF; // E_ALL - E_DEPRECATED - E_USER_DEPRECATED
private int $tracedErrors = 0x77FB; // E_ALL - E_STRICT - E_PARSE
private int $screamedErrors = 0x55; // E_ERROR + E_CORE_ERROR + E_COMPILE_ERROR + E_PARSE
private int $loggedErrors = 0;
private \Closure $configureException;
private bool $debug;
private $isRecursive = 0;
private $isRoot = false;
private bool $isRecursive = false;
private bool $isRoot = false;
private $exceptionHandler;
private $bootstrappingLogger;
private ?BufferingLogger $bootstrappingLogger = null;
private static $reservedMemory;
private static $toStringException;
private static $silencedErrorCache = [];
private static $silencedErrorCount = 0;
private static $exitCode = 0;
private static ?string $reservedMemory = null;
private static array $silencedErrorCache = [];
private static int $silencedErrorCount = 0;
private static int $exitCode = 0;
/**
* Registers the error handler.
@@ -158,11 +157,9 @@ class ErrorHandler
/**
* Calls a function and turns any PHP error into \ErrorException.
*
* @return mixed What $function(...$arguments) returns
*
* @throws \ErrorException When $function(...$arguments) triggers a PHP error
*/
public static function call(callable $function, ...$arguments)
public static function call(callable $function, mixed ...$arguments): mixed
{
set_error_handler(static function (int $type, string $message, string $file, int $line) {
if (__FILE__ === $file) {
@@ -188,7 +185,6 @@ class ErrorHandler
$this->setDefaultLogger($bootstrappingLogger);
}
$traceReflector = new \ReflectionProperty(\Exception::class, 'trace');
$traceReflector->setAccessible(true);
$this->configureException = \Closure::bind(static function ($e, $trace, $file = null, $line = null) use ($traceReflector) {
$traceReflector->setValue($e, $trace);
$e->file = $file ?? $e->file;
@@ -205,7 +201,7 @@ class ErrorHandler
* @param array|int|null $levels An array map of E_* to LogLevel::* or an integer bit field of E_* constants
* @param bool $replace Whether to replace or not any existing logger
*/
public function setDefaultLogger(LoggerInterface $logger, $levels = \E_ALL, bool $replace = false): void
public function setDefaultLogger(LoggerInterface $logger, array|int|null $levels = \E_ALL, bool $replace = false): void
{
$loggers = [];
@@ -216,9 +212,7 @@ class ErrorHandler
}
}
} else {
if (null === $levels) {
$levels = \E_ALL;
}
$levels ??= \E_ALL;
foreach ($this->loggers as $type => $log) {
if (($type & $levels) && (empty($log[0]) || $replace || $log[0] === $this->bootstrappingLogger)) {
$log[0] = $logger;
@@ -235,8 +229,6 @@ class ErrorHandler
*
* @param array $loggers Error levels to [LoggerInterface|null, LogLevel::*] map
*
* @return array The previous map
*
* @throws \InvalidArgumentException
*/
public function setLoggers(array $loggers): array
@@ -283,13 +275,6 @@ class ErrorHandler
return $prev;
}
/**
* Sets a user exception handler.
*
* @param callable(\Throwable $e)|null $handler
*
* @return callable|null The previous exception handler
*/
public function setExceptionHandler(?callable $handler): ?callable
{
$prev = $this->exceptionHandler;
@@ -303,8 +288,6 @@ class ErrorHandler
*
* @param int $levels A bit field of E_* constants for thrown errors
* @param bool $replace Replace or amend the previous value
*
* @return int The previous value
*/
public function throwAt(int $levels, bool $replace = false): int
{
@@ -323,8 +306,6 @@ class ErrorHandler
*
* @param int $levels A bit field of E_* constants for scoped errors
* @param bool $replace Replace or amend the previous value
*
* @return int The previous value
*/
public function scopeAt(int $levels, bool $replace = false): int
{
@@ -342,8 +323,6 @@ class ErrorHandler
*
* @param int $levels A bit field of E_* constants for traced errors
* @param bool $replace Replace or amend the previous value
*
* @return int The previous value
*/
public function traceAt(int $levels, bool $replace = false): int
{
@@ -361,8 +340,6 @@ class ErrorHandler
*
* @param int $levels A bit field of E_* constants for screamed errors
* @param bool $replace Replace or amend the previous value
*
* @return int The previous value
*/
public function screamAt(int $levels, bool $replace = false): int
{
@@ -406,7 +383,7 @@ class ErrorHandler
*/
public function handleError(int $type, string $message, string $file, int $line): bool
{
if (\PHP_VERSION_ID >= 70300 && \E_WARNING === $type && '"' === $message[0] && false !== strpos($message, '" targeting switch is equivalent to "break')) {
if (\E_WARNING === $type && '"' === $message[0] && str_contains($message, '" targeting switch is equivalent to "break')) {
$type = \E_DEPRECATED;
}
@@ -430,10 +407,7 @@ class ErrorHandler
$logMessage = $this->levels[$type].': '.$message;
if (null !== self::$toStringException) {
$errorAsException = self::$toStringException;
self::$toStringException = null;
} elseif (!$throw && !($type & $level)) {
if (!$throw && !($type & $level)) {
if (!isset(self::$silencedErrorCache[$id = $file.':'.$line])) {
$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);
@@ -457,7 +431,7 @@ class ErrorHandler
return true;
}
} else {
if (false !== strpos($message, '@anonymous')) {
if (str_contains($message, '@anonymous')) {
$backtrace = debug_backtrace(false, 5);
for ($i = 1; isset($backtrace[$i]); ++$i) {
@@ -487,61 +461,18 @@ class ErrorHandler
}
if ($throw) {
if (\PHP_VERSION_ID < 70400 && \E_USER_ERROR & $type) {
for ($i = 1; isset($backtrace[$i]); ++$i) {
if (isset($backtrace[$i]['function'], $backtrace[$i]['type'], $backtrace[$i - 1]['function'])
&& '__toString' === $backtrace[$i]['function']
&& '->' === $backtrace[$i]['type']
&& !isset($backtrace[$i - 1]['class'])
&& ('trigger_error' === $backtrace[$i - 1]['function'] || 'user_error' === $backtrace[$i - 1]['function'])
) {
// Here, we know trigger_error() has been called from __toString().
// PHP triggers a fatal error when throwing from __toString().
// A small convention allows working around the limitation:
// given a caught $e exception in __toString(), quitting the method with
// `return trigger_error($e, E_USER_ERROR);` allows this error handler
// to make $e get through the __toString() barrier.
$context = 4 < \func_num_args() ? (func_get_arg(4) ?: []) : [];
foreach ($context as $e) {
if ($e instanceof \Throwable && $e->__toString() === $message) {
self::$toStringException = $e;
return true;
}
}
// Display the original error message instead of the default one.
$this->handleException($errorAsException);
// Stop the process by giving back the error to the native handler.
return false;
}
}
}
throw $errorAsException;
}
if ($this->isRecursive) {
$log = 0;
} else {
if (\PHP_VERSION_ID < (\PHP_VERSION_ID < 70400 ? 70316 : 70404)) {
$currentErrorHandler = set_error_handler('is_int');
restore_error_handler();
}
try {
$this->isRecursive = true;
$level = ($type & $level) ? $this->loggers[$type][1] : LogLevel::DEBUG;
$this->loggers[$type][0]->log($level, $logMessage, $errorAsException ? ['exception' => $errorAsException] : []);
} finally {
$this->isRecursive = false;
if (\PHP_VERSION_ID < (\PHP_VERSION_ID < 70400 ? 70316 : 70404)) {
set_error_handler($currentErrorHandler);
}
}
}
@@ -566,7 +497,7 @@ class ErrorHandler
}
if ($this->loggedErrors & $type) {
if (false !== strpos($message = $exception->getMessage(), "@anonymous\0")) {
if (str_contains($message = $exception->getMessage(), "@anonymous\0")) {
$message = $this->parseAnonymousClass($message);
}
@@ -606,7 +537,7 @@ class ErrorHandler
if (null !== $exceptionHandler) {
return $exceptionHandler($exception);
}
$handlerException = $handlerException ?: $exception;
$handlerException ??= $exception;
} catch (\Throwable $handlerException) {
}
if ($exception === $handlerException && null === $this->exceptionHandler) {
@@ -682,7 +613,7 @@ class ErrorHandler
$handler->throwAt(0, true);
$trace = $error['backtrace'] ?? null;
if (0 === strpos($error['message'], 'Allowed memory') || 0 === strpos($error['message'], 'Out of memory')) {
if (str_starts_with($error['message'], 'Allowed memory') || str_starts_with($error['message'], 'Out of memory')) {
$fatalError = new OutOfMemoryError($handler->levels[$error['type']].': '.$error['message'], 0, $error, 2, false, $trace);
} else {
$fatalError = new FatalError($handler->levels[$error['type']].': '.$error['message'], 0, $error, 2, true, $trace);
@@ -696,7 +627,7 @@ class ErrorHandler
self::$exitCode = 255;
$handler->handleException($fatalError);
}
} catch (FatalError $e) {
} catch (FatalError) {
// Ignore this re-throw
}

View File

@@ -23,9 +23,6 @@ class_exists(CliDumper::class);
*/
class CliErrorRenderer implements ErrorRendererInterface
{
/**
* {@inheritdoc}
*/
public function render(\Throwable $exception): FlattenException
{
$cloner = new VarCloner();

View File

@@ -20,6 +20,16 @@ use Symfony\Component\ErrorHandler\Exception\FlattenException;
*/
interface ErrorRendererInterface
{
public const IDE_LINK_FORMATS = [
'textmate' => 'txmt://open?url=file://%f&line=%l',
'macvim' => 'mvim://open?url=file://%f&line=%l',
'emacs' => 'emacs://open?url=file://%f&line=%l',
'sublime' => 'subl://open?url=file://%f&line=%l',
'phpstorm' => 'phpstorm://open?file=%f&line=%l',
'atom' => 'atom://core/open/file?filename=%f&line=%l',
'vscode' => 'vscode://file/%f:%l',
];
/**
* Renders a Throwable as a FlattenException.
*/

View File

@@ -33,41 +33,32 @@ class HtmlErrorRenderer implements ErrorRendererInterface
private const GHOST_HEART = 'M125.91386369681868,8.305165958366445 C128.95033202169043,-0.40540639102854037 140.8469835342744,8.305165958366445 125.91386369681868,19.504526138305664 C110.98208663272044,8.305165958366445 122.87795231771452,-0.40540639102854037 125.91386369681868,8.305165958366445 z';
private const GHOST_PLUS = 'M111.36824226379395,8.969108581542969 L118.69175148010254,8.969108581542969 L118.69175148010254,1.6455793380737305 L126.20429420471191,1.6455793380737305 L126.20429420471191,8.969108581542969 L133.52781105041504,8.969108581542969 L133.52781105041504,16.481630325317383 L126.20429420471191,16.481630325317383 L126.20429420471191,23.805158615112305 L118.69175148010254,23.805158615112305 L118.69175148010254,16.481630325317383 L111.36824226379395,16.481630325317383 z';
private $debug;
private $charset;
private $fileLinkFormat;
private $projectDir;
private $outputBuffer;
private $logger;
private bool|\Closure $debug;
private string $charset;
private string|array|FileLinkFormatter|false $fileLinkFormat;
private ?string $projectDir;
private string|\Closure $outputBuffer;
private ?LoggerInterface $logger;
private static $template = 'views/error.html.php';
private static string $template = 'views/error.html.php';
/**
* @param bool|callable $debug The debugging mode as a boolean or a callable that should return it
* @param string|FileLinkFormatter|null $fileLinkFormat
* @param bool|callable $outputBuffer The output buffer as a string or a callable that should return it
* @param bool|callable $debug The debugging mode as a boolean or a callable that should return it
* @param string|callable $outputBuffer The output buffer as a string or a callable that should return it
*/
public function __construct($debug = false, string $charset = null, $fileLinkFormat = null, string $projectDir = null, $outputBuffer = '', LoggerInterface $logger = null)
public function __construct(bool|callable $debug = false, string $charset = null, string|FileLinkFormatter $fileLinkFormat = null, string $projectDir = null, string|callable $outputBuffer = '', LoggerInterface $logger = null)
{
if (!\is_bool($debug) && !\is_callable($debug)) {
throw new \TypeError(sprintf('Argument 1 passed to "%s()" must be a boolean or a callable, "%s" given.', __METHOD__, \gettype($debug)));
}
if (!\is_string($outputBuffer) && !\is_callable($outputBuffer)) {
throw new \TypeError(sprintf('Argument 5 passed to "%s()" must be a string or a callable, "%s" given.', __METHOD__, \gettype($outputBuffer)));
}
$this->debug = $debug;
$this->debug = \is_bool($debug) ? $debug : $debug(...);
$this->charset = $charset ?: (\ini_get('default_charset') ?: 'UTF-8');
$this->fileLinkFormat = $fileLinkFormat ?: (\ini_get('xdebug.file_link_format') ?: get_cfg_var('xdebug.file_link_format'));
$fileLinkFormat ??= $_ENV['SYMFONY_IDE'] ?? $_SERVER['SYMFONY_IDE'] ?? null;
$this->fileLinkFormat = \is_string($fileLinkFormat)
? (ErrorRendererInterface::IDE_LINK_FORMATS[$fileLinkFormat] ?? $fileLinkFormat ?: false)
: ($fileLinkFormat ?: \ini_get('xdebug.file_link_format') ?: get_cfg_var('xdebug.file_link_format') ?: false);
$this->projectDir = $projectDir;
$this->outputBuffer = $outputBuffer;
$this->outputBuffer = \is_string($outputBuffer) ? $outputBuffer : $outputBuffer(...);
$this->logger = $logger;
}
/**
* {@inheritdoc}
*/
public function render(\Throwable $exception): FlattenException
{
$headers = ['Content-Type' => 'text/html; charset='.$this->charset];
@@ -156,9 +147,6 @@ class HtmlErrorRenderer implements ErrorRendererInterface
]);
}
/**
* Formats an array as a string.
*/
private function formatArgs(array $args): string
{
$result = [];
@@ -205,19 +193,14 @@ class HtmlErrorRenderer implements ErrorRendererInterface
{
$file = str_replace('\\', '/', $file);
if (null !== $this->projectDir && 0 === strpos($file, $this->projectDir)) {
if (null !== $this->projectDir && str_starts_with($file, $this->projectDir)) {
return ltrim(substr($file, \strlen($this->projectDir)), '/');
}
return null;
}
/**
* Returns the link for a given file/line pair.
*
* @return string|false
*/
private function getFileLink(string $file, int $line)
private function getFileLink(string $file, int $line): string|false
{
if ($fmt = $this->fileLinkFormat) {
return \is_string($fmt) ? strtr($fmt, ['%f' => $file, '%l' => $line]) : $fmt->format($file, $line);
@@ -320,7 +303,7 @@ class HtmlErrorRenderer implements ErrorRendererInterface
private function formatLogMessage(string $message, array $context)
{
if ($context && false !== strpos($message, '{')) {
if ($context && str_contains($message, '{')) {
$replacements = [];
foreach ($context as $key => $val) {
if (\is_scalar($val)) {

View File

@@ -24,35 +24,24 @@ use Symfony\Component\Serializer\SerializerInterface;
*/
class SerializerErrorRenderer implements ErrorRendererInterface
{
private $serializer;
private $format;
private $fallbackErrorRenderer;
private $debug;
private SerializerInterface $serializer;
private string|\Closure $format;
private ErrorRendererInterface $fallbackErrorRenderer;
private bool|\Closure $debug;
/**
* @param string|callable(FlattenException) $format The format as a string or a callable that should return it
* formats not supported by Request::getMimeTypes() should be given as mime types
* @param bool|callable $debug The debugging mode as a boolean or a callable that should return it
*/
public function __construct(SerializerInterface $serializer, $format, ErrorRendererInterface $fallbackErrorRenderer = null, $debug = false)
public function __construct(SerializerInterface $serializer, string|callable $format, ErrorRendererInterface $fallbackErrorRenderer = null, bool|callable $debug = false)
{
if (!\is_string($format) && !\is_callable($format)) {
throw new \TypeError(sprintf('Argument 2 passed to "%s()" must be a string or a callable, "%s" given.', __METHOD__, \gettype($format)));
}
if (!\is_bool($debug) && !\is_callable($debug)) {
throw new \TypeError(sprintf('Argument 4 passed to "%s()" must be a boolean or a callable, "%s" given.', __METHOD__, \gettype($debug)));
}
$this->serializer = $serializer;
$this->format = $format;
$this->format = \is_string($format) ? $format : $format(...);
$this->fallbackErrorRenderer = $fallbackErrorRenderer ?? new HtmlErrorRenderer();
$this->debug = $debug;
$this->debug = \is_bool($debug) ? $debug : $debug(...);
}
/**
* {@inheritdoc}
*/
public function render(\Throwable $exception): FlattenException
{
$headers = [];
@@ -76,7 +65,7 @@ class SerializerErrorRenderer implements ErrorRendererInterface
'debug' => $debug,
]))
->setHeaders($flattenException->getHeaders() + $headers);
} catch (NotEncodableValueException $e) {
} catch (NotEncodableValueException) {
return $this->fallbackErrorRenderer->render($exception);
}
}

View File

@@ -24,54 +24,25 @@ use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface;
*/
class FlattenException
{
/** @var string */
private $message;
private string $message;
private string|int $code;
private ?self $previous = null;
private array $trace;
private string $traceAsString;
private string $class;
private int $statusCode;
private string $statusText;
private array $headers;
private string $file;
private int $line;
private ?string $asString = null;
/** @var int|string */
private $code;
/** @var self|null */
private $previous;
/** @var array */
private $trace;
/** @var string */
private $traceAsString;
/** @var string */
private $class;
/** @var int */
private $statusCode;
/** @var string */
private $statusText;
/** @var array */
private $headers;
/** @var string */
private $file;
/** @var int */
private $line;
/** @var string|null */
private $asString;
/**
* @return static
*/
public static function create(\Exception $exception, int $statusCode = null, array $headers = []): self
public static function create(\Exception $exception, int $statusCode = null, array $headers = []): static
{
return static::createFromThrowable($exception, $statusCode, $headers);
}
/**
* @return static
*/
public static function createFromThrowable(\Throwable $exception, int $statusCode = null, array $headers = []): self
public static function createFromThrowable(\Throwable $exception, int $statusCode = null, array $headers = []): static
{
$e = new static();
$e->setMessage($exception->getMessage());
@@ -84,9 +55,7 @@ class FlattenException
$statusCode = 400;
}
if (null === $statusCode) {
$statusCode = 500;
}
$statusCode ??= 500;
if (class_exists(Response::class) && isset(Response::$statusTexts[$statusCode])) {
$statusText = Response::$statusTexts[$statusCode];
@@ -98,7 +67,7 @@ class FlattenException
$e->setStatusCode($statusCode);
$e->setHeaders($headers);
$e->setTraceFromThrowable($exception);
$e->setClass(\get_class($exception));
$e->setClass(get_debug_type($exception));
$e->setFile($exception->getFile());
$e->setLine($exception->getLine());
@@ -133,7 +102,7 @@ class FlattenException
/**
* @return $this
*/
public function setStatusCode(int $code): self
public function setStatusCode(int $code): static
{
$this->statusCode = $code;
@@ -148,7 +117,7 @@ class FlattenException
/**
* @return $this
*/
public function setHeaders(array $headers): self
public function setHeaders(array $headers): static
{
$this->headers = $headers;
@@ -163,9 +132,9 @@ class FlattenException
/**
* @return $this
*/
public function setClass(string $class): self
public function setClass(string $class): static
{
$this->class = false !== strpos($class, "@anonymous\0") ? (get_parent_class($class) ?: key(class_implements($class)) ?: 'class').'@anonymous' : $class;
$this->class = str_contains($class, "@anonymous\0") ? (get_parent_class($class) ?: key(class_implements($class)) ?: 'class').'@anonymous' : $class;
return $this;
}
@@ -178,7 +147,7 @@ class FlattenException
/**
* @return $this
*/
public function setFile(string $file): self
public function setFile(string $file): static
{
$this->file = $file;
@@ -193,7 +162,7 @@ class FlattenException
/**
* @return $this
*/
public function setLine(int $line): self
public function setLine(int $line): static
{
$this->line = $line;
@@ -208,7 +177,7 @@ class FlattenException
/**
* @return $this
*/
public function setStatusText(string $statusText): self
public function setStatusText(string $statusText): static
{
$this->statusText = $statusText;
@@ -223,9 +192,9 @@ class FlattenException
/**
* @return $this
*/
public function setMessage(string $message): self
public function setMessage(string $message): static
{
if (false !== strpos($message, "@anonymous\0")) {
if (str_contains($message, "@anonymous\0")) {
$message = preg_replace_callback('/[a-zA-Z_\x7f-\xff][\\\\a-zA-Z0-9_\x7f-\xff]*+@anonymous\x00.*?\.php(?:0x?|:[0-9]++\$)[0-9a-fA-F]++/', function ($m) {
return class_exists($m[0], false) ? (get_parent_class($m[0]) ?: key(class_implements($m[0])) ?: 'class').'@anonymous' : $m[0];
}, $message);
@@ -239,17 +208,15 @@ class FlattenException
/**
* @return int|string int most of the time (might be a string with PDOException)
*/
public function getCode()
public function getCode(): int|string
{
return $this->code;
}
/**
* @param int|string $code
*
* @return $this
*/
public function setCode($code): self
public function setCode(int|string $code): static
{
$this->code = $code;
@@ -264,7 +231,7 @@ class FlattenException
/**
* @return $this
*/
public function setPrevious(?self $previous): self
public function setPrevious(?self $previous): static
{
$this->previous = $previous;
@@ -293,7 +260,7 @@ class FlattenException
/**
* @return $this
*/
public function setTraceFromThrowable(\Throwable $throwable): self
public function setTraceFromThrowable(\Throwable $throwable): static
{
$this->traceAsString = $throwable->getTraceAsString();
@@ -303,7 +270,7 @@ class FlattenException
/**
* @return $this
*/
public function setTrace(array $trace, ?string $file, ?int $line): self
public function setTrace(array $trace, ?string $file, ?int $line): static
{
$this->trace = [];
$this->trace[] = [
@@ -350,7 +317,7 @@ class FlattenException
if ($value instanceof \__PHP_Incomplete_Class) {
$result[$key] = ['incomplete-object', $this->getClassNameFromIncomplete($value)];
} elseif (\is_object($value)) {
$result[$key] = ['object', \get_class($value)];
$result[$key] = ['object', get_debug_type($value)];
} elseif (\is_array($value)) {
if ($level > 10) {
$result[$key] = ['array', '*DEEP NESTED ARRAY*'];
@@ -390,7 +357,7 @@ class FlattenException
/**
* @return $this
*/
public function setAsString(?string $asString): self
public function setAsString(?string $asString): static
{
$this->asString = $asString;

View File

@@ -20,10 +20,10 @@ class SilencedErrorContext implements \JsonSerializable
{
public $count = 1;
private $severity;
private $file;
private $line;
private $trace;
private int $severity;
private string $file;
private int $line;
private array $trace;
public function __construct(int $severity, string $file, int $line, array $trace = [], int $count = 1)
{

View File

@@ -24,7 +24,7 @@ if (\in_array('-h', $argv) || \in_array('--help', $argv)) {
'',
' Available configuration via environment variables:',
' SYMFONY_PATCH_TYPE_DECLARATIONS',
' An url-encoded string to change the behavior of the script. Available parameters:',
' A url-encoded string to change the behavior of the script. Available parameters:',
' - "force": any value enables deprecation notices - can be any of:',
' - "phpdoc" to patch only docblock annotations',
' - "2" to add all possible return types',
@@ -75,7 +75,7 @@ set_error_handler(function ($type, $msg, $file, $line, $context = []) use (&$dep
$exclude = getenv('SYMFONY_PATCH_TYPE_EXCLUDE') ?: null;
foreach ($loader->getClassMap() as $class => $file) {
if (false !== strpos($file = realpath($file), \DIRECTORY_SEPARATOR.'vendor'.\DIRECTORY_SEPARATOR)) {
if (str_contains($file = realpath($file), \DIRECTORY_SEPARATOR.'vendor'.\DIRECTORY_SEPARATOR)) {
continue;
}
@@ -93,6 +93,6 @@ foreach ($deprecations as $class => $classDeprecations) {
echo implode(PHP_EOL, $classDeprecations).PHP_EOL.PHP_EOL;
}
if ($deprecations && false !== strpos(getenv('SYMFONY_PATCH_TYPE_DECLARATIONS') ?? '', 'force')) {
if ($deprecations && str_contains(getenv('SYMFONY_PATCH_TYPE_DECLARATIONS') ?? '', 'force')) {
echo 'These deprecations might be fixed by the patch script, run this again to check for type deprecations.'.PHP_EOL;
}

View File

@@ -4,6 +4,7 @@
<meta charset="<?= $this->charset; ?>" />
<meta name="robots" content="noindex,nofollow,noarchive" />
<title>An Error Occurred: <?= $statusText; ?></title>
<link rel="icon" href="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 128 128%22><text y=%221.2em%22 font-size=%2296%22>❌</text></svg>">
<style><?= $this->include('assets/css/error.css'); ?></style>
</head>
<body>

View File

@@ -35,7 +35,7 @@
$last = $exceptionAsArrayCount - 1;
foreach ($exceptionAsArray as $i => $e) {
foreach ($e['trace'] as $trace) {
if ($trace['file'] && false === mb_strpos($trace['file'], '/vendor/') && false === mb_strpos($trace['file'], '/var/cache/') && $i < $last) {
if ($trace['file'] && !str_contains($trace['file'], '/vendor/') && !str_contains($trace['file'], '/var/cache/') && $i < $last) {
$exceptionWithUserCode[] = $i;
}
}

View File

@@ -31,7 +31,7 @@
<?php
$isFirstUserCode = true;
foreach ($exception['trace'] as $i => $trace) {
$isVendorTrace = $trace['file'] && (false !== mb_strpos($trace['file'], '/vendor/') || false !== mb_strpos($trace['file'], '/var/cache/'));
$isVendorTrace = $trace['file'] && (str_contains($trace['file'], '/vendor/') || str_contains($trace['file'], '/var/cache/'));
$displayCodeSnippet = $isFirstUserCode && !$isVendorTrace;
if ($displayCodeSnippet) {
$isFirstUserCode = false;

View File

@@ -18,10 +18,7 @@ use Symfony\Component\ErrorHandler\Exception\SilencedErrorContext;
*/
class ThrowableUtils
{
/**
* @param SilencedErrorContext|\Throwable
*/
public static function getSeverity($throwable): int
public static function getSeverity(SilencedErrorContext|\Throwable $throwable): int
{
if ($throwable instanceof \ErrorException || $throwable instanceof SilencedErrorContext) {
return $throwable->getSeverity();

View File

@@ -16,13 +16,13 @@
}
],
"require": {
"php": ">=7.2.5",
"php": ">=8.1",
"psr/log": "^1|^2|^3",
"symfony/var-dumper": "^4.4|^5.0|^6.0"
"symfony/var-dumper": "^5.4|^6.0"
},
"require-dev": {
"symfony/http-kernel": "^4.4|^5.0|^6.0",
"symfony/serializer": "^4.4|^5.0|^6.0",
"symfony/http-kernel": "^5.4|^6.0",
"symfony/serializer": "^5.4|^6.0",
"symfony/deprecation-contracts": "^2.1|^3"
},
"autoload": {