Skip to content
Permalink
Browse files

Integrate the new ActionDispatcher into Dispatcher

Reduce code duplication by integrating the new dispatcher with the old
one. This removes some protected methods, but that is within our
backwards compability guidelines.

I've also added a new Dispatcher.invokeController method to allow
IntegrationTests and other use cases to more easily access the
controller being used in a request. This will be useful long term when
we mainline the PSR7 dispatching.
  • Loading branch information...
markstory committed Apr 17, 2016
1 parent 5a90c3d commit 268de40f2f264e93f0f315dbf90e8f0a2d725931
@@ -78,14 +78,24 @@ public function __construct($factory = null, $eventManager = null)
*/
public function dispatch(Request $request, Response $response)
{
Router::pushRequest($request);
if (Router::getRequest(true) !== $request) {
Router::pushRequest($request);
}
$beforeEvent = $this->dispatchEvent('Dispatcher.beforeDispatch', compact('request', 'response'));
$request = $beforeEvent->data['request'];
if ($beforeEvent->result instanceof Response) {
return $beforeEvent->result;
}
$controller = $this->factory->create($request, $response);
// Use the controller built by an beforeDispatch
// event handler if there is one.
if (isset($beforeEvent->data['controller'])) {
$controller = $beforeEvent->data['controller'];
} else {
$controller = $this->factory->create($request, $response);
}
$response = $this->_invoke($controller);
if (isset($request->params['return'])) {
return $response;
@@ -104,6 +114,8 @@ public function dispatch(Request $request, Response $response)
*/
protected function _invoke(Controller $controller)
{
$this->dispatchEvent('Dispatcher.invokeController', ['controller' => $controller]);
$result = $controller->startupProcess();
if ($result instanceof Response) {
return $result;
@@ -17,6 +17,7 @@
use Cake\Controller\Controller;
use Cake\Event\EventDispatcherTrait;
use Cake\Event\EventListenerInterface;
use Cake\Http\ActionDispatcher;
use Cake\Network\Request;
use Cake\Network\Response;
use LogicException;
@@ -58,69 +59,15 @@ class Dispatcher
*/
public function dispatch(Request $request, Response $response)
{
$beforeEvent = $this->dispatchEvent('Dispatcher.beforeDispatch', compact('request', 'response'));
$request = $beforeEvent->data['request'];
if ($beforeEvent->result instanceof Response) {
if (isset($request->params['return'])) {
return $beforeEvent->result->body();
}
$beforeEvent->result->send();
return null;
}
if (!isset($beforeEvent->data['controller'])) {
throw new LogicException(
'The Dispatcher.beforeDispatch event did not create a controller. ' .
'Ensure you have added the ControllerFactoryFilter.'
);
$actionDispatcher = new ActionDispatcher(null, $this->eventManager());
foreach ($this->_filters as $filter) {
$actionDispatcher->addFilter($filter);
}
$controller = $beforeEvent->data['controller'];
$response = $this->_invoke($controller);
$response = $actionDispatcher->dispatch($request, $response);
if (isset($request->params['return'])) {
return $response->body();
}
$afterEvent = $this->dispatchEvent('Dispatcher.afterDispatch', compact('request', 'response'));
$afterEvent->data['response']->send();
}
/**
* Initializes the components and models a controller will be using.
* Triggers the controller action and invokes the rendering if Controller::$autoRender
* is true. If a response object is returned by controller action that is returned
* else controller's $response property is returned.
*
* @param \Cake\Controller\Controller $controller Controller to invoke
* @return \Cake\Network\Response The resulting response object
* @throws \LogicException If data returned by controller action is not an
* instance of Response
*/
protected function _invoke(Controller $controller)
{
$result = $controller->startupProcess();
if ($result instanceof Response) {
return $result;
}
$response = $controller->invokeAction();
if ($response !== null && !($response instanceof Response)) {
throw new LogicException('Controller action can only return an instance of Response');
}
if (!$response && $controller->autoRender) {
$response = $controller->render();
} elseif (!$response) {
$response = $controller->response;
}
$result = $controller->shutdownProcess();
if ($result instanceof Response) {
return $result;
}
return $response;
return $response->send();
}
/**
@@ -136,7 +83,6 @@ protected function _invoke(Controller $controller)
public function addFilter(EventListenerInterface $filter)
{
$this->_filters[] = $filter;
$this->eventManager()->on($filter);
}
/**
@@ -48,7 +48,9 @@ class RoutingFilter extends DispatcherFilter
public function beforeDispatch(Event $event)
{
$request = $event->data['request'];
Router::setRequestInfo($request);
if (Router::getRequest(true) !== $request) {
Router::setRequestInfo($request);
}
try {
if (empty($request->params['controller'])) {
@@ -124,7 +124,6 @@ abstract class IntegrationTestCase extends TestCase
protected $_csrfToken = false;
/**
*
*
* @var null|string
*/
@@ -357,7 +356,7 @@ protected function _sendRequest($url, $method, $data = [])
$response = new Response();
$dispatcher = DispatcherFactory::create();
$dispatcher->eventManager()->on(
'Dispatcher.beforeDispatch',
'Dispatcher.invokeController',
['priority' => 999],
[$this, 'controllerSpy']
);
@@ -379,15 +378,13 @@ protected function _sendRequest($url, $method, $data = [])
* Adds additional event spies to the controller/view event manager.
*
* @param \Cake\Event\Event $event A dispatcher event.
* @param \Cake\Controller\Controller $controller Controller instance.
* @return void
*/
public function controllerSpy($event)
public function controllerSpy($event, $controller)
{
if (empty($event->data['controller'])) {
return;
}
$this->_controller = $event->data['controller'];
$events = $this->_controller->eventManager();
$this->_controller = $controller;
$events = $controller->eventManager();
$events->on('View.beforeRender', function ($event, $viewFile) {
if (!$this->_viewName) {
$this->_viewName = $viewFile;
Oops, something went wrong.

0 comments on commit 268de40

Please sign in to comment.
You can’t perform that action at this time.