 So, we're down here in the basement in DrupalCon Latin America and we're going to talk about capturing the Drupal8 flag. You might be wondering who this weird person is standing in front of you. And yes, at 3 a.m. when I'm writing tests, I really do sound like that and make that expression. My name is Tess Flynn. I am SocketWench on Twitter on various other social networks. That's Wench, not Wrench. I am a developer with Blink Reaction. I'm the module co-maintainer for Flag, for Flag Friend, and for example, Module. So the first question is, why port flag, other than we really need a Drupal8 module? So it was back in 2013, and I was actually sitting in the auditorium watching WebChick at DrupalCon Portland talk about how we really need modules to be ported now to Drupal8. Because the idea was that they had plenty of time working on core itself, but they didn't have a lot of time actually using real modules and testing all of their ideas to make sure that they actually worked. So you might wonder, well, why not just contribute to Drupal8 directly instead of porting flag module? Well, I was doing that actually. I was doing that for about a year at this point. And I was going pretty well, but then I kind of got stuck. Working on issues, working on core every night, but then I started realizing I was stuck in kind of a pattern. I was in what I call, I had the reverse Sisyphus problem. Now, Sisyphus is a myth where we had a man condemned by the gods to roll a boulder up a hill for all eternity, and by the time he got to the very top of the hill, it rolled all the way back down again, and he had to start all over again. The problem is, with Drupal8, I had the opposite problem. The boulder was already running down the hill, and all I had to do was run after it as much as I could, try to catch up to it every night and hope that maybe, just maybe, I will impart some small sense of momentum into Drupal8 before it rolls away from me again. And this is the problem that I was facing. Every hour or every night, for about three hours I had available, I had to spend a lot of time studying Drupal8 and by the time I got caught up to actually contribute to an issue, I couldn't find anything or I was too tired to go to bed. So what was I going to do? I had this problem and I couldn't figure out what was going on. I was stuck in the valley of dirt. When you're a beginner and you're working and contributing to Drupal4, you're on beginner's hill. And there's plenty of stuff to do. Issue summaries, you can run tests, you can re-roll patches, but everyone really wants to be in Dev City, where there's real issues and you can contribute real code to the project. But the problem is, there's a big valley in between those two points. What do you work on there? API docs, code style? You tend to just sit there looking up at Dev City wanting to be there, but rarely finding the opportunity to actually contribute. So I was sitting trying to figure this out and as all good ideas come to you, this one came to me with a shower, and there's got to be a better way. And it occurred to me that I should just port flag module. I was a Comey beginner or flag module at the time, but I didn't have a lot of knowledge in how Drupal8 and Drupal7 work, the module was a little bit unfamiliar to me. I tried work contributing to it, but I didn't know it that well. And I was so focused on contributing back to Drupal8 that I never got back to it. So I was having a problem. What do I do? Importing flag module seems like the most bizarre, ridiculous idea that I could come up with that would satisfy both requirements. So before I go any further, who in this room doesn't know what flag module is? Anyone? Raise your hand. No one? Okay, you. This section is for you because you raised your hand. So here we have a node display, and it looks like any other typical node display in Drupal, except for these two little links at the bottom. These two little links are flag links, and we've attached them to the node. So if we generalize this a little bit, we imagine our node, our happy little node sitting out on Drupal, and we have a user come by, and they go, ooh, shiny, and they stick a flag in. The module that makes the point sound has yet to be developed. Other users come along. They also add flags to it. Now from this, we can actually define what flag module is. It enables administrators to define boolean fields that can be attached to site content which each user, they set or unset. It kind of works like this. There's three principal objects involved. An administrator defines a flag and attaches it to any kind of entity on the site. This entity is called a flagable, a term that makes my eighth grade English teacher cry. Once we've defined the flag, users can come along and actually use that flag on that piece of content. In so doing, they create a flagging. Users can also unflag an entity at any time if they flagged it and have the appropriate permission to unflag it. Administrators, obviously, can also delete the flag at any time and therefore remove all of the flaggings that apply to that flag. So let's break this down. Flags are an administrator-defined boolean field. They've been stored as an entity since 2.x. They may be attached to only one entity type but multiple bundles of the same entity type. So you can define a node flag and have that flag apply to articles, to stories, to pages, or any one of those or any combination of those. You can also define a user flag and have it work on users or a common flag and define it on common. In fact, any entity type. You can create flags under admin structure. Flags and flags may also be fielded since version 3.x. Flaggings are an entity that is created to store when a user sets a flag. It basically stores four pieces of information. Which flag was set? What entity the flag was set? When was the flag set? And who set the flag? Flagables are any piece of content on your site. Any entity that has a flag defined for it and for which flaggings may be created. All right, so we know what flag does. We're going to port it. So what's the first thing we're going to do? We're going to sit down. We're going to open our IDE. We're going to start writing code, right? No. The very first thing that you should do when you're looking at porting a module to Drupal 8 is to first do a code review. What you want to do is ask your module, how does it really work? When it comes to flag module, we had Drupal on the bottom and we had several implemented hooks and alters like any other module, a function-based API like itself also defined a number of flag hooks and also implemented those hooks for its own purposes. Behind that, we had a number of straight backend functions but the majority of the code was in handler classes. We had a base handler class called flag flag and then we had specific cases for each entity type. One for all entities, one for nodes, users, comments, and so on. We also had a special case flag, flag broken, that was used when an entity type no longer existed on the site. Mostly this is a pretty typical Drupal 7 module. We have a large surface area of straight functions. Entity support was refactored in later in its life. Object-oriented programming was used but what's a bit like the blob? Blob is a 1958 movie in which an alien space creature devours an entire town and that's what a lot of PHP 4 classes look like today. They have weird factory methods. We have all methods were public, all class variables were public. Basically, we had a big blob of functions. So now that we've done a code review, we need to pick where we need to start a reporting process. The first thing you can do to really help yourself is to question everything. Nothing is secret. Sit down and act. Does it really have to work this way? When we defined this module before, we had to assume certain assumptions. Do those really apply anymore? Do people really use it that way? Can we do this better? Can we do this simpler? Then sets on the expectations. If you're the kind of person who just wants to go sit down and get work done, you might want to wait. While Drupal 8 has largely solidified in the last year, of tooling and documentation, that's yet to be written. Or yet to be very well documented. As a result, you might have some frustration if you just want to sit down, port and get it over with. If, on the other hand, you're here to learn, go for it. Don't wait today. Don't wait. Just start right now, this minute, this second. Go ahead, open your laptop. I'm waiting. If you're like most people, you're probably in the middle. You kind of want to learn, and in that case, you kind of want to keep it experimental. You want to start working on it, but don't really commit to it. Don't make a huge fuss that you're doing it. Just start working on it and see where it goes. You might be tempted to actually start by porting your test, so you can use test-driven development. Simple test is available in Drupal 8, but it's a bit of a double-edged sword. While it's easy to port your tests to Drupal 8, it might also limit your thinking. Then you're no longer questioning all the things. The best piece of advice is to start with the most central piece within your module and work your way out. Now, with Flag Module, it was the flag entity. That was the most central piece on which everything depended, so that's where I started my work. First, we wanted to design the flag class. Now, we could start with just a plain base class, but that's not very good object-oriented design. What we started with is we used an interface. An interface is a new concept in the PHP world, but it's been an object-oriented language for the better part of a decade. It's rather common. Also, once we find the flag interface, we also want to derive our class from a Drupal-provided class called config entity base. Now, I'll get back to that in a sec. We have flag interface. Flag interface is kind of like a contract. It sketches out what the object can do and what we can do with it. It is basically like a class, but it only has method names. It doesn't have any function bodies. It doesn't have any variables. It has no state assigned or attached to it. Defining an interface is best practice object-oriented programming, because it's a very light layer. And then we can define classes underneath that. It allows people to later on completely replace, in this case, the flag class, to do whatever you want afterwards. The flag entity is also a configuration entity. Now, in Drupal 7, we have entities. An entity was an entity was an entity was an entity. But in Drupal 8, we have configuration entities and we have content entities. Configuration entities are best for administrator-defined structures. While they live in the database, they may be exported to YAML. And it's basically structure, not data. Any time that you create, say, a node type, that's a configuration entity. Instead of doing a lot of work and implementing a whole bunch of hooks in order to define our entity type, we simply derive the flag class from ConfigEntityBase. ConfigEntityBase does all the foundation work that we need for configuration entities. It does all the Drupal stuff, so we configure it on our stuff. Now that we have our configuration entity, we need to add fields to it. This is done by defining a config entity schema. It defines what the config entity fields are, the data type of each field, and it basically tells Drupal what to save for this entity. This is what the flag schema looks like. It lives in the module root directory slash config slash schema, and it's a file called flag dot schema dot YAML. And it's a fairly straightforward YAML file. We actually have the kind of entity it is, so we can tell Drupal what to do with it, and then a number of fields. It's a very simple file to define. Once we have our schema defined, we need to actually take those schema variables and create class variables within our entity object. And what we want to do is we want to match every field we define in our schema to a class variable in our entity class. The reason for this is that it provides you code completion in your integrated development environment, and it's the easiest place to document your schema. Don't document it in the YAML file. Document it instead in the entity object. This gets to another point. Please, please use an IDE and a debugger. I'll get on with these, but I think the mic would fall off in my outfit. Yes, really, it's time. Drupal set 3,000 files, and some of those were very sizable and well-organized. Drupal 8 has at least four times as many and probably several more by this time. But the strategy is also different. Instead of large, single files that contain a huge suite of functions, it's many small files. Once we've defined our class variables, we want to define getters and setters. The best thing to do is to define a getter and setter for every variable in your schema. Your interface will not be complete unless if you do this first. Also, never mark schema class variables as private, because Drupal won't be able to read them. Drupal actually uses the config entity base class to actually read class variables. So any protected class variables that aren't visible outside of the class are still visible to the config entity. So we have our configuration entity, and now we need to plug it into Drupal. So what do we do? Well... So we have our flag object, and we have Drupal 8. So what do we do? We hand this on, we build this class, we hand it off to Drupal, and then Drupal says, that's just a class. What the heck am I supposed to do with that? And the flag is just sitting there going, I'm so lonely. What we need is we need an additional piece of information. We need to tell Drupal what this class does. It'd be really handy if we had, like, I know, a config entity assembly manual for flag. What this assembly manual is, is actually something we call, something we call an annotation. An annotation is an assembly manual that's used by Drupal to know what the class does. So Drupal can go off and build stuff. It's metadata that's included in the class doc block. It tells Drupal a few very important pieces of information. What the following class is, why it's important, and where to find other important pieces of functionality related to this object. This is a portion of flag's annotation. So we have a number of different things here. It's basically a hierarchical structure of key value pairs. We can actually see, at the very top, something called config entity type. So let's start there. Basically this annotation tells Drupal that the following class is a configuration entity. So any time that we perform a cache clear, it's going to appear within Drupal. Next we have a handler sequence. The handler sequence tells Drupal where to find other related pieces of functionality, such as the list all entities page, and also forms, like the add, edit, and delete form. Speaking of add, edit, and delete, it's time to build that administration interface. So this is what the flag administration interface looks like. It's very straightforward. We have a table of one flag per row. We have a button for add new flag, and we have some text at the bottom. How do we provide this page to Drupal? Well, what we do is we create a class called flag list controller. It derives from a Drupal provided class called config entity list builder, and basically it provides the admin structure flag page. It only has two important methods. The first method will actually tell you what the columns are in the build header method, and the other one is actually for to build each individual row. You don't even have to get the entity. Drupal does that for you. It grabs that and puts it in a parameter to the method. Next, we have the add and edit pages. The add and edit pages and flag are very similar. So similar that we might as well take advantage of that and reuse a lot of code. So what we do is we create the following class structure. So we start with a Drupal provided class called entity form, and for the add and edit form, we create another base class called flag form base. There's also the flag delete form, which tries from another Drupal provided class called entity confirm form base. And I'll get back to that. Flag form base does all the real form stuff. It builds the form. It handles this out of the validation. It handles the submit. It does all the real work. So what does flag add and flag edit form actually do? It modifies the behavior, and it tells you where the default values come from, such as with the add page, it just grabs them from static values, or the edit page, it loads them from the entity. And it also modifies the name of the submit button. This is actually a very common pattern within Drupal modules, to define a base class and then two very similar classes that will do the add and edit form. The delete form is a completely different animal. It derives from confirm form base, and it basically provides a simple yes-no question. Can and do you want to do this or not? The class that it uses is entity confirm form base, and it really only has a few different methods it has. What the question is, what the title of the page should be, what to do if someone clicks cancel, and what to do if someone clicks go ahead. So we have our forms, we have our entities, and we need to make it routable. So, user comes by with their web browser and goes to Drupal 8 and say, I want some content. Drupal 8 now, Drupal 8 needs to match whatever that path is to some other piece of code within Drupal. Now, in previous versions, we used hookmenu, but we don't have hookmenu anymore, so what do we do? Well, we actually define a new file called flag.routing.yaml. And this basically provides a list of route names combined with a list of path names. This is an important point. Drupal 8 doesn't think in paths. It thinks in route names. So, when we have route names, how do we add stuff to existing paths? Well, you'd think, well, we were going to add that to the routing page, right? I mean, that, oh, no, that doesn't work. Because flag.routing.yaml only adds new routes. It doesn't allow you to modify existing routes. For that, we need another file, flag.links.menu.yaml. This will allow us to add to existing routes. And it basically contains the destination route name followed by the parent route name. In this case, structure.system.admin structure is for the admin structure page. So now we have that. We need to connect our ad form to our page. And we do that through a local action. So how do we do that? Well, we have another file. flag.links.action.yaml. This allows us to attach click actions to existing routes. It also contains two really important pieces of information. The route name to attach and where it goes to. Okay. So we have all of our big entity stuff ready to go, and now we can actually start making flaggings. So we need to start porting the flagging entity. So how do we do that? Well, we pretty much the same way. We know it's a content entity because it's user created. So we create a flagging interface, just like we created a flag interface, and we create a content entity. We derive our flagging class from content entity base, another Drupal provided class. This is used for user defined objects. Fields are defined not by creating a schema, but by actually overloading a method called base field definitions. Interestingly enough, we don't need to use hook schema to actually define database tables. Drupal will use the information in the field definitions to actually create the tables for us, so we don't have to do all that extra work. The flagging contains a few pieces of information that maps it to other objects. A flag ID for the parent flag, the entity type an ID for the flaggable, and the ID of the user that created the flagging. Beyond that, flaggings are kind of weird because they're not really created with forms. So what do we do? What happens? Well, a user comes by and uses the web browser, and they go and view a node. And what happens is that we use flag entity view in order to attach that link to the node. The user clicks the flag link, and then it goes to Drupal in some route. Well, what happens then? Because what we really want to do is we want to get to entity save to create the flagging entity. So we need to figure out what we're going to do in the middle. Before, we have a great method called flag, but that's not really a very Drupal-8 way of doing things, so we don't want to do that. What we want to do instead is we create a flag service. The flag service is basically a plain old PHP object, but it's special in that it's registered container-wide through the file flag.services.yaml. So all other modules within Drupal know how to locate flagging configuration information and flagging methods. To flag your unflagged entity, we simply call flag service with the flag service and then flag... You can also inject the flag service into your own services for your own use. So we have the ability to flag stuff now, but now we need to make it expandable because there's still one more problem left. So we have our flag entity and we have several different target flagable entities, such as Node User and other entities. So if we're looking at this, you might say, well, okay, flag one, and, well, why don't we just create a new flag node subclass and a flag user subclass? I mean, that makes sense, right? Then we can handle all those special cases and configuration stuff. But then we get to entities, and then we get a problem because there are a lot of entities in Drupal 8. Drupal 7 had a lot of entities. Drupal 8 is even bigger. So this also looks really familiar, doesn't it? Oh, I need to get to our classes again. We don't want to create handler classes. We don't want the blob to come and eat our module. So we want to do something instead. The problem with handler classes is they're hard to expand because you have to derive from base class and they're not discoverable in any way. So if you're not the flag module, you can do nothing. So there's got to be a better one. So we have our flag entity and we have our flagables and we need some way to relate them. What we do instead is we use a plugin. In this case, a flag type plugin. The flag type plugin relates the flag to the flagable entity. Flag type plugins are also discoverable via a custom flag type annotation. It's not a subclass. It's added dynamically into the flag class. The wonderful thing about this is that any other module that needs to define their own flag type because they have their own custom entity has to create a flag type annotation and then they derive from flag type base and they can do whatever they want and flag will just pick it up automatically. So we have a very similar structure for the handler classes to the plugins. We have plugin base, which is a Drupal provided class which does all the plugin stuff. We have flag type base. We have entity flag type and then several specific flag types. What do we do with all those other entities? What we use is we use plugin derivatives. With plugin derivatives what we can do is we use data to create the appearance of multiple different plugin types, one for each entity, and we do so dynamically. So everybody gets their own plugin. So now we have how to handle the flag to the flagable, but we still have one more problem. We still have some route after we click the flag link. Where does that come from? Who does that? What we do is we have another plugin. We have a link type plugin. The link type plugin provides the route that will connect the clicked flag link to the flag service. Again, this is also discoverable. There's a link type annotation so that any other module can define their own link type. You can create all kinds of crazy link types. Because it's also a plugin, it's also dynamically selectable or add a flag. All right, we have most of our functionality. Now we need to open up even further. We need to create an API. So what we had in flag seven was hooks for everything. We did everything with hooks. If there wasn't a hook, we would make a hook for it. We did it to define flags, to validate racks, to interact with events, to provide flag types, to provide link types. There was a whole bunch of stuff. Well, in Triple 8 hooks aren't everything. It's a bigger world now. And it looks a lot like this. We use the configuration management in order to define flags. We use plugins for flag types and link types. We use events to react to events. And we use state and grant access. We actually still use hooks in Triple 8. What about this event thing? How does that work? We have the flag service and we have another service within Triple called the event dispatcher. People subscribe to the event dispatcher to receive particular kinds of events. I want to listen to whenever somebody flags a node or unflags a node, or something like that. Whenever that happens, flag service is going to dispatch a flag event class to the event dispatcher and then have that populated to all the different subscribers automatically. All flag service has to do is just submit that one event class once. There's only a few flag events so far but there might be more in the future. We still use hooks. How we do that is instead of having the straight invoke all method, what we do is we actually inject the modular handler interface into the flag service and from there we can call any other hooks that we need to. So there's flag. So there's a few things that I learned during this. How do we run our projects more effectively with Triple 8? Well, the first thing I can tell you is when you're starting your Drupal 8 project you're not sure if you're going to start and with the same code that you start with. You might end up in a back alley. You might go down an interesting idea and find it's not really viable. So you really don't want to just put it on your module page. You could. You could actually put it on your Drupal.org project. But is your module really ready? Do you really want to do that? I mean sure, you could work in private and develop all this stuff and then push it to Drupal. But then you're not doing it in public anymore. You're not generating that interest. Well then, so what do you do? We could put it in Sandbox. And that's easy, but few people see Drupal Sandboxes. It's hard to get visibility there. Although the community processes are exactly the same. So then you might wonder, okay, maybe I just need a clean break. Let's put it on a completely different public repo like GitHub or Bitbucket or something like that. What we did with flag is we decided to completely new break because I had no idea if I was going to get anywhere with this. I had no idea if it would work out. And I was getting some pushback from some of the other contributors. So it was probably a good idea to just move it off of the Drupal.org project page entirely. Next, when you're working on this you're going to have problems. You're going to have questions that you can't answer. You're going to update core at 7pm that night and then spend the next three hours wondering why nothing works again. And beg that some core developer will show up on IRC that you could beg for an answer for. And they're there to help, but you've got to be patient. And when they do help you, you need to really show your appreciation for it. I can't tell you how many beers that I owe people right now. There are plenty of places to find help. You can find it on Drupal Contribute. You can go to the Drupal.org list changes page. There's also the issue queue for Drupal itself. The list changes page is your one-stop shop or anything that's changed in Drupal core. After that, it contributes really useful for tracking down and debugging specific issues. Next, you might find yourself needing money in order to do stuff. You might need travel money to go get your team together so you can sit down and just hack. Maybe you need to attend a conference. Maybe you need to take them off from work just so that you can code. There's a lot of different reasons why you might need funding in order to support your module development efforts. So what you can do and what I did is I actually ran a crowdfund on Drupal Fund. My goal was to actually get me to Drupal Con Austin last year so that I could sit down with some core developers and really push the module forward. And in a few days, we went from no-view support to complete-view support. It was really, really impressive. Later on in your project, you might start wondering, especially if you've moved your project off of Drupal.org or into a sandbox, when should I move back to my project page? I'll make this official. You have a lot of different things that you need to balance. You'd be worried that being on your module out there right on your project page might result in a lot of people posting issues while you're still developing your module. Yes, I know that feature doesn't work yet because I haven't written it yet. Or you might have Git log pollution, especially if you've moved your module off Drupal.org. And now you reference pull requests that exist on Drupal.org, but you do that. On the other hand, if you put it in a project branch, you can leverage your community, but it also comes with a lot of visibility. And if you end up in a back alley, that can be really discouraging to a lot of people. You might be tempted looking at this to do this, to slide the fulcrum all the way over so that you keep it in the sandbox as long as possible until you're certain that it's ready to go. Don't do this. This will cause you problems. The problem is that the longer you keep it in the sandbox, the more the lack of visibility and the lack of leveraging your community will hinder your module development. What you want to do is this instead. You want to wait until your module is just done enough to do the major stuff it needs to do and then move it back to your project page. You need to define a minimum point of module viability. And that's when you should move your module and that will eliminate the issue cue noise and the get-in-a-log pollution a lot faster. The more you keep it off, the more that will accumulate. In reality, Flag actually only had about 120 issue tickets and most of them were reminders to myself. So these issues are way overblown. Also, things are a lot easier now than they were last year and even in 2013. We have an example module for Drupal 8 and it does a lot of stuff. We have a config entity example. We have a content entity example. We have a plugin example that's in progress and that will have you very far in doing stuff. There's also wonderful things like Drupal console which can actually provide you a lot of that stub code necessary to get your module off the ground a lot faster. Looking back at all of this, if you're looking at working on a Drupal 8 module, you want to learn port now. Right now, don't wait. Go. Go back to your hotel room, open your laptop. Come on. If you're waiting to work, you just want to sit down and get it over with and then move on with your life. You might want to wait, but don't wait too long. Drupal 8 has actually been fairly stable module-wise for the last year. There's only been a few times that I've really needed to massively modify my module in order to make it work again because this base class changed, this interface changed, and then it took longer for me to track it down and figure out what broke than to actually fix it. So in reality, don't wait too long. Do a code review. Make sure that you know how your module really works. You have to get up at 3 in the morning after a long vacation to go and look at it with fresh new eyes. Do whatever you have to do. Also question everything. Nothing is sacred. Really look at your module and see if there's any way that you can make it work better. Please use an IDE and a debugger. I can't stress this enough. Finding your code completion is a wonderful thing, and you will thank yourself after you get over the initial frustration of not using one. There are lots of them available. Many of them are open source or free. There's also plenty of demo versions that you need help patiently ask for it and show appreciation when you get it. That will help people to be more encouraged to help you in the future. Do it in public. Don't sit in your basement and work like we are right now, and work on your module in the dark and then push it up to Drupal.org. Start working on it. Let people know, but also put a warning label on it. If money is your problem, consider crowdfunding. Move out of your sandbox as fast as possible. Don't get stuck in the sandbox. As soon as you hit that point of minimum module viability, move out. Things are a lot easier now because there's example module, there's Drupal code, there's a lot of things you can do to make your module development effort a lot easier. I'd like to take a moment to give special thanks to a lot of people that made flag the role of David Reed, Whizwon Solutions, which helped me a lot with this presentation. Lauren Shea, which is why I'm here today, and Blink Reaction, which I now work for. Thanks, everyone. You can find me on D.O. and Twitter on SocketWench, and you can find this presentation on...