Skip to content

Commit

Permalink
Add support for using plugin error controller within prefixes
Browse files Browse the repository at this point in the history
When within a plugin + prefix routing scope if there isn't an
ErrorController for the plugin + prefix, fallback to just the plugin
before falling back to the application/core error controller.

This allows plugins to provide error handling for all of their routes if
they need it.

Fixes #17025
  • Loading branch information
markstory committed Mar 19, 2023
1 parent c33dff1 commit 59ca3e9
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 6 deletions.
9 changes: 8 additions & 1 deletion src/Error/Renderer/WebExceptionRenderer.php
Original file line number Diff line number Diff line change
Expand Up @@ -167,10 +167,17 @@ protected function _getController(): Controller
$params['controller'] = 'Error';

$factory = new ControllerFactory(new Container());
// Check including plugin + prefix
$class = $factory->getControllerClass($request->withAttribute('params', $params));

if (!$class && !empty($params['prefix']) && !empty($params['plugin'])) {
unset($params['prefix']);
// Fallback to only plugin
$class = $factory->getControllerClass($request->withAttribute('params', $params));
}

if (!$class) {
/** @var string $class */
// Fallback to app/core provided controller.
$class = App::className('Error', 'Controller', 'Controller');
}

Expand Down
34 changes: 29 additions & 5 deletions tests/TestCase/Error/ExceptionRendererTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -44,12 +44,13 @@
use Exception;
use OutOfBoundsException;
use RuntimeException;
use TestApp\Controller\Admin\ErrorController;
use TestApp\Controller\Admin\ErrorController as PrefixErrorController;
use TestApp\Error\Exception\MissingWidgetThing;
use TestApp\Error\Exception\MissingWidgetThingException;
use TestApp\Error\Exception\MyPDOException;
use TestApp\Error\MyCustomExceptionRenderer;
use TestApp\Error\TestAppsExceptionRenderer;
use TestPlugin\Controller\ErrorController as PluginErrorController;

class ExceptionRendererTest extends TestCase
{
Expand Down Expand Up @@ -91,8 +92,7 @@ public function tearDown(): void

public function testControllerInstanceForPrefixedRequest(): void
{
$namespace = Configure::read('App.namespace');
Configure::write('App.namespace', 'TestApp');
$this->setAppNamespace('TestApp');

$exception = new NotFoundException('Page not found');
$request = new ServerRequest();
Expand All @@ -103,11 +103,35 @@ public function testControllerInstanceForPrefixedRequest(): void
$ExceptionRenderer = new MyCustomExceptionRenderer($exception, $request);

$this->assertInstanceOf(
ErrorController::class,
PrefixErrorController::class,
$ExceptionRenderer->__debugInfo()['controller']
);
}

Configure::write('App.namespace', $namespace);
/**
* Test that prefixed controllers in plugins use the plugin
* error controller if it exists.
*
* @return void
*/
public function testControllerInstanceForPluginPrefixedRequest(): void
{
$this->loadPlugins(['TestPlugin']);
$this->setAppNamespace('TestApp');

$exception = new NotFoundException('Page not found');
$request = new ServerRequest();
$request = $request
->withParam('controller', 'Comments')
->withParam('plugin', 'TestPlugin')
->withParam('prefix', 'Admin');

$ExceptionRenderer = new MyCustomExceptionRenderer($exception, $request);

$this->assertInstanceOf(
PluginErrorController::class,
$ExceptionRenderer->__debugInfo()['controller']
);
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?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
* 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 4.5.0
* @license https://opensource.org/licenses/mit-license.php MIT License
*/
namespace TestPlugin\Controller;

use Cake\Controller\ErrorController as CoreErrorController;

/**
* Error Handling Controller
*
* Controller used by ErrorHandler to render error views.
*/
class ErrorController extends CoreErrorController
{
}

0 comments on commit 59ca3e9

Please sign in to comment.