logo

Extra Block Types (EBT) - Nieuwe Layout Builder ervaring❗

Extra Block Types (EBT) - gestileerde, aanpasbare bloktypes: Slideshows, Tabs, Cards, Accordions en vele andere. Ingebouwde instellingen voor achtergrond, DOM Box, javascript-plugins. Ervaar vandaag al de toekomst van layout building.

Demo EBT-modules Download EBT-modules

❗Extra Paragraph Types (EPT) - Nieuwe Paragraphs ervaring

Extra Paragraph Types (EPT) - analoge op paragrafen gebaseerde set modules.

Demo EPT-modules Download EPT-modules

Scroll

Beperk toegang tot Taxonomy-termenvocabularium met behulp van een Event Subscriber

02/09/2025, by Ivan

Menu

Soms heb je vaste, permanente categorieën nodig op de site die niet per ongeluk gewijzigd mogen worden. In dit geval kun je gebruikmaken van aangepaste code met een Event Subscriber.

Laten we een nieuwe Event Subscriber-klasse toevoegen in een aangepaste module.

drupalbook_custom.services.yml

services:  
  drupalbook_custom.tag_redirect_subscriber:
    class: Drupal\drupalbook_custom\EventSubscriber\TagRedirectSubscriber
    arguments:
      - '@entity_type.manager'
      - '@current_user'
    tags:
      - { name: event_subscriber }

En voeg onze Event Subscriber toe in drupalbook_custom/src/EventSubscriber/TagRedirectSubscriber:

<?php

namespace Drupal\drupalbook_custom\EventSubscriber;

use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Routing\TrustedRedirectResponse;
use Drupal\Core\Session\AccountProxyInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\Event\RequestEvent;
use Symfony\Component\HttpKernel\KernelEvents;

/**
 * Verwijst niet-beheerders door vanaf de adminpagina’s van de tag-vocabulaire.
 *
 * Een subscriber op request-niveau wordt vroeg uitgevoerd, waardoor we het
 * verzoek kunnen onderbreken en een redirectresponse kunnen retourneren voordat
 * de bijbehorende controller wordt uitgevoerd.
 */
class TagRedirectSubscriber implements EventSubscriberInterface {

  /**
   * De entity type manager service.
   *
   * Wordt als voorbeelddependency behouden; niet strikt nodig voor de huidige
   * logica, maar handig voor toekomstige uitbreidingen.
   *
   * @var \Drupal\Core\Entity\EntityTypeManagerInterface
   */
  protected EntityTypeManagerInterface $entityTypeManager;

  /**
   * De huidige gebruiker (proxy service).
   *
   * Wordt gebruikt om snel gebruikersrollen te controleren om beheerders
   * toegang te geven.
   *
   * @var \Drupal\Core\Session\AccountProxyInterface
   */
  protected AccountProxyInterface $currentUser;

  /**
   * Constructor voor de subscriber.
   */
  public function __construct(
    EntityTypeManagerInterface $entity_type_manager,
    AccountProxyInterface $current_user,
  ) {
    $this->entityTypeManager = $entity_type_manager;
    $this->currentUser = $current_user;
  }

  /**
   * {@inheritdoc}
   */
  public static function getSubscribedEvents(): array {
    // Prioriteit 32 zorgt ervoor dat routering is voltooid,
    // maar de controller nog niet is uitgevoerd.
    return [
      KernelEvents::REQUEST => ['onKernelRequest', 32],
    ];
  }

  /**
   * Voert de redirect uit voor niet-beheerders die tag-adminroutes bezoeken.
   */
  public function onKernelRequest(RequestEvent $event): void {
    if (!$event->isMainRequest()) {
      return;
    }

    if ($this->currentUser->hasRole('administrator')) {
      return;
    }

    $request = $event->getRequest();
    $route_name = $request->attributes->get('_route');

    $redirect_to = 'https://drupalbook.org/admin/structure'
      . '/taxonomy/manage/tag/overview';

    switch ($route_name) {
      case 'entity.taxonomy_vocabulary.overview_form':
      case 'entity.taxonomy_vocabulary.overview_terms':
      case 'entity.taxonomy_term.add_form':
        $vocabulary = $request->attributes->get('taxonomy_vocabulary');
        if (!empty($vocabulary) && $vocabulary->id() === 'tag') {
          $event->setResponse(new TrustedRedirectResponse($redirect_to));
        }
        return;

      case 'entity.taxonomy_term.edit_form':
      case 'entity.taxonomy_term.delete_form':
        /** @var \Drupal\taxonomy\Entity\Term|null $term */
        $term = $request->attributes->get('taxonomy_term');
        if ($term && $term->bundle() === 'tag') {
          $event->setResponse(new TrustedRedirectResponse($redirect_to));
        }
        return;

      default:
        return;
    }
  }

}

De klasse TagRedirectSubscriber is een aangepaste Event Subscriber in Drupal, bedoeld om toegang tot de beheerpagina's van een specifieke taxonomy-vocabulaire (in dit geval "tag") te beperken voor niet-beheerders. Hieronder een overzicht van de structuur en belangrijke kenmerken van de code:

1. Doel en gebruikssituatie

  • Doel: Voorkom ongewenste of per ongeluk aangebrachte wijzigingen aan de "tag"-vocabulaire door niet-beheerders door te verwijzen van adminroutes.
  • Voordeel: Biedt een extra laag UI-/UX-gebaseerde toegangscontrole voor kritieke taxonomieën, en waarborgt stabiliteit voor vaste categorieën.

2. Klassenstructuur en dependencies

  • De klasse implementeert EventSubscriberInterface, en maakt zo gebruik van het event-systeem van Symfony dat Drupal hanteert.
  • Injectie van dependencies via de constructor:
    • EntityTypeManagerInterface: Voor toekomstige uitbreidingen zoals het laden van entiteiten.
    • AccountProxyInterface: Voor het efficiënt controleren van gebruikersrollen.
    Dependency injection maakt de subscriber testbaar, herbruikbaar en conform aan de best practices van de service container.

3. Subscribed events

  • De subscriber luistert naar KernelEvents::REQUEST met prioriteit 32.
    • Routering is reeds uitgevoerd (routeparameters zijn beschikbaar).
    • De controller is nog niet gestart, waardoor de subscriber kan ingrijpen.

4. Redirectlogica

  • De methode onKernelRequest() voert de toegangscontrole en redirect uit:
    • Alleen hoofdverzoeken: Vermijdt dubbele verwerking bij subverzoeken.
    • Beheerders worden doorgelaten: Gebruikers met de rol administrator worden niet omgeleid.
    • Routecontrole: Alleen specifieke routes met betrekking tot de vocabulaire of termen worden gecontroleerd.
    • Redirect van niet-beheerders:
      • Bijv. entity.taxonomy_vocabulary.overview_form, entity.taxonomy_term.add_form worden gecontroleerd op vocabulaire tag.
      • Voor edit en delete-routes wordt het vocabulaire gecontroleerd via $term->bundle().
    • Vertrouwde redirect: Gebruikers worden veilig doorgestuurd naar het overzicht van "tag".
  • Uitbreidbaarheid: Makkelijk aan te passen voor meerdere vocabularia of andere rollen.

5. Beveiliging en best practices

  • Vroege interceptie: Voorkomt dat gevoelige routes worden uitgevoerd door vroeg in het verzoek in te grijpen.
  • Rolgebaseerde uitzonderingen: Alleen niet-beheerders worden geblokkeerd.
  • Duidelijke verantwoordelijkheden: Routing, gebruikerscontrole en redirect zijn gescheiden voor onderhoudbaarheid.

6. Mogelijke uitbreidingen

  • Gebruikmaken van EntityTypeManagerInterface om toegang te beperken op basis van specifieke termkenmerken.
  • Algemenere implementatie met ondersteuning voor meerdere vocabularia en configureerbare redirects via instellingen.

7. Belangrijkste inzichten

  • Deze Event Subscriber toont een praktische aanpak voor toegangscontrole in Drupal met behulp van Symfony’s event-architectuur.
  • Ideaal om taxonomy-vocabularia te beschermen die alleen door vertrouwde gebruikers beheerd mogen worden.