Browse Source

Merge pull request #12396 from cakephp/3.7-exception-renderer

Add supported for prefixed ErrorController.
Mark Story 7 years ago
parent
commit
6ab102e3a0

+ 23 - 5
src/Error/ExceptionRenderer.php

@@ -22,6 +22,7 @@ use Cake\Core\Exception\MissingPluginException;
 use Cake\Event\Event;
 use Cake\Http\Exception\HttpException;
 use Cake\Http\Response;
+use Cake\Http\ServerRequest;
 use Cake\Http\ServerRequestFactory;
 use Cake\Routing\DispatcherFactory;
 use Cake\Routing\Router;
@@ -29,7 +30,6 @@ use Cake\Utility\Inflector;
 use Cake\View\Exception\MissingTemplateException;
 use Exception;
 use PDOException;
-use Psr\Http\Message\ServerRequestInterface;
 
 /**
  * Exception Renderer.
@@ -83,7 +83,7 @@ class ExceptionRenderer implements ExceptionRendererInterface
      * If set, this will be request used to create the controller that will render
      * the error.
      *
-     * @var \Psr\Http\Message\ServerRequestInterface|null
+     * @var \Cake\Http\ServerRequest|null
      */
     protected $request = null;
 
@@ -93,9 +93,9 @@ class ExceptionRenderer implements ExceptionRendererInterface
      * code error depending on the code used to construct the error.
      *
      * @param \Exception $exception Exception.
-     * @param \Psr\Http\Message\ServerRequestInterface $request The request - if this is set it will be used instead of creating a new one
+     * @param \Cake\Http\ServerRequest $request The request - if this is set it will be used instead of creating a new one
      */
-    public function __construct(Exception $exception, ServerRequestInterface $request = null)
+    public function __construct(Exception $exception, ServerRequest $request = null)
     {
         $this->error = $exception;
         $this->request = $request;
@@ -134,7 +134,25 @@ class ExceptionRenderer implements ExceptionRendererInterface
         $controller = null;
 
         try {
-            $class = App::className('Error', 'Controller', 'Controller');
+            $namespace = 'Controller';
+            $prefix = $request->getParam('prefix');
+            if ($prefix) {
+                if (strpos($prefix, '/') === false) {
+                    $namespace .= '/' . Inflector::camelize($prefix);
+                } else {
+                    $prefixes = array_map(
+                        'Cake\Utility\Inflector::camelize',
+                        explode('/', $prefix)
+                    );
+                    $namespace .= '/' . implode('/', $prefixes);
+                }
+            }
+
+            $class = App::className('Error', $namespace, 'Controller');
+            if (!$class && $namespace !== 'Controller') {
+                $class = App::className('Error', 'Controller', 'Controller');
+            }
+
             /* @var \Cake\Controller\Controller $controller */
             $controller = new $class($request, $response);
             $controller->startupProcess();

+ 17 - 0
tests/TestCase/Error/ExceptionRendererTest.php

@@ -43,6 +43,7 @@ use Cake\View\Exception\MissingLayoutException;
 use Cake\View\Exception\MissingTemplateException;
 use Exception;
 use RuntimeException;
+use TestApp\Controller\Admin\ErrorController;
 
 /**
  * BlueberryComponent class
@@ -184,6 +185,22 @@ class ExceptionRendererTest extends TestCase
         }
     }
 
+    public function testControllerInstanceForPrefixedRequest()
+    {
+        $namespace = Configure::read('App.namespace');
+        Configure::write('App.namespace', 'TestApp');
+
+        $exception = new NotFoundException('Page not found');
+        $request = new ServerRequest();
+        $request = $request->withParam('prefix', 'admin');
+
+        $ExceptionRenderer = new MyCustomExceptionRenderer($exception, $request);
+
+        $this->assertInstanceOf(ErrorController::class, $ExceptionRenderer->controller);
+
+        Configure::write('App.namespace', $namespace);
+    }
+
     /**
      * test that methods declared in an ExceptionRenderer subclass are not converted
      * into error400 when debug > 0

+ 46 - 0
tests/test_app/TestApp/Controller/Admin/ErrorController.php

@@ -0,0 +1,46 @@
+<?php
+/**
+ * CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
+ * Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
+ *
+ * Licensed under The MIT License
+ * 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         3.7.0
+ * @license       https://opensource.org/licenses/mit-license.php MIT License
+ */
+namespace TestApp\Controller\Admin;
+
+use Cake\Controller\Controller;
+use Cake\Event\Event;
+
+/**
+ * Error Handling Controller
+ *
+ * Controller used by ErrorHandler to render error views.
+ */
+class ErrorController extends Controller
+{
+    /**
+     * Initialization hook method.
+     *
+     * @return void
+     */
+    public function initialize()
+    {
+        $this->loadComponent('RequestHandler');
+    }
+
+    /**
+     * beforeRender callback.
+     *
+     * @param \Cake\Event\Event $event Event.
+     * @return void
+     */
+    public function beforeRender(Event $event)
+    {
+        $this->viewBuilder()->setTemplatePath('Error');
+    }
+}