But further ado, we are very happy to have Tianyu telling us about pipe dreams, bumpless pipe dreams and bruh head chains. Please go ahead. Thank you for the introduction and thanks for the opportunity, it's my honor here to tell you something about pipe dreams, bumpless pipe dreams and bruh head chains. So in today's talk I will be first telling you three different formulas to compute the, sorry, the compute the superpoinomials, we are going to compute superpoinomials using pipe dreams, bumpless pipe dreams and bruh head chains. And then we are going to use some connections to somehow jump back and forth between these three objects for superpoinomials. This time I'm not going to define these superpoinomials, I'll just tell you how to compute the superpoinomials using these three different kamikara objects. Let's just start from the pipe dreams. So this looks like a video game, so it's like you have an N, then you have a staircase grid, and then what you write game here is to put these tiles into this grid. So the rightmost tile in this grid have to be this elbow, this red elbow that looks like this, and then every single, every single other tile can be either a crossing or a bump, but keep in mind that we cannot have double crossing, meaning that two pipes cannot cross more than once. Once you have a pipe dream satisfying these conditions, you can attach a permutation to this pipe dream. To attach the permutation, you just write 1, 2, 3, 4 on top, you follow the pipes and read 2, 1, 4, 3 on the left. So these three are pipe dreams of the permutation 2, 1, 4, 3. This time, if I want to compute a superpoinomial of 2, 1, 4, 3, I first find all these pipe dreams of 2, 1, 4, 3, each pipe dream gives me a monomial. To find the monomial, you just remember a crossing in row i gives you xi. So here I have x of x1 times x1, that's x1 squared. Right here I have x1 times x2, that's the monomial, and I have x1 times x3. The last step is to add them all up, and that's your superpoinomial of 2, 1, 4, 3. We can also use bumpless pipe dreams to compute the superpoinomial, so this time the grid is a square, and every tile can have six options. This time the pipes enter from the bottom and they go to the right. And again, we don't want to see double crossings, like two pipes cannot cross more than once. This time we look at these blank tiles. Your blank tile in row i gives you an xi. So here we have x1 times x1, x1 times x2, and the next one times x3. We add them up, and we also get the superpoinomial of 2, 1, 4, 3. So these two rows are fairly diagrammatic, and I'm going to tell you the more complicated one, which is the Bruja chain formula. Let's just start from something called Bruja order. So this is a very famous partial order on permutations. So here we have the Hase diagram of this partial order. Whenever you can see an edge going from 2, 1, 3, going up to 3, 1, 2, we just write 3, 1, 3, covered by 3, 1, 2. And to describe this copper relation, we need a few notations. So this tij here is the transposition that swaps i and j. So wtij is obtained from w by switching wi and wj. We say w is covered by wtij if first i is less than j, wi is less than wj, meaning that I'm swapping a small number on the left with a large number on the right. Moreover, I want to make sure that numbers in between are not in between. This just means whenever I'm swapping two numbers, I have to make sure that every number that's physically standing between do not have values in between. For instance, 2, 1, 3 here is covered by 3, 1, 2, because if I swap 2 and 3, the one sitting between doesn't have values in between, so the 1 is happy. However, 1, 2, 3 is not covered by 3, 2, 1. That's because if I want to swap this 1 and the 3 here, the two sitting in between might not be happy about this. And once we have w covered by wtij, we can draw such a funny diagram. We can have an arrow going from w to wtij, and then we can put a label k here on top of this arrow. The k can be any number that's in between i and j minus 1. Whenever we have a sequence of permutations where each one is covered by the guy on its right, and whenever I can put the same k on each of these arrows, we say this is a k-chain. Right here, I have a 2-chain. So one way to think about the 2-chain is, you just go ahead and put a bar after the first two numbers, and then you always make sure you swap a small number on the left of the bar with a large number on the right of the bar, making sure that whenever you do a swap, numbers in between are not in between. For instance, right here, I can first swap the 1 and the 4 across the bar, then I swap the 2 and 3 across the bar, then I swap the 4 and 5 across the bar. This is a 2-chain. I made 3 swaps, so this is a 2-chain with length 3. This is actually not just an arbitrary 2-chain. This is what people call an increasing 2-chain. If you look at a smaller number being swapped, it's 1, and then 2, and then 4. So the smaller number being swapped is increasing. People call such chains increasing 2-chains. Here's one fact. If you grab two permutations, u and w, and grab a label k, and then there either exists exactly one increasing k-chain from u to w, or there exists no such increasing k-chain. So we can just use these increasing k-chains to compute Schrodinger polynomials. That's why Bedroian and Sotila, they just go ahead, and try to compute a Schrodinger polynomial of 2, 1, 4, 3. So this time we start at 2, 1, 4, 3. We take an increase in 1-chain and go to some permutation. Then we take an increase in 2-chain and go to some other permutation. And we take an increase in 3-chain afterwards. We have to make sure our final destination is the guy 4, 3, 2, 1. The permutation where the numbers are decreasing. So these three are the chains satisfying the conditions. And you can see that now we have three terms. Each term should give me one monomial. To write down this monomial, I'm going to use the way that's slightly different from what Bedroian and Sotila had, but ultimately the same. I'm going to count the number of fixed points on the right side of the bar. So for instance, this one-chain right here, on the right of the bar, it fixes the 1. It fixes the 3. It doesn't fix the 4. That's x1 squared. This guy, this chain, the second chain right here, it fixes the 1 on the right side of the bar. So this is an increase in 1-chains or have an x1. This increase in 2-chain fixes a number on the right side of the bar. That's an x2. So this chain corresponds to the monomial x1, x2. And the 1 on the bottom corresponds to x1, x3. I just add them up. And I also get a super polynomial of 2, 1, 4, 3. So now we have three different formulas to compute the super polynomials. And now let me just describe their connections. So I'm going to start with the bi-jaction between pipe dreams and bombless pipe dreams. So it's well known that these pipe dreams on the right are corresponding to these pairs of words like this. Go and find a way to somehow bi-jack these pairs of words with these bombless pipe dreams using some sort of insertion algorithm. So that's a bi-jaction between bombless pipe dreams and pipe dreams. Recently, Knudsen and Udall defined all these hybrid pipe dreams which are like a grid where this time, some rows are satisfying the pipe dream convention and some rows are satisfying the bombless pipe dream convention. So they just start from a pipe dream and gradually change the convention of each row into bombless pipe dream and eventually they just arrive at a bombless pipe dream but upside down. And what they can show is that their bi-jaction agrees with the Gaohan bi-jaction. There are also bi-jactions between pipe dreams and chains. So I'm going to give you the one from the NARS or TLA but I'm going to tell you this bi-jaction in a slightly different way. So let's just start from this pipe dream which is the pipe dream of two, one, four, three. If I go ahead and erase the first row, I get a smaller pipe dream that's a pipe dream of the permutation one, three, two. So I just write one, three, two here and then I put four, I just prepare four in front. And then let's just erase the first two rows and I get a pipe dream of the permutation one, two. Let me put four and three in front. Eventually I reach a pipe dream of the permutation one and then I put four, three, two in front. Let's just denote this four, three, two, one permutation as the W naught. So what they're getting is like a sequence of permutations and you see that to go from two, one, four, three to four, one, three, two, you just take an increase in one chain and then you take an increase in two chain and then increase in three chain. So what they can show is that this is actually a way preserving bi-jaction between these pipe dreams and these chains where the labels look like one, two all the way to M minus one. That's those chains that appeared in the Bruja chain formula of superpoinomials. Well, if you think about bumpless pipe dreams, you might ask, well, can we do the same thing for these bumpless pipe dreams? So right here, I grab the bumpless pipe dream of the permutation two, one, four, three. It's for two, one, four, three because, well, this topmost pipe ends in column two. This second topmost pipe comes from this column one and then four and then three. What happens if I ignore the last row? Well, I can still try to read the permutation. This time I will read two, one, four. If I ignore the last two rows, I can still try to read the permutation. I would read two, three. This time if I erase the last three rows, I can still try to read two, while what I'm getting here are not permutations. But we can just go ahead and append the missing numbers and decrease in order afterwards. So I get two, one, four, three, then two, three, four, one, then two, four, three, one. Well, let's just put four, three, two, one at the very end. That seems like the formula for drawing Stotilla, but not quite. So this time we have to first take an increasing three chain and then increasing two chain and then increasing one chain. You see that labels here now three, two, one, instead of one, two, three. But we can still define weights in the same way. We can still say that this guy has weight x two times x one. That's because there's two chains, six is one number on the right side of the bar. This one chain also fixes one number on the right side of the bar. So this guy has weight x one times x two, which is the same as the weight of the bumpless pipe dream I started with. And what I can show here is that this is actually a weight-preserving bijection between bumpless pipe dreams and chains that look like this. Now you might ask, well, are we getting new formulas? Because this doesn't look the same as the withdrawn Stotilla formula. Well, here's the fact. If you grab two permutations, U and W, you grab two labels, K one and K two, and you grab two numbers, A and B, you count the number of such Vs. So you first take an increase in K one chain from U to V with length A, and then take an increase in K two chain from V to W with length B. Such V, well, the quantity is the same as the V prime, such that you first take the K two chain of length B, and then take the K one chain of length A. So for those experts wondering why this is the correct, the quantity on top is actually the coefficient of super W inside super U times the homogeneous metric polynomial in the first K one variable with degree A, and then in the first K two variable with degree B. But we know that when we are multiplying two Hs, we can of course swap them. So we know this quantity, these two quantities must be the same. An open problem here would be well find a bijection between these two sets that have the same size. Well, we have this observation here and then actually I'm lying in the very beginning of the talk. So my talk is actually about two plus M minus one factorial formulas for super polynomial because you can see that for these Brach chain formulas, they come in M minus one factorial flavor. You can just go ahead and grab your favorite permutation of M minus one. Let's say I grab two, one, three, then I wanna first start with an increase in two chain, then the increase in one chain, then the increase in three chain. I just look at a lot of chains that look like this. That will give you a formula of the super polynomial. So Mounties M minus one factorial different formulas. One of them, the guy where the labels are like one, two, three, corresponds to pipe dreams. The other extreme, when the labels are look like three, two, one, correspond to bumpers pipe dreams. Now, an actual question you hear to ask is, well, can we somehow interpolate from this one, two, three chain to this three, two, one chain by doing some local swaps? If you think about this, well, that's actually asking the question, that's actually asking the same question as the open problem in the previous page. Well, this open problem can be partially solved in this very special case. But this time, I have to require one of the label here is one. The other label here can be K, but I have to make sure that the permutation W has no ascent after K. Once this is the case, I have a black box called the Nars-Gromes Diagrams. So we can just treat this as a black box filled with the Nars magic. To use this black box, we put my increase in K chain on the bottom of this box and then I put this increase in one chain on the right side of the box. The Nars-Gromes just somehow miraculously give me this V prime permutation on the top left edge. I just grab this V prime, that's a bi-jaction between these Vs and these V prime. So that solves the problem a few slides earlier in this very, very special case. However, that's actually enough for us to give a bi-jaction between bombless pipe dreams and pipe dreams. So here's one bi-jaction. Bombless pipe dreams correspond to chains that look like this. We can use the Nars to somehow grab this one chain all the way to the front. And once we grab this one chain all the way to the front, we just realize that after the one chain, all these permutations start with the number four. And if we ignore this four, actually these are permutations in S3. So actually this two chain is actually just one chain and I can still use the Nars to grab it to the front. So in general, we can just go ahead and grab the one chain all the way to the last most position and then grab the two chain and then the three chain and then the four chain. And eventually the labels will become one, two, three, four. And I conjecture that this bi-jaction agrees with the Galvan bi-jaction and I have tested this conjecture on S7. Well, now we have this picture and I have five minutes left. So let me just discuss some future directions. Well, we have these M-1 factorial chain formulas to extreme correspond to two pipe-like objects and you might ask, what about the rest? Well, if you recall those hybrid pipe dreams, you do correspond to certain chains. So you can do the same trick. You can just go ahead and erase some of these rows and re-permutation out. But this time you have to append the missing numbers on both ends. So here I'm appending missing numbers on both left and right side. So you can see that this hybrid pipe dream correspond to a chain that starts with a three chain and then one chain and then two chain. And then in general, these hybrid pipe dreams correspond to two to the N minus two chain formulas, which is actually not as much as N minus one factorial. When N is four, this quantity here is also four. So these hybrid pipe dreams will cover the first one and the second one and the last two. The two in between are actually, well, we don't know how to turn these chain formulas into pipe-like formulas. So in general, if we can have N minus one factorial different pipe-like objects corresponding to these chains, that would be really cool. Another thing people might wonder is about double-fibro polynomials. These are polynomials, which have two sets of variables, X and Y. To compute these double-fibro polynomials, you can either use pipe dreams or bumpless pipe dreams. If you choose to use pipe dreams, this time, a crossing in row I column J gives you something called XI minus YJ. So here this is X1 minus Y1, this is X2 minus Y2.  If you wanna do bumpless pipe dream, well, then this time of blanking row I column J gives you XI minus YJ. So this is X1 minus Y1 times X2 minus Y1. If you look at the corresponding chain, well, this time this increasing one chain fixes the number one on the right of the bar. And this increasing two chain fixes the number two on the right of the bar. That's somehow similar to this X1, Y1, and X2, Y2 thing. On the bottom, you can see that this increasing two chain fixes the one on the right of the bar. And this increasing one chain fixes the one on the right of the bar. That somehow corresponds to this X1 minus Y1, X2 minus Y1 thing. So I would conjecture that these M minus Y1 fact power formula is actually extend to double Schrodinger polynomials via the following rule. So this time you just grab your favorite permutation of M minus one, and let's say it's 213. You just grab a chain that looked like this and then if the increasing two chain fixes the number three on the right of the bar, that's giving you X2 minus Y3. If this increasing one chain fixes the number one on the right of the bar, that's giving you X1 minus Y1. I would conjecture that this is actually giving me a minus one fact power formula for double Schrodinger polynomials and this conjecture has been tested for S8. All right, that's all I wanna say today. Thank you so much for listening. Thank you very much for a very nice talk.


All right, so we hit 10.50, you've all had five extra minutes for coffee, hopefully that was enough. Again, PDF is already posted if you want to follow along on your laptop or make a copy of that for later. Thanks for coming, everyone. Amanda here told me we don't have a session right after, so if we run over a couple minutes for questions, that will be okay, too. This talk is titled, Drupal 8, where did the code go from info hook to plug-in? And the broad idea behind this talk is I wanted to really make Drupal 8 feel a little bit more accessible for people coming from Drupal 7, it might be trying to get their head around where some of the familiar pieces of code in Drupal 7 went in Drupal 8. This is also a good talk if you're just interested in the Drupal 8 plug-in system, but I'm gonna spend some time talking about a comparison between the code in Drupal 7 and Drupal 8. So if you've looked at Drupal 8, you might realize there's a lot of things that are gone. All these hooks, they're dead. Completely removed from the code base, you can't use them anymore. So what do we do? We replace them with plug-ins. So what I'm gonna talk about is really just give you a little bit of background about some, a couple key terms or changes in Drupal 8 just so you don't get lost when I keep talking about them over and over again.  Then I'm gonna dive into a first example. We're showing you where the code in a Drupal 7 info hook and corresponding implementation hooks went in a plug-in in Drupal 8. Then start showing you some code for a little custom module and how you can implement plug-ins in a custom module. So we'll start with putting a couple of tabs on a page as local tasks. Then get into a little more advanced examples where I'll show you how you can define a custom block, how you can define a custom text filter. And finally, a couple of best practices if you want your module to define its own plug-in type. So that's the roadmap for today's talk. This is me. Hopefully I look like that picture. I've been a Drupal core contributor since Drupal 5. I'm on the Drupal security team. I work for Biaraff now, which makes a web application for self-laboratory safety and compliance. And I helped create some of the Drupal 8 plug-ins that we're gonna be talking about.  So we'll certainly be happy to take questions on any of those. And I also help organize Drupal Camp New Jersey. So if you're in that area, I look for it next winter. So this is the key Drupal 8 background. Some things that you need to know without which you'll be lost. So I'll keep referencing them the rest of the talk. So the first thing is the dependency injection container, sometimes called the DIC, more commonly just the container or the service container. And this is an object that's available in Drupal 8. And it just contains instances of other objects. And each of these objects is a service. And what that means is you can grab that service, have it do some work for you, and then let it go. And they're stateless. That means they don't change. You use them to do some unit of work. But the service itself doesn't retain any state. So it has things like, who's the current logged in user? How do I take a route and render it into a URL? Things like that. But when the service is done, the service itself has not changed. It's stateless. So that's important. We'll be talking about services a lot in terms of how you get and interact with plug-ins. The other thing I'm gonna mention quite a few times is the new routing system in Drupal 8. So the key conceptual difference really between Drupal 7 and Drupal 8 is that we now have route names instead of using system paths. So the route name is just a machine name. And that machine name is connected to a path and to call backs to provide the page content, the title, all the things that a Drupal 7 menu router would have given you. But again, we're using these machine names. And so there's not a direct one-to-one correlation between the machine name and a path necessarily. Finally, you'll see a lot of full namespace class names in this talk. So if you're not familiar with namespacing, this is a feature that came in PHP 5.3. So it's been around a little while now. And what that means is a PHP class name can look like that full string on the bottom. So it's a Drupal search plug-in block search block. And that entire string is the class name. But you see each of those backslashes separates a section of that class name as part of the namespace. And that gives you information about where that class lives and what it does. So you can see that obviously it's part of Drupal. It's provided by the search module. It's a plug-in. It's a block plug-in. And then we get to the specific actual plug-in that it is. So this namespace is kind of like a little map. And it's also really important for auto-loading, which is something I'll talk about later. OK, so that's all the background. Hopefully that's enough to get you through the rest of the talk. The big topic here is plug-ins. And plug-ins encapsulate reusable functionality in a class, and they implement one or more specific interfaces. And all three of those things are really important to wrap your head around for plug-ins. So they're reusable. We can have multiple plug-ins and keep using them over and over again. We're not constrained to use it only once. It's all class-based. And what's really important is they use interfaces. And interfaces are something that make Drupal 8 actually much more powerful and much more malleable than previous versions of Drupal. Because all these plug-ins, all the services I'm going to talk about in this talk use interfaces. What that means is if you don't like the way that the implementation works provided by Drupal Core, provided by some other module, you can substitute your own implementation as long as it follows the same interface. And the interface just means essentially what methods does the class have and what parameters they take and what kind of return value they give you. That's what the interface tells you. As long as your code implements the same interface, you can substitute your version for anything in Drupal Core or a contributed module. So imagine it's essentially like swapping out the module file in Drupal 7 of some module when you want it to work a little bit differently. That's what you can do in Drupal 8. And so that's an extremely powerful new feature of Drupal 8 that makes it more pluggable, more changeable, that I think a lot of people don't yet appreciate. So a little diversion there on interfaces. So if you think about what a plug-in does, again, it's a reusable functionality. And it combines in Drupal 7 what was generally an info hook and a number of implementation hooks. So if you implemented hook search info in Drupal 7, this is probably not too common to implement, but if you wanted a custom search, you're searching something that's not nodes or users, something custom, you would have to also implement in your module hook search execute. So there's the info hook that tells you that my module provides a search. Hook search execute actually does the work. And those two functions both had to be present, but they didn't necessarily have to be in the same place. They might not even be in the same file or next to each other. The documentation might not be clear if someone was reading your module that these two things were coupled together and essential that they both be present in order for your search system to work. Similarly, a lot of you probably implemented a custom block to implement hook block info in your module. That tells Drupal about the list of blocks that are available to be turned on. But of course, if you did that, you also had to implement hook block view, which actually returned the render array for that custom block. If you only implemented hook block info, it was no good. Drupal thought there was a block, and it had no way to render it. Similarly, you might implement hook block configure, hook block save, in order to capture configuration about your block. But these different functions might not have been in the same file. Again, collated might not be documented as being connected to each other in your module. So it was often hard to understand the code in Drupal 7 how these different hooks actually work together to make your custom block work. So if you dove pretty deep into Drupal 7, especially something like C-Tools and Views, you might have seen that those modules in Drupal 7 had a plug-in system. So what we have in Drupal 8, in a lot of ways, is kind of a grandchild, you might say, evolved from C-Tools and Views plug-ins in Drupal 7. But a lot of the mechanisms used to find those plug-ins and create instances are completely different from Drupal 7. So there's a connection there. But you really can't have a one-to-one, you can't just copy over a Drupal 7 plug-in and have it work in Drupal 8. OK. So how do I get an instance of a plug-in? How do I do something with it? So that's through plug-in managers. So every plug-in type, so like blocks, I have a plug-in manager that's registered as a service in that service container that I mentioned earlier as an important background. So you basically say, hey, service container, can I have the block manager? I'd like an instance of a block and the block plug-in manager will give you back the object that knows how to render that custom block. So that's how we get to those through a manager. Every plug-in has an ID, which may generally be in its derivative, just a static string. And we'll see a lot of those in this talk as examples. But we can also have derivatives. So a derivative, more commonly, would look like a static string, a colon, and then a UUID. So that's a very common pattern for derivatives. And so essentially, there's a base definition and then a lot of unique versions of that plug-in. And I'll come back to those later and give you a little more information about derivatives. But the thing you need to know is that for each plug-in ID, which might just be a simple string, that basically corresponds to a one-to-one mapping to a class. So I have a specific plug-in ID. Every time I ask the plug-in manager for a plug-in with that ID, it's going to give me an instance of a specific class. As I mentioned before, you can actually go behind the scenes and replace, substitute your preferred class for the class provided by a Drupal core module if you need to. But again, once you've done that, the one plug-in ID always maps to the same class. Finally, we want a plug-in instance. We want something that's actually working. And so we not only need to know the class, we need to be able to instantiate the class. And in general, a plug-in instance, the thing you actually use is a combination of that class, and then it is instantiated with specific configuration. And we'll get back to that a little more. But think about blocks. If you use blocks in Drupal 8, you know that you can take the same block, and you can place it as many times as you want in your site in different regions, in different themes. So every one of those is the same plug-in ID using the same class, but different configuration. So it's that combination of the plug-in ID slash class and the configuration that gives you an actual useful block instance. That configuration is often specified by a config entity. So just store that in your mind. We'll come back and talk about that a little bit more later. OK. So as I said, sort of an intro. This talk is a little bit designed to be reassuring for people coming from Drupal 7 that they can understand the code in Drupal 8. So you know the saying the drop is always moving means we kind of break things and rearrange things between versions of Drupal. But the message I have for you is that Drupal 8 and Drupal 7 still share sort of the fundamental DNA. And a lot of the code is actually line-to-line the same. It's just moved to a different place. So that's why the subtitle of the talk, Where Do The Code Go, this is intended to give you some sense of how the code moved from Drupal 7 and where it lives in Drupal 8 and how it works in parallel to how it worked in Drupal 7. OK. So the first info hook conversion I want to talk about is hook image toolkits. And you might be complaining that this does not have the word info in the hook name, sorry. But it is actually an info hook. Info hooks just generally returned you an array of metadata. And you see here the metadata has a top-level key of GD. So that's the image toolkit we want to use. We have a translated title. And then we have a key that's basically dynamically populated here with a method that says whether or not this image toolkit is available. So this is pretty simple info hook, right? If you've ever implemented something like that, you just return the metadata and that's it. So in Drupal 8, things end up working the same way, essentially, but they're organized very differently. And so in Drupal 8, this is a class that implements an image toolkit. And you see above the class definition is the special code comment, which is an annotation. You see that at image toolkit. And what Drupal 8 is actually doing is it parses these annotations out. So these annotations are not actually code comments in a pure sense. They're actually providing Drupal information about this class. And so they need to be formatted precisely. They need to use the right keys and values to tell Drupal what you want to do with this class. And so this at image toolkit annotation is parsed out. And the result of that is actually essentially the same as the info hook in Drupal 7. So what we get back at parsing this annotation is an array. And you'll see the top level key is this ID GD. That's exactly the same as the top level key that we used in the Drupal 7 return value from the info hook. We have, again, a translated title, which is, I think, the same string as it was in Drupal 7. So the result of finding the plugins, this process called plugin discovery, gives us an array of metadata that's essentially the same as the info hook return value in Drupal 7. And again, you see we have a method here is available. So this method is used, then, by the manager to do this sort of dynamic flagging that we did in Drupal 7. So the plugins themselves can't give you this metadata back. We actually need the manager. So I told you every plugin type has a plugin manager. Plugin manager has a method to pull back the list available plugins, this particular one get available toolkits. And it's a little different than other plugin managers, because it's going ahead and is running this method on each image toolkit. This is available method. So just like in Drupal 7, we were dynamically setting the property saying, is this toolkit actually available in the version of PHP I'm running? In Drupal 8, we're doing exactly the same thing. We're checking if the image toolkit is available. And if it's available, we include it in the list. If it's not available, we leave it out of the list.  Again, these two things work almost exactly the same. It's just the way we get to that information is a little bit different. So let's dive in a little more. So image toolkits aren't very useful if you can't actually work on images. So you have operations that happen on images. So the image to saturate function is an example of this in Drupal 7. You see this function. We're passing in a standard class object. So that's a really boring object. It just has some properties we set on it. It doesn't have any methods. It doesn't tell us anything special about what it does. And how do we actually carry out a method on this image? We call image toolkit invoke. So we delegate the actual work to the current image toolkit. We're just passing the string saying desaturate. So here's the object. Here's the operation. Image toolkit, please handle this for us. Drupal 8 works actually in a very similar way. So we have the plugin, the image toolkit plugin that we need to call basically to have this desaturate operation happen. In Drupal 8, we've turned the relationship a little bit on its head. So instead of a standard class object, we have a proper object now. We have an image class. And the image class has methods, has predefined properties. And so the image object essentially knows how to call desaturate on itself. So it has a desaturate method. You see that desaturate method that works basically the same as Drupal 7. It says here's a string operation desaturate. And I'm going to just pass that off to the image toolkit that is currently active and ask the image toolkit to actually do the operation of desaturate. So again, Drupal 7 and Drupal 8 working almost exactly the same way. It's just the organization of the code. Here it's inside the image object. In Drupal 7, it was inside that image toolkit function. Finally, we go one level deeper and want to look at how this image toolkit actually did that work. In Drupal 7, for hooks and many things like these image toolkit operations, we had this process of building up a function name by prefixes. We'd say, hey, all right, so this is an image operation. So the first part of the function name must be image. It's the GD toolkit. So the second part of the function name must be GD. And the operations desaturate. So that must be the third part of the function name. And if that function exists, I'm going to call it. And nothing would go wrong. Did everyone ever have a case where you accidentally implemented a hook or something just by accidentally naming it? Yeah. That could be a little scary. So again, like Drupal doesn't actually know that this function is going to exist ahead of time. It just builds up the name and calls, hey, function exists. Great, call it. But you'll see inside there, it's pretty simple code. We're just checking if the PHP version we have supports this operation. If not, we log a warning or a notice and return. And then we call the built-in function on the resource and say convert it to grayscale. Drupal 8, if we go this one level deeper, each individual operation is also a plug-in. And as I talked about, your ability to substitute things in Drupal 8, if you didn't like the way this particular operation worked on images, you wanted it to behave differently. You could substitute a different class for this specific operation, and none of the rest of Drupal would be any of the wiser. We call this your preferred class instead of the built-in one that comes with core. So here you see this is, again, a plug-in. We have a different annotation. We have an image tool kit operation annotation, an ID. We're told it's associated with the G tool kit and that it's going to do the desaturate operation. But you'll see that inside there, the code is essentially identical to the Drupal 7 code. So executing this desaturate option, we are, again, checking if exactly the same built-in function exists. If it doesn't exist, we log a notice. And if it does exist, we go ahead and we perform the grayscale operation on the related image resource. So again, there's a one-to-one mapping between what happened in Drupal 7, what's happening in Drupal 8, where the code went from those hooks, from those functions named based on prefixes, into these plug-in classes. So code is still there. It still works the same way. It's still kind of Drupal, but it went into these class-based plug-ins instead of being in functions. OK, so you may be thinking, what about hooks? I remember hooks as being the most important thing in Drupal. And for good or ill, hooks still have their place in Drupal 8. In fact, there might even be more hooks in Drupal 8. And the reason for that is that every one of these plug-in managers basically implements an alter hook, or provides an alter hook, so that this is the way you and your module can go in and change what these plug-in managers are doing, which classes they're using for a given plug-in, or even which plug-ins are available in the system. So this is, if you're thinking about, how can I change the behavior of my site? I want to change the way one of these plug-ins operates. This alter hook would usually be the first place you'd want to look. And you could go in your module and just do a quick substitution, say, use my class instead of the built-in class from Drupal Core. So an example, hook block alter. This might be one you want to use. You're not quite happy with the way a core block works. You want to subclass it, change its behavior. You could go in and in hook block alter, say, use my modules block instead of Drupal Core's block. And that would happen. So there's also hooks that really weren't candidates for being converted to plug-ins. So there were info hooks that just returned a data array. And they didn't have any associated code. They didn't have that implementation hook. And so there was no reason that those would become plug-ins, because all they were was metadata. But you may find some of these hooks, probably most of them, got removed also. And what happened to those instead of making them plug-ins, we just turned them into static YAML files. If people aren't familiar with YAML, this is a fairly simple human-readable way to write a data file, basically to write out arrays into a file in a way that's safe for Drupal to parse it back in. So an example of this in Drupal 8 is hook permissions. If you remember, hook permissions from Drupal 7. Hook permissions just gave you back an array. Said, here's the permissions. Here's what I call them in the admin UI. Here's a flag that says if it's a dangerous admin permission, things like that. But there's no logic. There's no execute permission function. So in Drupal 8, permissions are actually stored in these YAML files associated with your module. So in Drupal just knows how to parse the YAML file into an array. So the end result is the same. In Drupal 7, you've got an array of permissions. In Drupal 8, you've got an array of permissions. It's just stored now in a file instead of being in PHP code. So there's a few other great hooks that we all love, like hook cron. That actually is still more or less the same in Drupal 8. Things like hook entity access. You might want to mess around with access controls. Some of these weren't converted because of lack of time, or some of them it's just still, it's such a Drupal thing to change entity access that there wasn't a clear mapping and just some more object oriented strategy there. OK, so I've mentioned plugin discovery already. Plugin discovery is how the plugin manager gets the metadata about your plugins. And I basically told you it's the same more or less in the end result as invoking an info hook. You get an array of metadata. It tells you about the available plugins and some things about their definitions. In fact, if you wanted to, you could actually implement a plugin type that had an info hook as this discovery mechanism. I wouldn't recommend this. Drupal Core doesn't do it except in a test to verify that it still works. But you can think about it again. The result of plugin discovery is just an array of metadata, and that gives you an array of plugin definitions. And that's just string keys and values. It's nothing exciting, but it just tells you the basic information about things like plugin IDs, which class to use, various things. The plugin process also fills in defaults, so every plugin wants to know it's provider, which is the module that's defining that specific plugin. And discovery can make derivatives. And so derivatives are a case of where you get many plugins, basically out of one plugin definition. And so let me explain that a little more and then I won't talk about it again. But an interesting example in Drupal Core is the field UI local task. So field UI local task is a plugin, and it wants to put a local task, which is a tab, usually in the UI, on every bundle of every entity, so that I can manage the fields associated with every bundle of every entity. So if you think about that right away, you say, well, I can't know in advance which entities are gonna be defined in my system and which bundles they're gonna be. So bundles are the same, basically, as node types in Drupal 7. So I have different entity types, they have different bundles like node types. For every single one of those, I need to define a tab that's in the admin interface associated with that entity and its bundle so I can manage the fields associated with that entity and bundle. So derivatives are the way we handle that case. So that plugin knows how to query Drupal, find the list of all entity types and all bundles, and dynamically make a derivative plugin associated with each one of those entity types and entity bundles, stick that tab on the associated admin page, allow you to manage the fields. So this is basically where derivatives are useful. You have something in your system that's dynamic, something like entity types, the bundles, the available languages, for example, and I wanna either define a tab or I wanna create some available behavior associated with each one of those dynamic things so I can have a derivative, I can query Drupal, find all those dynamic things and associate a plugin with each one of them. So that's it for derivatives. If people have questions at the end, we can talk more about them. Let me just give you a little overview of how plugin discovery works most commonly in Drupal Core. So we have two sort of broad categories, I would say, which is the YAML-based discovery and then annotation-based discovery and I showed you a couple examples already of annotations. YAML-based are for a bunch of these things that we pulled out of hook menu in Drupal 7. So we have the menu links, local tasks, local actions, contextual links. These are the things you most often use YAML-based discovery in Drupal 8, which means you would basically just author a YAML file in your modules directory and that would basically tell Drupal that there should be a plugin created with some specific definition. And we'll go into those and show you what a local task plugin implementation might look like. And the reason we do that is that basically all of these things, all the local tasks, more or less, or 95% of them, use the same class behind the scene. In contrast, most of the plugin systems in Drupal Core use annotation. So the couple of these, one I showed you already, the image toolkit, which uses annotation and maybe some configuration, but doesn't have a config entity. Then the vast, vast majority of plugins in Drupal 8 use a combination of an annotation-based plugin discovery system and a config entity in order to combine those things together and give you a specific plugin instance. So things like blocks, which I've referenced a bunch of times and we'll talk about more, views, all the views plugins, so like a views display, image effects, searches, if you wanna define a search. So those all use a combination of annotation and a config entity. Finally, just a little warning, if you wanna go look at the code and figure out how plugins work, the entity system in Drupal, more or less works like a plugin, it has annotations, but there's so many things layered on top of the entity system, you should not try to use the entity system to understand the plugin system. So start with a much simpler plugin system, even like the block system, which is a little bit complex, as much easier to understand than the entity system. So focus on one of these other ones if you wanna understand how plugins work. The entity system obviously is great for a lot of things, but it's just not an easy example to dive into first thing. Okay, so as I said at the beginning, we're gonna look at a little code. I'm gonna show you how you can implement in a module some of these plugins. So we're gonna start with the Drupal 8 plugin toolkit. So you need a module. You're gonna write your own module in Drupal 8. All you need to define a module in Drupal 8 is a .info.yml file, which is a .yml file. I said .yml is all over Drupal 8. So you don't even need an empty module file. In Drupal 7, you needed at least a .module file to exist in the file system. In Drupal 8, you don't even need that. You could just write this one .yml file and Drupal will recognize your module and allow you to enable it. The reason for that is that most of the module code is now in classes, it's not in the .module file. So it's perfectly fine for there not to be .module file because all you might have in there would be a few hooks anyway. The other thing that's fun to know about Drupal 8 is the code base was reorganized and if you ever developed a site and handed it over to someone in Drupal 7, you had to keep telling them over and over again, don't put modules in the modules directory. That would make sense, but don't do it. You have to put it in sites all modules. Something, right, Drupal 8 is different. Drupal 8, you can actually put all your modules directly in the modules directory. All the core modules now live under the core directory under core modules. So people, you don't see them, it's under the core directory and you can actually go ahead now and put all of your custom modules or you contributed modules under the top levels modules directory, it's a lot easier to find and manage them. So here's what basically all you would need to write to enable a custom module, have it appear in the UI and turn it on. All the code I'm showing you is in a sandbox. I'll give you a link at the end if you want to clone that sandbox and look at the code yourself. Turn it on in a Drupal 8 site, play with it. So the .info.yml file contents looks basically the same as a .info file in Drupal 7. It tells you the name, tells you this is a module. Options there are basically module, profile and theme for the type, description and of course that it's a Drupal 8 module. So once we've done that, we can start adding some plugins to our module. So I'm gonna add two local tasks. Local tasks, tabs, I don't know what term people prefer. So in order to that, all I have to do is write a YAML file. I just have to follow this naming pattern, mymodule, links.tas.yml. In that file, it's a very simple format. The top level key is the plugin ID. So I talked about plugin IDs, a plugin ID is gonna map to a class that's gonna provide the functionality. Route name, so I told you route name is a machine name as basically tells you how this tab is gonna have a link rendered to appear on the tab. So the link is gonna link to that route name wherever that goes. The title and then a base route. And so this is new in Drupal 8. When we rewrote this local task system, I was really sick of this default local task thing that you used to have to do in Drupal 7. Jump through hoops to make two tabs appear together. So in Drupal 8, basically this is all you have to do. You just tell it, okay, this base route is sort of the grouping principle. All my tabs are gonna appear together there. And the one, the first one you see, that route is the route that it's linked to. So that's gonna be the default tab. So the default tab is the one that links to the base route. All the other tabs are gonna be the secondary tabs associated with it. So hopefully this makes for a little easier developer experience, easier to wrap your head around. So I put this on my module, I turn it on. You may have to clear cache if you write a new file, of course, because the plugin managers cache the definitions they've found before. But once I do that, I get two tabs appearing on the page. You'll see the right tab, the right hand screenshot is the default tab, the list tab. And that has path admin config my module list. The screenshot behind on the left is the secondary tab has path admin config also my module settings. So what have I done here? If you remember we were using route names, route names use our machine names. So Drupal no longer cares about the two paths. I can put these two tabs right next to each other in the admin page, even though the paths are not hierarchically related in any way. So this is a cute little feature of Drupal 8, hopefully makes it easier to build admin interfaces because you no longer have to jump through hoops aligning the paths where your pages appear in order to have a group of tabs related to functionality. Okay, and you see I printed some output on these two pages and now you may be wondering wait a minute, I think he just skipped a step because he pointed to some routes and he didn't tell us about the routes. So yes, all right, I skipped a step. So we back up, we also need to define the two routes. So these are custom routes in the module. Again, if you pull down the code, you can look at these. So the most common way in Drupal 8 to define routes is again a YAML file. So again, if you're not familiar with YAML files please read up on them. So this looks very similar to the plugin definitions but it's a routing definition and most of the keys in here are actually taken from the symphony routing system. So you can actually find, discover most of the things that are going on here by looking at the symphony documentation. And again, it's pretty simple. The top level key is the route name. You see module.list or module.settings. Those are the two route names. There's a path. Where does this route actually go? What path is connected to this route? And then the controller, which is essentially the page callback. And these two controllers I defined are stupidly simple. I'm not even gonna show you the code. It basically just prints out the class name and method. It's in the example code. A title and then access check, which is just true. So anyone can access these two pages. So this is how you define a route in your module. And then when we have these routes defined again then we can use them for things like our local tasks linked to them or we can use them in the block. You'll see later linking to them from our block. Okay, great. So hopefully that's, moving us forward, but you may be wondering, okay, I saw you wrote those two YAML files to define the plugins, but how the hell do I know what valid keys can go in those YAML files and what do they mean? And so that's something you have to dig in a little bit and we've put that information on in the plugin managers. So the YAML files aren't really self-documenting the way that you'll see that class annotations can be. But in the plugin manager you see here is the list of all the valid keys if you're defining a local task or a tab. So some of them you already saw like the route name, the route parameters goes along with the route name and that's things like a node ID. So if you wanted to link to a specific node that would be a route parameter. Title, the base route I told you about is where they're grouped. A parent ID allows you to have a hierarchy of tasks of tabs, so if you remember making secondary tabs based again on a convoluted system of paths and previous versions Drupal. Now all you have to say is this particular plugin I want to be underneath it and that works with that parent ID, the weight, the options for rendering the URL and again the class. So if you want to have a specific class rather than the default class you can provide that in your plugin definition. Okay. So that was a pretty simple example in a way. All I had to do was essentially define some routes or use some existing routes and then write a YAML file to get two tabs to appear which are basically implementing plugins in my module. So now we're gonna go into blocks and this is I think a really common use case. One of the first things people might do in a custom module say I wanna block, exposes a widget, it gives me a list of something on the site custom and hopefully you will like the new block in Drupal 8 compared to Drupal 7. Again blocks are plugins now. So every custom block is its own class. It's completely encapsulated. It lives separate from every other block. When you as the administrator go to the back end and I'll show you some screenshots of this to place a block, so you're placing a block in a region in a theme with a specific weight, a configuration object is created to track that setting. So now we know there's a specific instance of this block in a specific region in a specific theme. That config object that's created is a config entity which I've mentioned several times now and we'll also pause to actually tell you what that is. So config entity is an abstraction on top of the configuration management initiative. So people remember the configuration management initiative was a big thing in Drupal 8 and that basically lets you export or import the configuration of your Drupal site as YAML files. Again YAML, so we'll also view them as YAML files. So what this config entity abstraction does is let you treat essentially that data object that's represented as a YAML file as an entity.  And that means it's very easy for Drupal now to have an API that allows you to easily find, list, and load these configuration objects using the same basic API as you would to find, list, or load something like nodes. So that's why this abstraction is useful. So now Drupal can more easily just say, hey, I wanna do a query and find all the list of active block instances corresponding to which are basically these configuration entities. And so that just works now much more naturally in the API. In the example I'll show you, if you're writing just a basic block, you don't have to worry about this. So we're gonna extend a base class that Drupal 8 gives us. Drupal 8's already gonna take care of all the work of saving this configuration entity for us if we use that base class. So you don't have to worry about it all in the example I'm gonna show you. But in the back of your mind, if you wanna add your own specific configuration for your block, you're gonna have to add a little bit more code to add those settings to the configuration entity that's saved along with your block. Okay, so, how do we implement a block? We're gonna implement the Drupal core block plugin interface. Remember I told you about interfaces. Interfaces are very important because it lets us substitute or reuse code. So any block has to implement the block interface, block plugin interface, and any block essentially could be substituted for a different block as long as you're both implementing this interface. If you extend this abstract class that Drupal core provides, the Drupal core block block base class, all you need to do is implement one method, which is the build method, which is the same as hook block view in Drupal 7. So hook block view, you return a render array. Drupal 8, the build method, return a render array, that will be rendered for your block, you're done. It's very simple to implement a custom block in Drupal 8. So for this example module I added, Drupal my module, plugin block, my block. And a quick side note, people may be wondering again why this name space is so important, why I need to use this very long naming for classes, and that's because of the way that auto-loading works. So we're using the PSR4 auto-loading standard, and what that means is that when I add, when I want to add a block with this kind of name to my module, there's a one-to-one mapping of where that lives in terms of the file system. So it's at the path under modules, my module, SRC, then plugin block, my block.php. And if you look at that, you can see very clearly the mapping, of course this is Drupal, it's a module, it's under my module, so that's the first two parts of the name space, then plugin block, my block, are the last three parts of the name space. If you basically take those backslashes, you flip them to forward slashes, that defines the file path under that SRC directory. Right, so I'm gonna create a class in a specific name space, I have to create the corresponding directory under my module, under its SRC directory, and put the class file there. And then auto-loading works like magic, the auto-loader knows how to scan the file system, if I ask for a class of that name, it knows exactly which directory to find it in. Okay, so what does a block plugin class look like? This is basically, I cut a couple extraneous lines, but this is essentially all there is to it. If you wanna write a custom block, it can be this simple. You see this is annotated again, it's an at block annotation, it tells you the plugin ID and gives you a label that's gonna show up in the administrative interface, which I will show you in a second, a screenshot of, and then it just returns a render array. The render array has two links, they link to those two routes I defined in my module. So bringing it together here, so I defined the routes, defined a block, the block has two links that point to the routes, which have those two tabs. So hopefully, if you're trying to get started, that example code might be useful. So if I define this class, maybe clear the caches so that the plugin manager finds it, then I can create an instance of this block. If you haven't used the Drupal 8 blocks, I haven't paid yet, it's got a new functionality called place block. If you remember Drupal 7, it told you available blocks. In Drupal 8, we're gonna place a new block, and we can do that as many times as we want with the same block. So we can have as many instances that we want of the same block. So click place block, I do a search here, I find my module block, that was the string that was in the annotation as the admin label. Click place block again, and then I get a configuration page. It looks pretty similar to a Drupal 7 block configuration page, and if I click here, I've gone ahead and created a new plugin instance. I've created an instance of that block. So there's a configuration saying this block exists in this region, in this theme, with these settings, and so when I now go to my front page, that block will be rendered. You see there on the left, it's rendered, has two links that came from that render array in the build method, and it shows up on the page. So that's all there is to it. Block plugins, again, conceptually doing the same things as Drupal 7, but that code has all moved into the block plugin class instead of being present in hooks. And just to make that a little more clear, let's just do, again, a one-to-one comparisons. You can see how this code is moving from Drupal 7 to Drupal 8. At Drupal 7, we had hook block info, right, and that just returned an array, listing the blocks your module provided. In Drupal 8, that's handled by the block plugin manager. Block plugin manager knows how to get all the metadata from the annotations, and basically builds up an array of all the available block plugins. Hook block view. In Drupal 7, you had to give it a delta, right, because that one hook had to handle every block from your module. In Drupal 8, every block is its own individual class. It has its own specific build method on that class. So basically, we moved from having to know the delta to simply knowing which class corresponds to my block. In Drupal 7, there was really no good way to control access to your blocks. So you had to hack something maybe into the view hook. Drupal 8, if you want to, there's a specific method on every block class that allows you to control access to that block. Similarly, in Drupal 7, the way we handle configuration was a little bit like one-off. So there was hook block configure and hook block save, which again, you had to pass in a delta. Hook block save had a array, kind of a form values, an edit array, but it wasn't a standard form API thing. Instead, in Drupal 8, we have a very standard form API workflow. So we have the method that defines the form, the method that validates the form, the method that submits the form. So if you've used form API in Drupal 8 for anything, this flow here for a block plugin works exactly the same as every other form in Drupal 8. So I think that's nice. We've got more consistency now in how we're using our APIs. We've made it easier to control access and we made it easier here to validate the configuration for your block. We actually have a validate step, which we didn't have in Drupal 7. Okay, so that's the mapping there. So block discovery and annotations. Each plugin type has to be in the expected namespace. So this is partly how the block is found and then it has to use the right annotation. All the core plugins have a custom annotation class so that at block, annotation actually corresponds to a class I'll show you. The annotation class provides that documentation about what things are allowed to be in that definition and provides some default values. And then there's a generic one that you can use basically as a starting point to extend. So this is what the block annotation class looks like. It extends that plugin annotation and again tells you things like the ID and the admin label are valid keys to put in the annotation, right? So that's what these mean. These variables here are the valid keys in the annotation. Okay, so last example is filtering text. We had an info hook in Drupal 7, hook filter info, which would tell you about text filters and how Drupal could, you could build up a text format that would apply different filters to your text. This example is taken from project module, not from core. And if you use Drupal.org ever on an issue, you've seen people put issue number in brackets with a hash sign that links to the issue, right? That's what this text filter does. You see in the info hook, we have the title, the description, and then we have, we're defining callbacks. So the process callback, the tips callback, and then we say whether or not this thing is cacheable. So that's the metadata we get out of the info hook in Drupal 7. We're told, again, the title description and then two callbacks and cacheability. In Drupal 8, it works a little bit differently. So we have, again, a plugin. If I would, so I'm basically implementing, re-implementing the project module's functionality in a slightly simpler form in Drupal 8 in this example module. We have an at filter plugin with an ID and a title. And then instead of those two callbacks that were functions in Drupal 7, we have methods on the plugin. So we have a process method and a tips method. And those do basically exactly what you think. We get some text passed in to the process method. We process it and then we return it. So we return it wrapped in this other object called a filter process result. And that's basically serving the same role as that cacheability flag in Drupal 7. So this process result object carries along with it some information about how cacheable this filtered result is. So it might only be cacheable for the current user or it might be cacheable for everyone. In this case it's just a link to a node. It's the same for everyone. I don't have to provide any special extra cacheability data. But in other cases you would wanna say this is only valid for the current user. And then the tips method of course just returns the filter tips that you see below the text edit area. So if I define this class, again, show you how that works. So let's say I create a nice first node on my site, node 2058. Now I want to enable this new filter plugin. So I go to my text filters in the configure section, edit, scroll down. I see this title I define in my plugin, format and node ID as a link. Click that off and save it. And now if I go and edit my second node, I can basically use this special format, these brackets, hash sign, node ID to create a link back to my first node. And you'll see that in the tips below we're getting just the return value of that tips method showing up in my filter tips. So great, if I save this, it works. I get the node title, I get a link back to my first node, which you can see if I hover over. And that's it. So now this little plugin that just had a, a couple methods to implement is able to provide me new filtering functionality for my Drupal site. And I can basically transform text from that sort of token format into an actual link with the title of the node that I care about. Okay, so hopefully that was all informative. A brief pause here for best practices. If you're, want to define a plugin type for your own module. So this means, for example, you defined an info hook in a module or you defined like a C tools plugin in a Drupal 7 module. Define it means you actually called like module invoke all to get the results of all other modules info hooks. So that's something you might convert to a plugin if you upgrade your module to Drupal 8. My strong advice to you is to use annotation-based discovery by default because it keeps that metadata, that annotation together with the class that's actually doing the work. So you have those two things in the same file, you can basically look at them together and make sure that you understand that they match up. The YAML discovery as I mentioned before is really only good for a few edge cases where the class implementing the plugins is almost always the same. So if 95% of the time, the class is gonna be the same no matter what module is implementing the plugin, you might wanna use YAML-based discovery. An example of where you might provide a specific class in Drupal 8 is let's say you want a tab in the page that shows the current user's name. So it has to be dynamic, it has to be specific for the current user, it has to pull in some other information, it's not a fixed string. So that's where you might provide that class name in the YAML file and tell Drupal, I don't wanna use the default class, I wanna use a specific one that has a different method for the title, but most of the time you're not gonna do that, you're just gonna have a fixed string for the title, a fixed link to a route and you're done. Okay, so here's some links towards the end of the presentation. So the sandbox where the code is, handbook pages on converting your modules if you haven't done that already, another handbook page on the plugin system and one that I wanna highlight specifically if you wanna dive in a little more about the philosophy of why we adopted this plugin system so broadly in Drupal 8 and finally a blog post from DrupalizeMe that covers a lot of the same things as talk does, but from, of course, a slightly different perspective, so you might find it helpful to compare notes from that blog post to what I was telling you today. So let's sort of move to wrapping up and I wanna just again give you a little excitement about using Drupal 8s, it has so many great features. So widespread uses of interfaces, everything in Drupal 8 pretty much has an interface, all the plugins, all the plugin managers, almost all the services use an interface and that means that you can replace them. You can say I wanna use my class instead of the one that was provided by core, as long as you implement the right interfaces, the rest of Drupal doesn't know that you've substituted, you've tricked it and given it your class instead of the one that it was expecting. In terms of building admin interfaces, you can now group tabs together regardless of what path they're referencing and that's partly because it's the route name that's the unique thing and not the system path. So we care about those machine names, we don't care about the path. What's also interesting about that is I can have multiple routes that are possibly serving the same path and why might you wanna do that? So imagine you wanna render a node either as HTML or as JSON. Well, it might be at the same path and I can then append a query string and get a different format and the query string basically might let Drupal choose between two different routes. So both these routes say I wanna serve the node content but in one case, if the query string is present, I'm gonna go to the route that gives you JSON. In the other case, I'm gonna give you HTML. Another example is get and post. So if I do a get request on this particular path, it goes to one route. If I do a post request, it goes to a different route. So that's really nice. It allows you to segregate out this functionality for different cases. That's something that wasn't easy to do in Drupal 7. Again, YAML, I've mentioned YAML, YAML, YAML. So if you're not familiar with YAML as a standard for those configuration data files, please take a look at it. Great thing about Drupal 8 is we have multiple instances of the same plugin. The key feature of plugins is reusability. So we can have as many instances of the same block as we want and reuse them anywhere you want on your site. And the way we do that is basically that each block instance has a corresponding config entity that captures that key configuration necessary to instantiate that one block instance. Okay, so to sum it up, plugins combine the discovery-available functionality with the implementation. In Drupal 7, that was really the combination of an info hook and multiple other implementation hooks and possibly spread across different files. So in Drupal 7, they were spread out. You weren't always sure where to look. In Drupal 8, they're actually nicely grouped together that metadata and the annotation and all the implementation is all in that one class file. If you're gonna define your own plugin type, please do use annotation unless you have a really clear reason to do something else. So that's pretty much it. I'll get to questions in a second. If you haven't been to Drupal Con Sprint before, strongly encourage you to stay for Friday. It's a lot of fun. So there's a half day in the morning of a first-time Sprinter workshop. There are people there that will help you set up whether you wanna do documentation or code. If you wanna do code, they'll help you get your local development environment set up to edit Drupal. So a great thing to do there and then all day there's the metric course sprint and the general sprint. So general sprint, you'll find people working in different contributed modules, documentation, marketing initiatives, all kinds of different things. And the metric course sprint, is people who specifically wanna work on Drupal core issues. And an exciting part of that is at the end of the day, they do one or more live commits of changes people made that day, issues that got all the way from start, not necessarily from start, but got all the way to finish in that day and get committed to Drupal core right in front of your eyes. So that's it. Please tell me what you think. Please go to the session node 21.025 on the site and please fill out the evaluations. That really helps me and helps the conference organizers know whether you appreciated this content, whether you got something useful out of it. And please also take the Drupal con and Nashville survey to tell them about the overall event. With that, I would be happy to take your questions. So if your questions, please come to the mic. So we get on the recording. Yeah, you mentioned that you could load a config entity, correct? Is there a way to alter it? Is there anything that would help you to change it on the fly? So there is a system, which I'm lucky on now, which you can dynamically alter configuration when it's loaded, yes. Great, okay, thank you. Yep. Hi, you talked about plugins, being able to use your own plugin to replace another one. Yeah. Is there a way to ensure which plugin, if there are multiple ones in the system, which one wins out and is actually being used? So which one wins out? I mean, that's really the same problem as like hook ordering in Drupal 7. So there's not a guaranteed way other than you can make sure that your alter hook is the last one to go, if you're worried about that. How would you make it sure that it's the last one to go? So Drupal 8 provides a hook module implements alter hook, which allows you to alter the order of in which module hooks are called. Okay. There's maybe still a module await, but I would recommend that hook is probably the preferred way to do it. Hi, great talk. Thanks. But first off, wherever you're working with QWorkers, is there a guaranteed way to make sure that the process item method is called? With QWorkers. Yeah, supposedly it's supposed to replace cron and the job that I'm trying to run is too big for cron to handle. So I've been looking at the QWorkers and I can make everything work, but I have to manually call process item in the constructor, which I know is just wrong. So I'm trying to figure out a way to make it. Yeah, we could talk about that though. So you might, so it doesn't really replace cron often what happens is, I don't know if you define the cron key in the annotation for your QWorker? Yeah, I did. You did, okay. So that should get called on cron then. I mean, that's, I've had it work, but yeah, generally you just break up those jobs into smaller chunks and put them in the queue and when cron runs it should call them. Well, do I have to implement hook cron for that to ever fire? Your module should not have to implement hook cron as long as you define that key in the annotation QWorker. Okay, well I'll dig into it some more. Thank you though. Yeah, sure. That's full of great talk. My question is regarding YML files. Okay. Sometimes you have to basically, I was doing a content import. So I have basically few different environments. So for if it's a Dev environment, get it from here. If it's a staging environment, get it from this URL. So how you can change the URL in YML depending on your environment dynamically? So did you go to Dries keynote today? Okay, so that was one of the things he highlighted as a problem is altering those. So there's a few different strategies. I mean, so one thing is you can, I mean, Drupal does ship with a system for altering config dynamically and that's for example how translations of configuration happen. Is that dynamic altering? But that's a little bit tricky. There are a couple modules that will let you basically substitute in different pieces of configuration. It's, I would say it's not a well solved problem. Unfortunately, which is why it was in the keynote. Okay, so it is a problem. It is a problem. Yeah, so substituting those values in, yeah, there's different environments. Kind of figured out I couldn't find anything on. Yeah, so I mean, you can override config values and settings PHP. So that's how we've been doing it. That's the only way for basically write some script which will when on Acquia post deploy hooks to directly alter your config. Yeah, I mean, there are, again, there are hooks that will allow you to swap things out and config at runtime. So it is possible to do in a module, but it's, yeah, it's not beautiful at this point. Great, thank you. Yep. Great talk by the way. Thanks. After you showed your routing YAML file, you showed the defaults property to show what properties you could use in that YAML file. Right, that was for the local task plugins. Right, okay. Now is there a way to see the sub properties, like the ones that begin with the underscore, like an easy way to find those? Oh, so those, that's the routing definition. So that's where I'd say look at the, starting point would be to look at the symphony documentation. I mean, I think there's some Drupal algorithms also, but if you start basically the symphony ones, most of those are fairly standard. Drupal has kind of repurposed a couple of them. So things like where a route is a form instead of just a controller, it uses like underscore form, things like that. All right, so a lot of those come from symphony now. But a lot of them come from symphony. So that's kind of, if you just want to get an overview of what goes in there, I'd start with the symphony docs. Great, thanks a lot. Hi, thank you for the talk. I had a question about the annotations. You said you could locate the definitions of the annotations. Where does that live? So those are classes themselves, so they're annotation classes. And the class name is basically the same as that annotation. So at block basically says there's a block annotation class. That's actually the name of the class. So you basically just look for a class name block that was under the annotation namespace of, in this case, Drupal core or under some module. Okay, and then another question on the routing. In symphony console, there was a command that you can show your routes, router debug controllers. Is there something corresponding in Drupal 8 so you can tie routes to controllers? So the Drupal console does have basically an equivalent command. So we'll list all the routes and then you can dive into specific routes to see the controllers. So the Drupal console, which basically wraps symphony console and some other things. Ah, okay, all right, thank you. Yep, you're welcome. Okay, any other questions? If not, thank you. And again, please fill out the evaluations. Maybe each other, about here, maybe you remember the search module and bypassing something, you know, the permission, you know the permission, if you remember. I remember your name, I don't remember the specific question then.


Anansi Boys by Neil Gaiman, the possibly but definitely not sequel to American Gods. It was published in 2005, four years after American Gods came out. It's an urban fantasy set in the world of American Gods, meaning that the same concept of anthropomorphized beliefs walking around as gods is a thing in this world. And we follow the son of a character that originally appears in American Gods. Mr. Nancy, aka Anansi the Spider, has a son, and we follow that son as he lives his life in England. He does not have the gifts that his father seems to have. He's a pretty average Joe, all-tolls, and he actually has generally quite bad luck. But when his father, Mr. Nancy, dies, then Charlie Nancy is confronted with a whole bunch of weirdness suddenly in his life. Okay, so is it a sequel? I mean, Wiki says no. But a lot of websites, bookstores, editions will label it as American Gods too. So, I don't know. There's no doubt that it's connected to American Gods, that it's related to American Gods. But in every other sense, is it a sequel? Like no, not really. You don't have to have read American Gods first. American Gods doesn't end on a cliffhanger. We were like, oh, I need to read Anansi Boys to close the loop on that. It can absolutely be read as a standalone. And American Gods, frankly, doesn't do all that much to explain the whole nature of Gods, really. Game and doesn't really do hard magic. So it's not like you're missing some really important information, like exposition. You're gonna pick up how the Gods and how that kind of stuff works. If you're gonna pick it up at all, you're gonna pick it up pretty much just as well in Anansi Boys as you would in American Gods. Again, Mr. Nancy does appear in American Gods, but he's not the main character or even among the main characters. And there isn't really anything you'd need to know about him from American Gods to make sense of him or to make sense of Anansi Boys. The events of American Gods have very little to no bearing on what happens in Anansi Boys, so it's not like you need to know the state of the world or anything like that. It seems to me that after having done American Gods, Gaiman had some other ideas for things that he could do utilizing this concept of the anthropomorphized belief God thing. So I think he just had some other ideas, and he had come up with this concept in American Gods, and so he just set it to write a different book doing something completely different in terms of the story or the themes and things like that. Just like another way to utilize this concept, but it's not a sequel in any other sense. Okay, so who is Anansi? So I was kind of surprised, or am surprised by how many people don't know or have never heard of Anansi the Spider. I am by no means an expert on frankly any mythology because I don't really like mythology all that much, but I remember hearing stories about Anansi the Spider when I was in grade school. I don't know if I just got luckier if that's like really unusual, but like in school we, when we had like stories read aloud to us, I remember there being like, they would, you know, feature like folk tales that are like not the ones you know, like not the Grimm's fairy tales. So they'd tell stories from other parts of the world, and I remember among them being some Anansi the Spider stories. So Anansi the Spider is a trickster and god that is featured prominently in West African, African American, and West Indian folklore, much like Loki from the Norse Pantheon. Anansi is known for his cunning, for his creativity, for his cleverness, his trickery, it's his ability to outwit and outsmart his opponents, not like brute strength that makes him so successful. Be wise, be brave, be tricky, am I right? And again, like Loki, he isn't necessarily the hero of the stories he's in, neither is he necessarily the villain of the stories that he's in. He can be both an ideal to aspire to and a cautionary tale, sometimes both in one story. Okay, so whether it's a sequel or not, how does it compare to American Gods? Well, American Gods is this massive sprawling all over the place meandering tome that is quite massive also in scope, not just in page count. And Anansi Boys is pretty much exactly the opposite. Where American Gods is about like the entire world of gods and men, Anansi Boys is really just about Mr. Nancy's family. That's it. And so the problems are much more intimate and specific and personal. There is some similarity, I would say, between the the protagonists Shadow Moon and Charlie and Anansi, which I don't know that that would be intentional. I think it's more just game and telling on himself like he has a way that he constructs protagonists a lot of the time. And so there's some similarity between the two. So they're both kind of directionless, kind of unlucky in love, confused, swept up in things that they don't quite understand. They're frustrated at being manipulated by forces that they don't understand. But there are definitely some differences. Charlie is more of a person than Shadow is. A lot of people complain about the kind of lack of personhood and lack of agency of Shadow in American Gods. So if that bothers you a ton, Charlie's a little bit that way, but he definitely has, I think, more of a presence and a personality and things that he wants and things that he's doing more than Shadow. Charlie has a life. He has goals. He has desires. And though he is tricked and manipulated by others, he's, I think, still the main driver of his actions, definitely more so anyway than Shadow Moon. Gaman is frequently humorous in a lot of his works. He's no Terry Pratchett. He's just not that interested in being comedic all the time. Oh, his books feature some humor. And I would say that while American Gods has some moments of humor, Anansi Boys is overall much more humorous just in general and has a lot more silly moments in it. And I think the overall tone of Anansi Boys is, again, partly just because the stakes of the story are so much lower. The tone of the story is a little bit more comedic. And then themes, there are some similarities in terms of the themes because they both deal with kind of the nature of belief by necessity, by virtue of having this concept in both of them. But Anansi Boys is more so about the nature of stories and storytelling, whereas American Gods is more about the nature of belief itself. They both have similar themes. They, I mean, they both have both themes. American Gods does have storytelling narrative themes, and Anansi Boys does have themes that relate to the nature of belief. But if I was to choose kind of like one big all caps theme, then American Gods is about the nature of belief, and Anansi Boys is about the nature of stories and storytelling. And I think having these different emphasis, no, that's not the plural of that. Having each one have its focus slightly elsewhere. It's a chicken or the egg, of course, but I think that has some bearing on why the tone and vibe of the books is different because depending on what you're focusing on is going to kind of like shape the type of story you're going to be telling. Not to be completely circling, looping around and around the nature of storytelling, having an effect on the story and the nature of the story that you're telling, but... Should you read Anansi Boys? I mean, not if you aren't a fan of this whole anthropomorphized beliefs thing, this concept. If you didn't like that, well, it's, you know, don't read it. If you need to have hard magic systems, honestly, I would tell you just not read Gaiman at all, but definitely not Anansi Boys. If you don't enjoy Gaiman's weirdness for lack of a better word, so things being kind of unexplained and strange and random and bizarre and kind of gross and just kind of out there, I mean, if you don't enjoy Gaiman's humor, again, Anansi Boys is even more humorous than American Gods, so if his sense of humor is not your sense of humor, then steer clear. And if you're not interested in storytelling itself being the topic of a story, which is quite meta, metatextual themes in general don't appeal to you, then yeah, steer clear. And if you want something exactly like American Gods, then also don't read Anansi Boys, because it's extremely different from American Gods. So if you wanted more of the same, you will be disappointed. But you should absolutely read Anansi Boys if you did enjoy American Gods and you would like to see some of the concepts and ideas in American Gods taken and used in a completely different type of story, a more intimate, smaller scale story. If you enjoyed the character of Mr. Anansi and would like to see more of him, if you enjoy Gaiman's unique style, his strangeness, his humor, if you don't mind or if you specifically enjoy stories that are more high concept, not really grounded, not realistic, not really intended to be fully understandable or explainable. And if you never read American Gods because this meandering, sprawling, directionless tone did not appeal to you and you much more are interested in a smaller, more intimate, smaller in scale, smaller in scope story. But you never read American Gods and so you thought you couldn't read Anansi Boys because it was American Gods too. Well, it's not. You're basically a standalone and if you want something really different from American Gods because you've no interest in reading something like American Gods, then you should read Anansi Boys because it's really different from American Gods. My thoughts? I enjoy it. It's not my favorite Neil Gaiman book, but I definitely enjoyed it more the second time and I enjoyed it the first time as well. Don't get me wrong. I think American Gods is more impressive in terms of what it sets out to do and then what it accomplishes, but Anansi Boys is more fun and I think Anansi Boys is a great example of Gaiman doing a lot of the things that he does best. His like efficient and distinct characterization where he gives you one sentence and you've got it. You know this character?  Like that never ceases to impress me. Is um quirky and inexplicable magic that kind of only makes its own kind of sense and his ability again to take the magical and make it mundane while making the mundane magical, imbuing everyday objects with wonder while these like really massively wondrous things kind of feel pedestrian? Is it my favorite Gaiman book? No, by no means, but would I recommend it? Absolutely. Have you read Anansi Boys? Would you recommend it? Do you agree with me? Do you disagree with me? Um as it stacks up with American Gods, which one do you like better? Whatever you want to let me know. I try to post videos on Saturdays, but other times as well so like and subscribe, join my Patreon if you feel so inclined and I'll see you when I see you. Bye.