1

I want to show a block only on a certain domain. I know I can use the domain access module for this but this looks like a to heavy module for my use case. How can a create a custom visibility tab for blocks?

I tried looking at other modules doing this but most of the time they are to complex for me to understand and filter out the right code to make it my own.

Can someone point me in the right direction? Is there a simple module I can look at to understand how this works? Or maybe a snippet of code?


Following up on the great answer of 4k4: I used the not node type module to work on my own, not perfect yet but already working for 90%.

<?php

namespace Drupal\block_visibility_conditions\Plugin\Condition;

use Drupal\Core\Condition\ConditionPluginBase;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\Core\Routing\CurrentRouteMatch;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * Provides a 'Domain Name' condition. The block will still be shown on all
 * other pages, including non-content types. This differs from the negated
 * condition "Content types", which will only be evaluated on node pages, which
 * means the block won't be shown on other pages like views.
 *
 * @Condition(
 *   id = "domain_name",
 *   label = @Translation("Domain Name")
 * )
 */
class DomainName extends ConditionPluginBase implements ContainerFactoryPluginInterface {

  /**
   * The EntityTypeManager object.
   *
   * @var \Drupal\Core\Entity\EntityTypeManagerInterface
   */
  protected $entityTypeManager;

  /**
   * The CurrentRouteMatch object.
   *
   * @var CurrentRouteMatch
   */
  protected $routeMatch;

  /**
   * Creates a new DomainName instance.
   *
   * @param array $configuration
   *   The plugin configuration, i.e. an array with configuration values keyed
   *   by configuration option name. The special key 'context' may be used to
   *   initialize the defined contexts by setting it to an array of context
   *   values keyed by context names.
   * @param string $plugin_id
   *   The plugin_id for the plugin instance.
   * @param mixed $plugin_definition
   *   The plugin implementation definition.
   * @param EntityTypeManagerInterface $entity_type_manager
   *   The entity type manager.
   * @param CurrentRouteMatch $route_match
   *   The route match.
   */
  public function __construct(array $configuration, $plugin_id, $plugin_definition, EntityTypeManagerInterface $entity_type_manager, CurrentRouteMatch $route_match) {
    parent::__construct($configuration, $plugin_id, $plugin_definition);
    $this->entityTypeManager = $entity_type_manager;
    $this->routeMatch = $route_match;
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
    return new static(
      $configuration,
      $plugin_id,
      $plugin_definition,
      $container->get('entity_type.manager'),
      $container->get('current_route_match')
    );
  }

  /**
   * {@inheritdoc}
   */
  public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
    $form = parent::buildConfigurationForm($form, $form_state);

    // Disallow negation of this condition.
    //unset($form['negate']);

    $form['domains'] = [
      '#type' => 'textarea',
      '#title' => $this->t('Domain'),
      '#rows' => 3,
      '#description' => $this->t('Add domain name without www. or https://. Separate multiple domains by a comma.'),
      '#wysiwyg' => FALSE,
      '#default_value' => implode(', ', $this->configuration['domains']),
    ];

    return $form;
  }

  /**
   * {@inheritdoc}
   */
  public function submitConfigurationForm(array &$form, FormStateInterface $form_state) {
    $domainList = explode(',',$form_state->getValue('domains'));
    $this->configuration['domains'] = array_filter($domainList);
    parent::submitConfigurationForm($form, $form_state);
  }

  /**
   * {@inheritdoc}
   */
  public function summary() {
    if (count($this->configuration['domains']) > 1) {
      $domains = $this->configuration['domains'];
      $last = array_pop($domains);
      $domains = implode(', ', $domains);
      return $this->t('The domain is @domains or @last', [
        '@domains' => $domains,
        '@last' => $last,
      ]);
    }
    $bundle = reset($this->configuration['domains']);
    return $this->t('The domain is @bundle', ['@bundle' => $bundle]);
  }

  /**
   * {@inheritdoc}
   */
  public function evaluate() {
    // Check if a setting has been set.
    if (empty($this->configuration['domains'])) {
      return TRUE;
    }

    //fetch host
    $host = \Drupal::request()->getHost();

    //if current domain is in domains array
    if($this->configuration['negate'] === false) {
      if (in_array($host, $this->configuration['domains'])) {
        return TRUE;
      }
      else {
        return FALSE;
      }
    }
    else{
      if (in_array($host, $this->configuration['domains'])) {
        return FALSE;
      }
      else {
        return TRUE;
      }
    }
  }

  /**
   * {@inheritdoc}
   */
  public function defaultConfiguration() {
    return ['domains' => []] + parent::defaultConfiguration();
  }
}
1

You need a condition plugin like RequestPath checking the host name in evaluate():

$request->getHost()

and set in getCacheContexts() a context for "per site" caching:

public function getCacheContexts() {
  $contexts = parent::getCacheContexts();
  $contexts[] = 'url.site';
  return $contexts;
}

This is a very simple module containing only one PHP file, see for example https://git.drupalcode.org/project/block_visibility_conditions/blob/8.x-1.x/src/Plugin/Condition/NotNodeType.php

  • This is great, I changed to example module to work for me. And it works...kinda. I have some additional questions. - Where do I put the cache code line? I don't have it in my code now and I seem to have some problems with the cache. - I don't understand every block in my code. Most import what do the __contruct, create and summary function do. A I added my current code to my initial question. – Joost Nov 19 '19 at 13:59
  • In getCacheContext(). You find this only in the core example, not in the contrib module. See the edited answer for the full function code. – 4k4 Nov 19 '19 at 14:37

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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