Access control handlers are used extensively throughout Drupal to control access to various parts of the system, including nodes, users, and administrative pages.
The access control handler in Drupal can be customized and extended through various modules and hooks to provide more advanced access control functionality, such as restricting access based on custom criteria, and implementing custom workflows.
In this gist, we will see how we can add our custom access control handler to the entity type 'node' and will restrict a field on the basis of our custom permission.
Let's start.
Step 1: Create mymodule.permissions.yml
Create mymodule.permissions.yml
with your custom permission in your module.
# mymodule.permissions.yml
view premium content:
title: 'View premium content'
description: 'Allow user to see premium content.'
Step 2: Implement custom access control handler class.
<?php
namespace Drupal\mymodule;
use Drupal\Core\Access\AccessResult;
use Drupal\Core\Field\FieldDefinitionInterface;
use Drupal\Core\Field\FieldItemListInterface;
use Drupal\Core\Session\AccountInterface;
use Drupal\node\NodeAccessControlHandler;
/**
* Defines the custom access control handler for the node entity type.
*/
class PremiumContentAccessControlHandler extends NodeAccessControlHandler {
/**
* {@inheritdoc}
*/
protected function checkFieldAccess(
$operation,
FieldDefinitionInterface $field_definition,
AccountInterface $account,
FieldItemListInterface $items = NULL
) {
/*
* Allow specific roles to access premium content.
*/
if ($field_definition->getName() === 'field_premium_content') {
if ($operation == 'view') {
return AccessResult::allowedIfHasPermission(
$account,
'view premium content'
);
}
}
// Run parent's checkFieldAccess.
return parent::checkFieldAccess(
$operation,
$field_definition,
$account,
$items
);
}
}
Step 3: Attach access control handler class to the entity.
Use hook_entity_type_alter to attach access control handler class to the entity.
<?php
/**
* @file mymodule.module
* Includes drupal hooks for module.
*/
use Drupal\mymodule\PremiumContentAccessControlHandler;
/**
* Implements hook_entity_type_alter().
*/
function mymodule_entity_type_alter(array &$entity_types) {
$entity_types['node']->setHandlerClass('access', PremiumContentAccessControlHandler::class);
}
That's it, By the way, if we do not have any specific or complex access control requirements, we can use the 'field_permission' module to easily restrict access to fields based on user roles or permissions.