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.
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.
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
Extend the 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 BlockAccessControlHandler via 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.
Diving deeper on Entity Access
Drupal\Core\Entity\EntityAccessControlHandler
Almost all entity access handlers, including Blocks and Nodes, extend EntityAccessControlHandler. BlockAccessControlHandler is the handler for blocks and NodeAccessControlHandler for nodes, both extend EntityAccessControlHandler.
As you can see from the image below, EntityAccessControlHandler access() method will first invoke hook_entity_access and hook_ENTITY_TYPE_access and then call on checkAccess(). The 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.
By extending EntityAccessControlHandler and only overriding checkAccess, most entity access control handlers will still respect hook_entity_access checks.
Dependency injection and Object Oriented Programming rocks!
Solving complex Drupal development challenges for our clients is what we do best at Promet Source. What can we do for you?
Other Insights & Resources you may like
Get our newsletter
Get weekly Drupal and AI technology advancement news, pro tips, ideas, insights, and more.
