Si algo bueno trajo la integración de drupal con symfony fue sin duda los eventos (Events), una nueva forma de permitir a otros módulos modificar/extender nuestras funcionalidad.

Para que os hagáis una idea de que son, los eventos, vienen a sustituir los ya antiguos «hooks» de drupal 7.

Los componentes de los Eventos.

Como ya pasaba con los hooks en d7 en esta nueva versión de drupal el core viene plagado de eventos, por no decir los que cada modulo contribuido o incluso nuestro modulo custom puede tener. y sí, si os estáis preguntando si podemos crear eventos propios, sí es posible!

Pero antes de ver como poder usarlos, vamos a tratar de entenderlos, ya que los eventos al principio son un poco complejos de entender, vamos definir las diferentes partes de este componente.

  • Event Subscriber: Es la clase donde estará toda la lógica de nuestra modificación. Hasta este momento deberia de implementar «Symfony\Component\EventDispatcher\EventSubscriberInterface«
  • Event Context: Es la clase que almacena toda la información relevante de la funcionalidad a modificar.  Hasta este momento debe extender de «Symfony\Contracts\EventDispatcher\Event»
  • Event Dispatcher: Es un objeto que nos ayudará a que este sistema funcione, nos servirá para lanzar el evento, podemos llamarlo de la siguiente forma:
    \Drupal::service(‘event_dispatcher’

Mi primer EventSubscriber

Ahora que ya hemos visto un poco de teoría, vamos a ver la práctica, para este ejemplo, primero vamos a suscribirnos a un eventos del core, luego lo complicamos más creando nuestro propio evento.

Primero añadimos nuestro EventSubscriber a nuestro archivo «mi_modulo.services.yml» (Este se encuentra en la raíz de nuestro módulo), de esta forma le diremos al symfony que aquí tenemos algo que tiene que llamar cuando alguien lance un evento.

				
					services:
  Drupal\mi_modulo\EventSubscriber\MiPropioSubscriber:
    tags:
      - { name: 'event_subscriber' }
				
			

Aunque el nombre de nuestra clase es libre, siempre que no se llame igual que otro Subscriber de otro módulo, es de buenas practicas añadir «Subscriber» al final, para definir así en el nombre que lo que vamos a encontrar aquí es un EventSubscriber.

Ahora definiremos nuestra lógica en nuestro EventSubscriber.

				
					# src/EventSubscriber/MiPropioSubscriber.php

namespace Drupal\mi_modulo\EventSubscriber;

use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;

/**
 * Class EntityTypeSubscriber.
 *
 * @package Drupal\mi_modulo\EventSubscriber
 */
class MiPropioSubscriber implements EventSubscriberInterface {

  /**
   * The current user.
   *
   * @var \Drupal\Core\Session\AccountInterface
   */
  protected $account;

  /**
   * @param \Drupal\Core\Session\AccountInterface $account
   *   The current user.
   */
  public function __construct(AccountInterface $account) {
    $this->account = $account;
  }

  /*
   * En este metodo definimos a que eventos queremos
   * subscibirnos y a donde queremos redirigirlo.
   */
  public static function getSubscribedEvents() {
    $events[KernelEvents::REQUEST][] = ['checkRedirect', 256];
    return $events;
  }
  
  public function checkRedirect(GetResponseEvent $event) {
     // La lógica de tu Subscriber.
  }

}
				
			

Si no sabéis muy bien cómo crear la estructura de archivos, os recomiendo que uséis "drupal Console" o "Drush" los cuales os crearán todo lo que necesitáis simplemente siguiendo una series de preguntas.
- drush generate service:event-subscriber (Recomendado).
- drupal generate:event:subscriber (OutOfDate).

Mi primer EventDipatcher

Bien, ya hemos visto lo fácil que es suscribirnos a un evento del core, ahora vamos a crear nuestro propio evento para que otros puedan modificar el comportamiento de nuestro código.

Para lanzar un evento, primero hemos de crear un evento y para definir nuestro evento, hemos de pensar que quiere contener, es decir, que queremos dejar que cambien otros usuarios.

				
					# src/MiPropioEvent.php

namespace Drupal\mi_modulo;
 
use Symfony\Component\EventDispatcher\Event;
 
class MiPropioEvent extends Event {
 
 const CHANGE = 'event.miPropioEvent';
 protected $elValorACambiar;
 
 public function __construct($elValorACambiar)
 {
   $this->elValorACambiar = $elValorACambiar;
 }
 
 public function getElValorACambiar()
 {
   return $this->elValorACambiar;
 }
 
 public function setElValorACambiar($cambioCustom)
 { 
   $this->elValorACambiar = $cambioCustom;
 }
 
 public function myEventDescription() {
   return "El texto ha cambiado";
 }
 
}
				
			

El contenido del «mi_modulo.services.yml» lo podemos dejar igual usaremos la clase del ejemplo anterior y lo modificaremos.

				
					# src/EventSubscriber/MiPropioSubscriber.php

namespace Drupal\mi_modulo\EventSubscriber;

use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Drupal\dn_event\MiPropioEvent;

/**
 * Class EntityTypeSubscriber.
 *
 * @package Drupal\mi_modulo\EventSubscriber
 */
class MiPropioSubscriber implements EventSubscriberInterface {

  /*
   * En este metodo definimos a que eventos queremos
   * subscibirnos y a donde queremos redirigirlo.
   */
  public static function getSubscribedEvents() {
    $events[MiPropioEvent::CHANGE][] = ['miCambioCustom', 256];
    return $events;
  }
  
  public function miCambioCustom(MiPropioEvent $event) {
     // La lógica de tu Subscriber.
     $event->setElValorACambiar = "El texto ha cambiado";
  }

}
				
			

Y ahora, que ya tenemos definido nuestro evento y nuestro subcriber, vamos a poner el EventDispatcher en nuestro código para que todo esto funcione.

				
					 // Cargamos el service dispatcher de symfony.
 $dispatcher = \Drupal::service('event_dispatcher');
 
 $texto = "Texto original";
 
 // Creamos un objeto evento de nuestra clase evento que hemos
 // creado previamente.
 $event = new MiPropioEvent($texto);
 
 // Lanzamos el evento con el metodo "dispatch",
 // Le pasamos el nombre del evento y el objeto como parametro.
 $dispatcher->dispatch(MiPropioEvent::CHANGE, $event);
 
 $texto = $event->getElValorACambiar();
 
 \Drupal::messenger()->addMessage($texto);
				
			

Como podéis ver, si yo ejecutase todo el código lo que veríamos es, que si tengo activado el módulo «mi_modulo», el valor del texto que inicialmente seria «Texto original» sería reemplazado por el texto de nuestro subscriber y veríamos el siguiente mensaje «El texto ha cambiado».

Conclusión

Si habeis llegado hasta aquí probablemente hayais entendido un poco mejor el tema de los eventos y los subscribers, la verdad que al principio se hace un poco tedioso y parece muy complicado y rebuscado, pero una vez entendeis como funciona, os preguntareis como habéis podido vivir sin el.

En términos generales, el EventSubscriber va muy para cambiar ciertos comportamientos de nuestro drupal, aunque tambien podrias usarlos simplemente para añadir más funcionalidad al original.

El uso de este sistema es infinito y yo os recomiendo que si desarrollais módulos custom permitáis que otros módulos puedan extender la funcionalidad de vuestro código y que la puedan modificar de este modo (incluso si sois vosotros mismos a vuestro mismo codigo), podréis tener un código base y otro que lo modifique, haciendo que si en un futuro esta nueva modificación deja de ser necesaria, con desinstalar el módulo ya sería suficiente.

Contadme vuestra experiencia en los comentarios!