Skip to content

Commit

Permalink
Drastially change how beforeRedirect callbacks work.
Browse files Browse the repository at this point in the history
Instead of relying on removed event system features, the beforeRedirect
callback now works differently. Each callback will receive the original
URL that the redirect was for and the response object. Any listener can
directly set the location header, statusCode or any other headers they
desire. The exit parameter cannot be altered and will most likely be
removed in the future as exiting from the controller makes a variety of
testing situations harder. This change also simplifies the testing
& behavior of the beforeRedirect callback.

If a beforeRedirect callback is stopped no redirection occurs as in the
past.
  • Loading branch information
markstory committed Jul 20, 2013
1 parent cab1a39 commit 2eafc1f
Show file tree
Hide file tree
Showing 6 changed files with 144 additions and 215 deletions.
16 changes: 8 additions & 8 deletions lib/Cake/Controller/Component/RequestHandlerComponent.php
Expand Up @@ -21,6 +21,7 @@
use Cake\Core\Configure;
use Cake\Error;
use Cake\Event\Event;
use Cake\Network\Response;
use Cake\Routing\Router;
use Cake\Utility\Inflector;
use Cake\Utility\Xml;
Expand Down Expand Up @@ -246,11 +247,10 @@ public function convertXml($xml) {
*
* @param Event $event The Controller.beforeRedirect event.
* @param string|array $url A string or array containing the redirect location
* @param integer|array $status HTTP Status for redirect
* @param boolean $exit
* @param Cake\Network\Response $response The response object.
* @return void
*/
public function beforeRedirect(Event $event, $url, $status = null, $exit = true) {
public function beforeRedirect(Event $event, $url, $response) {
if (!$this->request->is('ajax')) {
return;
}
Expand All @@ -265,13 +265,13 @@ public function beforeRedirect(Event $event, $url, $status = null, $exit = true)
$url = Router::url($url + array('base' => false));
}
if (!empty($status)) {
$statusCode = $this->response->httpCodes($status);
$statusCode = $response->httpCodes($status);
$code = key($statusCode);
$this->response->statusCode($code);
$response->statusCode($code);
}
$controller = $event->subject();
$this->response->body($controller->requestAction($url, array('return', 'bare' => false)));
$this->response->send();
$response->body($controller->requestAction($url, array('return', 'bare' => false)));
$response->send();
$this->_stop();
}

Expand Down Expand Up @@ -310,7 +310,7 @@ public function isAjax() {
public function isFlash() {
return $this->request->is('flash');
}

;
/**
* Returns true if the current request is over HTTPS, false otherwise.
*
Expand Down
19 changes: 9 additions & 10 deletions lib/Cake/Controller/Controller.php
Expand Up @@ -738,32 +738,31 @@ public function redirect($url, $status = null, $exit = true) {
if (is_array($status)) {
extract($status, EXTR_OVERWRITE);
}
$event = new Event('Controller.beforeRedirect', $this, array($url, $status, $exit));
$response = $this->response;
$event = new Event('Controller.beforeRedirect', $this, [$response, $url, $status]);
$this->getEventManager()->dispatch($event);

if ($event->isStopped()) {
return;
}
$response = $event->result;
extract($this->_parseBeforeRedirect($response, $url, $status, $exit), EXTR_OVERWRITE);

if ($url !== null) {
$this->response->header('Location', Router::url($url, true));
$headers = $response->header();
if ($url !== null && empty($headers['Location'])) {
$response->header('Location', Router::url($url, true));
}

if (is_string($status)) {
$codes = array_flip($this->response->httpCodes());
$codes = array_flip($response->httpCodes());
if (isset($codes[$status])) {
$status = $codes[$status];
}
}

if ($status) {
$this->response->statusCode($status);
if ($status && $response->statusCode() === 200) {
$response->statusCode($status);
}

if ($exit) {
$this->response->send();
$response->send();
$this->_stop();
}
}
Expand Down

0 comments on commit 2eafc1f

Please sign in to comment.