diff --git a/src/Symfony/Bundle/FrameworkBundle/Console/Application.php b/src/Symfony/Bundle/FrameworkBundle/Console/Application.php index 08595ce91714..1b5be3bcc1b7 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Console/Application.php +++ b/src/Symfony/Bundle/FrameworkBundle/Console/Application.php @@ -20,7 +20,7 @@ use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Style\SymfonyStyle; use Symfony\Component\DependencyInjection\ContainerAwareInterface; -use Symfony\Component\ErrorHandler\Exception\FatalThrowableError; +use Symfony\Component\ErrorHandler\Exception\ErrorException; use Symfony\Component\HttpKernel\Bundle\Bundle; use Symfony\Component\HttpKernel\Kernel; use Symfony\Component\HttpKernel\KernelInterface; @@ -208,7 +208,7 @@ private function renderRegistrationErrors(InputInterface $input, OutputInterface foreach ($this->registrationErrors as $error) { if (!$error instanceof \Exception) { - $error = new FatalThrowableError($error); + $error = new ErrorException($error); } $this->doRenderException($error, $output); diff --git a/src/Symfony/Component/Console/Application.php b/src/Symfony/Component/Console/Application.php index e66705ab37bc..995aceaf1907 100644 --- a/src/Symfony/Component/Console/Application.php +++ b/src/Symfony/Component/Console/Application.php @@ -44,7 +44,7 @@ use Symfony\Component\Debug\ErrorHandler as LegacyErrorHandler; use Symfony\Component\Debug\Exception\FatalThrowableError as LegacyFatalThrowableError; use Symfony\Component\ErrorHandler\ErrorHandler; -use Symfony\Component\ErrorHandler\Exception\FatalThrowableError; +use Symfony\Component\ErrorHandler\Exception\ErrorException; use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Symfony\Component\EventDispatcher\LegacyEventDispatcherProxy; use Symfony\Contracts\Service\ResetInterface; @@ -129,7 +129,7 @@ public function run(InputInterface $input = null, OutputInterface $output = null $renderException = function (\Throwable $e) use ($output) { if (!$e instanceof \Exception) { - $e = class_exists(FatalThrowableError::class) ? new FatalThrowableError($e) : (class_exists(LegacyFatalThrowableError::class) ? new LegacyFatalThrowableError($e) : new \ErrorException($e->getMessage(), $e->getCode(), E_ERROR, $e->getFile(), $e->getLine())); + $e = class_exists(ErrorException::class) ? new ErrorException($e) : (class_exists(LegacyFatalThrowableError::class) ? new LegacyFatalThrowableError($e) : new \ErrorException($e->getMessage(), $e->getCode(), E_ERROR, $e->getFile(), $e->getLine())); } if ($output instanceof ConsoleOutputInterface) { $this->renderException($e, $output->getErrorOutput()); diff --git a/src/Symfony/Component/Debug/Exception/ClassNotFoundException.php b/src/Symfony/Component/Debug/Exception/ClassNotFoundException.php index 21e2c0db53a9..6c87f98c55be 100644 --- a/src/Symfony/Component/Debug/Exception/ClassNotFoundException.php +++ b/src/Symfony/Component/Debug/Exception/ClassNotFoundException.php @@ -11,14 +11,14 @@ namespace Symfony\Component\Debug\Exception; -@trigger_error(sprintf('The "%s" class is deprecated since Symfony 4.4, use "%s" instead.', ClassNotFoundException::class, \Symfony\Component\ErrorHandler\Exception\ClassNotFoundException::class), E_USER_DEPRECATED); +@trigger_error(sprintf('The "%s" class is deprecated since Symfony 4.4, use "%s" instead.', ClassNotFoundException::class, \Symfony\Component\ErrorHandler\Error\ClassNotFoundError::class), E_USER_DEPRECATED); /** * Class (or Trait or Interface) Not Found Exception. * * @author Konstanton Myakshin * - * @deprecated since Symfony 4.4, use Symfony\Component\ErrorHandler\Exception\ClassNotFoundException instead. + * @deprecated since Symfony 4.4, use Symfony\Component\ErrorHandler\Error\ClassNotFoundError instead. */ class ClassNotFoundException extends FatalErrorException { diff --git a/src/Symfony/Component/Debug/Exception/FatalErrorException.php b/src/Symfony/Component/Debug/Exception/FatalErrorException.php index 23c2ede7eb96..571f3975da49 100644 --- a/src/Symfony/Component/Debug/Exception/FatalErrorException.php +++ b/src/Symfony/Component/Debug/Exception/FatalErrorException.php @@ -11,14 +11,14 @@ namespace Symfony\Component\Debug\Exception; -@trigger_error(sprintf('The "%s" class is deprecated since Symfony 4.4, use "%s" instead.', FatalErrorException::class, \Symfony\Component\ErrorHandler\Exception\FatalErrorException::class), E_USER_DEPRECATED); +@trigger_error(sprintf('The "%s" class is deprecated since Symfony 4.4, use "%s" instead.', FatalErrorException::class, \Symfony\Component\ErrorHandler\Exception\ErrorException::class), E_USER_DEPRECATED); /** * Fatal Error Exception. * * @author Konstanton Myakshin * - * @deprecated since Symfony 4.4, use Symfony\Component\ErrorHandler\Exception\FatalErrorException instead. + * @deprecated since Symfony 4.4, use Symfony\Component\ErrorHandler\Exception\ErrorException instead. */ class FatalErrorException extends \ErrorException { diff --git a/src/Symfony/Component/Debug/Exception/FatalThrowableError.php b/src/Symfony/Component/Debug/Exception/FatalThrowableError.php index d7d36ac17e31..53c410b014b1 100644 --- a/src/Symfony/Component/Debug/Exception/FatalThrowableError.php +++ b/src/Symfony/Component/Debug/Exception/FatalThrowableError.php @@ -11,14 +11,14 @@ namespace Symfony\Component\Debug\Exception; -@trigger_error(sprintf('The "%s" class is deprecated since Symfony 4.4, use "%s" instead.', FatalThrowableError::class, \Symfony\Component\ErrorHandler\Exception\FatalThrowableError::class), E_USER_DEPRECATED); +@trigger_error(sprintf('The "%s" class is deprecated since Symfony 4.4, use "%s" instead.', FatalThrowableError::class, \Symfony\Component\ErrorHandler\Exception\ErrorException::class), E_USER_DEPRECATED); /** * Fatal Throwable Error. * * @author Nicolas Grekas * - * @deprecated since Symfony 4.4, use Symfony\Component\ErrorHandler\Exception\FatalThrowableError instead. + * @deprecated since Symfony 4.4, use Symfony\Component\ErrorHandler\Exception\ErrorException instead. */ class FatalThrowableError extends FatalErrorException { diff --git a/src/Symfony/Component/Debug/Exception/OutOfMemoryException.php b/src/Symfony/Component/Debug/Exception/OutOfMemoryException.php index 5b02d52ad8bb..a4a90ee99796 100644 --- a/src/Symfony/Component/Debug/Exception/OutOfMemoryException.php +++ b/src/Symfony/Component/Debug/Exception/OutOfMemoryException.php @@ -11,14 +11,14 @@ namespace Symfony\Component\Debug\Exception; -@trigger_error(sprintf('The "%s" class is deprecated since Symfony 4.4, use "%s" instead.', OutOfMemoryException::class, \Symfony\Component\ErrorHandler\Exception\OutOfMemoryException::class), E_USER_DEPRECATED); +@trigger_error(sprintf('The "%s" class is deprecated since Symfony 4.4, use "%s" instead.', OutOfMemoryException::class, \Symfony\Component\ErrorHandler\Error\OutOfMemoryError::class), E_USER_DEPRECATED); /** * Out of memory exception. * * @author Nicolas Grekas * - * @deprecated since Symfony 4.4, use Symfony\Component\ErrorHandler\Exception\OutOfMemoryException instead. + * @deprecated since Symfony 4.4, use Symfony\Component\ErrorHandler\Error\OutOfMemoryError instead. */ class OutOfMemoryException extends FatalErrorException { diff --git a/src/Symfony/Component/Debug/Exception/UndefinedFunctionException.php b/src/Symfony/Component/Debug/Exception/UndefinedFunctionException.php index fefd7d248eda..0a7037aee831 100644 --- a/src/Symfony/Component/Debug/Exception/UndefinedFunctionException.php +++ b/src/Symfony/Component/Debug/Exception/UndefinedFunctionException.php @@ -11,14 +11,14 @@ namespace Symfony\Component\Debug\Exception; -@trigger_error(sprintf('The "%s" class is deprecated since Symfony 4.4, use "%s" instead.', UndefinedFunctionException::class, \Symfony\Component\ErrorHandler\Exception\UndefinedFunctionException::class), E_USER_DEPRECATED); +@trigger_error(sprintf('The "%s" class is deprecated since Symfony 4.4, use "%s" instead.', UndefinedFunctionException::class, \Symfony\Component\ErrorHandler\Error\UndefinedFunctionError::class), E_USER_DEPRECATED); /** * Undefined Function Exception. * * @author Konstanton Myakshin * - * @deprecated since Symfony 4.4, use Symfony\Component\ErrorHandler\Exception\UndefinedFunctionException instead. + * @deprecated since Symfony 4.4, use Symfony\Component\ErrorHandler\Error\UndefinedFunctionError instead. */ class UndefinedFunctionException extends FatalErrorException { diff --git a/src/Symfony/Component/Debug/Exception/UndefinedMethodException.php b/src/Symfony/Component/Debug/Exception/UndefinedMethodException.php index 48559415868d..4d31c56d37e4 100644 --- a/src/Symfony/Component/Debug/Exception/UndefinedMethodException.php +++ b/src/Symfony/Component/Debug/Exception/UndefinedMethodException.php @@ -11,14 +11,14 @@ namespace Symfony\Component\Debug\Exception; -@trigger_error(sprintf('The "%s" class is deprecated since Symfony 4.4, use "%s" instead.', UndefinedMethodException::class, \Symfony\Component\ErrorHandler\Exception\UndefinedMethodException::class), E_USER_DEPRECATED); +@trigger_error(sprintf('The "%s" class is deprecated since Symfony 4.4, use "%s" instead.', UndefinedMethodException::class, \Symfony\Component\ErrorHandler\Error\UndefinedMethodError::class), E_USER_DEPRECATED); /** * Undefined Method Exception. * * @author Grégoire Pineau * - * @deprecated since Symfony 4.4, use Symfony\Component\ErrorHandler\Exception\UndefinedMethodException instead. + * @deprecated since Symfony 4.4, use Symfony\Component\ErrorHandler\Error\UndefinedMethodError instead. */ class UndefinedMethodException extends FatalErrorException { diff --git a/src/Symfony/Component/Debug/FatalErrorHandler/UndefinedFunctionFatalErrorHandler.php b/src/Symfony/Component/Debug/FatalErrorHandler/UndefinedFunctionFatalErrorHandler.php index ce9f4c0bb947..67b7ddd1610e 100644 --- a/src/Symfony/Component/Debug/FatalErrorHandler/UndefinedFunctionFatalErrorHandler.php +++ b/src/Symfony/Component/Debug/FatalErrorHandler/UndefinedFunctionFatalErrorHandler.php @@ -14,14 +14,14 @@ use Symfony\Component\Debug\Exception\FatalErrorException; use Symfony\Component\Debug\Exception\UndefinedFunctionException; -@trigger_error(sprintf('The "%s" class is deprecated since Symfony 4.4, use "%s" instead.', UndefinedFunctionFatalErrorHandler::class, \Symfony\Component\ErrorHandler\FatalErrorHandler\UndefinedFunctionFatalErrorHandler::class), E_USER_DEPRECATED); +@trigger_error(sprintf('The "%s" class is deprecated since Symfony 4.4, use "%s" instead.', UndefinedFunctionFatalErrorHandler::class, \Symfony\Component\ErrorHandler\ErrorEnhancer\UndefinedFunctionErrorEnhancer::class), E_USER_DEPRECATED); /** * ErrorHandler for undefined functions. * * @author Fabien Potencier * - * @deprecated since Symfony 4.4, use Symfony\Component\ErrorHandler\FatalErrorHandler\UndefinedFunctionFatalErrorHandler instead. + * @deprecated since Symfony 4.4, use Symfony\Component\ErrorHandler\ErrorEnhancer\UndefinedFunctionErrorEnhancer instead. */ class UndefinedFunctionFatalErrorHandler implements FatalErrorHandlerInterface { diff --git a/src/Symfony/Component/Debug/FatalErrorHandler/UndefinedMethodFatalErrorHandler.php b/src/Symfony/Component/Debug/FatalErrorHandler/UndefinedMethodFatalErrorHandler.php index 4fa3e46cd599..8ee359ab2777 100644 --- a/src/Symfony/Component/Debug/FatalErrorHandler/UndefinedMethodFatalErrorHandler.php +++ b/src/Symfony/Component/Debug/FatalErrorHandler/UndefinedMethodFatalErrorHandler.php @@ -14,14 +14,14 @@ use Symfony\Component\Debug\Exception\FatalErrorException; use Symfony\Component\Debug\Exception\UndefinedMethodException; -@trigger_error(sprintf('The "%s" class is deprecated since Symfony 4.4, use "%s" instead.', UndefinedMethodFatalErrorHandler::class, \Symfony\Component\ErrorHandler\FatalErrorHandler\UndefinedMethodFatalErrorHandler::class), E_USER_DEPRECATED); +@trigger_error(sprintf('The "%s" class is deprecated since Symfony 4.4, use "%s" instead.', UndefinedMethodFatalErrorHandler::class, \Symfony\Component\ErrorHandler\ErrorEnhancer\UndefinedMethodErrorEnhancer::class), E_USER_DEPRECATED); /** * ErrorHandler for undefined methods. * * @author Grégoire Pineau * - * @deprecated since Symfony 4.4, use Symfony\Component\ErrorHandler\FatalErrorHandler\UndefinedMethodFatalErrorHandler instead. + * @deprecated since Symfony 4.4, use Symfony\Component\ErrorHandler\ErrorEnhancer\UndefinedMethodErrorEnhancer instead. */ class UndefinedMethodFatalErrorHandler implements FatalErrorHandlerInterface { diff --git a/src/Symfony/Component/ErrorHandler/Error/ClassNotFoundError.php b/src/Symfony/Component/ErrorHandler/Error/ClassNotFoundError.php new file mode 100644 index 000000000000..443fba2c3bee --- /dev/null +++ b/src/Symfony/Component/ErrorHandler/Error/ClassNotFoundError.php @@ -0,0 +1,33 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\ErrorHandler\Error; + +class ClassNotFoundError extends \Error +{ + /** + * {@inheritdoc} + */ + public function __construct(string $message, \Throwable $previous) + { + parent::__construct($message, $previous->getCode(), $previous->getPrevious()); + + foreach ([ + 'file' => $previous->getFile(), + 'line' => $previous->getLine(), + 'trace' => $previous->getTrace(), + ] as $property => $value) { + $refl = new \ReflectionProperty(\Error::class, $property); + $refl->setAccessible(true); + $refl->setValue($this, $value); + } + } +} diff --git a/src/Symfony/Component/ErrorHandler/Exception/FatalErrorException.php b/src/Symfony/Component/ErrorHandler/Error/FatalError.php similarity index 68% rename from src/Symfony/Component/ErrorHandler/Exception/FatalErrorException.php rename to src/Symfony/Component/ErrorHandler/Error/FatalError.php index ab6268a5c041..68172d876cb5 100644 --- a/src/Symfony/Component/ErrorHandler/Exception/FatalErrorException.php +++ b/src/Symfony/Component/ErrorHandler/Error/FatalError.php @@ -9,18 +9,22 @@ * file that was distributed with this source code. */ -namespace Symfony\Component\ErrorHandler\Exception; +namespace Symfony\Component\ErrorHandler\Error; -/** - * Fatal Error Exception. - * - * @author Konstanton Myakshin - */ -class FatalErrorException extends \ErrorException +class FatalError extends \Error { - 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) + private $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) { - parent::__construct($message, $code, $severity, $filename, $lineno, $previous); + parent::__construct($message, $code); + + $this->error = $error; if (null !== $trace) { if (!$traceArgs) { @@ -28,8 +32,6 @@ public function __construct(string $message, int $code, int $severity, string $f unset($frame['args'], $frame['this'], $frame); } } - - $this->setTrace($trace); } elseif (null !== $traceOffset) { if (\function_exists('xdebug_get_function_stack')) { $trace = xdebug_get_function_stack(); @@ -63,15 +65,24 @@ public function __construct(string $message, int $code, int $severity, string $f } else { $trace = []; } + } - $this->setTrace($trace); + foreach ([ + 'file' => $error['file'], + 'line' => $error['line'], + 'trace' => $trace, + ] as $property => $value) { + $refl = new \ReflectionProperty(\Error::class, $property); + $refl->setAccessible(true); + $refl->setValue($this, $value); } } - protected function setTrace(array $trace): void + /** + * {@inheritdoc} + */ + public function getError(): array { - $traceReflector = new \ReflectionProperty('Exception', 'trace'); - $traceReflector->setAccessible(true); - $traceReflector->setValue($this, $trace); + return $this->error; } } diff --git a/src/Symfony/Component/ErrorHandler/Exception/OutOfMemoryException.php b/src/Symfony/Component/ErrorHandler/Error/OutOfMemoryError.php similarity index 56% rename from src/Symfony/Component/ErrorHandler/Exception/OutOfMemoryException.php rename to src/Symfony/Component/ErrorHandler/Error/OutOfMemoryError.php index 18c367596f63..d685c3d36933 100644 --- a/src/Symfony/Component/ErrorHandler/Exception/OutOfMemoryException.php +++ b/src/Symfony/Component/ErrorHandler/Error/OutOfMemoryError.php @@ -9,13 +9,8 @@ * file that was distributed with this source code. */ -namespace Symfony\Component\ErrorHandler\Exception; +namespace Symfony\Component\ErrorHandler\Error; -/** - * Out of memory exception. - * - * @author Nicolas Grekas - */ -class OutOfMemoryException extends FatalErrorException +class OutOfMemoryError extends FatalError { } diff --git a/src/Symfony/Component/ErrorHandler/Error/UndefinedFunctionError.php b/src/Symfony/Component/ErrorHandler/Error/UndefinedFunctionError.php new file mode 100644 index 000000000000..b57dd1579dee --- /dev/null +++ b/src/Symfony/Component/ErrorHandler/Error/UndefinedFunctionError.php @@ -0,0 +1,33 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\ErrorHandler\Error; + +class UndefinedFunctionError extends \Error +{ + /** + * {@inheritdoc} + */ + public function __construct(string $message, \Throwable $previous) + { + parent::__construct($message, $previous->getCode(), $previous->getPrevious()); + + foreach ([ + 'file' => $previous->getFile(), + 'line' => $previous->getLine(), + 'trace' => $previous->getTrace(), + ] as $property => $value) { + $refl = new \ReflectionProperty(\Error::class, $property); + $refl->setAccessible(true); + $refl->setValue($this, $value); + } + } +} diff --git a/src/Symfony/Component/ErrorHandler/Error/UndefinedMethodError.php b/src/Symfony/Component/ErrorHandler/Error/UndefinedMethodError.php new file mode 100644 index 000000000000..adc8731f36c4 --- /dev/null +++ b/src/Symfony/Component/ErrorHandler/Error/UndefinedMethodError.php @@ -0,0 +1,33 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\ErrorHandler\Error; + +class UndefinedMethodError extends \Error +{ + /** + * {@inheritdoc} + */ + public function __construct(string $message, \Throwable $previous) + { + parent::__construct($message, $previous->getCode(), $previous->getPrevious()); + + foreach ([ + 'file' => $previous->getFile(), + 'line' => $previous->getLine(), + 'trace' => $previous->getTrace(), + ] as $property => $value) { + $refl = new \ReflectionProperty(\Error::class, $property); + $refl->setAccessible(true); + $refl->setValue($this, $value); + } + } +} diff --git a/src/Symfony/Component/ErrorHandler/FatalErrorHandler/ClassNotFoundFatalErrorHandler.php b/src/Symfony/Component/ErrorHandler/ErrorEnhancer/ClassNotFoundErrorEnhancer.php similarity index 87% rename from src/Symfony/Component/ErrorHandler/FatalErrorHandler/ClassNotFoundFatalErrorHandler.php rename to src/Symfony/Component/ErrorHandler/ErrorEnhancer/ClassNotFoundErrorEnhancer.php index ee9930c09785..38111078bc31 100644 --- a/src/Symfony/Component/ErrorHandler/FatalErrorHandler/ClassNotFoundFatalErrorHandler.php +++ b/src/Symfony/Component/ErrorHandler/ErrorEnhancer/ClassNotFoundErrorEnhancer.php @@ -9,45 +9,45 @@ * file that was distributed with this source code. */ -namespace Symfony\Component\ErrorHandler\FatalErrorHandler; +namespace Symfony\Component\ErrorHandler\ErrorEnhancer; use Composer\Autoload\ClassLoader as ComposerClassLoader; use Symfony\Component\ClassLoader\ClassLoader as SymfonyClassLoader; use Symfony\Component\ErrorHandler\DebugClassLoader; -use Symfony\Component\ErrorHandler\Exception\ClassNotFoundException; -use Symfony\Component\ErrorHandler\Exception\FatalErrorException; +use Symfony\Component\ErrorHandler\Error\ClassNotFoundError; +use Symfony\Component\ErrorHandler\Error\FatalError; /** - * ErrorHandler for classes that do not exist. - * * @author Fabien Potencier */ -class ClassNotFoundFatalErrorHandler implements FatalErrorHandlerInterface +class ClassNotFoundErrorEnhancer implements ErrorEnhancerInterface { /** * {@inheritdoc} */ - public function handleError(array $error, FatalErrorException $exception) + public function enhance(\Throwable $error): ?\Throwable { - $messageLen = \strlen($error['message']); + // Some specific versions of PHP produce a fatal error when extending a not found class. + $message = !$error instanceof FatalError ? $error->getMessage() : $error->getError()['message']; + $messageLen = \strlen($message); $notFoundSuffix = '\' not found'; $notFoundSuffixLen = \strlen($notFoundSuffix); if ($notFoundSuffixLen > $messageLen) { return null; } - if (0 !== substr_compare($error['message'], $notFoundSuffix, -$notFoundSuffixLen)) { + if (0 !== substr_compare($message, $notFoundSuffix, -$notFoundSuffixLen)) { return null; } foreach (['class', 'interface', 'trait'] as $typeName) { $prefix = ucfirst($typeName).' \''; $prefixLen = \strlen($prefix); - if (0 !== strpos($error['message'], $prefix)) { + if (0 !== strpos($message, $prefix)) { continue; } - $fullyQualifiedClassName = substr($error['message'], $prefixLen, -$notFoundSuffixLen); + $fullyQualifiedClassName = substr($message, $prefixLen, -$notFoundSuffixLen); if (false !== $namespaceSeparatorIndex = strrpos($fullyQualifiedClassName, '\\')) { $className = substr($fullyQualifiedClassName, $namespaceSeparatorIndex + 1); $namespacePrefix = substr($fullyQualifiedClassName, 0, $namespaceSeparatorIndex); @@ -69,8 +69,10 @@ public function handleError(array $error, FatalErrorException $exception) } $message .= "\nDid you forget a \"use\" statement".$tail; - return new ClassNotFoundException($message, $exception); + return new ClassNotFoundError($message, $error); } + + return null; } /** @@ -81,7 +83,7 @@ public function handleError(array $error, FatalErrorException $exception) * * @param string $class A class name (without its namespace) * - * @return array An array of possible fully qualified class names + * Returns an array of possible fully qualified class names */ private function getClassCandidates(string $class): array { diff --git a/src/Symfony/Component/ErrorHandler/ErrorEnhancer/ErrorEnhancerInterface.php b/src/Symfony/Component/ErrorHandler/ErrorEnhancer/ErrorEnhancerInterface.php new file mode 100644 index 000000000000..7c3f4ef94068 --- /dev/null +++ b/src/Symfony/Component/ErrorHandler/ErrorEnhancer/ErrorEnhancerInterface.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\ErrorHandler\ErrorEnhancer; + +interface ErrorEnhancerInterface +{ + /** + * Returns an \Throwable instance if the class is able to improve the error, null otherwise. + */ + public function enhance(\Throwable $error): ?\Throwable; +} diff --git a/src/Symfony/Component/ErrorHandler/FatalErrorHandler/UndefinedFunctionFatalErrorHandler.php b/src/Symfony/Component/ErrorHandler/ErrorEnhancer/UndefinedFunctionErrorEnhancer.php similarity index 75% rename from src/Symfony/Component/ErrorHandler/FatalErrorHandler/UndefinedFunctionFatalErrorHandler.php rename to src/Symfony/Component/ErrorHandler/ErrorEnhancer/UndefinedFunctionErrorEnhancer.php index b944b8e11cd8..f4c49c2856c2 100644 --- a/src/Symfony/Component/ErrorHandler/FatalErrorHandler/UndefinedFunctionFatalErrorHandler.php +++ b/src/Symfony/Component/ErrorHandler/ErrorEnhancer/UndefinedFunctionErrorEnhancer.php @@ -9,41 +9,44 @@ * file that was distributed with this source code. */ -namespace Symfony\Component\ErrorHandler\FatalErrorHandler; +namespace Symfony\Component\ErrorHandler\ErrorEnhancer; -use Symfony\Component\ErrorHandler\Exception\FatalErrorException; -use Symfony\Component\ErrorHandler\Exception\UndefinedFunctionException; +use Symfony\Component\ErrorHandler\Error\FatalError; +use Symfony\Component\ErrorHandler\Error\UndefinedFunctionError; /** - * ErrorHandler for undefined functions. - * * @author Fabien Potencier */ -class UndefinedFunctionFatalErrorHandler implements FatalErrorHandlerInterface +class UndefinedFunctionErrorEnhancer implements ErrorEnhancerInterface { /** * {@inheritdoc} */ - public function handleError(array $error, FatalErrorException $exception) + public function enhance(\Throwable $error): ?\Throwable { - $messageLen = \strlen($error['message']); + if ($error instanceof FatalError) { + return null; + } + + $message = $error->getMessage(); + $messageLen = \strlen($message); $notFoundSuffix = '()'; $notFoundSuffixLen = \strlen($notFoundSuffix); if ($notFoundSuffixLen > $messageLen) { return null; } - if (0 !== substr_compare($error['message'], $notFoundSuffix, -$notFoundSuffixLen)) { + if (0 !== substr_compare($message, $notFoundSuffix, -$notFoundSuffixLen)) { return null; } $prefix = 'Call to undefined function '; $prefixLen = \strlen($prefix); - if (0 !== strpos($error['message'], $prefix)) { + if (0 !== strpos($message, $prefix)) { return null; } - $fullyQualifiedFunctionName = substr($error['message'], $prefixLen, -$notFoundSuffixLen); + $fullyQualifiedFunctionName = substr($message, $prefixLen, -$notFoundSuffixLen); if (false !== $namespaceSeparatorIndex = strrpos($fullyQualifiedFunctionName, '\\')) { $functionName = substr($fullyQualifiedFunctionName, $namespaceSeparatorIndex + 1); $namespacePrefix = substr($fullyQualifiedFunctionName, 0, $namespaceSeparatorIndex); @@ -79,6 +82,6 @@ public function handleError(array $error, FatalErrorException $exception) $message .= "\nDid you mean to call ".$candidates; } - return new UndefinedFunctionException($message, $exception); + return new UndefinedFunctionError($message, $error); } } diff --git a/src/Symfony/Component/ErrorHandler/FatalErrorHandler/UndefinedMethodFatalErrorHandler.php b/src/Symfony/Component/ErrorHandler/ErrorEnhancer/UndefinedMethodErrorEnhancer.php similarity index 73% rename from src/Symfony/Component/ErrorHandler/FatalErrorHandler/UndefinedMethodFatalErrorHandler.php rename to src/Symfony/Component/ErrorHandler/ErrorEnhancer/UndefinedMethodErrorEnhancer.php index 90bb09837e6d..ad0e4b3eef00 100644 --- a/src/Symfony/Component/ErrorHandler/FatalErrorHandler/UndefinedMethodFatalErrorHandler.php +++ b/src/Symfony/Component/ErrorHandler/ErrorEnhancer/UndefinedMethodErrorEnhancer.php @@ -9,24 +9,27 @@ * file that was distributed with this source code. */ -namespace Symfony\Component\ErrorHandler\FatalErrorHandler; +namespace Symfony\Component\ErrorHandler\ErrorEnhancer; -use Symfony\Component\ErrorHandler\Exception\FatalErrorException; -use Symfony\Component\ErrorHandler\Exception\UndefinedMethodException; +use Symfony\Component\ErrorHandler\Error\FatalError; +use Symfony\Component\ErrorHandler\Error\UndefinedMethodError; /** - * ErrorHandler for undefined methods. - * * @author Grégoire Pineau */ -class UndefinedMethodFatalErrorHandler implements FatalErrorHandlerInterface +class UndefinedMethodErrorEnhancer implements ErrorEnhancerInterface { /** * {@inheritdoc} */ - public function handleError(array $error, FatalErrorException $exception) + public function enhance(\Throwable $error): ?\Throwable { - preg_match('/^Call to undefined method (.*)::(.*)\(\)$/', $error['message'], $matches); + if ($error instanceof FatalError) { + return null; + } + + $message = $error->getMessage(); + preg_match('/^Call to undefined method (.*)::(.*)\(\)$/', $message, $matches); if (!$matches) { return null; } @@ -38,7 +41,7 @@ public function handleError(array $error, FatalErrorException $exception) if (!class_exists($className) || null === $methods = get_class_methods($className)) { // failed to get the class or its methods on which an unknown method was called (for example on an anonymous class) - return new UndefinedMethodException($message, $exception); + return new UndefinedMethodError($message, $error); } $candidates = []; @@ -61,6 +64,6 @@ public function handleError(array $error, FatalErrorException $exception) $message .= "\nDid you mean to call ".$candidates; } - return new UndefinedMethodException($message, $exception); + return new UndefinedMethodError($message, $error); } } diff --git a/src/Symfony/Component/ErrorHandler/ErrorHandler.php b/src/Symfony/Component/ErrorHandler/ErrorHandler.php index 37047911f703..5bb43df04dbc 100644 --- a/src/Symfony/Component/ErrorHandler/ErrorHandler.php +++ b/src/Symfony/Component/ErrorHandler/ErrorHandler.php @@ -13,15 +13,13 @@ use Psr\Log\LoggerInterface; use Psr\Log\LogLevel; -use Symfony\Component\ErrorHandler\Exception\FatalErrorException; -use Symfony\Component\ErrorHandler\Exception\OutOfMemoryException; +use Symfony\Component\ErrorHandler\Error\FatalError; +use Symfony\Component\ErrorHandler\Error\OutOfMemoryError; +use Symfony\Component\ErrorHandler\ErrorEnhancer\ClassNotFoundErrorEnhancer; +use Symfony\Component\ErrorHandler\ErrorEnhancer\ErrorEnhancerInterface; +use Symfony\Component\ErrorHandler\ErrorEnhancer\UndefinedFunctionErrorEnhancer; +use Symfony\Component\ErrorHandler\ErrorEnhancer\UndefinedMethodErrorEnhancer; use Symfony\Component\ErrorHandler\Exception\SilencedErrorContext; -use Symfony\Component\ErrorHandler\FatalErrorHandler\ClassNotFoundFatalErrorHandler; -use Symfony\Component\ErrorHandler\FatalErrorHandler\FatalErrorHandlerInterface; -use Symfony\Component\ErrorHandler\FatalErrorHandler\UndefinedFunctionFatalErrorHandler; -use Symfony\Component\ErrorHandler\FatalErrorHandler\UndefinedMethodFatalErrorHandler; -use Symfony\Component\ErrorRenderer\ErrorRenderer\HtmlErrorRenderer; -use Symfony\Component\ErrorRenderer\Exception\FlattenException; /** * A generic ErrorHandler for the PHP engine. @@ -538,64 +536,50 @@ public function handleError(int $type, string $message, string $file, int $line) /** * Handles an exception by logging then forwarding it to another handler. * - * @param array $error An array as returned by error_get_last() - * * @internal */ - public function handleException(\Throwable $exception, array $error = null) + public function handleException(\Throwable $exception) { - if (null === $error) { + $handlerException = null; + + if (!$exception instanceof FatalError) { self::$exitCode = 255; - } - $type = ThrowableUtils::getSeverity($exception); - $handlerException = null; + $type = ThrowableUtils::getSeverity($exception); + } else { + $type = $exception->getError()['type']; + } - if (($this->loggedErrors & $type) || $exception instanceof \Error) { + if ($this->loggedErrors & $type) { if (false !== strpos($message = $exception->getMessage(), "class@anonymous\0")) { $message = $this->parseAnonymousClass($message); } - if ($exception instanceof FatalErrorException) { + if ($exception instanceof FatalError) { $message = 'Fatal '.$message; - } elseif ($exception instanceof \ErrorException) { - $message = 'Uncaught '.$message; } elseif ($exception instanceof \Error) { - $error = [ - 'type' => $type, - 'message' => $message, - 'file' => $exception->getFile(), - 'line' => $exception->getLine(), - ]; $message = 'Uncaught Error: '.$message; + } elseif ($exception instanceof \ErrorException) { + $message = 'Uncaught '.$message; } else { $message = 'Uncaught Exception: '.$message; } - } - if ($this->loggedErrors & $type) { try { $this->loggers[$type][0]->log($this->loggers[$type][1], $message, ['exception' => $exception]); } catch (\Throwable $handlerException) { } } - // temporary until fatal error handlers rework - $originalException = $exception; - if (!$exception instanceof \Exception) { - $exception = new FatalErrorException($exception->getMessage(), $exception->getCode(), $type, $exception->getFile(), $exception->getLine(), null, true, $exception->getTrace()); - } - - if ($exception instanceof FatalErrorException && !$exception instanceof OutOfMemoryException && $error) { - foreach ($this->getFatalErrorHandlers() as $handler) { - if ($e = $handler->handleError($error, $exception)) { - $convertedException = $e; + if (!$exception instanceof OutOfMemoryError) { + foreach ($this->getErrorEnhancers() as $errorEnhancer) { + if ($e = $errorEnhancer->enhance($exception)) { + $exception = $e; break; } } } - $exception = $convertedException ?? $originalException; $exceptionHandler = $this->exceptionHandler; if ((!\is_array($exceptionHandler) || !$exceptionHandler[0] instanceof self || 'sendPhpResponse' !== $exceptionHandler[1]) && !\in_array(\PHP_SAPI, ['cli', 'phpdbg'], true)) { $this->exceptionHandler = [$this, 'sendPhpResponse']; @@ -613,6 +597,7 @@ public function handleException(\Throwable $exception, array $error = null) self::$reservedMemory = null; // Disable the fatal error handler throw $exception; // Give back $exception to the native handler } + $this->handleException($handlerException); } @@ -673,20 +658,20 @@ public static function handleFatalError(array $error = null): void $trace = isset($error['backtrace']) ? $error['backtrace'] : null; if (0 === strpos($error['message'], 'Allowed memory') || 0 === strpos($error['message'], 'Out of memory')) { - $exception = new OutOfMemoryException($handler->levels[$error['type']].': '.$error['message'], 0, $error['type'], $error['file'], $error['line'], 2, false, $trace); + $fatalError = new OutOfMemoryError($handler->levels[$error['type']].': '.$error['message'], 0, $error, 2, false, $trace); } else { - $exception = new FatalErrorException($handler->levels[$error['type']].': '.$error['message'], 0, $error['type'], $error['file'], $error['line'], 2, true, $trace); + $fatalError = new FatalError($handler->levels[$error['type']].': '.$error['message'], 0, $error, 2, true, $trace); } } else { - $exception = null; + $fatalError = null; } try { - if (null !== $exception) { + if (null !== $fatalError) { self::$exitCode = 255; - $handler->handleException($exception, $error); + $handler->handleException($fatalError); } - } catch (FatalErrorException $e) { + } catch (FatalError $e) { // Ignore this re-throw } @@ -730,18 +715,16 @@ private function sendPhpResponse(\Throwable $exception) } /** - * Gets the fatal error handlers. - * - * Override this method if you want to define more fatal error handlers. + * Override this method if you want to define more error enhancers. * - * @return FatalErrorHandlerInterface[] An array of FatalErrorHandlerInterface + * @return ErrorEnhancerInterface[] */ - protected function getFatalErrorHandlers(): array + protected function getErrorEnhancers(): iterable { return [ - new UndefinedFunctionFatalErrorHandler(), - new UndefinedMethodFatalErrorHandler(), - new ClassNotFoundFatalErrorHandler(), + new UndefinedFunctionErrorEnhancer(), + new UndefinedMethodErrorEnhancer(), + new ClassNotFoundErrorEnhancer(), ]; } diff --git a/src/Symfony/Component/ErrorHandler/Exception/ClassNotFoundException.php b/src/Symfony/Component/ErrorHandler/Exception/ClassNotFoundException.php deleted file mode 100644 index b0638826d641..000000000000 --- a/src/Symfony/Component/ErrorHandler/Exception/ClassNotFoundException.php +++ /dev/null @@ -1,36 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\ErrorHandler\Exception; - -/** - * Class (or Trait or Interface) Not Found Exception. - * - * @author Konstanton Myakshin - */ -class ClassNotFoundException extends FatalErrorException -{ - public function __construct(string $message, \ErrorException $previous) - { - parent::__construct( - $message, - $previous->getCode(), - $previous->getSeverity(), - $previous->getFile(), - $previous->getLine(), - null, - true, - null, - $previous->getPrevious() - ); - $this->setTrace($previous->getTrace()); - } -} diff --git a/src/Symfony/Component/ErrorHandler/Exception/FatalThrowableError.php b/src/Symfony/Component/ErrorHandler/Exception/ErrorException.php similarity index 77% rename from src/Symfony/Component/ErrorHandler/Exception/FatalThrowableError.php rename to src/Symfony/Component/ErrorHandler/Exception/ErrorException.php index 460d3e1ae832..759d3fdc47a3 100644 --- a/src/Symfony/Component/ErrorHandler/Exception/FatalThrowableError.php +++ b/src/Symfony/Component/ErrorHandler/Exception/ErrorException.php @@ -13,12 +13,7 @@ use Symfony\Component\ErrorHandler\ThrowableUtils; -/** - * Fatal Throwable Error. - * - * @author Nicolas Grekas - */ -class FatalThrowableError extends FatalErrorException +class ErrorException extends \ErrorException { private $originalClassName; @@ -26,7 +21,7 @@ public function __construct(\Throwable $e) { $this->originalClassName = \get_class($e); - \ErrorException::__construct( + parent::__construct( $e->getMessage(), $e->getCode(), ThrowableUtils::getSeverity($e), @@ -35,7 +30,9 @@ public function __construct(\Throwable $e) $e->getPrevious() ); - $this->setTrace($e->getTrace()); + $refl = new \ReflectionProperty(\Exception::class, 'trace'); + $refl->setAccessible(true); + $refl->setValue($this, $e->getTrace()); } public function getOriginalClassName(): string diff --git a/src/Symfony/Component/ErrorHandler/Exception/UndefinedFunctionException.php b/src/Symfony/Component/ErrorHandler/Exception/UndefinedFunctionException.php deleted file mode 100644 index bb2f46564d4d..000000000000 --- a/src/Symfony/Component/ErrorHandler/Exception/UndefinedFunctionException.php +++ /dev/null @@ -1,36 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\ErrorHandler\Exception; - -/** - * Undefined Function Exception. - * - * @author Konstanton Myakshin - */ -class UndefinedFunctionException extends FatalErrorException -{ - public function __construct(string $message, \ErrorException $previous) - { - parent::__construct( - $message, - $previous->getCode(), - $previous->getSeverity(), - $previous->getFile(), - $previous->getLine(), - null, - true, - null, - $previous->getPrevious() - ); - $this->setTrace($previous->getTrace()); - } -} diff --git a/src/Symfony/Component/ErrorHandler/Exception/UndefinedMethodException.php b/src/Symfony/Component/ErrorHandler/Exception/UndefinedMethodException.php deleted file mode 100644 index 12efdc716c5d..000000000000 --- a/src/Symfony/Component/ErrorHandler/Exception/UndefinedMethodException.php +++ /dev/null @@ -1,36 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\ErrorHandler\Exception; - -/** - * Undefined Method Exception. - * - * @author Grégoire Pineau - */ -class UndefinedMethodException extends FatalErrorException -{ - public function __construct(string $message, \ErrorException $previous) - { - parent::__construct( - $message, - $previous->getCode(), - $previous->getSeverity(), - $previous->getFile(), - $previous->getLine(), - null, - true, - null, - $previous->getPrevious() - ); - $this->setTrace($previous->getTrace()); - } -} diff --git a/src/Symfony/Component/ErrorHandler/FatalErrorHandler/FatalErrorHandlerInterface.php b/src/Symfony/Component/ErrorHandler/FatalErrorHandler/FatalErrorHandlerInterface.php deleted file mode 100644 index daf5dcd1fdd1..000000000000 --- a/src/Symfony/Component/ErrorHandler/FatalErrorHandler/FatalErrorHandlerInterface.php +++ /dev/null @@ -1,31 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\ErrorHandler\FatalErrorHandler; - -use Symfony\Component\ErrorHandler\Exception\FatalErrorException; - -/** - * Attempts to convert fatal errors to exceptions. - * - * @author Fabien Potencier - */ -interface FatalErrorHandlerInterface -{ - /** - * Attempts to convert an error into an exception. - * - * @param array $error An array as returned by error_get_last() - * - * @return FatalErrorException|null A FatalErrorException instance if the class is able to convert the error, null otherwise - */ - public function handleError(array $error, FatalErrorException $exception); -} diff --git a/src/Symfony/Component/ErrorHandler/Tests/ErrorEnhancer/ClassNotFoundErrorEnhancerTest.php b/src/Symfony/Component/ErrorHandler/Tests/ErrorEnhancer/ClassNotFoundErrorEnhancerTest.php new file mode 100644 index 000000000000..3098200b0160 --- /dev/null +++ b/src/Symfony/Component/ErrorHandler/Tests/ErrorEnhancer/ClassNotFoundErrorEnhancerTest.php @@ -0,0 +1,149 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\ErrorHandler\Tests\ErrorEnhancer; + +use Composer\Autoload\ClassLoader as ComposerClassLoader; +use PHPUnit\Framework\TestCase; +use Symfony\Component\ErrorHandler\DebugClassLoader; +use Symfony\Component\ErrorHandler\Error\ClassNotFoundError; +use Symfony\Component\ErrorHandler\Error\FatalError; +use Symfony\Component\ErrorHandler\ErrorEnhancer\ClassNotFoundErrorEnhancer; + +class ClassNotFoundErrorEnhancerTest extends TestCase +{ + public static function setUpBeforeClass(): void + { + foreach (spl_autoload_functions() as $function) { + if (!\is_array($function)) { + continue; + } + + // get class loaders wrapped by DebugClassLoader + if ($function[0] instanceof DebugClassLoader) { + $function = $function[0]->getClassLoader(); + } + + if ($function[0] instanceof ComposerClassLoader) { + $function[0]->add('Symfony_Component_ErrorHandler_Tests_Fixtures', \dirname(__DIR__, 5)); + break; + } + } + } + + /** + * @dataProvider provideClassNotFoundData + */ + public function testEnhance(string $originalMessage, string $enhancedMessage, $autoloader = null) + { + try { + if ($autoloader) { + // Unregister all autoloaders to ensure the custom provided + // autoloader is the only one to be used during the test run. + $autoloaders = spl_autoload_functions(); + array_map('spl_autoload_unregister', $autoloaders); + spl_autoload_register($autoloader); + } + + $expectedLine = __LINE__ + 1; + $error = (new ClassNotFoundErrorEnhancer())->enhance(new \Error($originalMessage)); + } finally { + if ($autoloader) { + spl_autoload_unregister($autoloader); + array_map('spl_autoload_register', $autoloaders); + } + } + + $this->assertInstanceOf(ClassNotFoundError::class, $error); + $this->assertSame($enhancedMessage, $error->getMessage()); + $this->assertSame(realpath(__FILE__), $error->getFile()); + $this->assertSame($expectedLine, $error->getLine()); + } + + public function provideClassNotFoundData() + { + $autoloader = new ComposerClassLoader(); + $autoloader->add('Symfony\Component\ErrorHandler\Error\\', realpath(__DIR__.'/../../Error')); + $autoloader->add('Symfony_Component_ErrorHandler_Tests_Fixtures', realpath(__DIR__.'/../../Tests/Fixtures')); + + $debugClassLoader = new DebugClassLoader([$autoloader, 'loadClass']); + + return [ + [ + 'Class \'WhizBangFactory\' not found', + "Attempted to load class \"WhizBangFactory\" from the global namespace.\nDid you forget a \"use\" statement?", + ], + [ + 'Class \'Foo\\Bar\\WhizBangFactory\' not found', + "Attempted to load class \"WhizBangFactory\" from namespace \"Foo\\Bar\".\nDid you forget a \"use\" statement for another namespace?", + ], + [ + 'Class \'UndefinedFunctionError\' not found', + "Attempted to load class \"UndefinedFunctionError\" from the global namespace.\nDid you forget a \"use\" statement for \"Symfony\Component\ErrorHandler\Error\UndefinedFunctionError\"?", + [$debugClassLoader, 'loadClass'], + ], + [ + 'Class \'PEARClass\' not found', + "Attempted to load class \"PEARClass\" from the global namespace.\nDid you forget a \"use\" statement for \"Symfony_Component_ErrorHandler_Tests_Fixtures_PEARClass\"?", + [$debugClassLoader, 'loadClass'], + ], + [ + 'Class \'Foo\\Bar\\UndefinedFunctionError\' not found', + "Attempted to load class \"UndefinedFunctionError\" from namespace \"Foo\Bar\".\nDid you forget a \"use\" statement for \"Symfony\Component\ErrorHandler\Error\UndefinedFunctionError\"?", + [$debugClassLoader, 'loadClass'], + ], + [ + 'Class \'Foo\\Bar\\UndefinedFunctionError\' not found', + "Attempted to load class \"UndefinedFunctionError\" from namespace \"Foo\Bar\".\nDid you forget a \"use\" statement for \"Symfony\Component\ErrorHandler\Error\UndefinedFunctionError\"?", + [$autoloader, 'loadClass'], + ], + [ + 'Class \'Foo\\Bar\\UndefinedFunctionError\' not found', + "Attempted to load class \"UndefinedFunctionError\" from namespace \"Foo\Bar\".\nDid you forget a \"use\" statement for \"Symfony\Component\ErrorHandler\Error\UndefinedFunctionError\"?", + [$debugClassLoader, 'loadClass'], + ], + [ + 'Class \'Foo\\Bar\\UndefinedFunctionError\' not found', + "Attempted to load class \"UndefinedFunctionError\" from namespace \"Foo\\Bar\".\nDid you forget a \"use\" statement for another namespace?", + function ($className) { /* do nothing here */ }, + ], + ]; + } + + public function testEnhanceWithFatalError() + { + $error = (new ClassNotFoundErrorEnhancer())->enhance(new FatalError('foo', 0, [ + 'type' => E_ERROR, + 'message' => "Class 'FooBarCcc' not found", + 'file' => $expectedFile = realpath(__FILE__), + 'line' => $expectedLine = __LINE__, + ])); + + $this->assertInstanceOf(ClassNotFoundError::class, $error); + $this->assertSame("Attempted to load class \"FooBarCcc\" from the global namespace.\nDid you forget a \"use\" statement?", $error->getMessage()); + $this->assertSame($expectedFile, $error->getFile()); + $this->assertSame($expectedLine, $error->getLine()); + } + + public function testCannotRedeclareClass() + { + if (!file_exists(__DIR__.'/../FIXTURES2/REQUIREDTWICE.PHP')) { + $this->markTestSkipped('Can only be run on case insensitive filesystems'); + } + + require_once __DIR__.'/../FIXTURES2/REQUIREDTWICE.PHP'; + + $enhancer = new ClassNotFoundErrorEnhancer(); + $error = $enhancer->enhance(new \Error("Class 'Foo\\Bar\\RequiredTwice' not found")); + + $this->assertInstanceOf(ClassNotFoundError::class, $error); + } +} diff --git a/src/Symfony/Component/ErrorHandler/Tests/ErrorEnhancer/UndefinedFunctionErrorEnhancerTest.php b/src/Symfony/Component/ErrorHandler/Tests/ErrorEnhancer/UndefinedFunctionErrorEnhancerTest.php new file mode 100644 index 000000000000..fe7d5371a11a --- /dev/null +++ b/src/Symfony/Component/ErrorHandler/Tests/ErrorEnhancer/UndefinedFunctionErrorEnhancerTest.php @@ -0,0 +1,62 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\ErrorHandler\Tests\ErrorEnhancer; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\ErrorHandler\Error\UndefinedFunctionError; +use Symfony\Component\ErrorHandler\ErrorEnhancer\UndefinedFunctionErrorEnhancer; + +class UndefinedFunctionErrorEnhancerTest extends TestCase +{ + /** + * @dataProvider provideUndefinedFunctionData + */ + public function testEnhance(string $originalMessage, string $enhancedMessage) + { + $enhancer = new UndefinedFunctionErrorEnhancer(); + + $expectedLine = __LINE__ + 1; + $error = $enhancer->enhance(new \Error($originalMessage)); + + $this->assertInstanceOf(UndefinedFunctionError::class, $error); + // class names are case insensitive and PHP do not return the same + $this->assertSame(strtolower($enhancedMessage), strtolower($error->getMessage())); + $this->assertSame(realpath(__FILE__), $error->getFile()); + $this->assertSame($expectedLine, $error->getLine()); + } + + public function provideUndefinedFunctionData() + { + return [ + [ + '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\\errorhandler\\tests\\errorenhancer\\test_namespaced_function\"?", + ], + [ + '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\\errorhandler\\tests\\errorenhancer\\test_namespaced_function\"?", + ], + [ + 'Call to undefined function foo()', + 'Attempted to call function "foo" from the global namespace.', + ], + [ + 'Call to undefined function Foo\\Bar\\Baz\\foo()', + 'Attempted to call function "foo" from namespace "Foo\Bar\Baz".', + ], + ]; + } +} + +function test_namespaced_function() +{ +} diff --git a/src/Symfony/Component/ErrorHandler/Tests/ErrorEnhancer/UndefinedMethodErrorEnhancerTest.php b/src/Symfony/Component/ErrorHandler/Tests/ErrorEnhancer/UndefinedMethodErrorEnhancerTest.php new file mode 100644 index 000000000000..d6ac6c029c6f --- /dev/null +++ b/src/Symfony/Component/ErrorHandler/Tests/ErrorEnhancer/UndefinedMethodErrorEnhancerTest.php @@ -0,0 +1,57 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\ErrorHandler\Tests\ErrorEnhancer; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\ErrorHandler\Error\UndefinedMethodError; +use Symfony\Component\ErrorHandler\ErrorEnhancer\UndefinedMethodErrorEnhancer; + +class UndefinedMethodErrorEnhancerTest extends TestCase +{ + /** + * @dataProvider provideUndefinedMethodData + */ + public function testEnhance(string $originalMessage, string $enhancedMessage) + { + $enhancer = new UndefinedMethodErrorEnhancer(); + + $expectedLine = __LINE__ + 1; + $error = $enhancer->enhance(new \Error($originalMessage)); + + $this->assertInstanceOf(UndefinedMethodError::class, $error); + $this->assertSame($enhancedMessage, $error->getMessage()); + $this->assertSame(realpath(__FILE__), $error->getFile()); + $this->assertSame($expectedLine, $error->getLine()); + } + + public function provideUndefinedMethodData() + { + return [ + [ + 'Call to undefined method SplObjectStorage::what()', + 'Attempted to call an undefined method named "what" of class "SplObjectStorage".', + ], + [ + 'Call to undefined method SplObjectStorage::walid()', + "Attempted to call an undefined method named \"walid\" of class \"SplObjectStorage\".\nDid you mean to call \"valid\"?", + ], + [ + '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\"?", + ], + [ + 'Call to undefined method class@anonymous::test()', + 'Attempted to call an undefined method named "test" of class "class@anonymous".', + ], + ]; + } +} diff --git a/src/Symfony/Component/ErrorHandler/Tests/ErrorHandlerTest.php b/src/Symfony/Component/ErrorHandler/Tests/ErrorHandlerTest.php index bb694cfc3bc5..1c170732e898 100644 --- a/src/Symfony/Component/ErrorHandler/Tests/ErrorHandlerTest.php +++ b/src/Symfony/Component/ErrorHandler/Tests/ErrorHandlerTest.php @@ -15,6 +15,8 @@ use Psr\Log\LogLevel; use Psr\Log\NullLogger; use Symfony\Component\ErrorHandler\BufferingLogger; +use Symfony\Component\ErrorHandler\Error\ClassNotFoundError; +use Symfony\Component\ErrorHandler\Error\FatalError; use Symfony\Component\ErrorHandler\ErrorHandler; use Symfony\Component\ErrorHandler\Exception\SilencedErrorContext; use Symfony\Component\ErrorHandler\Tests\Fixtures\ErrorHandlerThatUsesThePreviousOne; @@ -518,7 +520,7 @@ public function testHandleFatalError() $logArgCheck = function ($level, $message, $context) { $this->assertEquals('Fatal Parse Error: foo', $message); $this->assertArrayHasKey('exception', $context); - $this->assertInstanceOf(\Exception::class, $context['exception']); + $this->assertInstanceOf(FatalError::class, $context['exception']); }; $logger @@ -552,7 +554,7 @@ public function testHandleErrorException() $handler->handleException($exception); - $this->assertInstanceOf('Symfony\Component\ErrorHandler\Exception\ClassNotFoundException', $args[0]); + $this->assertInstanceOf(ClassNotFoundError::class, $args[0]); $this->assertStringStartsWith("Attempted to load class \"IReallyReallyDoNotExistAnywhereInTheRepositoryISwear\" from the global namespace.\nDid you forget a \"use\" statement", $args[0]->getMessage()); } diff --git a/src/Symfony/Component/ErrorHandler/Tests/FatalErrorHandler/ClassNotFoundFatalErrorHandlerTest.php b/src/Symfony/Component/ErrorHandler/Tests/FatalErrorHandler/ClassNotFoundFatalErrorHandlerTest.php deleted file mode 100644 index 0661d742c03c..000000000000 --- a/src/Symfony/Component/ErrorHandler/Tests/FatalErrorHandler/ClassNotFoundFatalErrorHandlerTest.php +++ /dev/null @@ -1,180 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\ErrorHandler\Tests\FatalErrorHandler; - -use Composer\Autoload\ClassLoader as ComposerClassLoader; -use PHPUnit\Framework\TestCase; -use Symfony\Component\ErrorHandler\DebugClassLoader; -use Symfony\Component\ErrorHandler\Exception\FatalErrorException; -use Symfony\Component\ErrorHandler\FatalErrorHandler\ClassNotFoundFatalErrorHandler; - -class ClassNotFoundFatalErrorHandlerTest extends TestCase -{ - public static function setUpBeforeClass(): void - { - foreach (spl_autoload_functions() as $function) { - if (!\is_array($function)) { - continue; - } - - // get class loaders wrapped by DebugClassLoader - if ($function[0] instanceof DebugClassLoader) { - $function = $function[0]->getClassLoader(); - } - - if ($function[0] instanceof ComposerClassLoader) { - $function[0]->add('Symfony_Component_ErrorHandler_Tests_Fixtures', \dirname(__DIR__, 5)); - break; - } - } - } - - /** - * @dataProvider provideClassNotFoundData - */ - public function testHandleClassNotFound(array $error, string $translatedMessage, callable $autoloader = null) - { - if ($autoloader) { - // Unregister all autoloaders to ensure the custom provided - // autoloader is the only one to be used during the test run. - $autoloaders = spl_autoload_functions(); - array_map('spl_autoload_unregister', $autoloaders); - spl_autoload_register($autoloader); - } - - $handler = new ClassNotFoundFatalErrorHandler(); - - $exception = $handler->handleError($error, new FatalErrorException('', 0, $error['type'], $error['file'], $error['line'])); - - if ($autoloader) { - spl_autoload_unregister($autoloader); - array_map('spl_autoload_register', $autoloaders); - } - - $this->assertInstanceOf('Symfony\Component\ErrorHandler\Exception\ClassNotFoundException', $exception); - $this->assertSame($translatedMessage, $exception->getMessage()); - $this->assertSame($error['type'], $exception->getSeverity()); - $this->assertSame($error['file'], $exception->getFile()); - $this->assertSame($error['line'], $exception->getLine()); - } - - public function provideClassNotFoundData(): array - { - $autoloader = new ComposerClassLoader(); - $autoloader->add('Symfony\Component\ErrorHandler\Exception\\', realpath(__DIR__.'/../../Exception')); - $autoloader->add('Symfony_Component_ErrorHandler_Tests_Fixtures', realpath(__DIR__.'/../../Tests/Fixtures')); - - $debugClassLoader = new DebugClassLoader([$autoloader, 'loadClass']); - - 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?", - ], - [ - [ - '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?", - ], - [ - [ - '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\ErrorHandler\Exception\UndefinedFunctionException\"?", - [$debugClassLoader, 'loadClass'], - ], - [ - [ - '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_ErrorHandler_Tests_Fixtures_PEARClass\"?", - [$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 \"Symfony\Component\ErrorHandler\Exception\UndefinedFunctionException\"?", - [$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 \"Symfony\Component\ErrorHandler\Exception\UndefinedFunctionException\"?", - [$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\ErrorHandler\Exception\UndefinedFunctionException\"?", - [$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() - { - if (!file_exists(__DIR__.'/../FIXTURES2/REQUIREDTWICE.PHP')) { - $this->markTestSkipped('Can only be run on case insensitive filesystems'); - } - - require_once __DIR__.'/../FIXTURES2/REQUIREDTWICE.PHP'; - - $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'])); - - $this->assertInstanceOf('Symfony\Component\ErrorHandler\Exception\ClassNotFoundException', $exception); - } -} diff --git a/src/Symfony/Component/ErrorHandler/Tests/FatalErrorHandler/UndefinedFunctionFatalErrorHandlerTest.php b/src/Symfony/Component/ErrorHandler/Tests/FatalErrorHandler/UndefinedFunctionFatalErrorHandlerTest.php deleted file mode 100644 index fa8dd42268da..000000000000 --- a/src/Symfony/Component/ErrorHandler/Tests/FatalErrorHandler/UndefinedFunctionFatalErrorHandlerTest.php +++ /dev/null @@ -1,81 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\ErrorHandler\Tests\FatalErrorHandler; - -use PHPUnit\Framework\TestCase; -use Symfony\Component\ErrorHandler\Exception\FatalErrorException; -use Symfony\Component\ErrorHandler\FatalErrorHandler\UndefinedFunctionFatalErrorHandler; - -class UndefinedFunctionFatalErrorHandlerTest extends TestCase -{ - /** - * @dataProvider provideUndefinedFunctionData - */ - public function testUndefinedFunction(array $error, string $translatedMessage) - { - $handler = new UndefinedFunctionFatalErrorHandler(); - $exception = $handler->handleError($error, new FatalErrorException('', 0, $error['type'], $error['file'], $error['line'])); - - $this->assertInstanceOf('Symfony\Component\ErrorHandler\Exception\UndefinedFunctionException', $exception); - // class names are case insensitive and PHP do not return the same - $this->assertSame(strtolower($translatedMessage), strtolower($exception->getMessage())); - $this->assertSame($error['type'], $exception->getSeverity()); - $this->assertSame($error['file'], $exception->getFile()); - $this->assertSame($error['line'], $exception->getLine()); - } - - public function provideUndefinedFunctionData(): 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\\errorhandler\\tests\\fatalerrorhandler\\test_namespaced_function\"?", - ], - [ - [ - '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\\errorhandler\\tests\\fatalerrorhandler\\test_namespaced_function\"?", - ], - [ - [ - 'type' => 1, - 'line' => 12, - 'file' => 'foo.php', - 'message' => 'Call to undefined function foo()', - ], - 'Attempted to call function "foo" from the global namespace.', - ], - [ - [ - '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".', - ], - ]; - } -} - -function test_namespaced_function() -{ -} diff --git a/src/Symfony/Component/ErrorHandler/Tests/FatalErrorHandler/UndefinedMethodFatalErrorHandlerTest.php b/src/Symfony/Component/ErrorHandler/Tests/FatalErrorHandler/UndefinedMethodFatalErrorHandlerTest.php deleted file mode 100644 index 17414e1eb925..000000000000 --- a/src/Symfony/Component/ErrorHandler/Tests/FatalErrorHandler/UndefinedMethodFatalErrorHandlerTest.php +++ /dev/null @@ -1,76 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\ErrorHandler\Tests\FatalErrorHandler; - -use PHPUnit\Framework\TestCase; -use Symfony\Component\ErrorHandler\Exception\FatalErrorException; -use Symfony\Component\ErrorHandler\FatalErrorHandler\UndefinedMethodFatalErrorHandler; - -class UndefinedMethodFatalErrorHandlerTest extends TestCase -{ - /** - * @dataProvider provideUndefinedMethodData - */ - public function testUndefinedMethod(array $error, string $translatedMessage) - { - $handler = new UndefinedMethodFatalErrorHandler(); - $exception = $handler->handleError($error, new FatalErrorException('', 0, $error['type'], $error['file'], $error['line'])); - - $this->assertInstanceOf('Symfony\Component\ErrorHandler\Exception\UndefinedMethodException', $exception); - $this->assertSame($translatedMessage, $exception->getMessage()); - $this->assertSame($error['type'], $exception->getSeverity()); - $this->assertSame($error['file'], $exception->getFile()); - $this->assertSame($error['line'], $exception->getLine()); - } - - public function provideUndefinedMethodData(): 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".', - ], - [ - [ - '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\"?", - ], - [ - [ - '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\"?", - ], - [ - [ - '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".', - ], - ]; - } -} diff --git a/src/Symfony/Component/ErrorHandler/Tests/phpt/decorate_exception_hander.phpt b/src/Symfony/Component/ErrorHandler/Tests/phpt/decorate_exception_handler.phpt similarity index 77% rename from src/Symfony/Component/ErrorHandler/Tests/phpt/decorate_exception_hander.phpt rename to src/Symfony/Component/ErrorHandler/Tests/phpt/decorate_exception_handler.phpt index 034d5a5292a4..5fb5981d2d02 100644 --- a/src/Symfony/Component/ErrorHandler/Tests/phpt/decorate_exception_hander.phpt +++ b/src/Symfony/Component/ErrorHandler/Tests/phpt/decorate_exception_handler.phpt @@ -23,14 +23,12 @@ if (true) { { } } - -?> --EXPECTF-- -object(Symfony\Component\ErrorHandler\Exception\ClassNotFoundException)#%d (8) { +object(Symfony\Component\ErrorHandler\Error\ClassNotFoundError)#%d (7) { ["message":protected]=> string(138) "Attempted to load class "missing" from namespace "Symfony\Component\ErrorHandler". Did you forget a "use" statement for another namespace?" - ["string":"Exception":private]=> + ["string":"Error":private]=> string(0) "" ["code":protected]=> int(0) @@ -38,10 +36,8 @@ Did you forget a "use" statement for another namespace?" string(%d) "%s" ["line":protected]=> int(%d) - ["trace":"Exception":private]=> + ["trace":"Error":private]=> array(%d) {%A} - ["previous":"Exception":private]=> + ["previous":"Error":private]=> NULL - ["severity":protected]=> - int(1) } diff --git a/src/Symfony/Component/ErrorHandler/Tests/phpt/fatal_with_nested_handlers.phpt b/src/Symfony/Component/ErrorHandler/Tests/phpt/fatal_with_nested_handlers.phpt index 532fe922410c..15933828bd42 100644 --- a/src/Symfony/Component/ErrorHandler/Tests/phpt/fatal_with_nested_handlers.phpt +++ b/src/Symfony/Component/ErrorHandler/Tests/phpt/fatal_with_nested_handlers.phpt @@ -35,7 +35,18 @@ array(1) { [0]=> string(37) "Error and exception handlers do match" } -object(Symfony\Component\ErrorHandler\Exception\FatalErrorException)#%d (%d) { +object(Symfony\Component\ErrorHandler\Error\FatalError)#%d (%d) { + ["error":"Symfony\Component\ErrorHandler\Error\FatalError":private]=> + array(4) { + ["type"]=> + int(1) + ["message"]=> + string(179) "Class Symfony\Component\ErrorHandler\Broken contains 1 abstract method and must therefore be declared abstract or implement the remaining methods (JsonSerializable::jsonSerialize)" + ["file"]=> + string(%d) "%s" + ["line"]=> + int(%d) + } ["message":protected]=> string(186) "Error: Class Symfony\Component\ErrorHandler\Broken contains 1 abstract method and must therefore be declared abstract or implement the remaining methods (JsonSerializable::jsonSerialize)" %a diff --git a/src/Symfony/Component/ErrorRenderer/Exception/FlattenException.php b/src/Symfony/Component/ErrorRenderer/Exception/FlattenException.php index eb544d935fc4..30995a111cdb 100644 --- a/src/Symfony/Component/ErrorRenderer/Exception/FlattenException.php +++ b/src/Symfony/Component/ErrorRenderer/Exception/FlattenException.php @@ -11,7 +11,7 @@ namespace Symfony\Component\ErrorRenderer\Exception; -use Symfony\Component\ErrorHandler\Exception\FatalThrowableError; +use Symfony\Component\ErrorHandler\Exception\ErrorException; use Symfony\Component\HttpFoundation\Exception\RequestExceptionInterface; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface; @@ -71,7 +71,7 @@ public static function createFromThrowable(\Throwable $exception, int $statusCod $e->setStatusCode($statusCode); $e->setHeaders($headers); $e->setTraceFromThrowable($exception); - $e->setClass($exception instanceof FatalThrowableError ? $exception->getOriginalClassName() : \get_class($exception)); + $e->setClass($exception instanceof ErrorException ? $exception->getOriginalClassName() : \get_class($exception)); $e->setFile($exception->getFile()); $e->setLine($exception->getLine()); diff --git a/src/Symfony/Component/ErrorRenderer/Tests/Exception/FlattenExceptionTest.php b/src/Symfony/Component/ErrorRenderer/Tests/Exception/FlattenExceptionTest.php index 7651e57f11d7..dc2678be8158 100644 --- a/src/Symfony/Component/ErrorRenderer/Tests/Exception/FlattenExceptionTest.php +++ b/src/Symfony/Component/ErrorRenderer/Tests/Exception/FlattenExceptionTest.php @@ -12,7 +12,7 @@ namespace Symfony\Component\ErrorRenderer\Tests\Exception; use PHPUnit\Framework\TestCase; -use Symfony\Component\ErrorHandler\Exception\FatalThrowableError; +use Symfony\Component\ErrorHandler\Exception\ErrorException; use Symfony\Component\ErrorRenderer\Exception\FlattenException; use Symfony\Component\HttpFoundation\Exception\SuspiciousOperationException; use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException; @@ -132,7 +132,7 @@ public function testFlattenHttpException(\Throwable $exception) public function testWrappedThrowable() { - $exception = new FatalThrowableError(new \DivisionByZeroError('Ouch', 42)); + $exception = new ErrorException(new \DivisionByZeroError('Ouch', 42)); $flattened = FlattenException::createFromThrowable($exception); $this->assertSame('Ouch', $flattened->getMessage(), 'The message is copied from the original error.'); diff --git a/src/Symfony/Component/HttpKernel/EventListener/DebugHandlersListener.php b/src/Symfony/Component/HttpKernel/EventListener/DebugHandlersListener.php index 03885a46b864..edff2d45d0e5 100644 --- a/src/Symfony/Component/HttpKernel/EventListener/DebugHandlersListener.php +++ b/src/Symfony/Component/HttpKernel/EventListener/DebugHandlersListener.php @@ -16,7 +16,7 @@ use Symfony\Component\Console\Event\ConsoleEvent; use Symfony\Component\Console\Output\ConsoleOutputInterface; use Symfony\Component\ErrorHandler\ErrorHandler; -use Symfony\Component\ErrorHandler\Exception\FatalThrowableError; +use Symfony\Component\ErrorHandler\Exception\ErrorException; use Symfony\Component\EventDispatcher\Event; use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\HttpKernel\Debug\FileLinkFormatter; @@ -113,7 +113,7 @@ public function configure(Event $event = null) } if (!$e instanceof \Exception) { - $e = new FatalThrowableError($e); + $e = new ErrorException($e); } $hasRun = true; @@ -127,7 +127,7 @@ public function configure(Event $event = null) } $this->exceptionHandler = static function (\Throwable $e) use ($app, $output) { if (!$e instanceof \Exception) { - $e = new FatalThrowableError($e); + $e = new ErrorException($e); } $app->renderException($e, $output);