Events: The Object Oriented
Hook System
Nida Ismail Shah
Developer at
d.o & twitter: @nidaismailshah
Acquia
nidashah.com/blog
Gulmarg, Kashmir
Overview
Kolahoi Peak, Kashmir
Overview
The Symfony Event Dispatcher component.
Installation and usage
Creating and dispatching an event
Subscribing/Listening to events
Events in Drupal 8
Creating Events.
Subscribing to Events
Intent/Purpose
Dal Lake, Kashmir
“ The idea is to be able to run random code at given places in the
engine. This random code should then be able to do whatever needed to
enhance the functionality. The places where code can be executed are
called “hooks” and are defined by a fixed interface.
~ Dries Buytaert.
“ The Event Dispatcher component provides
tools that allow your application components to
communicate with each other by dispatching
events and listening to them.
“ an event is an action or an occurrence
recognised by software that may be handled
by software.
event?
Extensibility
Modularity
Maintainability
Developer Experience
Background Tulian Lake,
Pahalgam, Kashmir
Extensibility
Hooks
Plugins
Mulitple instances
Admin forms
Configuration
Tagged Services
Simple Extensions
Events
Alter something?
React to something?
Symfony Event Dispatcher
Component
Installation and usage
Installing the symfony event
dispatcher component
Text
Text
Use the official Git repository
( )https://github.com/symfony/event-dispatcher
composer require symfony/event-dispatcher
Using version ^3.2 for symfony/event-dispatcher
./composer.json has been created
Loading composer repositories with package information
Updating dependencies (including require-dev)
- Installing symfony/event-dispatcher (v3.2.6)
Loading from cache
symfony/event-dispatcher suggests installing symfony/dependency-injection ()
symfony/event-dispatcher suggests installing symfony/http-kernel ()
Writing lock file
Generating autoload files
Using the symfony event dispatcher
component
1. Event - representing the event or the state of the application.
2. Dispatcher - to notify the subscribers or listeners about the occurrence of the
event.
3. Subscriber/Listener - to extend the application once the event has occurred.
Pub-Sub pattern
The pub sub exemplifies the
proper decoupling of
components of an application.
Publishers publish the messages
into classes without knowledge
of which subscribers would be
interested in the message.
Subscribers express interest in
one or more classes and only
receive messages that are of
interest, without knowledge of
which publishers.
Mediator pattern
Define an object that
encapsulates how a set of
objects interact.
Mediator promotes loose
coupling by keeping objects
from referring to each other
explicitly, and it lets you vary
their interaction independently.
Design an intermediary to
decouple many peers.
Workflow
Workflow
A listener (PHP object) tells a central dispatcher object that it wants to listen to
the 'xyz' event
At some point, Symfony tells the dispatcher object to dispatch the 'xyz' event,
passing with it an Event object that has access to the Object defining the state
of the application at that point.
The dispatcher notifies (i.e. calls a method on) all listeners of the 'xyz' event,
allowing each of them to make modifications to the State object.
Components
The dispatcher object
The Event object
The subscriber/listener
the dispatcher
// create an EventDispatcher instance.

$dispatcher = new EventDispatcher();


// the order is somehow created or retrieved
// contains the state of our application
// or the information we want expose.

$order = new Order();

// ...


// create the OrderPlacedEvent and dispatch it

$event = new OrderPlacedEvent($order);


// dispatch the event.

$dispatcher->dispatch(OrderPlacedEvent::NAME, $event);

// or $dispatcher->dispatch('order.placed', $event);
the event


/**

* The order.placed event is dispatched each time an order is created

* in the system.

*/

class OrderPlacedEvent extends Event {



const NAME = 'order.placed';


protected $order;


public function __construct(Order $order) {

$this->order = $order;

}


public function getOrder() {

return $this->order;

}

}
the base event
/**
* Event is the base class for classes containing event data.
* This class contains no event data. It is used by events that do not pass
* state information to an event handler when an event is raised.
*/
class Event
{
/**
* @var bool Whether no further event listeners should be triggered
*/
private $propagationStopped = false;
/**
* Returns whether further event listeners should be triggered.
*/
public function isPropagationStopped()
{
return $this->propagationStopped;
}
/**
* Stops the propagation of the event to further event listeners.
*/
public function stopPropagation()
{
$this->propagationStopped = true;
}
}
“ The base Event class provided by the Event
Dispatcher component is deliberately sparse to
allow the creation of API specific event objects by
inheritance using OOP. This allows for elegant and
readable code in complex applications.
the subscriber
class StoreSubscriber implements EventSubscriberInterface
 {

public static function getSubscribedEvents()
 {

return array(

KernelEvents::RESPONSE => array(

array('onKernelResponsePre', 10),

array('onKernelResponsePost', -10),

),

OrderPlacedEvent::NAME => 'onStoreOrder',

);

}


public function onKernelResponsePre(FilterResponseEvent $event)
 {
// do something.


}


public function onKernelResponsePost(FilterResponseEvent $event)
 {
// do something.


}




 public function onStoreOrder(OrderPlacedEvent $event)
 {
// do something.


}



}
the listener
class AcmeListener
 {

// ...


public function onFooAction(Event $event)
 {

// ... do something

}

}
// This is very similar to a subscriber class,
// except that the class itself cant tell the dispatcher which events it should listen to.
register listener/subscriber
// create an EventDispatcher instance.

$dispatcher = new EventDispatcher();


$subscriber = new StoreSubscriber();

// Register subscriber

$dispatcher->addSubscriber($subscriber);


// add a listener

$listener = new AcmeListener();

$dispatcher->addListener('acme.foo.action', array($listener, 'onFooAction'));


// create the OrderPlacedEvent and dispatch it

$event = new OrderPlacedEvent($order);


// dispatch the event.

$dispatcher->dispatch(OrderPlacedEvent::NAME, $event);

// or $dispatcher->dispatch(order.placed, $event);
other ways to register
# app/config/services.yml
services:
kernel.listener.your_listener_name:
class: AppBundleEventListenerAcmeExceptionListener
tags:
- { name: kernel.event_listener, event: kernel.exception, method:
onKernelException }
With the use of ContainerAwareEventDispatcher and dependency
injection:
Use the to tag services as event
listeners/subscribers.
Define event subscriber/listener as a service.
Tag them as kernel.event_listener or kernel.event_subscriber.
RegisterListenersPass
subscriber vs listener
Event listeners and Subscribers serve the same purpose and can be used in
an application indistinctly.
Event listeners can be added via service definition and also with
addListener()method.
Event subscribers are added via service definition and by implementing the
getSubscribedEvents() method and also with addSubscriber() method.
Event subscribers are easier to use and reuse.
Event listener is registered specifying the events on which it listens. The
subscriber has a method telling the dispatcher what events it is listening to.
More here: http://nidashah.com/drupal/events-and-listeners.html
more dispatchers
ContainerAwareEventDispatcher
Use services within your events, and subscribers as services
TraceableEventDispatcher
wraps any other event dispatcher and can then be used to determine
which event listeners have been called by the dispatcher
ImmutableEventDispatcher
is a locked or frozen event dispatcher. The dispatcher cannot register
new listeners or subscribers.
ContainerAwareEventDispatcher
The ContainerAwareEventDispatcher is a special Event Dispatcher
implementation which is coupled to the service container that is part of the
DependencyInjection component.
It allows services to be specified as event listeners making the
EventDispatcher extremely powerful.
Services are lazy loaded meaning the services attached as listeners will only
be created if an event is dispatched that requires those listeners.
ContainerAwareEventDispatcher
use SymfonyComponentDependencyInjectionContainerBuilder;
use SymfonyComponentEventDispatcherContainerAwareEventDispatcher;
$container = new ContainerBuilder();
$dispatcher = new ContainerAwareEventDispatcher($container);
// Add the listener and subscriber services
$dispatcher->addListenerService($eventName, array('foo', 'logListener'));
$dispatcher->addSubscriberService(
'kernel.store_subscriber',
'StoreSubscriber'
);
TraceableEventDispatcher
The TraceableEventDispatcher is an event dispatcher that wraps any other
event dispatcher and can then be used to determine which event listeners have
been called by the dispatcher.
// the event dispatcher to debug
$eventDispatcher = ...;
$traceableEventDispatcher = new TraceableEventDispatcher( $eventDispatcher, new Stopwatch()
);
$traceableEventDispatcher->addListener(
'event.the_name',
$eventListener,
$priority
);
// dispatch an event
$traceableEventDispatcher->dispatch('event.the_name', $event);
$calledListeners = $traceableEventDispatcher->getCalledListeners();
$notCalledListeners = $traceableEventDispatcher->getNotCalledListeners();
ImmutableEventDispatcher
The ImmutableEventDispatcher is a locked or frozen event dispatcher. The
dispatcher cannot register new listeners or subscribers.
The ImmutableEventDispatcher takes another event dispatcher with all the
listeners and subscribers. The immutable dispatcher is just a proxy of this
original dispatcher.
Using it
first create a normal dispatcher (EventDispatcher or
ContainerAwareEventDispatcher) and register some listeners or
subscribers
Now, inject that into an ImmutableEventDispatcher
ImmutableEventDispatcher
use SymfonyComponentEventDispatcherEventDispatcher;
use SymfonyComponentEventDispatcherImmutableEventDispatcher;
$dispatcher = new EventDispatcher();
$dispatcher->addListener('foo.action', function ($event) {
// ...
});
// ...
// ...
$immutableDispatcher = new ImmutableEventDispatcher($dispatcher);
Events in Drupal 8
Events are part of the Symfony framework: they allow for different
components of the system to interact and communicate with each
other.
Object oriented way of interaction with core and other modules.
Mediator Pattern
Container Aware dispatcher
Will probably replace hooks in future drupal versions.
Since Drupal is using ContainerAwareEventDispatcher, we always
have the dispatcher object available as a service.
Consequently, Drupal supports the service definition way of adding
event subscribers.
Service definition way of adding event listeners is not supported.
something to note
1. Get the dispatcher object from the service container.
2. Create the event.
3. Dispatch the event.
4. Define a service tagged with event_subscriber in services.yml.
5. Implement the EventSubscriberInterface to write getSubscribedEvents()
method to return what events you want to subscribe to.
Workflow in Drupal
event subscriber class
class ConfigFactory implements ConfigFactoryInterface, EventSubscriberInterface {

static function getSubscribedEvents() {

$events[ConfigEvents::SAVE][] = array('onConfigSave', 255);

$events[ConfigEvents::DELETE][] = array('onConfigDelete', 255);

return $events;

}
}
// services.yml
config.factory:

class: DrupalCoreConfigConfigFactory

tags:

- { name: event_subscriber }

- { name: service_collector, tag: 'config.factory.override', call: addOverride }

arguments: ['@config.storage', '@event_dispatcher', ‘@config.typed']
services:

event_demo.alter_response:

class: Drupalevent_demoEventSubscriberAlterResponse

arguments: [ '@logger.factory' ]

tags:

- { name: event_subscriber }
dispatching the event
$dispatcher = Drupal::service('event_dispatcher');


// or inject as a dependency
$event = new EventDemo($config);


$event = $dispatcher->dispatch(EVENT_NAME, $event);
core registering event subscribers
namespace DrupalCoreDependencyInjectionCompiler;
use SymfonyComponentDependencyInjectionContainerBuilder;
use SymfonyComponentDependencyInjectionCompilerCompilerPassInterface;
/**
* Registers all event subscribers to the event dispatcher.
*/
class RegisterEventSubscribersPass implements CompilerPassInterface {
/**
* {@inheritdoc}
*/
public function process(ContainerBuilder $container) {
if (!$container->hasDefinition('event_dispatcher')) {
return;
}
$definition = $container->getDefinition('event_dispatcher');
$event_subscriber_info = [];
foreach ($container->findTaggedServiceIds('event_subscriber') as $id => $attributes) {
// We must assume that the class value has been correctly filled, even if
// the service is created by a factory.
$class = $container->getDefinition($id)->getClass();
$refClass = new ReflectionClass($class);
$interface = 'SymfonyComponentEventDispatcherEventSubscriberInterface';
if (!$refClass->implementsInterface($interface)) {
throw new InvalidArgumentException(sprintf('Service "%s" must implement interface "%s".', $id, $interface));
}
// Get all subscribed events.
foreach ($class::getSubscribedEvents() as $event_name => $params) {
if (is_string($params)) {
$priority = 0;
KernelEvents::CONTROLLER, EXCEPTION, REQUEST, RESPONSE,
TERMINATE, VIEW
ConfigEvents::DELETE, IMPORT, SAVE, RENAME ...
EntityTypeEvents::CREATE, UPDATE, DELETE
FieldStorageDefinitionEvents::CREATE, UPDATE, DELETE
ConsoleEvents::COMMAND, EXCEPTION, TERMINATE
MigrateEvents:: MAP_DELETE, MAP_SAVE, POST_IMPORT,
POST_ROLLBACK, POST_ROW_DELETE, POST_ROW_SAVE,
RoutingEvents::ALTER, DYNAMIC, FINISHED
Events in Drupal 8 core
path forward
Writing your own module?
trigger an Event for everything.
Interacting with or alter core?
subscribe to an event (if one is fired).
Hooks … you don't have too many options.
Configuration, Admin forms?
Plugins
Simple Extensions
Tagged services
summary
demo
Questions?
Hazratbal, Kashmir
Join Us for Contribution Sprints
Friday, April 28, 2017
First-Time Sprinter
Workshop
9:00am-12:00pm
Room: 307-308
Mentored Core Sprint
9:00am-12:00pm
Room:301-303
General Sprints
9:00am-6:00pm
Room:309-310
#drupalsprints
WHAT DID
YOU THINK?
Locate this session at the DrupalCon
Baltimore website:
Take the survey!
https://www.surveymonkey.com/r/dr
upalconbaltimore
http://baltimore2017.drupal.org/schedule
THANK YOU!
email: nida@nidashah.com
twitter: @nidaismailshah

Events: The Object Oriented Hook System.

  • 1.
    Events: The ObjectOriented Hook System
  • 2.
    Nida Ismail Shah Developerat d.o & twitter: @nidaismailshah Acquia nidashah.com/blog Gulmarg, Kashmir
  • 3.
  • 4.
    Overview The Symfony EventDispatcher component. Installation and usage Creating and dispatching an event Subscribing/Listening to events Events in Drupal 8 Creating Events. Subscribing to Events
  • 5.
  • 6.
    “ The ideais to be able to run random code at given places in the engine. This random code should then be able to do whatever needed to enhance the functionality. The places where code can be executed are called “hooks” and are defined by a fixed interface. ~ Dries Buytaert.
  • 7.
    “ The EventDispatcher component provides tools that allow your application components to communicate with each other by dispatching events and listening to them.
  • 8.
    “ an eventis an action or an occurrence recognised by software that may be handled by software. event?
  • 9.
  • 10.
  • 11.
    Extensibility Hooks Plugins Mulitple instances Admin forms Configuration TaggedServices Simple Extensions Events Alter something? React to something?
  • 12.
  • 13.
    Installing the symfonyevent dispatcher component Text Text Use the official Git repository ( )https://github.com/symfony/event-dispatcher composer require symfony/event-dispatcher Using version ^3.2 for symfony/event-dispatcher ./composer.json has been created Loading composer repositories with package information Updating dependencies (including require-dev) - Installing symfony/event-dispatcher (v3.2.6) Loading from cache symfony/event-dispatcher suggests installing symfony/dependency-injection () symfony/event-dispatcher suggests installing symfony/http-kernel () Writing lock file Generating autoload files
  • 14.
    Using the symfonyevent dispatcher component 1. Event - representing the event or the state of the application. 2. Dispatcher - to notify the subscribers or listeners about the occurrence of the event. 3. Subscriber/Listener - to extend the application once the event has occurred.
  • 15.
    Pub-Sub pattern The pubsub exemplifies the proper decoupling of components of an application. Publishers publish the messages into classes without knowledge of which subscribers would be interested in the message. Subscribers express interest in one or more classes and only receive messages that are of interest, without knowledge of which publishers. Mediator pattern Define an object that encapsulates how a set of objects interact. Mediator promotes loose coupling by keeping objects from referring to each other explicitly, and it lets you vary their interaction independently. Design an intermediary to decouple many peers.
  • 16.
  • 17.
    Workflow A listener (PHPobject) tells a central dispatcher object that it wants to listen to the 'xyz' event At some point, Symfony tells the dispatcher object to dispatch the 'xyz' event, passing with it an Event object that has access to the Object defining the state of the application at that point. The dispatcher notifies (i.e. calls a method on) all listeners of the 'xyz' event, allowing each of them to make modifications to the State object.
  • 18.
    Components The dispatcher object TheEvent object The subscriber/listener
  • 19.
    the dispatcher // createan EventDispatcher instance.
 $dispatcher = new EventDispatcher();

 // the order is somehow created or retrieved // contains the state of our application // or the information we want expose. 
$order = new Order(); 
// ...

 // create the OrderPlacedEvent and dispatch it
 $event = new OrderPlacedEvent($order);

 // dispatch the event.
 $dispatcher->dispatch(OrderPlacedEvent::NAME, $event);
 // or $dispatcher->dispatch('order.placed', $event);
  • 20.
    the event 

/**
 * Theorder.placed event is dispatched each time an order is created
 * in the system. 
*/ 
class OrderPlacedEvent extends Event { 

 const NAME = 'order.placed';

 protected $order;

 public function __construct(Order $order) {
 $this->order = $order;
 }

 public function getOrder() {
 return $this->order;
 } 
}
  • 21.
    the base event /** *Event is the base class for classes containing event data. * This class contains no event data. It is used by events that do not pass * state information to an event handler when an event is raised. */ class Event { /** * @var bool Whether no further event listeners should be triggered */ private $propagationStopped = false; /** * Returns whether further event listeners should be triggered. */ public function isPropagationStopped() { return $this->propagationStopped; } /** * Stops the propagation of the event to further event listeners. */ public function stopPropagation() { $this->propagationStopped = true; } }
  • 22.
    “ The baseEvent class provided by the Event Dispatcher component is deliberately sparse to allow the creation of API specific event objects by inheritance using OOP. This allows for elegant and readable code in complex applications.
  • 23.
    the subscriber class StoreSubscriberimplements EventSubscriberInterface
 {
 public static function getSubscribedEvents()
 {
 return array(
 KernelEvents::RESPONSE => array(
 array('onKernelResponsePre', 10),
 array('onKernelResponsePost', -10),
 ),
 OrderPlacedEvent::NAME => 'onStoreOrder',
 );
 }

 public function onKernelResponsePre(FilterResponseEvent $event)
 { // do something. 
 }

 public function onKernelResponsePost(FilterResponseEvent $event)
 { // do something. 
 }

 

 public function onStoreOrder(OrderPlacedEvent $event)
 { // do something. 
 }

 
}
  • 24.
    the listener class AcmeListener
{
 // ...

 public function onFooAction(Event $event)
 {
 // ... do something
 } 
} // This is very similar to a subscriber class, // except that the class itself cant tell the dispatcher which events it should listen to.
  • 25.
    register listener/subscriber // createan EventDispatcher instance.
 $dispatcher = new EventDispatcher(); 

$subscriber = new StoreSubscriber(); 
// Register subscriber
 $dispatcher->addSubscriber($subscriber);

 // add a listener
 $listener = new AcmeListener();
 $dispatcher->addListener('acme.foo.action', array($listener, 'onFooAction'));

 // create the OrderPlacedEvent and dispatch it
 $event = new OrderPlacedEvent($order);

 // dispatch the event. 
$dispatcher->dispatch(OrderPlacedEvent::NAME, $event); 
// or $dispatcher->dispatch(order.placed, $event);
  • 26.
    other ways toregister # app/config/services.yml services: kernel.listener.your_listener_name: class: AppBundleEventListenerAcmeExceptionListener tags: - { name: kernel.event_listener, event: kernel.exception, method: onKernelException } With the use of ContainerAwareEventDispatcher and dependency injection: Use the to tag services as event listeners/subscribers. Define event subscriber/listener as a service. Tag them as kernel.event_listener or kernel.event_subscriber. RegisterListenersPass
  • 27.
    subscriber vs listener Eventlisteners and Subscribers serve the same purpose and can be used in an application indistinctly. Event listeners can be added via service definition and also with addListener()method. Event subscribers are added via service definition and by implementing the getSubscribedEvents() method and also with addSubscriber() method. Event subscribers are easier to use and reuse. Event listener is registered specifying the events on which it listens. The subscriber has a method telling the dispatcher what events it is listening to. More here: http://nidashah.com/drupal/events-and-listeners.html
  • 28.
    more dispatchers ContainerAwareEventDispatcher Use serviceswithin your events, and subscribers as services TraceableEventDispatcher wraps any other event dispatcher and can then be used to determine which event listeners have been called by the dispatcher ImmutableEventDispatcher is a locked or frozen event dispatcher. The dispatcher cannot register new listeners or subscribers.
  • 29.
    ContainerAwareEventDispatcher The ContainerAwareEventDispatcher isa special Event Dispatcher implementation which is coupled to the service container that is part of the DependencyInjection component. It allows services to be specified as event listeners making the EventDispatcher extremely powerful. Services are lazy loaded meaning the services attached as listeners will only be created if an event is dispatched that requires those listeners.
  • 30.
    ContainerAwareEventDispatcher use SymfonyComponentDependencyInjectionContainerBuilder; use SymfonyComponentEventDispatcherContainerAwareEventDispatcher; $container= new ContainerBuilder(); $dispatcher = new ContainerAwareEventDispatcher($container); // Add the listener and subscriber services $dispatcher->addListenerService($eventName, array('foo', 'logListener')); $dispatcher->addSubscriberService( 'kernel.store_subscriber', 'StoreSubscriber' );
  • 31.
    TraceableEventDispatcher The TraceableEventDispatcher isan event dispatcher that wraps any other event dispatcher and can then be used to determine which event listeners have been called by the dispatcher. // the event dispatcher to debug $eventDispatcher = ...; $traceableEventDispatcher = new TraceableEventDispatcher( $eventDispatcher, new Stopwatch() ); $traceableEventDispatcher->addListener( 'event.the_name', $eventListener, $priority ); // dispatch an event $traceableEventDispatcher->dispatch('event.the_name', $event); $calledListeners = $traceableEventDispatcher->getCalledListeners(); $notCalledListeners = $traceableEventDispatcher->getNotCalledListeners();
  • 32.
    ImmutableEventDispatcher The ImmutableEventDispatcher isa locked or frozen event dispatcher. The dispatcher cannot register new listeners or subscribers. The ImmutableEventDispatcher takes another event dispatcher with all the listeners and subscribers. The immutable dispatcher is just a proxy of this original dispatcher. Using it first create a normal dispatcher (EventDispatcher or ContainerAwareEventDispatcher) and register some listeners or subscribers Now, inject that into an ImmutableEventDispatcher
  • 33.
    ImmutableEventDispatcher use SymfonyComponentEventDispatcherEventDispatcher; use SymfonyComponentEventDispatcherImmutableEventDispatcher; $dispatcher= new EventDispatcher(); $dispatcher->addListener('foo.action', function ($event) { // ... }); // ... // ... $immutableDispatcher = new ImmutableEventDispatcher($dispatcher);
  • 34.
  • 35.
    Events are partof the Symfony framework: they allow for different components of the system to interact and communicate with each other. Object oriented way of interaction with core and other modules. Mediator Pattern Container Aware dispatcher Will probably replace hooks in future drupal versions.
  • 36.
    Since Drupal isusing ContainerAwareEventDispatcher, we always have the dispatcher object available as a service. Consequently, Drupal supports the service definition way of adding event subscribers. Service definition way of adding event listeners is not supported. something to note
  • 37.
    1. Get thedispatcher object from the service container. 2. Create the event. 3. Dispatch the event. 4. Define a service tagged with event_subscriber in services.yml. 5. Implement the EventSubscriberInterface to write getSubscribedEvents() method to return what events you want to subscribe to. Workflow in Drupal
  • 38.
    event subscriber class classConfigFactory implements ConfigFactoryInterface, EventSubscriberInterface { 
static function getSubscribedEvents() {
 $events[ConfigEvents::SAVE][] = array('onConfigSave', 255);
 $events[ConfigEvents::DELETE][] = array('onConfigDelete', 255);
 return $events;
 } } // services.yml config.factory:
 class: DrupalCoreConfigConfigFactory
 tags:
 - { name: event_subscriber }
 - { name: service_collector, tag: 'config.factory.override', call: addOverride }
 arguments: ['@config.storage', '@event_dispatcher', ‘@config.typed'] services:
 event_demo.alter_response:
 class: Drupalevent_demoEventSubscriberAlterResponse
 arguments: [ '@logger.factory' ]
 tags:
 - { name: event_subscriber }
  • 39.
    dispatching the event $dispatcher= Drupal::service('event_dispatcher');

 // or inject as a dependency $event = new EventDemo($config); 

$event = $dispatcher->dispatch(EVENT_NAME, $event);
  • 40.
    core registering eventsubscribers namespace DrupalCoreDependencyInjectionCompiler; use SymfonyComponentDependencyInjectionContainerBuilder; use SymfonyComponentDependencyInjectionCompilerCompilerPassInterface; /** * Registers all event subscribers to the event dispatcher. */ class RegisterEventSubscribersPass implements CompilerPassInterface { /** * {@inheritdoc} */ public function process(ContainerBuilder $container) { if (!$container->hasDefinition('event_dispatcher')) { return; } $definition = $container->getDefinition('event_dispatcher'); $event_subscriber_info = []; foreach ($container->findTaggedServiceIds('event_subscriber') as $id => $attributes) { // We must assume that the class value has been correctly filled, even if // the service is created by a factory. $class = $container->getDefinition($id)->getClass(); $refClass = new ReflectionClass($class); $interface = 'SymfonyComponentEventDispatcherEventSubscriberInterface'; if (!$refClass->implementsInterface($interface)) { throw new InvalidArgumentException(sprintf('Service "%s" must implement interface "%s".', $id, $interface)); } // Get all subscribed events. foreach ($class::getSubscribedEvents() as $event_name => $params) { if (is_string($params)) { $priority = 0;
  • 41.
    KernelEvents::CONTROLLER, EXCEPTION, REQUEST,RESPONSE, TERMINATE, VIEW ConfigEvents::DELETE, IMPORT, SAVE, RENAME ... EntityTypeEvents::CREATE, UPDATE, DELETE FieldStorageDefinitionEvents::CREATE, UPDATE, DELETE ConsoleEvents::COMMAND, EXCEPTION, TERMINATE MigrateEvents:: MAP_DELETE, MAP_SAVE, POST_IMPORT, POST_ROLLBACK, POST_ROW_DELETE, POST_ROW_SAVE, RoutingEvents::ALTER, DYNAMIC, FINISHED Events in Drupal 8 core
  • 42.
    path forward Writing yourown module? trigger an Event for everything. Interacting with or alter core? subscribe to an event (if one is fired). Hooks … you don't have too many options. Configuration, Admin forms? Plugins Simple Extensions Tagged services
  • 43.
  • 44.
  • 45.
    Join Us forContribution Sprints Friday, April 28, 2017 First-Time Sprinter Workshop 9:00am-12:00pm Room: 307-308 Mentored Core Sprint 9:00am-12:00pm Room:301-303 General Sprints 9:00am-6:00pm Room:309-310 #drupalsprints
  • 46.
    WHAT DID YOU THINK? Locatethis session at the DrupalCon Baltimore website: Take the survey! https://www.surveymonkey.com/r/dr upalconbaltimore http://baltimore2017.drupal.org/schedule
  • 47.