Allow controller middleware in backend controllers (#4106)

Credit to @bennothommo Related: https://github.com/octobercms/october/pull/4088
This commit is contained in:
Ben Thomson 2019-02-28 04:27:41 +08:00 committed by Luke Towers
parent 7f3fb06945
commit 57a074364e
2 changed files with 115 additions and 13 deletions

View File

@ -6,13 +6,13 @@ use File;
use View;
use Event;
use Config;
use Request;
use Response;
use Closure;
use Illuminate\Routing\Controller as ControllerBase;
use October\Rain\Router\Helper as RouterHelper;
use Closure;
use System\Classes\PluginManager;
/**
* This is the master controller for all back-end pages.
* All requests that are prefixed with the backend URI pattern are sent here,
@ -55,6 +55,28 @@ class BackendController extends ControllerBase
*/
public function __construct()
{
// Find requested controller to determine if any middleware has been attached
$pathParts = explode('/', str_replace(Request::root() . '/', '', Request::url()));
if (count($pathParts)) {
// Drop off preceding backend URL part if needed
if (!empty(Config::get('cms.backendUri', 'backend'))) {
array_shift($pathParts);
}
$path = implode('/', $pathParts);
$requestedController = $this->getRequestedController($path);
if (!is_null($requestedController) && count($requestedController['controller']->getMiddleware())) {
$action = $requestedController['action'];
// Collect applicable middleware and insert middleware into pipeline
collect($requestedController['controller']->getMiddleware())->reject(function ($data) use ($action) {
return static::methodExcludedByOptions($action, $data['options']);
})->pluck('middleware')->map(function ($middleware) {
$this->middleware($middleware);
});
}
}
$this->extendableConstruct();
}
@ -110,6 +132,34 @@ class BackendController extends ControllerBase
: $this->passToCmsController($url);
}
$controllerRequest = $this->getRequestedController($url);
if (!is_null($controllerRequest)) {
return $controllerRequest['controller']->run(
$controllerRequest['action'],
$controllerRequest['params']
);
}
/*
* Fall back on Cms controller
*/
return $this->passToCmsController($url);
}
/**
* Determines the controller and action to load in the backend via a provided URL.
*
* If a suitable controller is found, this will return an array with the controller class name as a string, the
* action to call as a string and an array of parameters. If a suitable controller and action cannot be found,
* this method will return null.
*
* @param string $url A URL to determine the requested controller and action for
* @return array|null A suitable controller, action and parameters in an array if found, otherwise null.
*/
protected function getRequestedController($url)
{
$params = RouterHelper::segmentizeUrl($url);
/*
* Look for a Module controller
*/
@ -123,7 +173,11 @@ class BackendController extends ControllerBase
$action,
base_path().'/modules'
)) {
return $controllerObj->run($action, $controllerParams);
return [
'controller' => $controllerObj,
'action' => $action,
'params' => $controllerParams
];
}
/*
@ -146,14 +200,15 @@ class BackendController extends ControllerBase
$action,
plugins_path()
)) {
return $controllerObj->run($action, $controllerParams);
return [
'controller' => $controllerObj,
'action' => $action,
'params' => $controllerParams
];
}
}
/*
* Fall back on Cms controller
*/
return $this->passToCmsController($url);
return null;
}
/**
@ -203,4 +258,17 @@ class BackendController extends ControllerBase
return $actionName;
}
}
/**
* Determine if the given options exclude a particular method.
*
* @param string $method
* @param array $options
* @return bool
*/
protected static function methodExcludedByOptions($method, array $options)
{
return (isset($options['only']) && !in_array($method, (array) $options['only'])) ||
(!empty($options['except']) && in_array($method, (array) $options['except']));
}
}

View File

@ -18,9 +18,9 @@ use October\Rain\Exception\AjaxException;
use October\Rain\Exception\SystemException;
use October\Rain\Exception\ValidationException;
use October\Rain\Exception\ApplicationException;
use October\Rain\Extension\Extendable;
use Illuminate\Database\Eloquent\MassAssignmentException;
use Illuminate\Http\RedirectResponse;
use Illuminate\Routing\Controller as ControllerBase;
/**
* The Backend base controller class, used by Backend controllers.
@ -29,7 +29,7 @@ use Illuminate\Http\RedirectResponse;
* @package october\backend
* @author Alexey Bobkov, Samuel Georges
*/
class Controller extends Extendable
class Controller extends ControllerBase
{
use \System\Traits\ViewMaker;
use \System\Traits\AssetMaker;
@ -37,6 +37,12 @@ class Controller extends Extendable
use \System\Traits\EventEmitter;
use \Backend\Traits\ErrorMaker;
use \Backend\Traits\WidgetMaker;
use \October\Rain\Extension\ExtendableTrait;
/**
* @var array Behaviors implemented by this controller.
*/
public $implement;
/**
* @var object Reference the logged in admin user.
@ -146,8 +152,6 @@ class Controller extends Extendable
*/
$this->user = BackendAuth::getUser();
parent::__construct();
/*
* Media Manager widget is available on all back-end pages
*/
@ -155,6 +159,36 @@ class Controller extends Extendable
$manager = new MediaManager($this, 'ocmediamanager');
$manager->bindToController();
}
$this->extendableConstruct();
}
/**
* Extend this object properties upon construction.
*/
public static function extend(Closure $callback)
{
self::extendableExtendCallback($callback);
}
public function __get($name)
{
return $this->extendableGet($name);
}
public function __set($name, $value)
{
$this->extendableSet($name, $value);
}
public function __call($name, $params)
{
return $this->extendableCall($name, $params);
}
public static function __callStatic($name, $params)
{
return self::extendableCallStatic($name, $params);
}
/**