diff --git a/core/core.services.yml b/core/core.services.yml index 66bc3f2bebc30790dc09360630dfd0f5a46be830..be51f0345a7f24ad5cdd1ce2d8ecfac31803c2f4 100644 --- a/core/core.services.yml +++ b/core/core.services.yml @@ -579,6 +579,7 @@ services: arguments: ['@csrf_token'] maintenance_mode_subscriber: class: Drupal\Core\EventSubscriber\MaintenanceModeSubscriber + arguments: ['@state', '@config.factory', '@string_translation', '@url_generator', '@current_user'] tags: - { name: event_subscriber } path_subscriber: diff --git a/core/includes/menu.inc b/core/includes/menu.inc index 27fb20cb15f0f3847d5dd0bdbef6aaa06fc8b9e3..46de223e32b706fd8226772e2bd1fdb8cc3a9921 100644 --- a/core/includes/menu.inc +++ b/core/includes/menu.inc @@ -102,26 +102,6 @@ * add more with menu_link_save(). */ -/** - * @defgroup menu_status_codes Menu status codes - * @{ - * Status codes for menu callbacks. - */ - -/** - * Internal menu status code -- Menu item inaccessible because site is offline. - */ -const MENU_SITE_OFFLINE = 4; - -/** - * Internal menu status code -- Everything is working fine. - */ -const MENU_SITE_ONLINE = 5; - -/** - * @} End of "defgroup menu_status_codes". - */ - /** * @defgroup menu_tree_parameters Menu tree parameters * @{ @@ -965,47 +945,6 @@ function _menu_set_expanded_menus() { \Drupal::state()->set('menu_expanded', $names); } - -/** - * Checks whether the site is in maintenance mode. - * - * This function will log the current user out and redirect to front page - * if the current user has no 'access site in maintenance mode' permission. - * - * @param $check_only - * If this is set to TRUE, the function will perform the access checks and - * return the site offline status, but not log the user out or display any - * messages. - * - * @return - * FALSE if the site is not in maintenance mode, the user login page is - * displayed, or the user has the 'access site in maintenance mode' - * permission. TRUE for anonymous users not being on the login page when the - * site is in maintenance mode. - */ -function _menu_site_is_offline($check_only = FALSE) { - // Check if site is in maintenance mode. - if (\Drupal::state()->get('system.maintenance_mode')) { - if (user_access('access site in maintenance mode')) { - // Ensure that the maintenance mode message is displayed only once - // (allowing for page redirects) and specifically suppress its display on - // the maintenance mode settings page. - if (!$check_only && current_path() != 'admin/config/development/maintenance') { - if (user_access('administer site configuration')) { - drupal_set_message(t('Operating in maintenance mode. <a href="@url">Go online.</a>', array('@url' => url('admin/config/development/maintenance'))), 'status', FALSE); - } - else { - drupal_set_message(t('Operating in maintenance mode.'), 'status', FALSE); - } - } - } - else { - return TRUE; - } - } - return FALSE; -} - /** * @} End of "defgroup menu". */ diff --git a/core/lib/Drupal/Core/EventSubscriber/MaintenanceModeSubscriber.php b/core/lib/Drupal/Core/EventSubscriber/MaintenanceModeSubscriber.php index 8c75e7b0c4e8d41f83ac4e9fd814360e0ea524a0..1b665f333432322bb68576a54c5a2d6afac04622 100644 --- a/core/lib/Drupal/Core/EventSubscriber/MaintenanceModeSubscriber.php +++ b/core/lib/Drupal/Core/EventSubscriber/MaintenanceModeSubscriber.php @@ -9,18 +9,97 @@ use Drupal\Component\Utility\String; use Drupal\Component\Utility\Xss; +use Drupal\Core\Config\ConfigFactoryInterface; use Drupal\Core\Page\DefaultHtmlPageRenderer; +use Drupal\Core\Routing\UrlGeneratorInterface; +use Drupal\Core\Session\AccountInterface; +use Drupal\Core\State\StateInterface; +use Drupal\Core\StringTranslation\StringTranslationTrait; +use Drupal\Core\StringTranslation\TranslationInterface; +use Symfony\Cmf\Component\Routing\RouteObjectInterface; +use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\HttpFoundation\RedirectResponse; use Symfony\Component\HttpFoundation\Response; -use Symfony\Component\HttpKernel\KernelEvents; use Symfony\Component\HttpKernel\Event\GetResponseEvent; -use Symfony\Component\EventDispatcher\EventSubscriberInterface; +use Symfony\Component\HttpKernel\KernelEvents; /** * Maintenance mode subscriber for controller requests. */ class MaintenanceModeSubscriber implements EventSubscriberInterface { + use StringTranslationTrait; + + /** + * The current account. + * + * @var \Drupal\Core\Session\AccountInterface + */ + protected $account; + + /** + * The state. + * + * @var \Drupal\Core\State\StateInterface + */ + protected $state; + + /** + * The config factory. + * + * @var \Drupal\Core\Config\ConfigFactoryInterface + */ + protected $config; + + /** + * The url generator. + * + * @var \Drupal\Core\Routing\UrlGeneratorInterface + */ + protected $urlGenerator; + + /** + * @defgroup menu_status_codes Menu status codes + * @{ + * Status codes to be used to check the maintenance code. + */ + + /** + * Internal menu status code -- Menu item inaccessible because site is offline. + */ + const SITE_OFFLINE = 4; + + /** + * Internal menu status code -- Everything is working fine. + */ + const SITE_ONLINE = 5; + + /** + * @} End of "defgroup menu_status_codes". + */ + + /** + * Constructs a new MaintenanceModeSubscriber. + * + * @param \Drupal\Core\State\StateInterface $state + * The state. + * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory + * The config factory. + * @param \Drupal\Core\StringTranslation\TranslationInterface $translation + * The string translation. + * @param \Drupal\Core\Routing\UrlGeneratorInterface $url_generator + * The url generator. + * @param \Drupal\Core\Session\AccountInterface $account + * The current user. + */ + public function __construct(StateInterface $state, ConfigFactoryInterface $config_factory, TranslationInterface $translation, UrlGeneratorInterface $url_generator, AccountInterface $account) { + $this->state = $state; + $this->config = $config_factory; + $this->stringTranslation = $translation; + $this->urlGenerator = $url_generator; + $this->account = $account; + } + /** * Determine whether the page is configured to be offline. * @@ -30,7 +109,7 @@ class MaintenanceModeSubscriber implements EventSubscriberInterface { public function onKernelRequestDetermineSiteStatus(GetResponseEvent $event) { // Check if the site is offline. $request = $event->getRequest(); - $is_offline = _menu_site_is_offline() ? MENU_SITE_OFFLINE : MENU_SITE_ONLINE; + $is_offline = $this->isSiteInMaintenance($request) ? static::SITE_OFFLINE : static::SITE_ONLINE; $request->attributes->set('_maintenance', $is_offline); } @@ -44,17 +123,55 @@ public function onKernelRequestMaintenance(GetResponseEvent $event) { $request = $event->getRequest(); $response = $event->getResponse(); // Continue if the site is online and the response is not a redirection. - if ($request->attributes->get('_maintenance') != MENU_SITE_ONLINE && !($response instanceof RedirectResponse)) { + if ($request->attributes->get('_maintenance') != static::SITE_ONLINE && !($response instanceof RedirectResponse)) { // Deliver the 503 page. drupal_maintenance_theme(); - $content = Xss::filterAdmin(String::format(\Drupal::config('system.maintenance')->get('message'), array( - '@site' => \Drupal::config('system.site')->get('name'), + $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); } + + $can_access_maintenance = $this->account->hasPermission('access site in maintenance mode'); + $is_maintenance = $this->state->get('system.maintenance_mode'); + // Ensure that the maintenance mode message is displayed only once + // (allowing for page redirects) and specifically suppress its display on + // the maintenance mode settings page. + $is_maintenance_route = $request->attributes->get(RouteObjectInterface::ROUTE_NAME) == 'system.site_maintenance_mode'; + if ($is_maintenance && $can_access_maintenance && !$is_maintenance_route) { + if ($this->account->hasPermission('administer site configuration')) { + $this->drupalSetMessage($this->t('Operating in maintenance mode. <a href="@url">Go online.</a>', array('@url' => $this->urlGenerator->generate('system.site_maintenance_mode'))), 'status', FALSE); + } + else { + $this->drupalSetMessage($this->t('Operating in maintenance mode.'), 'status', FALSE); + } + } + } + + /** + * Checks whether the site is in maintenance mode. + * + * @return bool + * FALSE if the site is not in maintenance mode + */ + protected function isSiteInMaintenance() { + // Check if site is in maintenance mode. + if ($this->state->get('system.maintenance_mode')) { + if (!$this->account->hasPermission('access site in maintenance mode')) { + return TRUE; + } + } + return FALSE; + } + + /** + * Wraps the drupal_set_message function. + */ + protected function drupalSetMessage($message = NULL, $type = 'status', $repeat = FALSE) { + return drupal_set_message($message, $type, $repeat); } /** @@ -67,4 +184,5 @@ static function getSubscribedEvents() { $events[KernelEvents::REQUEST][] = array('onKernelRequestMaintenance', 30); return $events; } + } diff --git a/core/modules/system/tests/modules/menu_test/src/EventSubscriber/MaintenanceModeSubscriber.php b/core/modules/system/tests/modules/menu_test/src/EventSubscriber/MaintenanceModeSubscriber.php index 2071a375a4bc90cbcf861144f9f0e27b8717e854..0b6ae6171fab166757c8732bbb026e81861d0d69 100644 --- a/core/modules/system/tests/modules/menu_test/src/EventSubscriber/MaintenanceModeSubscriber.php +++ b/core/modules/system/tests/modules/menu_test/src/EventSubscriber/MaintenanceModeSubscriber.php @@ -10,6 +10,8 @@ use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\HttpKernel\Event\GetResponseEvent; use Symfony\Component\HttpKernel\KernelEvents; +use Drupal\Core\EventSubscriber\MaintenanceModeSubscriber as CoreMaintenanceModeSubscriber; + /** * Maintenance mode subscriber to set site online on a test. @@ -25,8 +27,8 @@ class MaintenanceModeSubscriber implements EventSubscriberInterface { public function onKernelRequestMaintenance(GetResponseEvent $event) { $request = $event->getRequest(); // Allow access to menu_login_callback even if in maintenance mode. - if ($request->attributes->get('_maintenance') == MENU_SITE_OFFLINE && $request->attributes->get('_system_path') == 'menu_login_callback') { - $request->attributes->set('_maintenance', MENU_SITE_ONLINE); + if ($request->attributes->get('_maintenance') == CoreMaintenanceModeSubscriber::SITE_OFFLINE && $request->attributes->get('_system_path') == 'menu_login_callback') { + $request->attributes->set('_maintenance', CoreMaintenanceModeSubscriber::SITE_ONLINE); } } diff --git a/core/modules/user/src/EventSubscriber/MaintenanceModeSubscriber.php b/core/modules/user/src/EventSubscriber/MaintenanceModeSubscriber.php index 3c478f7b6075cdc1c5a7941f217b71c37cb02dc4..1e8d114dcff20ee53a39692f2d5abd9dcc28986a 100644 --- a/core/modules/user/src/EventSubscriber/MaintenanceModeSubscriber.php +++ b/core/modules/user/src/EventSubscriber/MaintenanceModeSubscriber.php @@ -11,6 +11,7 @@ use Symfony\Component\HttpFoundation\RedirectResponse; use Symfony\Component\HttpKernel\Event\GetResponseEvent; use Symfony\Component\HttpKernel\KernelEvents; +use Drupal\Core\EventSubscriber\MaintenanceModeSubscriber as CoreMaintenanceModeSubscriber; /** * Maintenance mode subscriber to logout users. @@ -28,7 +29,7 @@ public function onKernelRequestMaintenance(GetResponseEvent $event) { $request = $event->getRequest(); $site_status = $request->attributes->get('_maintenance'); $path = $request->attributes->get('_system_path'); - if ($site_status == MENU_SITE_OFFLINE) { + if ($site_status == CoreMaintenanceModeSubscriber::SITE_OFFLINE) { // If the site is offline, log out unprivileged users. if ($user->isAuthenticated() && !$user->hasPermission('access site in maintenance mode')) { user_logout(); @@ -46,12 +47,12 @@ public function onKernelRequestMaintenance(GetResponseEvent $event) { case 'user/login': case 'user/password': // Disable offline mode. - $request->attributes->set('_maintenance', MENU_SITE_ONLINE); + $request->attributes->set('_maintenance', CoreMaintenanceModeSubscriber::SITE_ONLINE); break; default: if (strpos($path, 'user/reset/') === 0) { // Disable offline mode. - $request->attributes->set('_maintenance', MENU_SITE_ONLINE); + $request->attributes->set('_maintenance', CoreMaintenanceModeSubscriber::SITE_ONLINE); } break; }