Browse Source

Add supported for prefixed ErrorController.

If error occurs on a prefix URL, exception renderer first tries to use
ErrorController from that prefix and if one does not exist fallsback to the
non prefixed ErrorController.
ADmad 7 years ago
parent
commit
67ba3bfe4c

+ 19 - 1
src/Error/ExceptionRenderer.php

@@ -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($request->getParam('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');
+    }
+}