diff --git a/core/core.services.yml b/core/core.services.yml
index 9bfc560..1b0a347 100644
--- a/core/core.services.yml
+++ b/core/core.services.yml
@@ -592,6 +592,8 @@ services:
site_status_negotiator:
class: Drupal\Core\Site\StatusNegotiator
arguments: ['@state', '@current_user']
+ tags:
+ - { name: service_collector, tag: maintenance_mode_exemption, call: addExemption }
maintenance_mode_subscriber:
class: Drupal\Core\EventSubscriber\MaintenanceModeSubscriber
arguments: ['@site_status_negotiator', '@config.factory', '@string_translation', '@url_generator', '@current_user']
diff --git a/core/lib/Drupal/Core/EventSubscriber/MaintenanceModeSubscriber.php b/core/lib/Drupal/Core/EventSubscriber/MaintenanceModeSubscriber.php
index d9b5f1f..2ae47c8 100644
--- a/core/lib/Drupal/Core/EventSubscriber/MaintenanceModeSubscriber.php
+++ b/core/lib/Drupal/Core/EventSubscriber/MaintenanceModeSubscriber.php
@@ -89,29 +89,31 @@ public function __construct(StatusNegotiatorInterface $status_negotiator, Config
*/
public function onKernelRequestMaintenance(GetResponseEvent $event) {
$request = $event->getRequest();
- if ($this->statusNegotiator->getStatus($this->account) != StatusNegotiatorInterface::SITE_ONLINE) {
- // Deliver the 503 page if the site is in maintenance mode and the logged
- // in user is not allowed to bypass it.
- drupal_maintenance_theme();
- $content = Xss::filterAdmin(String::format($this->config->get('system.maintenance')->get('message'), array(
- '@site' => $this->config->get('system.site')->get('name'),
- )));
- $content = DefaultHtmlPageRenderer::renderPage($content, t('Site under maintenance'));
- $response = new Response('Service unavailable', 503);
- $response->setContent($content);
- $event->setResponse($response);
- }
- elseif ($this->statusNegotiator->getStatus() != StatusNegotiatorInterface::SITE_ONLINE) {
- // Display a message if the logged in user has access to the site in
- // maintenance mode. However, suppress it on the maintenance mode setting
- // spage.
- $is_maintenance_route = $request->attributes->get(RouteObjectInterface::ROUTE_NAME) == 'system.site_maintenance_mode';
- if (!$is_maintenance_route) {
- if ($this->account->hasPermission('administer site configuration')) {
- $this->drupalSetMessage($this->t('Operating in maintenance mode. Go online.', array('@url' => $this->urlGenerator->generate('system.site_maintenance_mode'))), 'status', FALSE);
- }
- else {
- $this->drupalSetMessage($this->t('Operating in maintenance mode.'), 'status', FALSE);
+ if ($this->statusNegotiator->getStatus() != StatusNegotiatorInterface::SITE_ONLINE) {
+ if (!$this->statusNegotiator->exempt($request, $this->account)) {
+ // Deliver the 503 page if the site is in maintenance mode and the
+ // logged in user is not allowed to bypass it.
+ drupal_maintenance_theme();
+ $content = Xss::filterAdmin(String::format($this->config->get('system.maintenance')->get('message'), array(
+ '@site' => $this->config->get('system.site')->get('name'),
+ )));
+ $content = DefaultHtmlPageRenderer::renderPage($content, t('Site under maintenance'));
+ $response = new Response('Service unavailable', 503);
+ $response->setContent($content);
+ $event->setResponse($response);
+ }
+ else {
+ // Display a message if the logged in user has access to the site in
+ // maintenance mode. However, suppress it on the maintenance mode
+ // setting spage.
+ $is_maintenance_route = $request->attributes->get(RouteObjectInterface::ROUTE_NAME) == 'system.site_maintenance_mode';
+ if (!$is_maintenance_route) {
+ if ($this->account->hasPermission('administer site configuration')) {
+ $this->drupalSetMessage($this->t('Operating in maintenance mode. Go online.', array('@url' => $this->urlGenerator->generate('system.site_maintenance_mode'))), 'status', FALSE);
+ }
+ else {
+ $this->drupalSetMessage($this->t('Operating in maintenance mode.'), 'status', FALSE);
+ }
}
}
}
diff --git a/core/lib/Drupal/Core/Site/MaintenanceExemptionInterface.php b/core/lib/Drupal/Core/Site/MaintenanceExemptionInterface.php
new file mode 100644
index 0000000..506985f
--- /dev/null
+++ b/core/lib/Drupal/Core/Site/MaintenanceExemptionInterface.php
@@ -0,0 +1,33 @@
+state = $state;
+ $this->exemptionHandlers = array();
}
/**
* {@inheritdoc}
*/
- public function getStatus(AccountInterface $account = NULL) {
- if (!isset($this->status)) {
- $this->status = $this->state->get('system.maintenance_mode') ? StatusNegotiatorInterface::SITE_OFFLINE : StatusNegotiatorInterface::SITE_ONLINE;
- }
+ public function getStatus() {
+ return $this->state->get('system.maintenance_mode') ? StatusNegotiatorInterface::SITE_OFFLINE : StatusNegotiatorInterface::SITE_ONLINE;
+ }
- if (isset($account) && $account->hasPermission('access site in maintenance mode')) {
- return StatusNegotiatorInterface::SITE_ONLINE;
+ /**
+ * {@inheritdoc}
+ */
+ public function exempt(Request $request, AccountInterface $account) {
+ foreach ($this->exemptionHandlers as $handler) {
+ if ($handler->exempt($request, $account)) {
+ return TRUE;
+ }
}
- return $this->status;
+ return FALSE;
}
/**
- * {@inheritdoc}
+ * Add an exemption handler.
+ *
+ * @param \Drupal\Core\Site\MaintenanceExemptionInterface $handler
+ * A maintenance exemption handler.
*/
- public function overrideStatus($status = NULL) {
- $this->status = $status;
+ public function addExemption(MaintenanceExemptionInterface $handler) {
+ $this->exemptionHandlers[] = $handler;
}
}
diff --git a/core/lib/Drupal/Core/Site/StatusNegotiatorInterface.php b/core/lib/Drupal/Core/Site/StatusNegotiatorInterface.php
index 153380f..0eabb49 100644
--- a/core/lib/Drupal/Core/Site/StatusNegotiatorInterface.php
+++ b/core/lib/Drupal/Core/Site/StatusNegotiatorInterface.php
@@ -8,12 +8,11 @@
namespace Drupal\Core\Site;
use Drupal\Core\State\StateInterface;
-use Drupal\Core\Session\AccountInterface;
/**
* Provides the default implementation of the site status negotiator.
*/
-interface StatusNegotiatorInterface {
+interface StatusNegotiatorInterface extends MaintenanceExemptionInterface {
/**
* @defgroup menu_status_codes Menu status codes
@@ -38,22 +37,9 @@
/**
* Returns whether the site is in maintenance mode.
*
- * @param \Drupal\Core\Session\AccountInterface $account
- * (optional) An account to use when checking whether the site should be
- * displayed in maintenance mode. If omitted, the site status is returned.
- *
* @return int
* Either static::SITE_OFFLINE or static::SITE_ONLINE.
*/
- public function getStatus(AccountInterface $account = NULL);
-
- /**
- * Overrides the site status for the current request.
- *
- * @param int $status
- * (optional) Either static::SITE_OFFLINE or static::SITE_ONLINE. If
- * omitted, the overridden status is cleared.
- */
- public function overrideStatus($status = NULL);
+ public function getStatus();
}
diff --git a/core/modules/system/src/Site/MaintenanceExemption.php b/core/modules/system/src/Site/MaintenanceExemption.php
new file mode 100644
index 0000000..24a8b37
--- /dev/null
+++ b/core/modules/system/src/Site/MaintenanceExemption.php
@@ -0,0 +1,28 @@
+hasPermission('access site in maintenance mode')) {
+ return TRUE;
+ }
+ }
+
+}
diff --git a/core/modules/system/system.services.yml b/core/modules/system/system.services.yml
index 8d09004..4caf4d8 100644
--- a/core/modules/system/system.services.yml
+++ b/core/modules/system/system.services.yml
@@ -33,3 +33,7 @@ services:
arguments: ['@cron', '@config.factory', '@state']
tags:
- { name: event_subscriber }
+ system.maintenance_mode_exemption:
+ class: Drupal\system\Site\MaintenanceExemption
+ tags:
+ - { name: maintenance_mode_exemption }
diff --git a/core/modules/user/src/EventSubscriber/MaintenanceModeSubscriber.php b/core/modules/user/src/EventSubscriber/MaintenanceModeSubscriber.php
index 2bcc631..ce4db76 100644
--- a/core/modules/user/src/EventSubscriber/MaintenanceModeSubscriber.php
+++ b/core/modules/user/src/EventSubscriber/MaintenanceModeSubscriber.php
@@ -58,31 +58,17 @@ public function onKernelRequestMaintenance(GetResponseEvent $event) {
$path = $request->attributes->get('_system_path');
if ($site_status == StatusNegotiatorInterface::SITE_OFFLINE) {
// If the site is offline, log out unprivileged users.
- if ($this->account->isAuthenticated() && !$this->account->hasPermission('access site in maintenance mode')) {
+ if ($this->account->isAuthenticated() && !$this->statusNegotiator->exempt($request, $this->account)) {
user_logout();
// Redirect to homepage.
$event->setResponse(new RedirectResponse(url('', array('absolute' => TRUE))));
return;
}
- if ($this->account->isAnonymous()) {
- switch ($path) {
- case 'user':
- // Forward anonymous user to login page.
- $event->setResponse(new RedirectResponse(url('user/login', array('absolute' => TRUE))));
- return;
- case 'user/login':
- case 'user/password':
- // Disable offline mode.
- $this->statusNegotiator->overrideStatus(StatusNegotiatorInterface::SITE_ONLINE);
- break;
- default:
- if (strpos($path, 'user/reset/') === 0) {
- // Disable offline mode.
- $this->statusNegotiator->overrideStatus(StatusNegotiatorInterface::SITE_ONLINE);
- }
- break;
- }
+ if ($this->account->isAnonymous() && $path == 'user') {
+ // Forward anonymous user to login page.
+ $event->setResponse(new RedirectResponse(url('user/login', array('absolute' => TRUE))));
+ return;
}
}
if ($this->account->isAuthenticated()) {
diff --git a/core/modules/user/src/Site/MaintenanceExemption.php b/core/modules/user/src/Site/MaintenanceExemption.php
new file mode 100644
index 0000000..05a3052
--- /dev/null
+++ b/core/modules/user/src/Site/MaintenanceExemption.php
@@ -0,0 +1,29 @@
+attributes->get('_system_path');
+ if ($path == 'user/login' || $path == 'user/password' || strpos($path, 'user/reset/') === 0) {
+ return TRUE;
+ }
+ }
+
+}
diff --git a/core/modules/user/user.services.yml b/core/modules/user/user.services.yml
index 3a3e3a8..74b68df 100644
--- a/core/modules/user/user.services.yml
+++ b/core/modules/user/user.services.yml
@@ -55,3 +55,7 @@ services:
user.tempstore:
class: Drupal\user\TempStoreFactory
arguments: ['@serialization.phpserialize', '@database', '@lock']
+ user.maintenance_mode_exemption:
+ class: Drupal\user\Site\MaintenanceExemption
+ tags:
+ - { name: maintenance_mode_exemption }