API CHANGE: Decoupled ErrorPage::response_for() from the request and updated it so it will only return a response if an appropriate error page can be found.

MINOR: Updated ContentController->httpError() to use Controller->httpError() if there is no error page.

From: Andrew Short <andrewjshort@gmail.com>

git-svn-id: svn://svn.silverstripe.com/silverstripe/open/modules/sapphire/trunk@88507 467b73ca-7a2a-4603-9d3b-597d59a354a9
This commit is contained in:
Andrew Short 2009-10-11 00:07:25 +00:00 committed by Sam Minnee
parent 53450e1221
commit 06fbb96f88
3 changed files with 61 additions and 73 deletions

View File

@ -115,6 +115,54 @@ class ContentController extends Controller {
}
/**
* This acts the same as {@link Controller::handleRequest()}, but if an action cannot be found this will attempt to
* fall over to a child controller in order to provide functionality for nested URLs.
*
* @return HTTPResponse
*/
public function handleRequest(HTTPRequest $request) {
$child = null;
$action = $request->param('Action');
// If nested URLs are enabled, and there is no action handler for the current request then attempt to pass
// control to a child controller. This allows for the creation of chains of controllers which correspond to a
// nested URL.
if($action && SiteTree::nested_urls() && !$this->hasAction($action)) {
Translatable::disable_locale_filter();
$child = DataObject::get_one('SiteTree', sprintf (
"\"ParentID\" = %s AND \"URLSegment\" = '%s'", $this->ID, Convert::raw2sql($action)
));
Translatable::enable_locale_filter();
}
if($child) {
$request->shiftAllParams();
$request->shift();
$response = ModelAsController::controller_for($child)->handleRequest($request);
} else {
Director::set_current_page($this->data());
$response = parent::handleRequest($request);
Director::set_current_page(null);
}
return $response;
}
/**
* @uses ErrorPage::response_for()
*/
public function httpError($code, $message = null) {
if($this->request->isMedia() || !$response = ErrorPage::response_for($code)) {
parent::httpError($code, $message);
} else {
throw new HTTPResponse_Exception($response);
}
}
/**
* Handles widgets attached to a page through one or more {@link WidgetArea} elements.
* Iterated through each $has_one relation with a {@link WidgetArea}
@ -161,51 +209,6 @@ class ContentController extends Controller {
return new $controllerClass($widget);
}
/**
* This acts the same as {@link Controller::handleRequest()}, but if an action cannot be found this will attempt to
* fall over to a child controller in order to provide functionality for nested URLs.
*
* @return HTTPResponse
*/
public function handleRequest(HTTPRequest $request) {
$child = null;
$action = $request->param('Action');
// If nested URLs are enabled, and there is no action handler for the current request then attempt to pass
// control to a child controller. This allows for the creation of chains of controllers which correspond to a
// nested URL.
if($action && SiteTree::nested_urls() && !$this->hasAction($action)) {
Translatable::disable_locale_filter();
$child = DataObject::get_one('SiteTree', sprintf (
"\"ParentID\" = %s AND \"URLSegment\" = '%s'", $this->ID, Convert::raw2sql($action)
));
Translatable::enable_locale_filter();
}
if($child) {
$request->shiftAllParams();
$request->shift();
$response = ModelAsController::controller_for($child)->handleRequest($request);
} else {
Director::set_current_page($this->data());
$response = parent::handleRequest($request);
Director::set_current_page(null);
}
return $response;
}
/**
* @uses ErrorPage::response_for()
* @return HTTPResponse
*/
public function httpError($code, $message = null) {
return ($resp = ErrorPage::response_for($code, $this->request)) ? $resp : parent::httpError($code, $message);
}
/**
* Get the project name
*

View File

@ -88,7 +88,7 @@ class ModelAsController extends Controller implements NestedController {
return $this->response;
}
if($response = ErrorPage::response_for(404, $this->request)) {
if($response = ErrorPage::response_for(404)) {
return $response;
} else {
$this->httpError(404, 'The requested page could not be found.');

View File

@ -25,19 +25,18 @@ class ErrorPage extends Page {
protected static $static_filepath = ASSETS_PATH;
/**
* Get a {@link HTTPResponse} that is suitable for responding to a reques that has thrown a specific error code.
* Get a {@link HTTPResponse} to response to a HTTP error code if an {@link ErrorPage} for that code is present.
*
* @param int $statusCode The HTTP error code.
* @param HTTPRequest $request The request object that triggered the error.
* @param int $statusCode
* @return HTTPResponse
*/
public static function response_for($statusCode, HTTPRequest $request = null) {
$errorPage = null;
public static function response_for($statusCode) {
// first attempt to dynamically generate the error page
if($errorPage = DataObject::get_one('ErrorPage', "\"ErrorCode\" = $statusCode")) {
return ModelAsController::controller_for($errorPage)->handleRequest(new HTTPRequest('GET', ''));
}
// First attempt to dynamically generate the error page, then fall back on using a cached version.
if (
(!$request || !$request->isMedia()) && !$errorPage = DataObject::get_one('ErrorPage', "\"ErrorCode\" = $statusCode")
) {
// then fall back on a cached version
$cachedPath = self::get_filepath_for_errorcode($statusCode, Translatable::get_current_locale());
if(file_exists($cachedPath)) {
@ -50,20 +49,6 @@ class ErrorPage extends Page {
}
}
// If the request is for a simple media type, or there was no matching dynamic or cached error page just return
// a simple error string to avoid clogging up server resources.
if(!$errorPage) {
$response = new HTTPResponse();
$response->setStatusCode($statusCode);
$response->setBody(sprintf('Error %s: %s', $response->getStatusCode(), $response->getStatusDescription()));
return $response;
}
return ModelAsController::controller_for($errorPage)->handleRequest(new HTTPRequest('GET', ''));
}
/**
* Ensures that there is always a 404 page
* by checking if there's an instance of