Skip to content

Commit

Permalink
Controller fixes
Browse files Browse the repository at this point in the history
* Set a request on controller with an isolated session
* Initialise controller
* Disable menu current page highlighting
* Set a negative page ID based on error response (for caching)
  • Loading branch information
jonom committed Jul 12, 2018
1 parent ebbd817 commit 451cba9
Showing 1 changed file with 22 additions and 6 deletions.
28 changes: 22 additions & 6 deletions src/CustomErrorControllerExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@
use Page;
use PageController;
use SilverStripe\Control\Director;
use SilverStripe\Control\HTTPRequest;
use SilverStripe\Control\HTTPResponse;
use SilverStripe\Control\HTTPResponse_Exception;
use SilverStripe\Control\Session;
use SilverStripe\Core\Config\Configurable;
use SilverStripe\Core\Extension;
use SilverStripe\Forms\TextField;
Expand Down Expand Up @@ -68,26 +70,40 @@ public function customError($errorCode, $customFields, $template = null, $contro
if (Director::is_ajax()) {
throw new HTTPResponse_Exception($errorMessage, $errorCode);
}

// Hey, what's up? If you know lots about controllers, requests and responses, feel free to rewrite all of this.

// Otherwise build a themed response
if (!$controllerType) $controllerType = $this->config()->get('default_controller');
if (!$template) $template = $this->config()->get('default_template');
$defaultCustomFields = $this->defaultCustomFieldsFor($errorCode);
$response = new HTTPResponse();
$response->setStatusCode($errorCode);
// Set some default properties, then override with custom ones if provided
// Reset current page in case we're getting a 404 on a nested page. This prevents menus being styled according to parent pages.
Director::set_current_page(null);
// Set some default properties for the page, then override with custom ones if provided
$customFields = array_merge(
// Use title from config if set, otherwise fall back to framework definition
['Title' => $response->getStatusDescription()],
$defaultCustomFields,
$customFields
);
// Remove 'Controller' from class name to get related Page type
// Create a dummy page to act as a failover for the controller. Remove 'Controller' from class name to get related Page type
$pageType = substr_replace($controllerType, '', strrpos($controllerType, 'Controller'), strlen('Controller'));
// Create a dummy page to act as a failover for the controller
$dataRecord = $pageType::create();
$dataRecord->ID = -1;
// Set the response body
$body = $controllerType::create($dataRecord)->renderWith($template, $customFields);
// Negative ID as it's a fake. Use error code so we have an ID for partial caching etc.
$dataRecord->ID = -$errorCode;
// Create a request with an empty session, so session data is not rendered and potentially lost to error responses.
$request = new HTTPRequest('GET', '');
$request->setSession(new Session([]));
// Render the response body
$controller = $controllerType::create($dataRecord);
$controller->setRequest($request);
$controller->setResponse(new HTTPResponse());
$controller->doInit();
$controller->pushCurrent();
$body = $controller->renderWith($template, $customFields);
$controller->popCurrent();
$response->setBody($body);
if ($response) {
throw new HTTPResponse_Exception($response, $errorCode);
Expand Down

0 comments on commit 451cba9

Please sign in to comment.