Question

I am trying to make certain routes exempt from maintenance mode by adding the option _maintenance_access to the route and setting it to TRUE.

I think (although I'm not 100%) that this works because in Drupal\Core\Site\MaintenanceMode there is the following method which checks for the _maintenance_access option and returns false if it is present -

public function applies(RouteMatchInterface $route_match) {
  if (!$this->state->get('system.maintenance_mode')) {
    return FALSE;
  }

  if ($route = $route_match->getRouteObject()) {
    if ($route->getOption('_maintenance_access')) {
      return FALSE;
    }
  }

  return TRUE;
}

I have followed this guide on drupal.org on how to alter existing routes

Here is my mymodule.services.yml file

services:
  mymodule.route_subscriber:
    class: Drupal\mymodule\Routing\MaintenanceModeRouteSubscriber
    tags:
      - { name: event_subscriber }

Here is my MaintenanceModeRouteSubscriber class

<?php

namespace Drupal\mymodule\Routing;

use Drupal\Core\Routing\RouteSubscriberBase;
use Symfony\Component\Routing\RouteCollection;

class MaintenanceModeRouteSubscriber extends RouteSubscriberBase {

  /**
   * {@inheritdoc}
   */
  protected function alterRoutes(RouteCollection $collection) {
    if ($route = $collection->get('entity.node.canonical')) {
      $route->addOptions(['_maintenance_access' => TRUE]);
    }
  }
}

But this is not working as when viewing this route (any node) it is still in maintenance mode.

Was it helpful?

Solution

You need to override the service directly.

mymodule.services.yml

services:
  maintenance_mode: # same ID as declared in core.services.yml
    class: Drupal\mymodule\Services\CustomMaintenanceMode # point to your class
    arguments: ['@state']

mymodule/src/Services/CustomMaintenaceMode.php

<?php

namespace Drupal\mymodule\Services;

use Drupal\Core\Session\AccountInterface;
use Drupal\Core\Site\MaintenanceMode;

class CustomMaintenanceMode extends MaintenanceMode {

  /**
   * {@inheritdoc}
   */
  public function exempt(AccountInterface $account) {
    $node = \Drupal::routeMatch()->getParameter('node');
    if ($node instanceof \Drupal\node\NodeInterface && $node->getType() == 'article') {
      return TRUE;
    }
    else {
      return $account->hasPermission('access site in maintenance mode');
    }
  }

}
Licensed under: CC-BY-SA with attribution
Not affiliated with drupal.stackexchange
scroll top