FIX Catch database exceptions in middleware when DB is not ready, set session ID after delegation

This commit is contained in:
Robbie Averill 2017-09-05 12:07:49 +12:00
parent 1ac6e78bb3
commit 65f85faff6
4 changed files with 37 additions and 24 deletions

View File

@ -7,6 +7,7 @@ use SilverStripe\Control\HTTPRequest;
use SilverStripe\Control\Middleware\HTTPMiddleware; use SilverStripe\Control\Middleware\HTTPMiddleware;
use SilverStripe\Core\Config\Configurable; use SilverStripe\Core\Config\Configurable;
use SilverStripe\Core\Injector\Injector; use SilverStripe\Core\Injector\Injector;
use SilverStripe\ORM\Connect\DatabaseException;
use SilverStripe\Subsites\Model\Subsite; use SilverStripe\Subsites\Model\Subsite;
use SilverStripe\Subsites\State\SubsiteState; use SilverStripe\Subsites\State\SubsiteState;
@ -27,28 +28,35 @@ class InitStateMiddleware implements HTTPMiddleware
public function process(HTTPRequest $request, callable $delegate) public function process(HTTPRequest $request, callable $delegate)
{ {
// Initialise and register the State try {
$state = SubsiteState::create(); // Initialise and register the State
Injector::inst()->registerService($state); $state = SubsiteState::create();
Injector::inst()->registerService($state);
// Detect whether the request was made in the CMS area (or other admin-only areas) // Detect whether the request was made in the CMS area (or other admin-only areas)
$isAdmin = $this->getIsAdmin($request); $isAdmin = $this->getIsAdmin($request);
$state->setUseSessions($isAdmin); $state->setUseSessions($isAdmin);
// Detect the subsite ID // Detect the subsite ID
$subsiteId = $this->detectSubsiteId($request); $subsiteId = $this->detectSubsiteId($request);
$state->setSubsiteId($subsiteId); $state->setSubsiteId($subsiteId);
// Persist to the session if using the CMS // Persist to the session if using the CMS
if ($state->getUseSessions()) { if ($state->getUseSessions()) {
$original = $request->getSession()->get('SubsiteID'); $originalSubsiteId = $request->getSession()->get('SubsiteID');
$request->getSession()->set('SubsiteID', $subsiteId); }
// Track session changes return $delegate($request);
$state->setSessionWasChanged($subsiteId === $original); } catch (DatabaseException $ex) {
// No-op, database is not ready
} finally {
if ($state->getUseSessions()) {
// Track session changes
$request->getSession()->set('SubsiteID', $subsiteId);
$state->setSessionWasChanged($subsiteId === $originalSubsiteId);
}
} }
return $delegate($request);
} }
/** /**

View File

@ -15,7 +15,7 @@ class ControllerSubsites extends Extension
{ {
if ($subsite = Subsite::currentSubsite()) { if ($subsite = Subsite::currentSubsite()) {
if ($theme = $subsite->Theme) { if ($theme = $subsite->Theme) {
SSViewer::add_themes([$theme]); SSViewer::set_themes([$theme, SSViewer::DEFAULT_THEME]);
} }
} }
} }

View File

@ -267,13 +267,18 @@ class LeftAndMainSubsites extends LeftAndMainExtension
if ($request->getVar('SubsiteID') !== null) { if ($request->getVar('SubsiteID') !== null) {
// Clear current page when subsite changes (or is set for the first time) // Clear current page when subsite changes (or is set for the first time)
if ($state->getSessionWasChanged()) { if ($state->getSessionWasChanged()) {
$session->clear($this->owner->sessionNamespace() . '.currentPage'); // sessionNamespace() is protected - see for info
$override = $this->owner->config()->get('session_namespace');
$sessionNamespace = $override ? $override : get_class($this->owner);
$session->clear($sessionNamespace . '.currentPage');
} }
// Subsite ID has already been set to the state via InitStateMiddleware // Subsite ID has already been set to the state via InitStateMiddleware
if ($this->owner->canView()) { if ($this->owner->canView()) {
// Redirect to clear the current page // Redirect to clear the current page, retaining the current URL parameters
return $this->owner->redirect($this->owner->Link()); return $this->owner->redirect(
Controller::join_links($this->owner->Link(), ...array_values($this->owner->getURLParams()))
);
} }
// Redirect to the default CMS section // Redirect to the default CMS section
return $this->owner->redirect(AdminRootController::config()->get('url_base') . '/'); return $this->owner->redirect(AdminRootController::config()->get('url_base') . '/');
@ -304,7 +309,7 @@ class LeftAndMainSubsites extends LeftAndMainExtension
if ($canViewElsewhere) { if ($canViewElsewhere) {
// Redirect to clear the current page // Redirect to clear the current page
return $this->owner->redirect( return $this->owner->redirect(
Controller::join_links($this->owner->Link(), $record->ID, '?SubsiteID=' . $record->SubsiteID) Controller::join_links($this->owner->Link('show'), $record->ID, '?SubsiteID=' . $record->SubsiteID)
); );
} }
// Redirect to the default CMS section // Redirect to the default CMS section

View File

@ -85,7 +85,7 @@ class SubsiteAdminFunctionalTest extends FunctionalTest
$this->assertEquals(302, $response->getStatusCode()); $this->assertEquals(302, $response->getStatusCode());
$this->assertContains( $this->assertContains(
'admin/pages/edit/' . $subsite1Home->ID . '?SubsiteID=' . $subsite1Home->SubsiteID, 'admin/pages/edit/show/' . $subsite1Home->ID . '?SubsiteID=' . $subsite1Home->SubsiteID,
$response->getHeader('Location') $response->getHeader('Location')
); );
@ -95,7 +95,7 @@ class SubsiteAdminFunctionalTest extends FunctionalTest
$response = $this->get("admin/pages/edit/show/$subsite1Home->ID"); $response = $this->get("admin/pages/edit/show/$subsite1Home->ID");
$this->assertEquals(302, $response->getStatusCode()); $this->assertEquals(302, $response->getStatusCode());
$this->assertContains( $this->assertContains(
'admin/pages/edit/' . $subsite1Home->ID . '?SubsiteID=' . $subsite1Home->SubsiteID, 'admin/pages/edit/show/' . $subsite1Home->ID . '?SubsiteID=' . $subsite1Home->SubsiteID,
$response->getHeader('Location') $response->getHeader('Location')
); );