How to Override Entity Access Handlers in Drupal
In this second part of our series on Mastering Entity Access, we present a scenario in which overriding the entity access handler proved to be the optimal solution for a client requirement that we override the menu set on Block Layout settings at the node level. In the process we gained valuable information information on entity access challenges.
By default depending on the market (country-language pair), we set a certain menu in the Block Layout settings. For example, on gb-en, we set menu A, but on ph-en we place menu B. A challenge arises when the client wants to be able to override those settings on a per node basis as needed.
Screen showing node edit form with menu type option
Our initial thought is to use,
hook_block_access, however on its own, this would not work because once a deny is issued on the Block Layout settings (see Caveat item 1 on Part 1: How to Master Entity Access in Drupal), any allow on
hook_block_access would not matter anymore.
Our solution is to override the access handler for the Block entity.
Overriding the access handler for the Block entity
1. Check the default access handler and the implementing class.
Screen showing block entity annotation
The image above shows
Drupal\block\Entity\Block.php entity annotation. We can override the access handler defined here to customize to our own use case.
2. Extend and implement your custom access handler
Screen showing implementation override on BlockAccessControlHandler
Drupal\block\BlockAccessControlHandler and override
checkAccess() method. You can inject your custom access control logic inside this method.
In our use case, we check first if we are looking at a node page and check if
field_masthead_type was set to override anything. If it does, then we provide access to certain blocks. Otherwise, we delegate the decision back to
parent::checkAccess() which respects the default Block Layout settings.
3. Replace the handler in your custom module.
Once we created the implementing class, we need to inform Drupal about this change by using
hook_entity_type_build as shown.
With these 3 steps, we are able to implement the client requirement. Don’t forget flush caches.
Screen showing how to override the access handler for the block entity
Diving deeper on Entity Access
Almost all entity access handlers, including Blocks and Nodes, extend
BlockAccessControlHandler is the handler for blocks and
NodeAccessControlHandler for nodes, both extend
As you can see from the image below,
EntityAccessControlHandler access() method will first invoke
hook_ENTITY_TYPE_access and then call on
checkAccess method is where most entity access control handlers implement their custom logic and is overridden. For blocks, this is where the Block Layout settings access are calculated.
EntityAccessControlHandler and only overriding
checkAccess, most entity access control handlers will still respect
Dependency injection and Object Oriented Programming rocks!
Screen showing the EntityAccessControlHandler Implementation
Solving complex Drupal development challenges for our clients is what we do best at Promet Source. What can we do for you?