 All right, I think it's time we should start. So good afternoon, everyone. Thanks for coming to my session. I hope everyone had a nice lunch. We should be talking about events, which is necessarily the object-oriented way of doing the same thing that we were able to do with hooks earlier. So let me ask a question. How many of you have actually used hooks before? Great. And how many of you have used events now? Cool, so those of you who have used events, this should be pretty basic stuff for you. You may feel a little bored, so I'm sorry for that. I've tried to keep this very basic. But then there is some, you know, I have tried to go a bit deeper into things on the way, so there should be stuff that is, I guess, new for you too as well. So as we know from Drupal 7 to Drupal 8, we have moved from, you know, hooks to events and other ways of extending our applications or, you know, letting others extend our applications. So we should be looking into that aspect of it. Before moving further, let me give a brief introduction about myself. So my name is Nidha Ismail Shah. I work for Acquia. It's been two years that I've been working for Acquia. Prior to this, I wasn't working anywhere, so I joined Acquia straight from my college. You can find me on my Twitter and on DDoTo as well. I sometimes blog as well, so you can check that out as well. I come from a beautiful place called Kashmir. It's in South Asia, north of India, so we have a little, you know, small Drupal community there as well. I encourage you to visit us, read about Kashmir and, you know, eventually visit us. So the overview of what I'm going to talk about today would be, we'd be basically looking about two things. One is the symphony way of doing events. We'll be looking into symphony event dispatcher component and then we'll move to, you know, how we can implement and how we can use events in Drupal 8 as well. Consequently, we'll be also looking at how we can install the symphony event dispatcher component in your standalone application, irrespective of Drupal. We'll also look into how you can create and dispatch events there and then subscribe or listen to your events that you have created or that have been created by other developers. Same things we'd be looking into, you know, we'll be looking into when, you know, same things, how same things can be done in Drupal 8 as well. So the intent, you know, let's look about the intent or the purpose of having events or having hooks in our application. So this is a commit message that Dries first wrote when he introduced the hook system. So the basic idea is to be able to, you know, run certain, you know, a random amount of code, a random code at a random point in your program. So as your program progresses, as your application progresses through its life cycle, you define certain moments, you define certain points where you want other developers, other people to, you know, hook into your application, hook into your application and alter something or do things about, you know, some things in your application, eventually, you know, extending your application to other functionalities as well. So that's the main interest earlier in Drupal 7, how we, you know, where that happened was hooks. Those hooks were defined by a fixed interface, as you might know, which was true for each hook as well. Event dispatcher component provides the same thing, it basically allows your application, you know, different components in your application to interact with each other, decoupled, you know, interact with each other in a decoupled way. It doesn't, you know, it basically forces your application to interact, two components of your application to interact with each other in a loosely coupled way. So what is an event? Does anyone have a formal definition of an event? Wait. Great, so. Events. Event would be the same random point in your program where you want other developers to run certain code. So it is an action that can be, you know, that is represented by a software and that can be handled by a software as well. So your action, how you can handle, how you can represent it by a software would be defining or dispatching an event at that point. And how you can handle it with software is to define a listener or a subscriber that can listen to your event. And as a result of, you know, consequently, when you implement events, when you have hook system in your place, in your application, so what you achieve is your application becomes extensible. So other developers, other people are able to extend your application, are able to hook into your application and perform there and extend your, you know, application to design custom functionalities. And your application becomes modular as well. So we know that Drupal 7 or Drupal, you know, in itself is a modular application or a modular software. But with the introduction of, with these new advancements in Drupal 8, for example, introduction of different symphony components, your Drupal itself has become, you know, more modular in a way that modules, itself modules in themselves are modular. So you have different components in your modules, which was not possible earlier with Drupal 7. And as a result, you have a highly maintainable code and you have a better developer experience as well. So let's talk a little bit about the background of, you know, what we are going to try to, you know, talk about today. Sorry. The whole thing is about extensibility. So you want to make your applications extensible. In Drupal 7, you had, you know, whatever you had to do, you had to do it with hooks. And then with the introduction of Drupal 8, we became a little happier. We had many ways of doing the same thing. We had many ways of, you know, allowing our applications to be extendable. We have plugins. We have tag services. We have events. And then we have hooks as well. So if you want your, you know, if you want your extensibility, if you want your extension to have the admins UI support to have multiple instances to use configuration, so you should be using plugins. If you want a simple extension, you should be using tag services. But if you want to alter something or if you want to react to something that's happening already, you may want to, you know, you may want to use events for that. And this is only when you're writing your own module. But then when you're extending someone else's code, it really, you know, you really don't have a choice. You have to do whatever, you know, you have to follow the way they have exposed their application. If they have exposed a hook, you have to alter, you have to implement that hook. If they have triggered an event at that point of time, you have to subscribe to that event. So you can, by the way, you can use hooks. You can expose hooks in Drupal 8 as well. I don't know why you would do that, but then you can. Now let's talk about symphony event dispatcher component, how you can, you know, basically use, install and use this component in your application. Installing is simple. You can require it with the Composer or you can simply clone it from GitHub. And you should be, you know, then require, you know, the auto loader and then you should be good to go. There are three things to, you know, using event dispatcher component in your application. One is the event. The event is in itself represents the state of your application, you know. It represents that point where in you want to, when you want to, you know, let other people do something about your application or extend your application. You may want to, you know, pass in your state information. You know, you have an object that represents your application at a certain point of time. It has certain properties. Those properties have values. You may want to pass in those values to your event object so that they become available to the listeners for any alteration they might want to make. And then you have a dispatcher that has the sole responsibility of dispatching your events. And then eventually notifying all the subscribers or all the listeners that this event has occurred and then actually calling those subscribers and listeners. A subscriber is necessarily, you know, that chunk of code that you want to run when a particular event has occurred. Event dispatcher component basically implements two patterns, PubSubPattern and MediatorPattern. Does anyone know what PubSubPattern is? So basically it's a messaging pattern wherein it exemplifies the decoupling of two components. In this pattern, what happens is a subscriber, a publisher publishes its message without the knowledge of what subscribers are going to listen to its message. And a subscriber to a message, expresses interest in listening to a message without the knowledge of where the message is coming from. Same thing is happening with event dispatcher component as well. A listener doesn't necessarily need to have the information of where the event is coming from. So our event doesn't have the responsibility of explicitly calling the listener. Event is being fired from a dispatcher, centralized dispatcher component, and listener is being called by the dispatcher component. The listener and the event are necessarily decoupled. Same thing happens with MediatorPattern as well. MediatorPattern design design designates the intermediate intermediary who is responsible for the communication between two different components. The two different components in your application don't necessarily have to interact with each other. An ideal example of this would be a runway of an airport. So two planes, a plane landing and a plane taking off, they don't necessarily have to contact each other as to when is the right time for one to take off and the other to land. They both contact with the centralized object here representing in an airport, it will be a control room. So they both have the job to contact the control room and not with each other. Workflow of using this event dispatcher component in your application would be, again, you have a listener object. You have a listener object that tells the dispatcher object as to what events it wants to listen to and what methods should be called when those events occur. And then at some point of time, in that point, you tell Symphony to dispatch that event. And then it is the job of the dispatcher component to actually call those methods on subscribers or listeners. And you have your event object containing all the information regarding the state of your application. So as I said, we have three components, the dispatcher component, the event object, and the subscriber or listener. We have been using these terms, the subscriber and the listener, indistinctly. So we'd be looking at how these are different. There are minor differences. We'd be also looking into that as well. So in your application to use the event dispatcher component, you have to instantiate the event dispatcher. You get the dispatcher object. And then your dispatcher object, you call a method dispatch on your dispatcher object to dispatch any event. Dispatch method takes in as argument two things. One, it can take in as argument as a constant that would represent your event, or it can also be a string name. So the constant would also be representing the same string name. It would be a unique string representing your event. It also takes in as an argument your event object. The event object, you would have to, if you want other people to alter something in your application, you might want to pass in that information into your event object. Like I have a scenario here. We have, suppose an e-commerce portal. We have an order object. We want other people to alter. We create an event and we pass in that order object as an argument to our event. And then we pass in that event object as an argument to our dispatcher and it dispatches the event. So that is the whole process of creating an event and dispatching the, dispatching that particular event. Let's look at the event object, what event object looks like. So event object is basically, extends the generic event object by symphony. So you have your, you can have custom methods for you can have getters and setters for your information or that represent the state of your application. And you basically, there is nothing, there's a constant that represents your application. And it's a simple sparse class that is available to developers to design APIs around that. The base event class has nothing. So it has only two methods and a variable. So it also has two methods, which are basically, you can get the status of the event, status of the propagation of the event and you can also force an event to be stopped, which was not possible with Drupal 7 when you were, you could not stop the execution of an event. Now here you can, in your application, you can stop, actually stop the execution of an event. The base event classes, it has been intentionally kept as sparse so as to allow people to design APIs around that. So you can have custom APIs around your information, whatever information you wanna expose to other people in your application, you can design APIs around that. Now we have a dispatcher object that has dispatched our custom event object. So we have reached a point in your application, in our application wherein we have an event object representing the state of our application and we have told the dispatcher component to dispatch our event. And then now we'd look into how we can subscribe to that event. So our subscriber would need to implement the event subscriber interface and as a result we'd be forced to define a method, get subscribed event. So this get subscribed event method basically returns all the information about what events our subscriber is implementing. What, sorry, subscribing to, what all events our subscriber is subscribing to or listening to. So basically you would return an array of either, you know, events and the corresponding methods that would get called. There are multiple things that you can return here. One, you can only return an array keyed by your event name, constant or string, both you can use here. And you can also, you know, like I've done here, you can also return it with a simple method name which would be having a default priority of zero or you can specify a priority as well. You can, you can subscribe to multiple events in the same subscriber and you can have multiple methods getting called for a single event as well on multiple priorities, different priorities. So the higher the priority here, the first year subscriber would get called. And then obviously you would have implementations of your, you know, subscriber methods and then your subscriber method, each subscriber method would get the same event object as an argument that we passed into the dispatch method of the dispatcher object. Now we have the listener. This was a subscriber, sorry. This was a subscriber and now we have the listener. So listener is a simple class which has a simple method and that's all. And you are doing something, whatever you wanna do with the event object that you receive as an argument to that method. So this is the basic difference between a listener and a subscriber. A subscriber specifically provides the information as to what events it's listening to which is not the case with a listener and a listener does not have the information of what events it's listening to. So whenever you add those subscribers or listeners to the dispatcher, you would not need to provide the information of what events your subscriber is listening to when you're registering your subscriber with the dispatcher. But when you're registering your listener with the dispatcher, you would need to explicitly pass in the information of what events it's listening to and what method should get called when those events occur and with what priorities. Like we have, like we see here, I have instantiated the same subscriber and I simply add, do a column method, add subscriber on the dispatcher and pass in the simple subscriber object which is not the case with a listener. I have to explicitly pass in the information of what event it is listening to and I have to pass in the listener object with the method name that should get called when this particular event occurs. I also would need to pass in the priority as well here but if you don't, default of zero would be taken. This method name is also optional here. So if you don't pass in the method name, it would call the method which has a name with prepended, with on prepended to the event name. So for example, if you want your subscriber to listen to an event called foo action and you don't want to pass in the method name here, so an on foo action method, if there is an on foo action method, it would get called automatically. So the rest of the process remains the same. Now this is one way of registering your subscribers and listeners to your event dispatcher component. Other ways can be, you can use, if you're using container event dispatcher, which means you have your container available within your event dispatcher, you can also end your using dependency injection component as well. You can use register listener pass to basically defining your listeners and subscribers as tag services and then your listeners and subscribers would be lazy loaded into your container. So whenever an event is fired. So how that would, how you would do that, you would define your listener and your subscriber and or your subscriber as a service in services.yml file. You would give in the class name for that and you would define it with a tag, whatever tag you want to choose, kernel event listener is the tag that symphony uses. Symphony has already written a register listener pass for these arguments for these tags. So you already have a register listener pass available in the HTTP kernel component of symphony. So whenever you tag a service with kernel event listener, it is defined as a listener to your, it is available to you as a listener. And if you tag it with a subscriber, kernel event subscriber, it is available to you as a subscriber. Same process has been followed in Drupalate as well. That is why we are required to define our subscribers as services. So there is one thing to note here. Similarly, as we have seen earlier as well in the process of registering your listeners and subscribers, when you're defining your subscriber as a service, you do not need to explicitly provide the information of what event it is listening to and what method should get called. But in the case of listeners, you would need to pass in that information explicitly. So we have seen these differences between subscribers and listeners. The only difference between subscriber and a listener is that a listener does not have the information of what events it's listening to. You would need to pass in that information at the point of service definition when you're defining your event listener as a service or when you're adding your listener to the dispatcher, you would need to explicitly pass in that information. So that is the basic difference between the listener and the subscriber. I have written a blog post around the same thing. You can check that out as well. So there are more event dispatchers available in Symphony. As I talked about container-avere event dispatcher, similarly, we have traceable event dispatcher that is basically used to profile your events, listeners and subscribers, and you also have an immutable event dispatcher. Let's look at container-avere event dispatcher. Basically, you have the container available to your container is being injected as a dependency to your event dispatcher. So you can leverage the power of services within your event listeners and within your dispatchers, making your code more powerful, and also your subscribers and listeners are lazy-loaded whenever your events are being fired. You do not have to explicitly instantiate those. This is how you would work with container-avere event dispatcher. You would have your container instantiated, and then you would pass in that as an argument to your container-avere event dispatcher, and then necessarily you would add your listeners and subscribers as services. The same process applies here as well. With listeners, you would need to pass in the extra information explicitly, unlike you would do with, which you would not need to do with subscribers. Grasable event dispatcher uses symphony stopwatch component to profile your code, and as a result, it has two methods, add get called listeners and get not called listeners. So at the end of the propagation of an event, you would have the information of what listeners have been called and what listeners have not been called. This event dispatcher has been exploited by web profiler, and that is how it gets the information of what events have been called and what listeners have been consequently called on those events. You also have immutable event dispatcher, wherein you can stop the process of, you can stop other people from adding further listeners and further subscribers to your event dispatcher. So you would have your normal event dispatcher, and then you would add certain listeners and subscribers to your event dispatcher, and then you would pass that event dispatcher as an argument to your immutable event dispatcher. And then when you call add listener on your immutable event dispatcher, you would get a bad method called exception. So this is how you would do it. You would have a normal event dispatcher, and then you would pass that as an argument to your immutable event dispatcher. So that takes us to droopulate. I mean, how we are doing events in droopulate. The process remains more or less the same. So I have cut this a bit short. Events in droopulate have been taken from symphony. They allow for different components to be able to interact with each other in a decoupled way. We had a procedural hook system, which is being slowly replaced by this object-oriented way of interaction between core modules and other components. This necessarily again implements the mediator pattern, and we are using container event dispatcher in droopulate extensively, and will probably replace hooks in future droopal versions. Something to note here is that since we are using container event dispatcher, we have to explicitly define our subscribers as services. But we are not supporting, we are not yet supporting the service definition way of adding listeners. I think that has been done so as to keep a single way of adding listeners to your event dispatcher. You do not want to confuse people with giving them multiple ways to add certain things. So how this has been done is that we will take a look at that later. So the workflow remains the same thing. You get your dispatcher object from the service container. You create an event. You then dispatch that event in the same process. You create tag service, tagged with event subscriber in services.yml, and then you write a class for that, which implements your event subscriber interface, and then eventually implementing the get subscribed events method as well, which returns the same array of events that you want your application to listen to. This is from core config factory class, how they have, how core is subscribing to events, basically define your class and implement the get subscribed events method. Define the array, that array of events and corresponding method names with corresponding priorities that you want to listen to your events with, and then returning the same information. And then you would obviously have the definition of these methods as well. This is what services.yml would look like in core. If you had a simpler implementation, you would simply define this service with a class and then argument whatever argument you want dependency injection container to inject in your class, and then you would define it with a tag event subscriber. And then this is how you would dispatch the event. You would get the dispatcher object from your service container. You would create the event and then you would dispatch it. This is how core is registering event subscribers. This is how you know, this is where you get to know that you only, if you define your event listener as a service in Drupal 8, it will not work. Why it will not work? Because it has not been, there is no way that your event listener would be added to your dispatcher. We have a compiler pass interface. We have a compiler pass implemented in Drupal 8 that basically fetches all the tag services that are tagged with event subscriber. And then does some checks if they are implementing the event subscriber interface. And then adding those subscribers to your event dispatcher. That is how basically tag services work. So events in Drupal code, we have certain events that are same because we are using symphony components that are same as what we can see in symphony. We have controller events, kernel events, exception, request, response, terminate, and view. We have config events. We have entity type events. We have field storage definition events, console and migrate events and other events. So the path forward from here would be, if you're writing your own module, you have to trigger an event for everything. And exposing hooks is not advised anymore. If you're interacting with or altering code, you subscribe to an event if one is fired. But if there is a hook has been exposed, then you would eventually, you don't have any option. You would have to implement that hook. But then if you need configuration form, if you need a configuration and if you want the support of admin UI, you would be using plugins. And for other simple extensions, you would be using tag services. So the summary of all of this would be that to use the event dispatcher component, you would have to create the event first, put in all the information that you want others to alter in that event object, pass that event object to the dispatcher and dispatch it, and then implement a subscriber, create a subscriber class, define it as a service with a tag with event subscriber, and you're good to go. So that's all. A simple demo of simple application using events. So what we'd be doing is I have a simple module here that would basically demonstrate how you would do since you don't have hook in it, exit and hook boot and drooplate, how you would implement a hook in it implementation in drooplate using event subscribers. So I have a subscriber class written that is basically subscribing to kernel event request that happens, this event is fired when a request is received. So I am defining a method custom redirection that should get called every time a request is made. So in this custom redirection method, I receive the get response event object. This event is the object is the same event object that was passed in as an argument when this kernel event request method was, the kernel event request event was fired or dispatched. So I get the URL from the, I get the URL from the request that was requested and if that is about us.html, if that matches the URL, and then I'd be creating a new response and then sending the new response to the browser. This is how that would be done. And then you would define this subscriber as a service in your services.yml file. This is how that would look. So first I would check if my module is enabled. My module is enabled. So if I visit the aboutus.html page, it should get redirected to aboutus page. But if I, it would not get redirected. I also have one more implementation. So I have a form rendered on this route. The form looks like this. It has basically three text fields. I am in the submit form, I am getting those all, you know, sorry, sorry for that. So is that clear now? Thank you, thank you. So you have basically in your form, you have three text fields. In the submit form, I get the value of these fields. I create an event there. I don't have to, I mean, this is not an ideal implementation of events, but then this is just to explain how you would do events. So I get these event, get the value of from these text fields. I get the dispatcher from the service container. I create and create a custom event past the config, you know, all the values that I got from these text fields to my custom event. And then I dispatch this event. What my event looks like, this is what my event would look like, you know. Whenever my event is created, it would take in the config object as an argument. And I also have setters and getters for the config that I have set. So get config would return my config and set config would set my config. So what I'm doing in the submit handler, in the submit function of this form is that once I've dispatched, this once I've gotten the values from the text fields, I am passing the same information to my event and I'm dispatching it. The same information would be available in my event subscriber. And then the control and then the same event object would be returned to my, you know, submit form function. And in that submit form function, I can basically then get the same information. If that has been altered, I would be receiving new values. And then I would be doing a merge and saving that config. So I have another module subscribing to this event. So that would look like this. I have a subscriber defined as an event subscriber. I also have a subscriber class here. I have the get subscribed events method is here. I am listening to this event that I have fired in the form, submit form function of my another module. I have two methods listening to the same event with different priorities. So as per the priorities, this method with the priority of 100 would get called first and with the priority of 10 would get called second. So alter config again is here. I am changing the value of the video field to this text. This would get called first. So this would get called afterwards. I am changing the value again. So let's visit that form. So if I change the value, let me just click clear cache, I might be doing something like that. So I'm changing the value of the video field here. The value is again the same because it was set here. So if I change the priorities now, if I keep this with the priority thousand, so alter config would get called first and alter config again would get called second. So since this would get called second, the value would change to this value. And whatever I'm giving, whatever value I'm giving from the UI would get over it. Configure. This with a thousand, this would get called first. Alter config again would get called second. I don't know why this one. It should work. Sorry. I think it's the live demo book. Sorry? The live demo book. No, no, that's not. Does the larger number get executed second or first? The larger priority would get executed first. From higher numbers to lower numbers or from lower numbers? Yeah, it's working now. It's working now, so it was a cache issue. So this is a little bit different from what we see in Drupal generally regarding the weights and stuff. So here, the higher the priority, the first it would get called. Whichever listener has a higher priority would get called first. Let's get back to the presentation. So demo is done. Are there any questions? Please join us for a contribution sprints and please don't forget to rate my session. I'd encourage you to do it here only. So that would really help me and thank you.