Restore middleware support in backend controllers.

Reverts f73d8e6d49.  While there are other ways to achieve some of the same end results, this code existed in the code base for 8 months without issues and is included in the official docs. This means that there could be devs that are depending on this behavior. Additionally, while this may make the internal logic to the BackendController class more complex, it simplifies the developer experience by bringing the Backend\Classes\Controller base class more in line with the standard Laravel controller class.
This commit is contained in:
Luke Towers 2019-11-07 11:59:00 -06:00
parent 490b1d6b00
commit d56dded458
2 changed files with 131 additions and 11 deletions

View File

@ -55,6 +55,44 @@ class BackendController extends ControllerBase
*/
public function __construct()
{
$this->middleware(function ($request, $next) {
// Process the request before retrieving controller middleware, to allow for the session and auth data
// to be made available to the controller's constructor.
$response = $next($request);
// 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)
&& is_array($requestedController)
&& count($requestedController['controller']->getMiddleware())
) {
$action = $requestedController['action'];
// Collect applicable middleware and insert middleware into pipeline
$controllerMiddleware = collect($requestedController['controller']->getMiddleware())
->reject(function ($data) use ($action) {
return static::methodExcludedByOptions($action, $data['options']);
})
->pluck('middleware');
foreach ($controllerMiddleware as $middleware) {
$middleware->call($requestedController['controller'], $request, $response);
}
}
}
return $response;
});
$this->extendableConstruct();
}
@ -113,6 +151,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
*/
@ -126,7 +192,11 @@ class BackendController extends ControllerBase
$action,
base_path().'/modules'
)) {
return $controllerObj->run($action, $controllerParams);
return [
'controller' => $controllerObj,
'action' => $action,
'params' => $controllerParams
];
}
/*
@ -149,14 +219,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;
}
/**
@ -169,6 +240,10 @@ class BackendController extends ControllerBase
*/
protected function findController($controller, $action, $inPath)
{
if (isset($this->requestedController)) {
return $this->requestedController;
}
/*
* Workaround: Composer does not support case insensitivity.
*/
@ -181,16 +256,16 @@ class BackendController extends ControllerBase
}
if (!class_exists($controller)) {
return false;
return $this->requestedController = null;
}
$controllerObj = App::make($controller);
if ($controllerObj->actionExists($action)) {
return $controllerObj;
return $this->requestedController = $controllerObj;
}
return false;
return $this->requestedController = null;
}
/**
@ -206,4 +281,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

@ -19,9 +19,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.
@ -30,7 +30,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;
@ -40,6 +40,12 @@ class Controller extends Extendable
use \System\Traits\SecurityController;
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.
@ -153,6 +159,32 @@ 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);
}
/**