Skip to content

Commit

Permalink
Hacky first/incomplete implementation of extending existing filters.
Browse files Browse the repository at this point in the history
The renames to middleware still need to happen, but my gut feeling is
that there isn't anything seriously broken with how filters work right
now beyond the configration bits.
  • Loading branch information
markstory committed May 15, 2014
1 parent 793e97a commit 0adf133
Show file tree
Hide file tree
Showing 3 changed files with 125 additions and 78 deletions.
101 changes: 23 additions & 78 deletions src/Routing/Dispatcher.php
Expand Up @@ -26,7 +26,6 @@
use Cake\Core\Plugin;
use Cake\Error\Exception;
use Cake\Event\Event;
use Cake\Event\EventListener;
use Cake\Event\EventManager;
use Cake\Network\Request;
use Cake\Network\Response;
Expand All @@ -38,7 +37,7 @@
* the controller.
*
*/
class Dispatcher implements EventListener {
class Dispatcher {

/**
* Event manager, used to handle dispatcher filters
Expand Down Expand Up @@ -67,61 +66,10 @@ public function __construct($base = false) {
public function getEventManager() {
if (!$this->_eventManager) {
$this->_eventManager = new EventManager();
$this->_eventManager->attach($this);
$this->_attachFilters($this->_eventManager);
}
return $this->_eventManager;
}

/**
* Returns the list of events this object listens to.
*
* @return array
*/
public function implementedEvents() {
return array('Dispatcher.beforeDispatch' => 'parseParams');
}

/**
* Attaches all event listeners for this dispatcher instance. Loads the
* dispatcher filters from the configured locations.
*
* @param \Cake\Event\EventManager $manager
* @return void
* @throws \Cake\Routing\Error\MissingDispatcherFilterException
*/
protected function _attachFilters($manager) {
$filters = Configure::read('Dispatcher.filters');
if (empty($filters)) {
return;
}

foreach ($filters as $index => $filter) {
$settings = array();
if (is_array($filter) && !is_int($index)) {
$settings = $filter;
$filter = $index;
}
if (is_string($filter)) {
$filter = array('callable' => $filter);
}
if (is_string($filter['callable'])) {
$callable = App::className($filter['callable'], 'Routing/Filter');
if (!$callable) {
throw new Error\MissingDispatcherFilterException($filter['callable']);
}
$manager->attach(new $callable($settings));
} else {
$on = strtolower($filter['on']);
$options = array();
if (isset($filter['priority'])) {
$options = array('priority' => $filter['priority']);
}
$manager->attach($filter['callable'], 'Dispatcher.' . $on . 'Dispatch', $options);
}
}
}

/**
* Dispatches and invokes given Request, handing over control to the involved controller. If the controller is set
* to autoRender, via Controller::$autoRender, then Dispatcher will render the view.
Expand All @@ -136,7 +84,6 @@ protected function _attachFilters($manager) {
*
* @param \Cake\Network\Request $request Request object to dispatch.
* @param \Cake\Network\Response $response Response object to put the results of the dispatch into.
* @param array $additionalParams Settings array ("bare", "return") which is melded with the GET and POST params
* @return string|void if `$request['return']` is set then it returns response body, null otherwise
* @throws \Cake\Controller\Error\MissingControllerException When the controller is missing.
*/
Expand Down Expand Up @@ -211,27 +158,6 @@ protected function _invoke(Controller $controller) {
return $response;
}

/**
* Applies Routing and additionalParameters to the request to be dispatched.
* If Routes have not been loaded they will be loaded, and app/Config/routes.php will be run.
*
* @param \Cake\Event\Event $event containing the request, response and additional params
* @return void
*/
public function parseParams(Event $event) {
$request = $event->data['request'];
Router::setRequestInfo($request);

if (empty($request->params['controller'])) {
$params = Router::parse($request->url);
$request->addParams($params);
}

if (!empty($event->data['additionalParams'])) {
$request->addParams($event->data['additionalParams']);
}
}

/**
* Get controller to use, either plugin controller or application controller
*
Expand All @@ -240,11 +166,25 @@ public function parseParams(Event $event) {
* @return mixed name of controller if not loaded, or object if loaded
*/
protected function _getController($request, $response) {
$ctrlClass = $this->_loadController($request);
if (!$ctrlClass) {
$pluginPath = $controller = null;
$namespace = 'Controller';
if (!empty($request->params['plugin'])) {
$pluginPath = Inflector::camelize($request->params['plugin']) . '.';
}
if (!empty($request->params['controller'])) {
$controller = Inflector::camelize($request->params['controller']);
}
if (!empty($request->params['prefix'])) {
$namespace .= '/' . Inflector::camelize($request->params['prefix']);
}
$className = false;
if ($pluginPath . $controller) {
$className = App::classname($pluginPath . $controller, $namespace, 'Controller');
}
if (!$className) {
return false;
}
$reflection = new \ReflectionClass($ctrlClass);
$reflection = new \ReflectionClass($className);
if ($reflection->isAbstract() || $reflection->isInterface()) {
return false;
}
Expand Down Expand Up @@ -276,4 +216,9 @@ protected function _loadController($request) {
return false;
}

public function add($filter) {
$this->_filters[] = $filter;
$this->getEventManager()->attach($filter);
}

}
72 changes: 72 additions & 0 deletions src/Routing/DispatcherFactory.php
@@ -0,0 +1,72 @@
<?php
/**
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
*
* Licensed under The MIT License
* For full copyright and license information, please see the LICENSE.txt
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
* @link http://cakephp.org CakePHP(tm) Project
* @since 3.0.0
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
namespace Cake\Routing;

use Cake\Routing\Dispatcher;

/**
* A factory for creating dispatchers with all the desired middleware
* connected.
*
* ### Adding middleware
*
* ### Adding lazy middleware
*/
class DispatcherFactory {

/**
* Stack of middleware to apply to dispatchers.
*
* @var array
*/
protected static $_stack = [];

/**
* Add a new middleware object to the stack of middleware
* that will be executed.
*
* @param \Cake\Routing\Middleware $middleware
* @return void
*/
public static function add($middleware) {
if (is_string($middleware)) {
$middleware = static::_createMiddleware($middleware);
}
static::$_stack[] = $middleware;
}

/**
* Create a dispatcher that has all the configured middleware applied.
*
* @return \Cake\Routing\Dispatcher
*/
public static function create() {
$dispatcher = new Dispatcher();
foreach (static::$_stack as $middleware) {
$dispatcher->add($middleware);
}
return $dispatcher;
}

/**
* Clear the middleware stack.
*
* @return void
*/
public static function clear() {
static::$_stack = [];
}

}
30 changes: 30 additions & 0 deletions src/Routing/Filter/RoutingFilter.php
@@ -0,0 +1,30 @@
<?php

namespace Cake\Routing\Filter;

use Cake\Event\Event;
use Cake\Routing\DispatcherFilter;
use Cake\Routing\Router;

class RoutingFilter extends DispatcherFilter {

public $priority = -10;

/**
* Applies Routing and additionalParameters to the request to be dispatched.
* If Routes have not been loaded they will be loaded, and app/Config/routes.php will be run.
*
* @param \Cake\Event\Event $event containing the request, response and additional params
* @return void
*/
public function beforeDispatch(Event $event) {
$request = $event->data['request'];
Router::setRequestInfo($request);

if (empty($request->params['controller'])) {
$params = Router::parse($request->url);
$request->addParams($params);
}
}

}

0 comments on commit 0adf133

Please sign in to comment.