Overriding a service in Drupal 8

Suppose we want to override the maintenance_mode service. This service is responsible for granting and denying permission to users while the website is in maintenance mode. 

Our overriding service will do everything the original service does, but will (for some mysterious reason) also grant permission to user with uid=2 to use the site in maintenance mode.

For the sole purpose of demonstrating service overriding we only need 3 files for our module (which will be named service_override).

service_override.info.yml:

name: Service Override
core: 8.x
type: module

We need a class extending ServiceProviderBase and put it in our src folder. For the name of this class cameltoe your module's machine name and append 'ServiceProvider' to it. In our case this would make:

service_override/src/ServiceOverrideServiceProvider:

<?php
namespace Drupal\service_override;

use Drupal\Core\DependencyInjection\ServiceProviderBase;
use Drupal\Core\DependencyInjection\ContainerBuilder;

class ServiceOverrideServiceProvider extends ServiceProviderBase{
	
	public function alter(ContainerBuilder $container) {
		
		$definition = $container->getDefinition('maintenance_mode');
		$definition->setClass('Drupal\service_override\ServiceOverrideMaintenanceMode');
	}
}

In the alter() method, the only method inside the ServiceOverrideServiceProvider class, we declare the class that we'll use to override the maintenance_mode service. Let's name this class ServiceOverrideMaintenanceMode. So in our src folder we'll need to add one more file.

service_override/src/ServiceOverrideMaintenanceMode:

<?php
/**
 * @file
 * Contains Drupal\service_override\ServiceOverrideMaintenanceMode
 */
namespace Drupal\service_override;

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

class ServiceOverrideMaintenanceMode extends MaintenanceMode{

	public function __construct(StateInterface $state) {
		parent::__construct($state);
        }

	public function exempt(AccountInterface $account) {		
                // Exempt user if UID = 2
		if($account->id() == 2) {
			return TRUE;
		}
		
		return $account->hasPermission('access site in maintenance mode');		
	}
}

Download the source code from GitHub