Browse Source

Merge pull request #11462 from cakephp/bugfix/php7-throwable

Fix PHP7 Throwable to be caught by low level try catch.
Mark Story 8 years ago
parent
commit
c159efc166
3 changed files with 54 additions and 21 deletions
  1. 1 1
      src/Error/Debugger.php
  2. 28 11
      src/Error/ErrorHandler.php
  3. 25 9
      src/Error/Middleware/ErrorHandlerMiddleware.php

+ 1 - 1
src/Error/Debugger.php

@@ -766,7 +766,7 @@ class Debugger
     /**
      * Takes a processed array of data from an error and displays it in the chosen format.
      *
-     * @param string $data Data to output.
+     * @param array $data Data to output.
      * @return void
      */
     public function outputError($data)

+ 28 - 11
src/Error/ErrorHandler.php

@@ -18,6 +18,7 @@ namespace Cake\Error;
 
 use Cake\Core\App;
 use Exception;
+use Throwable;
 
 /**
  * Error Handler provides basic error and exception handling for your application. It captures and
@@ -121,7 +122,7 @@ class ErrorHandler extends BaseErrorHandler
     /**
      * Displays an exception response body.
      *
-     * @param \Exception $exception The exception to display
+     * @param \Exception $exception The exception to display.
      * @return void
      * @throws \Exception When the chosen exception renderer is invalid.
      */
@@ -137,16 +138,10 @@ class ErrorHandler extends BaseErrorHandler
             $response = $renderer->render();
             $this->_clearOutput();
             $this->_sendResponse($response);
-        } catch (Exception $e) {
-            // Disable trace for internal errors.
-            $this->_options['trace'] = false;
-            $message = sprintf(
-                "[%s] %s\n%s", // Keeping same message format
-                get_class($e),
-                $e->getMessage(),
-                $e->getTraceAsString()
-            );
-            trigger_error($message, E_USER_ERROR);
+        } catch (Throwable $exception) {
+            $this->_logInternalError($exception);
+        } catch (Exception $exception) {
+            $this->_logInternalError($exception);
         }
     }
 
@@ -165,6 +160,28 @@ class ErrorHandler extends BaseErrorHandler
     }
 
     /**
+     * Logs both PHP5 and PHP7 errors.
+     *
+     * The PHP5 part will be removed with 4.0.
+     *
+     * @param \Throwable|\Exception $exception Exception.
+     *
+     * @return void
+     */
+    protected function _logInternalError($exception)
+    {
+        // Disable trace for internal errors.
+        $this->_options['trace'] = false;
+        $message = sprintf(
+            "[%s] %s\n%s", // Keeping same message format
+            get_class($exception),
+            $exception->getMessage(),
+            $exception->getTraceAsString()
+        );
+        trigger_error($message, E_USER_ERROR);
+    }
+
+    /**
      * Method that can be easily stubbed in testing.
      *
      * @param string|\Cake\Http\Response $response Either the message or response object.

+ 25 - 9
src/Error/Middleware/ErrorHandlerMiddleware.php

@@ -21,6 +21,7 @@ use Cake\Core\InstanceConfigTrait;
 use Cake\Error\ExceptionRenderer;
 use Cake\Log\Log;
 use Exception;
+use Throwable;
 
 /**
  * Error handling middleware.
@@ -93,8 +94,10 @@ class ErrorHandlerMiddleware
     {
         try {
             return $next($request, $response);
-        } catch (Exception $e) {
-            return $this->handleException($e, $request, $response);
+        } catch (Throwable $exception) {
+            return $this->handleException($exception, $request, $response);
+        } catch (Exception $exception) {
+            return $this->handleException($exception, $request, $response);
         }
     }
 
@@ -114,19 +117,32 @@ class ErrorHandlerMiddleware
             $this->logException($request, $exception);
 
             return $res;
-        } catch (Exception $e) {
-            $this->logException($request, $e);
-
-            $body = $response->getBody();
-            $body->write('An Internal Server Error Occurred');
-            $response = $response->withStatus(500)
-                ->withBody($body);
+        } catch (Throwable $exception) {
+            $this->logException($request, $exception);
+            $response = $this->handleInternalError($response);
+        } catch (Exception $exception) {
+            $this->logException($request, $exception);
+            $response = $this->handleInternalError($response);
         }
 
         return $response;
     }
 
     /**
+     * @param \Psr\Http\Message\ResponseInterface $response The response
+     *
+     * @return \Psr\Http\Message\ResponseInterface A response
+     */
+    protected function handleInternalError($response)
+    {
+        $body = $response->getBody();
+        $body->write('An Internal Server Error Occurred');
+
+        return $response->withStatus(500)
+            ->withBody($body);
+    }
+
+    /**
      * Get a renderer instance
      *
      * @param \Exception $exception The exception being rendered.