Browse Source

Remove deprecated ErrorHandler and ConsoleErrorHandler

Mark Story 4 years ago
parent
commit
719f1c979d

+ 0 - 391
src/Error/BaseErrorHandler.php

@@ -1,391 +0,0 @@
-<?php
-declare(strict_types=1);
-
-/**
- * CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
- * Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
- *
- * Licensed under The MIT License
- * For full copyright and license information, please see the LICENSE.txt
- * Redistributions of files must retain the above copyright notice.
- *
- * @copyright     Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
- * @link          https://cakephp.org CakePHP(tm) Project
- * @since         2.0.0
- * @license       https://opensource.org/licenses/mit-license.php MIT License
- */
-namespace Cake\Error;
-
-use Cake\Core\Configure;
-use Cake\Core\InstanceConfigTrait;
-use Cake\Routing\Router;
-use Psr\Http\Message\ServerRequestInterface;
-use RuntimeException;
-use Throwable;
-
-/**
- * Base error handler that provides logic common to the CLI + web
- * error/exception handlers.
- *
- * Subclasses are required to implement the template methods to handle displaying
- * the errors in their environment.
- */
-abstract class BaseErrorHandler
-{
-    use InstanceConfigTrait;
-
-    /**
-     * Options to use for the Error handling.
-     *
-     * @var array<string, mixed>
-     */
-    protected array $_defaultConfig = [
-        'log' => true,
-        'trace' => false,
-        'skipLog' => [],
-        'errorLogger' => ErrorLogger::class,
-    ];
-
-    /**
-     * @var bool
-     */
-    protected bool $_handled = false;
-
-    /**
-     * Exception logger instance.
-     *
-     * @var \Cake\Error\ErrorLoggerInterface|null
-     */
-    protected ?ErrorLoggerInterface $logger = null;
-
-    /**
-     * Display an error message in an environment specific way.
-     *
-     * Subclasses should implement this method to display the error as
-     * desired for the runtime they operate in.
-     *
-     * @param array $error An array of error data.
-     * @param bool $debug Whether the app is in debug mode.
-     * @return void
-     */
-    abstract protected function _displayError(array $error, bool $debug): void;
-
-    /**
-     * Display an exception in an environment specific way.
-     *
-     * Subclasses should implement this method to display an uncaught exception as
-     * desired for the runtime they operate in.
-     *
-     * @param \Throwable $exception The uncaught exception.
-     * @return void
-     */
-    abstract protected function _displayException(Throwable $exception): void;
-
-    /**
-     * Register the error and exception handlers.
-     *
-     * @return void
-     */
-    public function register(): void
-    {
-        deprecationWarning(
-            '4.4.0',
-            'Use of `BaseErrorHandler` and subclasses are deprecated. ' .
-            'Upgrade to the new `ErrorTrap` and `ExceptionTrap` subsystem. ' .
-            'See https://book.cakephp.org/4/en/appendices/4-4-migration-guide.html'
-        );
-
-        $level = $this->_config['errorLevel'] ?? -1;
-        error_reporting($level);
-        set_error_handler([$this, 'handleError'], $level);
-        set_exception_handler([$this, 'handleException']);
-        register_shutdown_function(function (): void {
-            if ((PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') && $this->_handled) {
-                return;
-            }
-            $megabytes = $this->_config['extraFatalErrorMemory'] ?? 4;
-            if ($megabytes > 0) {
-                $this->increaseMemoryLimit($megabytes * 1024);
-            }
-            $error = error_get_last();
-            if (!is_array($error)) {
-                return;
-            }
-            $fatals = [
-                E_USER_ERROR,
-                E_ERROR,
-                E_PARSE,
-            ];
-            if (!in_array($error['type'], $fatals, true)) {
-                return;
-            }
-            $this->handleFatalError(
-                $error['type'],
-                $error['message'],
-                $error['file'],
-                $error['line']
-            );
-        });
-    }
-
-    /**
-     * Set as the default error handler by CakePHP.
-     *
-     * Use config/error.php to customize or replace this error handler.
-     * This function will use Debugger to display errors when debug mode is on. And
-     * will log errors to Log, when debug mode is off.
-     *
-     * You can use the 'errorLevel' option to set what type of errors will be handled.
-     * Stack traces for errors can be enabled with the 'trace' option.
-     *
-     * @param int $code Code of error
-     * @param string $description Error description
-     * @param string|null $file File on which error occurred
-     * @param int|null $line Line that triggered the error
-     * @param array<string, mixed>|null $context Context
-     * @return bool True if error was handled
-     */
-    public function handleError(
-        int $code,
-        string $description,
-        ?string $file = null,
-        ?int $line = null,
-        ?array $context = null
-    ): bool {
-        if (!(error_reporting() & $code)) {
-            return false;
-        }
-        $this->_handled = true;
-        [$error, $log] = static::mapErrorCode($code);
-        if ($log === LOG_ERR) {
-            /** @psalm-suppress PossiblyNullArgument */
-            return $this->handleFatalError($code, $description, $file, $line);
-        }
-        $data = [
-            'level' => $log,
-            'code' => $code,
-            'error' => $error,
-            'description' => $description,
-            'file' => $file,
-            'line' => $line,
-        ];
-
-        $debug = (bool)Configure::read('debug');
-        if ($debug) {
-            // By default trim 3 frames off for the public and protected methods
-            // used by ErrorHandler instances.
-            $start = 3;
-
-            // Can be used by error handlers that wrap other error handlers
-            // to coerce the generated stack trace to the correct point.
-            if (isset($context['_trace_frame_offset'])) {
-                $start += $context['_trace_frame_offset'];
-                unset($context['_trace_frame_offset']);
-            }
-            $data += [
-                'context' => $context,
-                'start' => $start,
-                'path' => Debugger::trimPath((string)$file),
-            ];
-        }
-        $this->_displayError($data, $debug);
-        $this->_logError($log, $data);
-
-        return true;
-    }
-
-    /**
-     * Handle uncaught exceptions.
-     *
-     * Uses a template method provided by subclasses to display errors in an
-     * environment appropriate way.
-     *
-     * @param \Throwable $exception Exception instance.
-     * @return void
-     * @throws \Exception When renderer class not found
-     * @see https://secure.php.net/manual/en/function.set-exception-handler.php
-     */
-    public function handleException(Throwable $exception): void
-    {
-        $this->_displayException($exception);
-        $this->logException($exception);
-        $code = $exception->getCode() ?: 1;
-        $this->_stop((int)$code);
-    }
-
-    /**
-     * Stop the process.
-     *
-     * Implemented in subclasses that need it.
-     *
-     * @param int $code Exit code.
-     * @return void
-     */
-    protected function _stop(int $code): void
-    {
-        // Do nothing.
-    }
-
-    /**
-     * Display/Log a fatal error.
-     *
-     * @param int $code Code of error
-     * @param string $description Error description
-     * @param string $file File on which error occurred
-     * @param int $line Line that triggered the error
-     * @return bool
-     */
-    public function handleFatalError(int $code, string $description, string $file, int $line): bool
-    {
-        $data = [
-            'code' => $code,
-            'description' => $description,
-            'file' => $file,
-            'line' => $line,
-            'error' => 'Fatal Error',
-        ];
-        $this->_logError(LOG_ERR, $data);
-
-        $this->handleException(new FatalErrorException($description, 500, $file, $line));
-
-        return true;
-    }
-
-    /**
-     * Increases the PHP "memory_limit" ini setting by the specified amount
-     * in kilobytes
-     *
-     * @param int $additionalKb Number in kilobytes
-     * @return void
-     */
-    public function increaseMemoryLimit(int $additionalKb): void
-    {
-        $limit = ini_get('memory_limit');
-        if ($limit === false || $limit === '' || $limit === '-1') {
-            return;
-        }
-        $limit = trim($limit);
-        $units = strtoupper(substr($limit, -1));
-        $current = (int)substr($limit, 0, strlen($limit) - 1);
-        if ($units === 'M') {
-            $current *= 1024;
-            $units = 'K';
-        }
-        if ($units === 'G') {
-            $current = $current * 1024 * 1024;
-            $units = 'K';
-        }
-
-        if ($units === 'K') {
-            ini_set('memory_limit', ceil($current + $additionalKb) . 'K');
-        }
-    }
-
-    /**
-     * Log an error.
-     *
-     * @param string|int $level The level name of the log.
-     * @param array $data Array of error data.
-     * @return bool
-     */
-    protected function _logError(string|int $level, array $data): bool
-    {
-        $message = sprintf(
-            '%s (%s): %s in [%s, line %s]',
-            $data['error'],
-            $data['code'],
-            $data['description'],
-            $data['file'],
-            $data['line']
-        );
-        $context = [];
-        if (!empty($this->_config['trace'])) {
-            $context['trace'] = Debugger::trace([
-                'start' => 1,
-                'format' => 'log',
-            ]);
-            $context['request'] = Router::getRequest();
-        }
-
-        return $this->getLogger()->logMessage($level, $message, $context);
-    }
-
-    /**
-     * Log an error for the exception if applicable.
-     *
-     * @param \Throwable $exception The exception to log a message for.
-     * @param \Psr\Http\Message\ServerRequestInterface|null $request The current request.
-     * @return bool
-     */
-    public function logException(Throwable $exception, ?ServerRequestInterface $request = null): bool
-    {
-        if (empty($this->_config['log'])) {
-            return false;
-        }
-
-        return $this->getLogger()->log($exception, $request ?? Router::getRequest());
-    }
-
-    /**
-     * Get exception logger.
-     *
-     * @return \Cake\Error\ErrorLoggerInterface
-     */
-    public function getLogger(): ErrorLoggerInterface
-    {
-        if ($this->logger === null) {
-            /** @var \Cake\Error\ErrorLoggerInterface $logger */
-            $logger = new $this->_config['errorLogger']($this->_config);
-
-            if (!$logger instanceof ErrorLoggerInterface) {
-                // Set the logger so that the next error can be logged.
-                $this->logger = new ErrorLogger($this->_config);
-
-                $interface = ErrorLoggerInterface::class;
-                $type = get_debug_type($logger);
-                throw new RuntimeException("Cannot create logger. `{$type}` does not implement `{$interface}`.");
-            }
-            $this->logger = $logger;
-        }
-
-        return $this->logger;
-    }
-
-    /**
-     * Map an error code into an Error word, and log location.
-     *
-     * @param int $code Error code to map
-     * @return array Array of error word, and log location.
-     */
-    public static function mapErrorCode(int $code): array
-    {
-        $levelMap = [
-            E_PARSE => 'error',
-            E_ERROR => 'error',
-            E_CORE_ERROR => 'error',
-            E_COMPILE_ERROR => 'error',
-            E_USER_ERROR => 'error',
-            E_WARNING => 'warning',
-            E_USER_WARNING => 'warning',
-            E_COMPILE_WARNING => 'warning',
-            E_RECOVERABLE_ERROR => 'warning',
-            E_NOTICE => 'notice',
-            E_USER_NOTICE => 'notice',
-            E_STRICT => 'strict',
-            E_DEPRECATED => 'deprecated',
-            E_USER_DEPRECATED => 'deprecated',
-        ];
-        $logMap = [
-            'error' => LOG_ERR,
-            'warning' => LOG_WARNING,
-            'notice' => LOG_NOTICE,
-            'strict' => LOG_NOTICE,
-            'deprecated' => LOG_NOTICE,
-        ];
-
-        $error = $levelMap[$code];
-        $log = $logMap[$error];
-
-        return [ucfirst($error), $log];
-    }
-}

+ 0 - 132
src/Error/ConsoleErrorHandler.php

@@ -1,132 +0,0 @@
-<?php
-declare(strict_types=1);
-
-/**
- * CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
- * Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
- *
- * Licensed under The MIT License
- * For full copyright and license information, please see the LICENSE.txt
- * Redistributions of files must retain the above copyright notice.
- *
- * @copyright     Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
- * @link          https://cakephp.org CakePHP(tm) Project
- * @since         2.0.0
- * @license       https://opensource.org/licenses/mit-license.php MIT License
- */
-namespace Cake\Error;
-
-use Cake\Console\CommandInterface;
-use Cake\Console\ConsoleOutput;
-use Cake\Console\Exception\ConsoleException;
-use Throwable;
-
-/**
- * Error Handler for Cake console. Does simple printing of the
- * exception that occurred and the stack trace of the error.
- */
-class ConsoleErrorHandler extends BaseErrorHandler
-{
-    /**
-     * Standard error stream.
-     *
-     * @var \Cake\Console\ConsoleOutput
-     */
-    protected ConsoleOutput $_stderr;
-
-    /**
-     * Constructor
-     *
-     * @param array<string, mixed> $config Config options for the error handler.
-     */
-    public function __construct(array $config = [])
-    {
-        $config += [
-            'stderr' => new ConsoleOutput('php://stderr'),
-            'log' => false,
-        ];
-
-        $this->setConfig($config);
-        $this->_stderr = $this->_config['stderr'];
-    }
-
-    /**
-     * Handle errors in the console environment. Writes errors to stderr,
-     * and logs messages if Configure::read('debug') is false.
-     *
-     * @param \Throwable $exception Exception instance.
-     * @return void
-     * @throws \Exception When renderer class not found
-     * @see https://secure.php.net/manual/en/function.set-exception-handler.php
-     */
-    public function handleException(Throwable $exception): void
-    {
-        $this->_displayException($exception);
-        $this->logException($exception);
-
-        $exitCode = CommandInterface::CODE_ERROR;
-        if ($exception instanceof ConsoleException) {
-            $exitCode = $exception->getCode();
-        }
-        $this->_stop($exitCode);
-    }
-
-    /**
-     * Prints an exception to stderr.
-     *
-     * @param \Throwable $exception The exception to handle
-     * @return void
-     */
-    protected function _displayException(Throwable $exception): void
-    {
-        $errorName = 'Exception:';
-        if ($exception instanceof FatalErrorException) {
-            $errorName = 'Fatal Error:';
-        }
-
-        $message = sprintf(
-            "<error>%s</error> %s\nIn [%s, line %s]\n",
-            $errorName,
-            $exception->getMessage(),
-            $exception->getFile(),
-            $exception->getLine()
-        );
-        $this->_stderr->write($message);
-    }
-
-    /**
-     * Prints an error to stderr.
-     *
-     * Template method of BaseErrorHandler.
-     *
-     * @param array $error An array of error data.
-     * @param bool $debug Whether the app is in debug mode.
-     * @return void
-     */
-    protected function _displayError(array $error, bool $debug): void
-    {
-        $message = sprintf(
-            "%s\nIn [%s, line %s]",
-            $error['description'],
-            $error['file'],
-            $error['line']
-        );
-        $message = sprintf(
-            "<error>%s Error:</error> %s\n",
-            $error['error'],
-            $message
-        );
-        $this->_stderr->write($message);
-    }
-
-    /**
-     * Stop the execution and set the exit code for the process.
-     *
-     * @param int $code The exit code.
-     * @return void
-     */
-    protected function _stop(int $code): void
-    {
-        exit($code);
-    }
-}

+ 0 - 217
src/Error/ErrorHandler.php

@@ -1,217 +0,0 @@
-<?php
-declare(strict_types=1);
-
-/**
- * ErrorHandler class
- *
- * CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
- * Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
- *
- * Licensed under The MIT License
- * For full copyright and license information, please see the LICENSE.txt
- * Redistributions of files must retain the above copyright notice.
- *
- * @copyright     Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
- * @link          https://cakephp.org CakePHP(tm) Project
- * @since         0.10.5
- * @license       https://opensource.org/licenses/mit-license.php MIT License
- */
-namespace Cake\Error;
-
-use Cake\Core\App;
-use Cake\Http\ResponseEmitter;
-use Cake\Routing\Router;
-use Psr\Http\Message\ResponseInterface;
-use Psr\Http\Message\ServerRequestInterface;
-use RuntimeException;
-use Throwable;
-
-/**
- * Error Handler provides basic error and exception handling for your application. It captures and
- * handles all unhandled exceptions and errors. Displays helpful framework errors when debug mode is on.
- *
- * ### Uncaught exceptions
- *
- * When debug mode is off a ExceptionRenderer will render 404 or 500 errors. If an uncaught exception is thrown
- * and it is a type that ExceptionRenderer does not know about it will be treated as a 500 error.
- *
- * ### Implementing application specific exception handling
- *
- * You can implement application specific exception handling in one of a few ways. Each approach
- * gives you different amounts of control over the exception handling process.
- *
- * - Modify config/error.php and setup custom exception handling.
- * - Use the `exceptionRenderer` option to inject an Exception renderer. This will
- *   let you keep the existing handling logic but override the rendering logic.
- *
- * #### Create your own Exception handler
- *
- * This gives you full control over the exception handling process. The class you choose should be
- * loaded in your config/error.php and registered as the default exception handler.
- *
- * #### Using a custom renderer with `exceptionRenderer`
- *
- * If you don't want to take control of the exception handling, but want to change how exceptions are
- * rendered you can use `exceptionRenderer` option to choose a class to render exception pages. By default
- * `Cake\Error\ExceptionRenderer` is used. Your custom exception renderer class should be placed in src/Error.
- *
- * Your custom renderer should expect an exception in its constructor, and implement a render method.
- * Failing to do so will cause additional errors.
- *
- * #### Logging exceptions
- *
- * Using the built-in exception handling, you can log all the exceptions
- * that are dealt with by ErrorHandler by setting `log` option to true in your config/error.php.
- * Enabling this will log every exception to Log and the configured loggers.
- *
- * ### PHP errors
- *
- * Error handler also provides the built in features for handling php errors (trigger_error).
- * While in debug mode, errors will be output to the screen using debugger. While in production mode,
- * errors will be logged to Log. You can control which errors are logged by setting
- * `errorLevel` option in config/error.php.
- *
- * #### Logging errors
- *
- * When ErrorHandler is used for handling errors, you can enable error logging by setting the `log`
- * option to true. This will log all errors to the configured log handlers.
- *
- * #### Controlling what errors are logged/displayed
- *
- * You can control which errors are logged / displayed by ErrorHandler by setting `errorLevel`. Setting this
- * to one or a combination of a few of the E_* constants will only enable the specified errors:
- *
- * ```
- * $options['errorLevel'] = E_ALL & ~E_NOTICE;
- * ```
- *
- * Would enable handling for all non Notice errors.
- *
- * @see \Cake\Error\ExceptionRenderer for more information on how to customize exception rendering.
- */
-class ErrorHandler extends BaseErrorHandler
-{
-    /**
-     * Constructor
-     *
-     * @param array<string, mixed> $config The options for error handling.
-     */
-    public function __construct(array $config = [])
-    {
-        $config += [
-            'exceptionRenderer' => ExceptionRenderer::class,
-        ];
-
-        $this->setConfig($config);
-    }
-
-    /**
-     * Display an error.
-     *
-     * Template method of BaseErrorHandler.
-     *
-     * @param array $error An array of error data.
-     * @param bool $debug Whether the app is in debug mode.
-     * @return void
-     */
-    protected function _displayError(array $error, bool $debug): void
-    {
-        if (!$debug) {
-            return;
-        }
-        Debugger::getInstance()->outputError($error);
-    }
-
-    /**
-     * Displays an exception response body.
-     *
-     * @param \Throwable $exception The exception to display.
-     * @return void
-     * @throws \Exception When the chosen exception renderer is invalid.
-     */
-    protected function _displayException(Throwable $exception): void
-    {
-        try {
-            $renderer = $this->getRenderer(
-                $exception,
-                Router::getRequest()
-            );
-            $response = $renderer->render();
-            $this->_sendResponse($response);
-        } catch (Throwable $exception) {
-            $this->_logInternalError($exception);
-        }
-    }
-
-    /**
-     * Get a renderer instance.
-     *
-     * @param \Throwable $exception The exception being rendered.
-     * @param \Psr\Http\Message\ServerRequestInterface|null $request The request.
-     * @return \Cake\Error\ExceptionRendererInterface The exception renderer.
-     * @throws \RuntimeException When the renderer class cannot be found.
-     */
-    public function getRenderer(
-        Throwable $exception,
-        ?ServerRequestInterface $request = null
-    ): ExceptionRendererInterface {
-        $renderer = $this->_config['exceptionRenderer'];
-
-        if (is_string($renderer)) {
-            /** @var class-string<\Cake\Error\ExceptionRendererInterface>|null $class */
-            $class = App::className($renderer, 'Error');
-            if (!$class) {
-                throw new RuntimeException(sprintf(
-                    "The '%s' renderer class could not be found.",
-                    $renderer
-                ));
-            }
-
-            return new $class($exception, $request);
-        }
-
-        /** @var callable $factory */
-        $factory = $renderer;
-
-        return $factory($exception, $request);
-    }
-
-    /**
-     * Log internal errors.
-     *
-     * @param \Throwable $exception Exception.
-     * @return void
-     */
-    protected function _logInternalError(Throwable $exception): void
-    {
-        // Disable trace for internal errors.
-        $this->_config['trace'] = false;
-        $message = sprintf(
-            "[%s] %s (%s:%s)\n%s", // Keeping same message format
-            get_class($exception),
-            $exception->getMessage(),
-            $exception->getFile(),
-            $exception->getLine(),
-            $exception->getTraceAsString()
-        );
-        trigger_error($message, E_USER_ERROR);
-    }
-
-    /**
-     * Method that can be easily stubbed in testing.
-     *
-     * @param \Psr\Http\Message\ResponseInterface|string $response Either the message or response object.
-     * @return void
-     */
-    protected function _sendResponse(ResponseInterface|string $response): void
-    {
-        if (is_string($response)) {
-            echo $response;
-
-            return;
-        }
-
-        $emitter = new ResponseEmitter();
-        $emitter->emit($response);
-    }
-}

+ 0 - 139
tests/TestCase/Error/ConsoleErrorHandlerTest.php

@@ -1,139 +0,0 @@
-<?php
-declare(strict_types=1);
-
-/**
- * CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
- * Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
- *
- * Licensed under The MIT License
- * For full copyright and license information, please see the LICENSE.txt
- * Redistributions of files must retain the above copyright notice.
- *
- * @copyright     Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
- * @link          https://cakephp.org CakePHP(tm) Project
- * @since         2.0.0
- * @license       https://opensource.org/licenses/mit-license.php MIT License
- */
-namespace Cake\Test\TestCase\Error;
-
-use Cake\Console\Exception\ConsoleException;
-use Cake\Controller\Exception\MissingActionException;
-use Cake\Log\Log;
-use Cake\TestSuite\Stub\ConsoleOutput;
-use Cake\TestSuite\TestCase;
-use InvalidArgumentException;
-
-/**
- * ConsoleErrorHandler Test case.
- */
-class ConsoleErrorHandlerTest extends TestCase
-{
-    /**
-     * @var \Cake\Error\ConsoleErrorHandler|\PHPUnit\Framework\MockObject\MockObject
-     */
-    protected $Error;
-
-    /**
-     * @var \Cake\TestSuite\Stub\ConsoleOutput
-     */
-    protected $stderr;
-
-    /**
-     * setup, create mocks
-     */
-    public function setUp(): void
-    {
-        parent::setUp();
-        $this->stderr = new ConsoleOutput();
-        $this->Error = $this->getMockBuilder('Cake\Error\ConsoleErrorHandler')
-            ->onlyMethods(['_stop'])
-            ->setConstructorArgs([['stderr' => $this->stderr]])
-            ->getMock();
-        Log::drop('stdout');
-        Log::drop('stderr');
-    }
-
-    /**
-     * tearDown
-     */
-    public function tearDown(): void
-    {
-        unset($this->Error);
-        parent::tearDown();
-    }
-
-    /**
-     * test that the console error handler can deal with Exceptions.
-     */
-    public function testHandleError(): void
-    {
-        $content = "<error>Notice Error:</error> This is a notice error\nIn [/some/file, line 275]\n";
-        $this->Error->expects($this->never())
-            ->method('_stop');
-
-        $this->Error->handleError(E_NOTICE, 'This is a notice error', '/some/file', 275);
-        $this->assertSame($content, $this->stderr->messages()[0]);
-    }
-
-    /**
-     * test that the console error handler can deal with fatal errors.
-     */
-    public function testHandleFatalError(): void
-    {
-        ob_start();
-        $content = "<error>Fatal Error:</error> This is a fatal error\nIn [/some/file, line 275]\n";
-
-        $this->Error->handleError(E_USER_ERROR, 'This is a fatal error', '/some/file', 275);
-        $this->assertCount(1, $this->stderr->messages());
-        $this->assertSame($content, $this->stderr->messages()[0]);
-        ob_end_clean();
-    }
-
-    /**
-     * test that the console error handler can deal with CakeExceptions.
-     */
-    public function testCakeErrors(): void
-    {
-        $exception = new MissingActionException('Missing action');
-        $message = sprintf("<error>Exception:</error> Missing action\nIn [%s, line %s]\n", $exception->getFile(), $exception->getLine());
-
-        $this->Error->expects($this->once())
-            ->method('_stop')
-            ->with(1);
-
-        $this->Error->handleException($exception);
-
-        $this->assertCount(1, $this->stderr->messages());
-        $this->assertSame($message, $this->stderr->messages()[0]);
-    }
-
-    /**
-     * test a non Cake Exception exception.
-     */
-    public function testNonCakeExceptions(): void
-    {
-        $exception = new InvalidArgumentException('Too many parameters.');
-
-        $this->Error->expects($this->once())
-            ->method('_stop')
-            ->with(1);
-
-        $this->Error->handleException($exception);
-        $this->assertStringContainsString('Too many parameters', $this->stderr->messages()[0]);
-    }
-
-    /**
-     * Test error code is used as exit code for ConsoleException.
-     */
-    public function testConsoleExceptions(): void
-    {
-        $exception = new ConsoleException('Test ConsoleException', 2);
-
-        $this->Error->expects($this->once())
-            ->method('_stop')
-            ->with(2);
-
-        $this->Error->handleException($exception);
-        $this->assertStringContainsString('Test ConsoleException', $this->stderr->messages()[0]);
-    }
-}

+ 0 - 497
tests/TestCase/Error/ErrorHandlerTest.php

@@ -1,497 +0,0 @@
-<?php
-declare(strict_types=1);
-
-/**
- * CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
- * Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
- *
- * Licensed under The MIT License
- * For full copyright and license information, please see the LICENSE.txt
- * Redistributions of files must retain the above copyright notice
- *
- * @copyright     Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
- * @link          https://cakephp.org CakePHP(tm) Project
- * @since         1.2.0
- * @license       https://opensource.org/licenses/mit-license.php MIT License
- */
-namespace Cake\Test\TestCase\Error;
-
-use Cake\Core\Configure;
-use Cake\Datasource\Exception\RecordNotFoundException;
-use Cake\Error\ErrorHandler;
-use Cake\Error\ErrorLoggerInterface;
-use Cake\Http\Exception\ForbiddenException;
-use Cake\Http\Exception\MissingControllerException;
-use Cake\Http\Exception\NotFoundException;
-use Cake\Http\ServerRequest;
-use Cake\Log\Log;
-use Cake\Routing\Router;
-use Cake\TestSuite\TestCase;
-use Exception;
-use RuntimeException;
-use stdClass;
-use TestApp\Error\TestErrorHandler;
-
-/**
- * ErrorHandlerTest class
- */
-class ErrorHandlerTest extends TestCase
-{
-    /**
-     * @var \Cake\Log\Engine\ArrayLog
-     */
-    protected $logger;
-
-    /**
-     * error level property
-     */
-    private static $errorLevel;
-
-    /**
-     * setup create a request object to get out of router later.
-     */
-    public function setUp(): void
-    {
-        parent::setUp();
-        Router::reload();
-
-        $request = new ServerRequest([
-            'base' => '',
-            'environment' => [
-                'HTTP_REFERER' => '/referer',
-            ],
-        ]);
-
-        Router::setRequest($request);
-        Configure::write('debug', true);
-
-        Log::reset();
-        Log::setConfig('error_test', ['className' => 'Array']);
-        $this->logger = Log::engine('error_test');
-    }
-
-    /**
-     * tearDown
-     */
-    public function tearDown(): void
-    {
-        parent::tearDown();
-        Log::reset();
-        $this->clearPlugins();
-        error_reporting(self::$errorLevel);
-    }
-
-    /**
-     * setUpBeforeClass
-     */
-    public static function setUpBeforeClass(): void
-    {
-        parent::setUpBeforeClass();
-        self::$errorLevel = error_reporting();
-    }
-
-    /**
-     * Test an invalid rendering class.
-     */
-    public function testInvalidRenderer(): void
-    {
-        $this->expectException(RuntimeException::class);
-        $this->expectExceptionMessage('The \'TotallyInvalid\' renderer class could not be found');
-
-        $errorHandler = new ErrorHandler(['exceptionRenderer' => 'TotallyInvalid']);
-        $errorHandler->getRenderer(new Exception('Something bad'));
-    }
-
-    /**
-     * test error handling when debug is on, an error should be printed from Debugger.
-     *
-     * @runInSeparateProcess
-     * @preserveGlobalState disabled
-     */
-    public function testHandleErrorDebugOn(): void
-    {
-        Configure::write('debug', true);
-        $errorHandler = new ErrorHandler();
-
-        $result = '';
-        $this->deprecated(function () use ($errorHandler, &$result) {
-            $errorHandler->register();
-
-            ob_start();
-            $wrong = $wrong + 1;
-            $result = ob_get_clean();
-        });
-
-        $this->assertMatchesRegularExpression('/<div class="cake-error">/', $result);
-        if (version_compare(PHP_VERSION, '8.0.0-dev', '<')) {
-            $this->assertMatchesRegularExpression('/<b>Notice<\/b>/', $result);
-            $this->assertMatchesRegularExpression('/variable:\s+wrong/', $result);
-        } else {
-            $this->assertMatchesRegularExpression('/<b>Warning<\/b>/', $result);
-            $this->assertMatchesRegularExpression('/variable \$wrong/', $result);
-        }
-        $this->assertStringContainsString(
-            'ErrorHandlerTest.php, line ' . (__LINE__ - 13),
-            $result,
-            'Should contain file and line reference'
-        );
-    }
-
-    /**
-     * test error handling with the _trace_offset context variable
-     */
-    public function testHandleErrorTraceOffset(): void
-    {
-        set_error_handler(function ($code, $message, $file, $line, $context = null): void {
-            $errorHandler = new ErrorHandler();
-            $context['_trace_frame_offset'] = 3;
-            $errorHandler->handleError($code, $message, $file, $line, $context);
-        });
-
-        ob_start();
-        $wrong = $wrong + 1;
-        $result = ob_get_clean();
-
-        restore_error_handler();
-
-        $this->assertStringNotContainsString(
-            'ErrorHandlerTest.php, line ' . (__LINE__ - 4),
-            $result,
-            'Should not contain file and line reference'
-        );
-        $this->assertStringNotContainsString('_trace_frame_offset', $result);
-    }
-
-    /**
-     * provides errors for mapping tests.
-     *
-     * @return array
-     */
-    public static function errorProvider(): array
-    {
-        return [
-            [E_USER_NOTICE, 'Notice'],
-            [E_USER_WARNING, 'Warning'],
-        ];
-    }
-
-    /**
-     * test error mappings
-     *
-     * @runInSeparateProcess
-     * @preserveGlobalState disabled
-     * @dataProvider errorProvider
-     */
-    public function testErrorMapping(int $error, string $expected): void
-    {
-        $errorHandler = new ErrorHandler();
-        $this->deprecated(function () use ($errorHandler, $error, $expected) {
-            $errorHandler->register();
-
-            ob_start();
-            trigger_error('Test error', $error);
-
-            $this->assertStringContainsString('<b>' . $expected . '</b>', ob_get_clean());
-        });
-    }
-
-    /**
-     * Test that errors go into Cake Log when debug = 0.
-     *
-     * @runInSeparateProcess
-     * @preserveGlobalState disabled
-     */
-    public function testHandleErrorDebugOff(): void
-    {
-        Configure::write('debug', false);
-        $errorHandler = new ErrorHandler();
-        $this->deprecated(function () use ($errorHandler) {
-            $errorHandler->register();
-            $out = $out + 1;
-        });
-
-        $messages = $this->logger->read();
-        $this->assertMatchesRegularExpression('/^(notice|debug|warning)/', $messages[0]);
-
-        $this->assertMatchesRegularExpression('/Undefined variable\:? \$?out in/', $messages[0]);
-        $this->assertStringContainsString('[' . __FILE__ . ', line ' . (__LINE__ - 7) . ']', $messages[0]);
-    }
-
-    /**
-     * Test that errors going into Cake Log include traces.
-     *
-     * @runInSeparateProcess
-     * @preserveGlobalState disabled
-     */
-    public function testHandleErrorLoggingTrace(): void
-    {
-        Configure::write('debug', false);
-        $errorHandler = new ErrorHandler(['trace' => true]);
-        $this->deprecated(function () use ($errorHandler) {
-            $errorHandler->register();
-            $out = $out + 1;
-        });
-
-        $messages = $this->logger->read();
-        $this->assertMatchesRegularExpression('/^(notice|debug|warning)/', $messages[0]);
-        $this->assertMatchesRegularExpression('/Undefined variable\:? \$?out in/', $messages[0]);
-        $this->assertStringContainsString('[' . __FILE__ . ', line ' . (__LINE__ - 6) . ']', $messages[0]);
-        $this->assertStringContainsString('Trace:', $messages[0]);
-        $this->assertStringContainsString(__NAMESPACE__ . '\ErrorHandlerTest::testHandleErrorLoggingTrace()', $messages[0]);
-        $this->assertStringContainsString('Request URL:', $messages[0]);
-        $this->assertStringContainsString('Referer URL:', $messages[0]);
-    }
-
-    /**
-     * test handleException generating a page.
-     */
-    public function testHandleException(): void
-    {
-        $error = new NotFoundException('Kaboom!');
-        $errorHandler = new TestErrorHandler();
-
-        $errorHandler->handleException($error);
-        $this->assertStringContainsString('Kaboom!', (string)$errorHandler->response->getBody(), 'message missing.');
-    }
-
-    /**
-     * test handleException generating log.
-     */
-    public function testHandleExceptionLog(): void
-    {
-        $errorHandler = new TestErrorHandler([
-            'log' => true,
-            'trace' => true,
-        ]);
-
-        $error = new NotFoundException('Kaboom!');
-        $errorHandler->handleException($error);
-        $this->assertStringContainsString('Kaboom!', (string)$errorHandler->response->getBody(), 'message missing.');
-
-        $messages = $this->logger->read();
-        $this->assertMatchesRegularExpression('/^error/', $messages[0]);
-        $this->assertStringContainsString('[Cake\Http\Exception\NotFoundException] Kaboom!', $messages[0]);
-        $this->assertStringContainsString(
-            str_replace('/', DS, 'vendor/phpunit/phpunit/src/Framework/TestCase.php'),
-            $messages[0]
-        );
-
-        $errorHandler = new TestErrorHandler([
-            'log' => true,
-            'trace' => false,
-        ]);
-        $errorHandler->handleException($error);
-
-        $messages = $this->logger->read();
-        $this->assertMatchesRegularExpression('/^error/', $messages[1]);
-        $this->assertStringContainsString('[Cake\Http\Exception\NotFoundException] Kaboom!', $messages[1]);
-        $this->assertStringNotContainsString(
-            str_replace('/', DS, 'vendor/phpunit/phpunit/src/Framework/TestCase.php'),
-            $messages[1]
-        );
-    }
-
-    /**
-     * test logging attributes with/without debug
-     */
-    public function testHandleExceptionLogAttributes(): void
-    {
-        $errorHandler = new TestErrorHandler([
-            'log' => true,
-            'trace' => true,
-        ]);
-
-        $error = new MissingControllerException(['class' => 'Derp']);
-        $errorHandler->handleException($error);
-
-        Configure::write('debug', false);
-        $errorHandler->handleException($error);
-
-        $messages = $this->logger->read();
-        $this->assertMatchesRegularExpression('/^error/', $messages[0]);
-        $this->assertStringContainsString(
-            '[Cake\Http\Exception\MissingControllerException] Controller class Derp could not be found.',
-            $messages[0]
-        );
-        $this->assertStringContainsString('Exception Attributes:', $messages[0]);
-        $this->assertStringContainsString('Request URL:', $messages[0]);
-        $this->assertStringContainsString('Referer URL:', $messages[0]);
-
-        $this->assertStringContainsString(
-            '[Cake\Http\Exception\MissingControllerException] Controller class Derp could not be found.',
-            $messages[1]
-        );
-        $this->assertStringNotContainsString('Exception Attributes:', $messages[1]);
-    }
-
-    /**
-     * test logging attributes with previous exception
-     */
-    public function testHandleExceptionLogPrevious(): void
-    {
-        $errorHandler = new TestErrorHandler([
-            'log' => true,
-            'trace' => true,
-        ]);
-
-        $previous = new RecordNotFoundException('Previous logged');
-        $error = new NotFoundException('Kaboom!', null, $previous);
-        $errorHandler->handleException($error);
-
-        $messages = $this->logger->read();
-        $this->assertStringContainsString('[Cake\Http\Exception\NotFoundException] Kaboom!', $messages[0]);
-        $this->assertStringContainsString(
-            'Caused by: [Cake\Datasource\Exception\RecordNotFoundException] Previous logged',
-            $messages[0]
-        );
-        $this->assertStringContainsString(
-            str_replace('/', DS, 'vendor/phpunit/phpunit/src/Framework/TestCase.php'),
-            $messages[0]
-        );
-    }
-
-    /**
-     * test handleException generating log.
-     */
-    public function testHandleExceptionLogSkipping(): void
-    {
-        $notFound = new NotFoundException('Kaboom!');
-        $forbidden = new ForbiddenException('Fooled you!');
-        $errorHandler = new TestErrorHandler([
-            'log' => true,
-            'skipLog' => ['Cake\Http\Exception\NotFoundException'],
-        ]);
-
-        $errorHandler->handleException($notFound);
-        $this->assertStringContainsString('Kaboom!', (string)$errorHandler->response->getBody(), 'message missing.');
-
-        $errorHandler->handleException($forbidden);
-        $this->assertStringContainsString('Fooled you!', (string)$errorHandler->response->getBody(), 'message missing.');
-
-        $messages = $this->logger->read();
-        $this->assertCount(1, $messages);
-        $this->assertMatchesRegularExpression('/^error/', $messages[0]);
-        $this->assertStringContainsString(
-            '[Cake\Http\Exception\ForbiddenException] Fooled you!',
-            $messages[0]
-        );
-    }
-
-    /**
-     * tests it is possible to load a plugin exception renderer
-     */
-    public function testLoadPluginHandler(): void
-    {
-        $this->loadPlugins(['TestPlugin']);
-        $errorHandler = new TestErrorHandler([
-            'exceptionRenderer' => 'TestPlugin.TestPluginExceptionRenderer',
-        ]);
-
-        $error = new NotFoundException('Kaboom!');
-        $errorHandler->handleException($error);
-
-        $result = $errorHandler->response;
-        $this->assertSame('Rendered by test plugin', (string)$result);
-    }
-
-    /**
-     * test handleFatalError generating a page.
-     *
-     * These tests start two buffers as handleFatalError blows the outer one up.
-     */
-    public function testHandleFatalErrorPage(): void
-    {
-        $line = __LINE__;
-        $errorHandler = new TestErrorHandler();
-        Configure::write('debug', true);
-
-        $errorHandler->handleFatalError(E_ERROR, 'Something wrong', __FILE__, $line);
-        $result = (string)$errorHandler->response->getBody();
-        $this->assertStringContainsString('Something wrong', $result, 'message missing.');
-        $this->assertStringContainsString(__FILE__, $result, 'filename missing.');
-        $this->assertStringContainsString((string)$line, $result, 'line missing.');
-
-        Configure::write('debug', false);
-        $errorHandler->handleFatalError(E_ERROR, 'Something wrong', __FILE__, $line);
-        $result = (string)$errorHandler->response->getBody();
-        $this->assertStringNotContainsString('Something wrong', $result, 'message must not appear.');
-        $this->assertStringNotContainsString(__FILE__, $result, 'filename must not appear.');
-        $this->assertStringContainsString('An Internal Error Has Occurred.', $result);
-    }
-
-    /**
-     * test handleFatalError generating log.
-     */
-    public function testHandleFatalErrorLog(): void
-    {
-        $errorHandler = new TestErrorHandler(['log' => true]);
-        $errorHandler->handleFatalError(E_ERROR, 'Something wrong', __FILE__, __LINE__);
-
-        $messages = $this->logger->read();
-        $this->assertCount(2, $messages);
-        $this->assertStringContainsString(__FILE__ . ', line ' . (__LINE__ - 4), $messages[0]);
-        $this->assertStringContainsString('Fatal Error (1)', $messages[0]);
-        $this->assertStringContainsString('Something wrong', $messages[0]);
-        $this->assertStringContainsString('[Cake\Error\FatalErrorException] Something wrong', $messages[1]);
-    }
-
-    /**
-     * Data provider for memory limit changing.
-     *
-     * @return array
-     */
-    public function memoryLimitProvider(): array
-    {
-        return [
-            // start, adjust, expected
-            ['256M', 4, '262148K'],
-            ['262144K', 4, '262148K'],
-            ['1G', 128, '1048704K'],
-        ];
-    }
-
-    /**
-     * Test increasing the memory limit.
-     *
-     * @dataProvider memoryLimitProvider
-     */
-    public function testIncreaseMemoryLimit(string $start, int $adjust, string $expected): void
-    {
-        $initial = ini_get('memory_limit');
-        $this->skipIf(strlen($initial) === 0, 'Cannot read memory limit, and cannot test increasing it.');
-
-        // phpunit.xml often has -1 as memory limit
-        ini_set('memory_limit', $start);
-
-        $errorHandler = new TestErrorHandler();
-        $errorHandler->increaseMemoryLimit($adjust);
-        $new = ini_get('memory_limit');
-        $this->assertEquals($expected, $new, 'memory limit did not get increased.');
-
-        ini_set('memory_limit', $initial);
-    }
-
-    /**
-     * Test getting a logger
-     */
-    public function testGetLogger(): void
-    {
-        $errorHandler = new TestErrorHandler(['key' => 'value', 'log' => true]);
-        $logger = $errorHandler->getLogger();
-
-        $this->assertInstanceOf(ErrorLoggerInterface::class, $logger);
-        $this->assertSame('value', $logger->getConfig('key'), 'config should be forwarded.');
-        $this->assertSame($logger, $errorHandler->getLogger());
-    }
-
-    /**
-     * Test getting a logger
-     */
-    public function testGetLoggerInvalid(): void
-    {
-        $errorHandler = new TestErrorHandler(['errorLogger' => stdClass::class]);
-        $this->expectException(RuntimeException::class);
-        $this->expectExceptionMessage('Cannot create logger');
-        $errorHandler->getLogger();
-    }
-}

+ 2 - 3
tests/TestCase/Error/Middleware/ErrorHandlerMiddlewareTest.php

@@ -18,7 +18,6 @@ namespace Cake\Test\TestCase\Error\Middleware;
 
 use Cake\Core\Configure;
 use Cake\Datasource\Exception\RecordNotFoundException;
-use Cake\Error\ErrorHandler;
 use Cake\Error\ExceptionRenderer;
 use Cake\Error\ExceptionRendererInterface;
 use Cake\Error\ExceptionTrap;
@@ -102,7 +101,7 @@ class ErrorHandlerMiddlewareTest extends TestCase
 
             return $mock;
         };
-        $middleware = new ErrorHandlerMiddleware(new ErrorHandler([
+        $middleware = new ErrorHandlerMiddleware(new ExceptionTrap([
             'exceptionRenderer' => $factory,
         ]));
         $handler = new TestRequestHandler(function (): void {
@@ -344,7 +343,7 @@ class ErrorHandlerMiddlewareTest extends TestCase
 
             return $mock;
         };
-        $middleware = new ErrorHandlerMiddleware(new ErrorHandler([
+        $middleware = new ErrorHandlerMiddleware(new ExceptionTrap([
             'exceptionRenderer' => $factory,
         ]));
         $handler = new TestRequestHandler(function (): void {

+ 0 - 1
tests/phpstan.neon

@@ -8,7 +8,6 @@ parameters:
 
 	excludePaths:
 		- TestCase/Error/DebuggerTest.php
-		- TestCase/Error/ErrorHandlerTest.php
 		- TestCase/Filesystem/FolderTest.php
 		- TestCase/Routing/RouterTest.php
 

+ 0 - 29
tests/test_app/TestApp/Error/TestErrorHandler.php

@@ -1,29 +0,0 @@
-<?php
-declare(strict_types=1);
-
-namespace TestApp\Error;
-
-use Cake\Error\ErrorHandler;
-
-/**
- * Testing stub.
- */
-class TestErrorHandler extends ErrorHandler
-{
-    /**
-     * Access the response used.
-     *
-     * @var \Cake\Http\Response
-     */
-    public $response;
-
-    /**
-     * Stub sending responses
-     *
-     * @param \Cake\Http\Response $response
-     */
-    protected function _sendResponse($response): void
-    {
-        $this->response = $response;
-    }
-}