 Good morning and welcome to the session on altering, extending and enhancing Drupal 8. This is room 271-273. I'm going to be talking about various ways that module developers can interact with the Drupal runtime in order to do whatever it is that your modules do. If that doesn't sound like what you're interested in or if partway through the session, you're like, I'm still not interested. While the sessions are recorded, totally feel free to get up and find something that is of interest to you. I will have no hard feelings. Otherwise, there's a link on this slide, a URL that you can go to that is a link to the slide deck itself so you can keep the slides for later. The other thing is there's a bunch of slides in here that are really just lists of links to various resources that I've found useful in order to help explain some of these concepts. I'm not going to actually expect you to write down all of those ones, so just write down this one and you can get links for the rest of them very easily. Before I get too far, a little bit about myself. My name is Joe. I work for Drupalize.me. I've been doing Drupal development for at least 10 years at this point. I kind of lost track somewhere along the line and decided that it didn't really matter so I usually just say, I've been doing this for a long time and I really love doing it which is why I'm still doing Drupal development. At Drupalize.me, I spend a lot of time working as a trainer. I help produce training material that does things like explain how you might interact with Drupal's runtime. I really get excited about sitting around and trying to come up with analogies for how you can take something like Drupal's event system and relate it to other real world things that people might know about. So if you like complex analogies that explain technical concepts, we can totally hang out and have a beer and talk about that. It'll be fun, I promise. Otherwise, yeah, I do that. I spend a lot of time teaching people Drupal and these types of concepts which is why this is a particularly exciting presentation for me to be able to give because it's really like this is the kind of thing that I enjoy doing. Being able to help explain some of the more technical bits of Drupal and hopefully make it a little bit less complex and a little easier to understand. Let's see if my slides actually change. There we go. So this presentation is going to cover a handful of things. Mostly, I'm going to be talking about the various ways that a module developer or really a module can extend Drupal Core. The ways that during the process that Drupal goes through to build a page or service or request that you can interact with Drupal and the things that it's doing. In Drupal 8, there are a handful of ways that you can do this, including plugins, services, events, and hooks, all of which we'll cover. I'm going to give examples of kind of the use case for each of these different methods and talk about sort of compare and contrast them. And the hope is that when you leave this session, you'll have a better idea of what tools are available to you so that you, when you're writing a module, you kind of get an idea of how you can participate in that request service. And then also allowing you to be able to choose or make an informed decision about do I want to create a plugin for this or should I be using services and being able to compare a little bit of those things. There's not a lot of code. There are a couple of code examples, mostly just to show some kind of a little bit about how things work, but mostly this presentation is geared towards helping you make that decision and understand what each of the methods are. I just want to change my slides. This is going to be an adventure. Here we go. So, and the reason that we talk about this and why I think this is important. In the Drupal community, we have this sort of phrase or axiom, don't hack core. The idea being that as a Drupal developer, I should be able to write code that interacts with anything that Drupal does or change anything that Drupal does without having to modify the core code. I should be able to alter the login process. I should be able to add new features kind of as a module developer. The hope is, anyways, that you can do all of these things without modifying core. The benefit is if you can write your code without having to change Drupal core's code. It makes things like making security updates easier. You don't have to keep track of the modifications that you made every time that you're applying Drupal 8.1 comes out or 8.1.1 with some security enhancements. You don't have to keep track of what did I change and do I need to apply those changes again or did they get applied already? Then there's also, I lost my train of thought, hold on. The other thing that I would say about this is if you find that you're in a scenario where you feel like you would like to write code that changes Drupal and you can't without modifying Drupal core, I would probably consider that to be a bug in Drupal core. That's something that's worth creating an issue for and filing a patch, making it possible for others to extend or enhance that aspect of Drupal without having to have core. The hope is that we end up with this infinitely flexible Drupal core and what you were free to come along and change anything that you would like at any point more or less. The other reason I think it's nice to talk about these tools is because as module developers we're often trying to create tools that are somewhat generic like Drupal core that other people can alter and enhance without having to hack our module. For all of the same reasons, I would like to be able to develop a module like for example devoting API module and allow other people to provide new plugins for how you might tally votes or interact with the forms that the module creates without having to hack that module themselves. If you understand how all of these interaction points work, you can both implement them in your code but you can also make it so that other people can use those tools to participate in whatever it is that your module is doing, tallying votes or displaying things on the screen or whatever that case may be. So in addition to looking at how you could implement each of these patterns, we'll also talk a little bit about how you could invoke one of the patterns, dispatch events or invoke hooks and so forth. I think that when you start trying to break down each of these concepts and understand which ones you should use and why, it helps to have a little bit of a background on the types of things that Drupal is trying to do or might want to ask your code about. And so I kind of break this up into like four different tasks that a module might do. One of them is respond to information or events. So certain things, all kinds of things happen whenever someone's viewing a page in Drupal and when a node gets saved or when somebody logs in or when the page itself is first loaded, Drupal dispatches events or says, hey, anyone that would like to participate in the fact that someone just entered their password and submitted the form, now is your chance to do so if you'd like to. So basically providing opportunities along the way for someone to step in and say, hold on a second, I'd like to do something a little bit different here. Another thing that modules do a lot of in Drupal is answer questions. And if you're familiar with Drupal 7 development, this is often done in the form of like an info hook. But there are questions like, hey module, do you have any blocks that you would like to provide so I can put them in the user interface so that someone could choose one of your blocks? Or do you provide any new field types that someone should be able to choose from when they're creating new content types or things like that? So basically your code needs to be able to answer questions that Drupal has about the functionality that that code provides. Modules provide new functionality. So Drupal Core does a lot, but there's also a bunch of things that doesn't do. And so one of the primary reasons you would write a module is to add a new feature. Whether that's a tool for building web forms or a system for telling votes or whatever the case may be, adding additional functionality above and beyond what core already provides. And the corollary to that is altering functionality that core already provides. So the various modules that are in core that, for example, provide a list of blocks or make it possible to create a contact form. Rather than just get rid of that module completely and replace it with new but only slightly different functionality, your module could also choose to alter the existing functionality. So these are kind of the types of things that a module might want to do during the process of servicing a request for a page in Drupal. Which again, comes back to that idea of don't hack core. Instead, take the opportunity to do things like answer a question with a hook or use a plugin to provide additional functionality or write a service that provides new functionality or respond to the fact that someone's trying to log in and you'd like to change the password verification system by responding to that event. We're going to talk about these four methods for altering Drupal hooks, plugins, services, and events. In no particular order either. I have no explanation for why they are in this order. It's not like this one's more important than the other ones. It just happened to be the order that I felt like talking about them in. The first one is plugins. Plugins is a system that's new in Drupal 8. Actually all of them, except for hooks, are new systems in Drupal 8. I think that likely as a module developer making the transition from Drupal 7 to Drupal 8, or even if you're just getting started the first time with Drupal 8, plugins are probably one of the first, if not the first developer experience you'll have creating a module. Usually people get started trying to do relatively simple tasks like create a new custom block. That's something that might be implemented as a plugin. But so we're talking about this because it's probably something you'll encounter pretty early on. What are plugins? Plugins are a combination of a tool that answers a question. So Drupal has some context in which it needs to know what are all of the things that provide blocks? What are all of the things that provide fields? What are all of the things that provide functionality X? So a plugin needs to provide metadata about the functionality that it provides. And then plugins also add new functionality that doesn't already exist in Drupal. Is that like? You guys hear the feedback? Well, I'll try to, I have no idea why that happens. But plugins, I know all about. So some of the things that I like about plugins, they think about plugins as a way of providing new configurable functionality for various components within Drupal. Almost always where you have a scenario where in Drupal 7 you would have done something like implement an info hook that describes the functionality and then a bunch of callback functions that implement the functionality. That's generally in Drupal 8 going to be replaced with plugins. Otherwise it's fairly similar. You've got a system for providing metadata about the functionality and then the code that actually provides it. I like plugins a lot. I feel like plugins provide a bit more of a consistent experience for people that are learning how to write code for Drupal. In Drupal 7 you would often end up with like, implementing a new block in Drupal 7. It's not necessarily hard, but you have to learn all of the right pieces and it's hard to understand what those are. You learn that you have to create an info hook so that the admin UI can find the block. And then you also have to like create a hook block view and hook block save. But there's nothing that really ties all of that together other than they happen to be hook underscore block underscore something. So you figure out how that works by searching api.drupal.org for hook block and then see what pops up in the automatic list and you're like oh that kind of sounds like what I want to do. The nice thing about plugins is that when it comes time to implement the functionality you're almost always going to be working off of a class so you'll have an interface that you can implement which describes basically the types of things that you could do with this plugin. And you also get to put all of the code that provides the functionality in one place instead of spreading it across a bunch of different randomly named functions or callbacks. You just generally create a single class that provides the plugin and encapsulates all of that functionality in one place is pretty slick. Examples of things that are plugins in Drupal 8. Blocks is the kind of example that I come up with the most. It's a classic example of there's, sorry. A system in which Drupal needs to be able to get a list of all of the things that provide this type of functionality and then Drupal also needs to be able to, oh really that's the thing I'm going to get applause for. All right. So plugins, blocks is a great example of a system where Drupal needs to know how to get a list of all of the blocks that are provided by all the modules that are currently installed on this particular site but not only that it needs to be able to do things like consistently be able to know what the label is of the block that it needs to display in the admin UI or it needs to have a known method that it can always call to display whatever the content of that block is. Field types, field formatters, views styles and actions in Drupal are also other instances of things that would be plugins. One of the things that I find frustrating about plugins is I can't really figure out the best way to know what all of the different types of plugins that I might want to implement are. I generally will look at core for an example of if I know that I want to add a new field formatter I'll try to go find a module in core that's adding a new field formatter. Once I see the code and we'll take a look at some examples you'll pretty quickly be able to recognize that this is a plugin implementation but there isn't that I know of yet any like one page that you can go to that lists all of the different plugin types. All right, fine, we'll go to the next slide. The recipe for implementing a plugin. So once you know that the thing that you're trying to create in your module is a plugin here's what you need to do. First you need to figure out what type of plugin it is that you're implementing. Is it a block? Is it a field formatter? Is it a field widget? Knowing what type of plugin it is and there's actually a handful of different plugin. There's the type, for example, it's a block plugin but then there's also various ways in which the plugin system can discover plugins of a given type. So is it an annotated plugin? Is it based on a YAML file and so forth. Knowing that will inform the rest of what you need to do in order to implement something of that type. So once I know that it's a block plugin I also know, okay, block plugins are annotated plugins which means that the metadata that I need to provide because you're gonna have to provide information for any plugin so that Drupal can read that and create a list. The metadata in this case is going to be part of an annotation on a class. And it'll also inform in that case for an annotated plugin where the class should live in the code base. So what name space it should live in so that Drupal can discover it. There is, I believe there is actually always in core though this may not be true. So it may be almost always a base class that you can extend for a given plugin type. If you think about it, tools like blocks for example, a lot of the functionality between all blocks is fairly similar. Like most blocks in Drupal have a configuration form that allow you to choose which pages it's going to show up on, set the title and some other basic information. And so instead of having to repeat that for every single block plugin, I could extend the base class which provides that configuration already. I can alter it if I want to by optionally like overriding that method or I can just leave it as is and get away with kind of doing the bare minimum amount of work. So I highly recommend extending the base class when it exists and you're implementing a plugin. And finally, depending on the plugin type there will also be an interface. This is required for every plugin type. So you'll find the class that is the interface for that plugin type. And the awesome thing about this is now I know all of the different methods that I could implement for this plugin type and what they're going to do. Instead of having to go to api.drupal.org and search for hook underscore block underscore and then wait for the list to populate so I can figure out what do these things do? I can just look at the interface. All the documentation will be right there. I can say, oh yeah, the thing that I want to do is change the content that's displayed. So I'm going to override this method. This is a very simple somewhat contrived example. Of what a plugin might look like. It's a class, it's extending a base class. So this plugin provides new flavors of ice cream because who doesn't like ice cream? It lives in a namespace that was determined based on me knowing that I'm adding a new ice cream flavor plugin. It provides the metadata that Drupal needs in order to discover the list of plugins here in the comment at the top of the class. This is called an annotation. And then the functionality of what that plugin does. If you're a module developer and you would like to add a new plugin type, the recipe for doing so is as follows. Examples of when you might want to add a new plugin type are any time that your module provides some kind of functionality that you would like others to be able to add to the list so that an administrator can choose one or more items from that list. I use the Voting API module as an example a lot for this. And so if you're the maintainer of a module like Voting API you might wanna provide one simple way of tallying votes but leave it open for people to provide infinite number of other ways of tallying votes. So I might do just add them all together but you might need instant runoff or you might need your votes are worth two if you vote on Tuesday at 2 p.m. Whatever the case may be, you could write those plugins. Drupal will provide a list that an administrator could choose from which one of those would be active at any given time. If you wanna implement a new, if you wanna allow for plugins, what you need to do is declare a new plugin type. The easiest way to do so is by extending the default plugin manager class that's part of Drupal Core. This will go through and basically set up a whole bunch of sane defaults for you in terms of how to collect metadata where the code should live but still give you the chance to override any of those as you need to. This slide has a lot of links on it which is not very useful when we're in a conference room like this. So like I said, you can download the slides at this link down in the bottom corner. This has a lot of resources that I've found useful when trying to understand the plugin system. Services is another way that we can alter Drupal. Services are probably best used when you're trying to provide new functionality to Drupal. So similar to plugins, the difference, the primary difference I think is probably that with plugins, you would like to allow administrators to choose from a list of many plugins and be able to have more than one active at any given time. So blocks, again, a page might have multiple blocks on it at the same time. Whereas services are generally useful for functionality where you'll probably only ever have one active instance of that functionality. You'll only ever have one database connection. You'll probably only ever have one Twitter API client service functionality at any given time. Services are a way of encapsulating functionality into a bundle, like generally just a class with a known interface making it easy to access any of the functionality that thing provides without necessarily having to understand the internal mechanics of how it works. So you could say, hey, Drupal database service, make a query to the database, and you could call the query method, but it doesn't really matter what happens during the time it might be querying Mongo, it might be querying MySQL, it might be querying some external database elsewhere on an API or something. As far as I'm the developer I'm concerned, I know I can call this method and expect this output when that happens. Services are awesome. They provide a way of allowing the functionality that we use to interact with all the various different things like external APIs or create forms in Drupal, or even the implementation of a plugin type to be decoupled from Drupal itself. This allows for better testing. It also allows, so basically you can swap out one service for another, assuming they implement the same interface, you could say the Twitter module has a service for querying the Twitter API, but when I'm running tests, I'd like to use a mock version of that service that doesn't actually do all of the work of going out and querying Twitter and getting the information back. It'll just respond every time with a known message, making the tests run really fast and a little bit easier for me to write. Services typically replace what in Drupal 7 were like global functions. So you'd have all these PHP functions, like for example, to access Drupal's database abstraction layer that were like db underscore something. And they're in the global namespace so that you can make use of them from everywhere. In Drupal 8, those are almost always replaced by services, and then services are accessed through the services container, which is basically just a giant repository of all of the services that Drupal knows about and a method for saying, hey, give me a copy of the database service or hey, give me a copy of the form building service. Some of the things that our services in Drupal 8 include, like I said, the database access is a really commonly used example. The caching system, all of the various tools that are used to optimize and collect the various CSS and JavaScript assets in your site. Plugin managers is actually kinda cool. The services are used to provide all of the other functionalities that we're talking about here. So hooks are provided by a service, events are provided by a service, and plugins, each plugin type, which is a plugin manager, is a service of its own. If you're writing new modules, probably the most common use case for when you would create a new service are things like I'm providing functionality to interact with an API. For example, the Twitter module would provide a Twitter client service, or any other time that your module is attempting to provide functionality that both your module and others might wanna make use of. So instead of declaring a bunch of global functions, you create a new service, declare it to Drupal, and others can make use of it as well. There's a ton of different services in Drupal 8, and I find that the best way at the moment to figure out what those all are is if you go to api.drupal.org, over on the right-hand column, there's a link for services. It'll give you a big list of the services that are available in Core, and you can start to filter through that list and find the things that you're after, whether it's the tool for connecting to the database or the HTTP client for making requests to other APIs. Excuse me. If you wanna create a new service in your module, so bundling up some functionality, both for yourself to keep it decoupled and easy to test, so you could maybe provide a mock version of that service, and so that other modules could make use of the service, what you would do is the following. The first thing you need to do is choose a unique name for your service, which basically means make sure that you prefix your service name with the name of your module, so you might end up with something like mymodule.twitterapi or mymodule.votingcounter. The next thing you need to do is define a interface for your service. Even if you're only going to provide one version of that service, I still highly recommend providing an interface so that one, you'll have really good and consistent documentation of the things that someone could do with that service, so your interface defines all of the methods on that class that someone can make use of, and two, it ensures that future you or anybody else could write another service that could be just as easily swapped in for the one that you're providing. You'll need to register your service with Drupal, so you add a .yml file that provides Drupal with a bit of information about the service so that it can add it to its service container, making sure that when you're ready to use the service, you can get a copy of it from the service container, just use that to identify it by name, Drupal will be like, sweet, I know where to find that code. Here's a copy of the class that you're after. And then finally, inside of your code, you would access that service via the service container. One example of how you might do that, sort of globally asking the service container, saying hey, give me a copy of the service by name, probably what you would more likely end up doing is using dependency injection so that the service gets injected into your controller that's displaying the page, and this is part of that whole process of being able to allow things to be more decoupled so that they can be tested. If you're injecting the service as a dependency into your class, it makes it much easier for someone to say, you know what, in this particular context, instead of injecting the full blown Twitter API, go ahead and just use my mock client instead. This is a page with a bunch of links, that's not that useful here. But again, you can download these slides and these links help provide more information about what services are available and how you can make use of them in your own code. There is also a presentation today at 1 p.m. that's going to talk about dependency injection. The title of the presentation is, what is services and dependency injection and how does it help me? If you're interested in this stuff, that seems like it would be a really good presentation to attend to get a better idea of how this aspect of extending Drupal will work. And there's also a presentation tomorrow at 3.45, titled OOP is nothing to be afraid of, which I was going to cover a lot of some of the basics of implementing interfaces and creating interfaces and how all of that works. Again, a great thing to attend if this idea of creating services and dependency injection and that is a little like, oh, I don't know what I'm getting into. Another way that you can extend Drupal is events. Events are used in instances where the Drupal system needs to be able to broadcast to anyone that might care. This is what just happened. Feel free to do something right now. An example of that might be something like when a user logs into the site, Drupal wants to be able to allow anyone that's interested to respond to the fact that a user just logged in. Now, you're probably not making any changes to that. You're not necessarily altering the fact that they logged in, but you're responding and saying, oh, hey, whenever somebody logs in, I also want to do this other thing above and beyond what Drupal already does. So basically, events are a way of allowing you to react to different actions that take place within the application without making changes to itself. Events are new in Drupal 8, and they're actually fairly limited at the moment. There aren't a lot of them at the moment. You will encounter them. There are a handful of instances where events are being used to replace what you probably would have done in the past by just implementing a hook. The reason that they're being incorporated initially is because Drupal 8 builds a lot on symphony components, and symphony makes heavy use of events in order to allow people to modify the way that different symphony components work, and then Drupal has started to implement some of this as well. The places that I've most commonly seen them so far are in when Drupal is building a list of routes, so the paths that someone could use in order to access content. There are a couple of different events that are triggered during that process that you can respond to in order to change the list of routes or how they work. They're also used a lot by the migration API in order to allow you to do things at various different points during that extract, transform, load process that your migration goes through. Events are a really common pattern outside of Drupal in the larger OOP world, and I think part of what we'll see is that over time, more and more of the things that we're used to doing with hooks in Drupal will start to transition to being events. When you talk about events, you're going to do one of two things. You're either going to subscribe to an event that someone else is broadcasting. You're going to tell Drupal, hey, anytime someone performs this event, let me know, because I'd like to do something. Well, at least I'd like to figure out if I'd like to do something. I just want to know that this is happening, and you do that by subscribing to an event. You need to figure out what the name of the event is that you're going to subscribe to. You need to, inside of your services.yml file in your module, you need to provide a bit of metadata. This is the part where you're basically telling Drupal, hey, whenever this event happens, let me know, and here's where I would like you to send the message to. And then you need to provide the code that deals with getting that message. So you might have a class that looks something like this, which has a couple of methods that say, give me the data. This event just happened. Call this method and give me the data, and I can choose if I want to do anything with that information or not. And so that's useful if what you're trying to do is respond to events provided by some other module or by Drupal Core. The other thing you might want to do is dispatch your own events. So if the voting API module wanted to allow people to modify the way that things work or simply respond to the fact that someone had just cast a vote, maybe the module would broadcast an event. So anytime someone cast a vote, it would say, hey, is there anybody that's subscribed to this particular event? And if there is, go ahead and notify them right now that that event just happened. You can do that by creating a new class using the events namespace. So this is the PSR4 namespace pattern that you would need to use for implementing an event. And you need to provide a couple of different classes the first one you need to provide is really just documentation. So you provide a new class that's in this events namespace. And if I remember correctly off the top of my head, it just has like one or maybe two different properties that are like, this is the name of the event. And it gives you an opportunity to say, here's the documentation for what this event does for anybody that would like to know. And then you need to add a new class to the, excuse me, you basically need to add another class that is an extension of the, or adds to the symphony event dispatcher. So like I said, the fact that Drupal is starting to make use of events started at least from the fact that we were making use of symphony components. We're building off of symphonies event dispatcher. We basically need to declare to that event dispatcher, hey, I've got events that I would like you to be able to know about so that I can broadcast them. And then finally, in your own code, whenever you reach the point in the flow of that code, where for example, someone just submitted a new vote or just logged in, you need to tell the event dispatcher that that just happened. Go ahead and send out the message to everyone that's listening. You can also at that time provide some additional context. Basically you can say, not only do I want you to notify everybody, here's the message that I would like you to put in the envelope when you send it. Again, some links to resources on responding to events. The second one on this list is one of my favorite, it's from the symphony documentation and I feel like it does a really great job of not only explaining how to dispatch or subscribe to events, but just kind of the principle of events in general. And there's a session about the symphony event dispatcher today at 2.15 p.m. So if you wanna know more about the innards of how dispatching events in Drupal 8 works, that would be a great one to attend. And finally, we gotta talk about hooks because without hooks, we wouldn't really have Drupal. Hooks are not new. Hooks have been around since basically forever. I tried to look this up for this presentation to see when hooks were first added to Drupal Core and like by like repping through the history and all of that and I ultimately decided that it's probably sometime around March or April of 2001 is when the concept of hooks were introduced. And then I looked at the code that's in like whatever version of Drupal is from 2001 that was like the implementation of the hooks and I compared it to the code that we used to like invoke and dispatch hooks today and it's like basically the same thing, which is kind of crazy to me, but I think it also helps give a sense of like, just the fact that like hooks work really well and they've served us really well for a long time. In previous versions of Drupal, everything that we've just talked about would have been handled with the hook. Providing new functionality, altering existing functionality, enhancing Drupal, all of that was done through hooks and now we have things like plugins, services and events that accomplish similar things in ways that are hopefully a bit more easier to understand, easier to document and make use of. So hooks work by basically providing a function in your module that follows a specific naming convention. As long as you name your function the right way, if your module's enabled, Drupal will call that function. And that's what this code does. It basically says if the function exists, call the function. And like the major difference between 2001 and 2016 is now there's like 13 layers of try catch statements before it calls the function. Hooks are awesome for situations in Drupal where you need to alter some existing data. And this is probably where you will encounter them the most as a module developer. Things like for example, Drupal has just gathered a list of all of the block plugins and it would like to give you a chance to make changes to that list before it does something with it. Or Drupal has just used the form API service to build a form that it's going to display on the page and wants to give anyone that is participating the opportunity to make changes to that form definition before it's displayed. Hooks are super fast. It's just simply a call that checks to see if a function exists and if it does it calls it. Whereas some of the other things like the event dispatcher are, I don't want to be like, wow, it's super slow, don't ever use it, but it's certainly a little bit slower and has a bit more overhead. Drupal provides a lot of functionality to make that faster. But one of the things, one of the reasons that we still see a lot of hooks in Drupal 8 despite the introduction of events is because they're just really fast. And there's also just an element of like they exist because at the time that they were added to Drupal Core there wasn't really a good way to do these other things. There wasn't PHP's object oriented syntax infrastructure was not nearly as good as it is today and didn't really allow us to do things like dependency injection with services, plugins and so forth. I don't actually know of any presentation this week that is going to cover hooks. But I bet if you went and looked up every single previous Drupal con you could probably find a presentation about hooks. Examples of hooks, the one that you're going to encounter first and use the most is definitely hook form alter. This is allowing you to make changes to any form that's displayed within Drupal. The other time that I see it used a lot still is anytime that you're trying to make changes to lists of data that Drupal has already aggregated from some other system like plugins or a service. The hook form alter one is particularly interesting. I think that again over time we're going to see more and more of Drupal move towards using events just because it's a more widely used pattern in the rest of the PHP world and just programming in general. It's a bit more, if you were at the keynote this morning Dries talked about one of the desires that came out of the results of the survey that he did was people really felt strongly that Drupal needed to move even more towards a fully object-oriented architecture and hooks are kind of like the exact opposite of that. They're specially named functions that live in a file that they all live in the same file. It's not very well organized, but man they're fast. But one of the reasons that we still have a lot of them is during the Drupalite development cycle there was work done to try to convert everything to events, but it became pretty quickly apparent that the hook form altar specifically was going to be quite a challenge to work as an event and for it to be really as performant as it is currently with just calling this function. But again I think that over time that will get worked out and we'll see a lot of this move towards events. If you want to implement a hook, it looks like this. Determine the name of the hook you want to implement which basically means go to api.drupal.oregon type hook underscore and then wait for the list to populate and then find one that sounds like it resembles what you want to do and then go read the documentation for it and discover that it's not actually the one you want so go find the other one. In your .module file you create a new function where you replace the word hook in the name of the hook with the name of your module and then you write your code inside of that function and that's it. As long as your module's enabled, whenever Drupal needs to execute or invoke that hook it will check if the function exists and calls it. One of the things you want to make sure of and this is actually true of all of these things we talked about but hooks in particular. After you add a new hook to your .module file you should make sure you clear Drupal's cache. There are a lot of hooks that the fact that it exists is cached so that Drupal doesn't have to look it up in the same way every single time. That's true of pretty much all of the ways that we extend or alter Drupal. If it feels like your functionality isn't working or isn't being added try clearing the cache and see if it's working then. If you would like to invoke hooks from within your module the pattern for doing that is this. You need to pick a unique name for your hook. I again recommend probably using the name of your module so it might be hook underscore name of my module underscore name of my hook to try to ensure that it's unique. This is actually one of the things that's great about things like plugins or services or events is we're no longer running into this same namespace collision problem that we have with hooks where you have to be really careful about the way that you name things so that you're not accidentally implementing hook node alter in your node underscore form module. Things like that. And then you use the module handler service in Drupal core in order to invoke that hook. If you want to learn more about hooks api.drupal.org has a list of all of the hooks that are available in Drupal core. And you can also for any module that provides them they should provide documentation of the hook in a file with name of the module.api.php. I talked about this a little and I'm gonna bring it up again because not only are we looking at a scenario where likely in the future Drupal is going to move more and more towards the use of events in a way from hooks but it's also like as a module developer how do I decide should my module invoke hooks or dispatch events. Personally I think events are the way of the future and that again we're going to move more and more in that direction and I would advocate for probably in most cases if you're writing a module dispatching events from that module documenting those events. I think that it'll help make your code a bit more future proof. But I also don't think hooks are going to go away anytime soon necessarily. It's certainly going to be for the lifetime of Drupal 8 we will continue to have hooks. Maybe by Drupal 9 you might see a scenario and watch everything all of the hooks as we know them at least are removed maybe we'll finally remove that code from April of 2001 but probably not. The scenario that I come up with in which I would probably use hooks inside of my own module is kind of if my module deals a lot with forms particularly because of hook form alter and the fact that that's kind of your primary way of interacting with Drupal's form API as a module in order to alter someone else's code. I kind of feel like if I was doing a bunch of hook form alters and interacting with making use of the form API I might stick with using hooks primarily because I think it might get confusing if my module was like half the things it did were hooks and half of them were events. I mean now you end up in the same scenario that we are here it's like is that a hook or is it an event and it's like well it's probably a hook but it might be an event. Mostly I would look for consistency. But either way I don't think hooks are going to go away anytime soon so I certainly wouldn't say you should never use hooks. To sort of tie this all together this is like how I might use each of these different things in the process of writing some hypothetical module. So I'm gonna write a module that offers the ability to take a video file and encode it to different formats. I might wanna do something like have my module allow for an end user to choose from one of a bunch of different encoding utilities. It might be something like encoding.com or FFMPEG or ZenCoder. There's a lot of different tools that could be used to process the file. So I would create a new plugin type that was, I don't know, encoding utility and maybe provide one or two of those with my module but this opens up the possibility for any one of you to come along and say you know what you should really use some other encoding thing. Those are the three that I know. So I would create a new plugin type there. I would implement that at least once so that you had some functionality with the module itself and I would provide an interface so that anybody else that wanted to could create a new encoding utility. I would also probably then create a new service. The responsibility of this service would be say to take a file and encode it and give me the output. The benefit again of it being these services with an interface is I don't really need to know everything about how it works inside. I just need to know I can give it a file. It will do whatever it needs to do to figure out what type of file it is, what plugin the user has selected to use as an encoder, how to encode it, get the file back and ultimately I've just handed the newly encoded version of it without really carrying what happened inside of that factory or black box. I might also implement another service for interacting with the various encoder utilities so a lot of times what you'll see is there's a plugin type which allows for that definition of the functionality to Drupal and allows for an administrator to choose from a list of functionality but then the plugin might just be a loose wrapper around a service which does the bulk of the work. In this case that might be a service that interacts with for example the encoding.com API. So now I've got an encoding.com client that can deal with sending files to and getting them back but it's also because it's a service I can easily mock that API client and write tests so I could say I actually don't want to send this two gigabyte file and wait for 15 minutes and spend $20 to encode the file. I just want you to pretend like you did it and tell me that it worked or it didn't work so I can write tests. I would probably dispatch some events as well. An example of that would be right before starting the process of encoding a file I would say hey I'm about to encode a file. Does anybody want to make changes to that file or change the parameters that I'm using to pass to the encoder and I would also probably trigger another event immediately after it happened. I would say hey I just got a file back from encoding. Here's a copy of that newly encoded file in case you want to do anything like maybe upload it to YouTube or post it on our site or whatever the case may be. And then finally you might inside of all of that code your plugin types that work with an encoder probably do something like have configuration options for the different parameters that the encoder takes and how it should deal with the file. I would probably want to provide a way for other modules to make changes to the configuration being passed to the encoder before that happens and that would probably be a good candidate for using an alter hook. So you've created an array that is all of the configuration options you're going to use for that particular file right before you encode it. You said is anybody want to change the configuration before I start this task? And that's our module and an example of how we might make use of all of those different things within our own module. As a quick recap of the things that we covered we talked about plugins which are primarily a way of providing new units of interchangeable functionality to Drupal. The best example, and I think easiest to conceptualize being blocks but also used in almost any case where Drupal needs to get a list of things that can do X and provide an end user with the option to choose one or more items from that list. We talked about services which are basically a replacement for things that used to be global functions encapsulating a bunch of functionality like for example the utility for accessing a database or encoding a video into a single class. So you've got that discrete unit of functionality providing an interface for the functionality and describing it for Drupal's service container so that those services can easily be mocked or swapped out for testing or just swapped out with a different database service if you'd rather use Postgres instead of MySQL. We talked about events which are a way of allowing code that's executing within the context of Drupal to communicate with any unknown number of potential listeners what's going on, saying things like hey I just got a file back from the encoding service do you wanna do anything about it? Events work by allowing code to either dispatch events to say this is what I'm doing right now if you'd like to react to that or to subscribe to events dispatched by other pieces of code to say whenever that happens I'd like to participate as well and finally hooks, sort of the ongoing workhorse of Drupal hooks are specially named functions that in some sense do all of these same things they allow you to add new functionality alter existing functionality and provide services. Primarily where I think you'll see them used initially at least when you're getting into module development is for working with the form API and altering the different forms that modules in Drupal or other modules are providing. Basically anything that isn't a plug in a service or an event is probably a hook. And that's what I know about writing modules for Drupal 8. I'm happy to answer questions now or if you've got questions later you can tweet them at me and it would be awesome. See how good I did at providing the link for you to go give me feedback. Maybe you could provide feedback like it'd be nice if you'd put a link to the page where I could provide feedback. Thanks for coming. And we've got a couple of minutes if anyone's got questions I'm happy to attempt to answer them. Sure so the question is are events synchronous or asynchronous and so when you trigger an event do you have to if there's five listeners do I have to wait for each one to finish before I can do my thing? It's PHP so it's basically they're synchronous. So but and then the other part of the question was if you sent something off to be encoded would you have to wait until it came back to trigger the event? Yeah yeah I think so the question is like if I sent something to be encoded and it takes 15 minutes to happen do I have to wait 15 minutes to respond? And the answer is yes and probably likely the situation you're looking at in that scenario is like your code would trigger FFMPEG to start the encoding and then you would also tell FFMPEG let me know when you're done call this PHP method when you're done. And so like I could kind of dispatch to the encoder and then continue on doing whatever it was I was doing in my code and I would expect that the encoder would call back to and basically create a whole new request that says hey the thing is done. Does that make sense? Okay cool the question? I can repeat it if it doesn't work. Yeah sure so the question is in Drupal 8.1 the Migrate API switched from using configuration entities to implementing a migration as a plugin and kind of what's the difference between the configuration entity and plugin or why would you choose one or the other and then why did Migrate make that choice? I think that like fundamentally plugins and configuration entities perform two totally different tasks. A configuration entity is like the idea that it provides configuration data. So something like the settings that you would send to FFMPEG for encoding like that's configuration. A plugin provides new functionality. That generally requires some execution of a code path in order to work. The Migrate one is like you said it's tricky and I don't necessarily fall strongly on one side or the other of whether they should be configuration entities or plugins and a lot of really smart people made some decisions about that and now it's so they're currently plugins. I think they were originally written as configuration entities because the idea being it would be nice if you could like a migration and the part of it that changed is basically the thing that does the field mapping where you're saying this field in the database over here is the title of the node over here and it was sort of this weird like is that configuration because it would be nice if it was because then you could for example provide a user interface that allowed someone to create that mapping. You could save it as configuration persist it so they could come back later and edit it and make changes or is that a plugin because it requires adding new functionality through a code execution path therein lies the real question is like which one should it be? I think that the it becoming plugins in Drupal 8.1 has a lot to do with that question of like are they actually configuration? Is the migration path actually configuration? And then also concerns about like polluting the data store with a bunch of information that was related to the migration that later on you're like we're done migrating we don't need all of this configuration anymore in some of that. To be totally honest I don't know exactly why it switched and it was one of those like I guess it changed and now I have to learn a new thing there's a really really long thread about it on Drupal.org that kind of discusses the pros and cons of plugins versus configuration in that instance. I also think that in your own code that's probably it's probably in most cases going to be a pretty clear delineation between things that are configuration like for example settings about how you're going to optimize images versus things that are plugins like for example a class that runs a bunch of PHP code that you know goes off to get information from amazon.com and store it locally as part of a field formatter. Does that help at all? Okay, cool. Yeah so the question is should I extend the class or should I implement the interface and how do I know which one to do? I would say it depends on what the class that you're extending does and whether or not the thing that it does is useful to you. And so if you're extending the class but really don't care about any of the things that the base class is providing any of that sort of prepackaged functionality go ahead and just implement the interface and skip extending that base class. Where it's nice is when a base class provides a bunch of generic functionality that you would probably make use of. A common example would be block plugins. You probably are going to want access to things like the service container injected into your block plugin and you're going to want to use Drupal's translation system because you're going to have strings in that block plugin and if you extend the base class those things are already made available for you. But if your block doesn't have any user interface strings and doesn't use the service container sure you could implement the interface. Yes, absolutely. Yeah, so I mean the concern there would be like what happens if the person who maintains the module that provides the base class changes what the base class does. I mean you could say the same thing about what if they change the interface that you're implementing it's a little bit of if you're working to extend someone else's code you're kind of always at their mercy a little bit because they could change things whenever they want to. Extending is good. Extending is almost always good because the reason that the base class exists is generally to provide like the 85% use case. And now you just need to do 15% of the work. If it doesn't provide that then skip it right because now you've got like a performance problem where it's like you're loading and executing all of this code that you're not actually doing anything with. Yeah, that's the weirdness of events in hooks is it's kind of like hooks could do the same thing. You could totally use a hook to say hey someone just logged in right like that's what Drupal 7 does. Hey a node was just saved. Hey someone just logged in. Do you want to do anything? And so that's a little bit of the weirdness of trying to figure out should I use an event or should I use a hook. My rule of thumb at the moment is I favor using hooks, especially if it's a scenario where really I'm just kind of trying to announce this happened and provide context right because you can like hook or events are like events you can send a message. You can say this just happened, send an envelope with a bunch of data in the envelope and then the receiving code can do whatever it want but it never gets a response back. Like the event doesn't say hey I finished. Here's some new things. Hooks handle that scenario currently where so the form alter is a great one where you say here's the form. Do you want to make any changes? But I need it back when you're done because I still need to display it or a configuration for the video encoder. It's kind of like here's the configuration we came up with but I still, I need your modified version back afterwards. Awesome. Yeah. I'm sure it's going to take a while. that can reach out and talk to you. Oh, you're right. But you could use Google's existing REST API for sales support that you can get into. Right, right, yeah, I mean, that's the wrong thing. Yeah, it was definitely the same in the first place. You know, there's some things that are going to be a little different in this world with Salesforce. Yeah, Salesforce is the truth of the force. So I don't think it's necessary. I'm just trying to find the disconnected that makes people hurt, you know, and I'm not absolutely sure. And you can get, yeah, it's a little bit... It's a little bit... Well, one, I guess... I'm trying to do that. Yeah, it does.