Как я могу контролировать видимость блока с помощью кода?

11

В Drupal 6 я мог управлять видимостью блока, используя PHP-код в конфигурации пользовательского интерфейса блока, например:

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

Эти функции просматривали текущий узел, таксономию и т. Д., Чтобы решить, отображать ли блок. Эта опция PHP отсутствует в Drupal 8, но есть $visibilityполе в BlockBase. Могу ли я использовать это для программной установки видимости во время выполнения?

Nic
источник
1
Вы должны объявить пользовательский плагин условия вместо этого. Поищите в ядре @Condition, чтобы найти рабочие примеры.
Eyal
Как правило, запись кода PHP в базу данных является плохой практикой, и ее следует избегать, насколько это возможно.
Eyal
Модуль фильтра php был удален из D8. В общем, плохая идея использовать php, введенный в пользовательский интерфейс и выполненный таким образом. Это плохая идея, потому что отсутствует; может нанести вред всему сайту, и тогда меня наймут для поиска в БД, чтобы найти пропавшего; Это случилось,
Фрэнк Роберт Андерсон
Согласовано! В модуль перенесено как можно больше кода, и я рад, что могу сделать это с чистым кодом в D8!
Nic

Ответы:

15

Фрагмент рабочего кода, как использовать hook_block_access(). Здесь я получаю условие из поля текущего узла:

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();
}

Спасибо @Insasse за то, что поделились следующей жемчужиной в комментариях. Для программно созданных пользовательских блоков вы можете управлять видимостью прямо из класса блока с помощью blockAccess():

class MyBlock extends BlockBase {
  /**
   * {@inheritdoc}
   */
  public function build() {
    return [
      '#markup' => $this->t('This is a simple block!'),
    ];
  }

  /**
   * {@inheritdoc}
   */
  protected function blockAccess(AccountInterface $account) {
    return AccessResult::allowedIfHasPermission($account, 'access content');
  }

}

Источник: Как программно создать блок в Drupal 8

leymannx
источник
1
Вы могли бы даже написать проверку доступа в своем классе блока -> webwash.net/programmatics-create-block-drupal-8
Insasse
7

Отсутствие фильтра php в Drupal 8, это больше невозможно из пользовательского интерфейса.

Единственный вариант - использовать блок api.

hook_block_access - ваш лучший кандидат. Оттуда вы можете проверить $operationи вернуть AccessResult в зависимости от ваших условий.

Так же, как и в пользовательском интерфейсе, только на этот раз вставляем php в модуль.

Фрэнк Роберт Андерсон
источник
4

Вот решение Drupal 8: блок исключать страницы .

Этот модуль добавляет фильтр исключения страниц для блоков.

Чтобы исключить определенные страницы после подстановочного знака или между подстановочными знаками, просто добавьте к шаблону пути префикс «!». в настройках видимости страницы блока.

Это работает для видимости, установленной как «показывать для перечисленных страниц», в этом случае пути исключения будут скрывать блок на страницах, которые соответствуют символу подстановки, установленному для отображения.

Или наоборот, если для списка страниц установлено «скрыть для перечисленных страниц», исключенные пути будут отображать блок на страницах, где шаблон соответствует, несмотря на то, что подстановочный знак скрыт.

Block Exclude Pages screenshot

Джуал Джи
источник
3

Для 8.2.x вам нужно создать плагин условия и реализовать ContextProviderInterface .

Смотрите пример из DO, но он как-то устарел (потому что BlockEvent и BlockSubscriberBase удалены в пользу службы хранилища контекста).

Также было бы неплохо использовать консоль Drupal для генерации плагина:

drupal generate:plugin:condition
TheodorosPloumis
источник
1

чтобы расширить возможности видимости блока, вы можете попробовать этот патч:

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

он вводит оператор соединения И / ИЛИ для условий видимости, так что вы можете сказать о, я хочу, чтобы этот блок был видимым, если он имеет тип my_content_type, ИЛИ у пользователя есть роль администратора, ИЛИ URL начинается с моего / path / to / * и т.д .. также условия можно отменить, чтобы вы могли установить множество условий, при которых вы не хотите, чтобы ваш блок был видимым

также, если вы используете модуль Drupal Commerce, вы можете попробовать описанное выше, установив модуль https://www.drupal.org/project/commerce_quick_purchase, отметив, что при установке модуль предоставляет эту функциональность для всех блоков в системе, даже если вы не используйте блок, предоставленный модулем, см. подробнее

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

Кроме того, вы можете создать свой собственный плагин условия см. пример из модуля

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

друган
источник