In Drupal 6, I could control block visibility using PHP code in the block UI configuration like:

<?php return MYMODULE_abc() || MYMODULE_def() ; ?>

These functions looked up the current node, taxonomy, etc. to decide on whether to display the block. This PHP option is gone in Drupal 8, but there is a $visibility field in BlockBase. Can I use this to programmatically set the visibility at runtime?

  • 1
    You should declare a custom condition plugin instead. Search the core for @Condition to find working examples. – Eyal Jun 6 '16 at 21:13
  • Generally writing PHP code into the database is bad practice and shoulder be avoided as much as possible. – Eyal Jun 6 '16 at 21:14
  • The php filter module has been removed from D8. In general it is a bad idea to use php entered in the UI and executed in this way. It is a bad idea because missing a ; could cripple a whole site and then I will get hired to search the db to find the missing ; This has happened, – Frank Robert Anderson Jun 7 '16 at 1:22
  • Agreed! Is moved as much code as I could into the module, and glad that I can do this with pure code in D8! – Nic Jun 7 '16 at 6:22

A working code snippet on how to use hook_block_access(). Here I retrieve the condition from a field of the current node:

use Drupal\block\Entity\Block;
use Drupal\Core\Session\AccountInterface;
use Drupal\node\NodeInterface;
use Drupal\Core\Access\AccessResult;

/**
 * Implements hook_block_access().
 */
function MYMODULE_block_access(Block $block, $operation, AccountInterface $account) {

  $node = \Drupal::routeMatch()->getParameter('node');

  $hero_image_exists = FALSE;

  if ($node instanceof NodeInterface) {
    if ($node->hasField('field_hero_image')) {
      if (!$node->get('field_hero_image')->isEmpty()) {
        $hero_image_exists = TRUE;
      }
    }
  }

  if ($operation == 'view' && $block->getPluginId() == 'MYBLOCK') {
    return AccessResult::forbiddenIf($hero_image_exists == FALSE)->addCacheableDependency($block);
  }

  return AccessResult::neutral();
}

Lacking the php filter in Drupal 8, this will no longer be possible from the UI.

The only option is to use the block api.

hook_block_access is your best canidate. From there you can check the $operation and return an AccessResult based on your conditions.

Just like in the UI only this time putting the php into a module.

For 8.2.x you need to create a Condition Plugin and implement the ContextProviderInterface.

See an example from D.O. but it is somehow outdated (because BlockEvent and BlockSubscriberBase removed in favor of a context repository service).

It would nice also to use Drupal console to generate the plugin:

drupal generate:plugin:condition

to extend block visibility possibilities you can try this patch:

https://www.drupal.org/project/drupal/issues/923934#comment-12401360

it introduces the AND / OR conjunction operator for the visibility conditions so you can say oh I want this block visible if it is of my_content_type OR user has admin role OR the url starts with my/path/to/* etc.. also the conditions could be negated so you can set a lot of conditions at which you don't want your block to be visible

also if you use the Drupal Commerce module you can try the above by installing the https://www.drupal.org/project/commerce_quick_purchase module note that being installed the module exposes this functionality for all blocks on the system even if you don't use the block provided by the module see more

https://github.com/drugan/commerce_quick_purchase#block-visibility

additionally you can create your own condition plugin see example from the module

https://cgit.drupalcode.org/commerce_quick_purchase/tree/src/Plugin/Condition

Here is the Drupal 8 solution.

Module Link - https://www.drupal.org/project/block_exclude_pages

Description - Block Exclude Pages

This module adds an exclude pages filter for blocks. To exclude specific pages after the wild card or in between wildcards, simply prefix the path pattern with a prefixed '!' in the block page visibility configuration.

This works for visibility set to "show for the listed pages", in this case, the exclude paths will hide the block on pages that match the despite the wildcard set to show.

Or the other way around, if the page list is set to "hide for the listed pages" the excluded paths will show the block on pages where the pattern matches despite the wild card set to hide.

Thanks

Your Answer

 
discard

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.