 All right, so welcome everybody. This is the lab session we have on upgrading your module to Drupal 8. About us, my name is Angie, that's Alex, and this is Jess. And we work at the AQUI Office of the CTO. We also work a lot on Drupal 8. And so we're here today to kind of give you some guidance on how to do that. Also, I'm obligatorily mentioned to mention that we are always hiring. So if you have a pulse and you know Drupal, you should probably come to our booth and tell us about that, no. And you all know Drupal 8 when you're done with this, so it's even better, all right. The agenda of today is we're gonna give a quick overview of where Drupal 8's currently at, which is relevant if you're a module developer, you should probably understand the state of the API changes and such. We're also gonna do a bit of hands-on with some first steps in the module, just to kind of get you used to Git and how to make basic changes, how to work with the basic change management tools we have in the Drupal project, so you know where to find answers for things, and also how to do some debugging. And then we'll go into a detailed Drupal 7 versus 8 code walkthrough. So I'll switch over to Alex. Alex will then have a Drupal 7 version of the module that he'll walk through so people can get familiar with that, and then compare and contrast how that's done in Drupal 8. And through that process, we'll expose you to major APIs like the move to object-oriented code, routing pages and forms and how that's done in Drupal 8, the new configuration system, entities and fields, plugins and blocks, and how to do themeable output. And then we're hoping we can finish the talky talky bits in about 40 minutes or so, and then basically we're gonna turn you guys loose and have you just port your modules and then raise your hand if you have questions, and we're gonna have people in the room running around helping you who've done Drupal 8 development before. So hopefully the goal is by the end of this session you will have something working in Drupal 8, which would be awesome, right? So we have some helpers in the room. Could helpers in the room raise your hand or stand up or otherwise indicate yourself? Gabor? Okay, there's one hand down here, Jess, and of course when we're not talking we'll also be helpers in the room to run around and help you so if you have questions, raise your hand and we'll do that. I've also put out a plea on Twitter so hopefully more people will come in here. There's a really highly technical conversation happening right now that a lot of the core developers wanted to attend so there'll be more people filtering in towards the middle to end of the lab. Also, this is important. If you've hit a DX or a developer experience problem we want you to tell us about it. So we have this link at vit.ly slash pants hyphen problems and if you are in the middle of porting your module and you hit something that doesn't make sense or you hit something that you're really struggling with please go to that issue and add a comment that explains that. Try not to swear at us, but maybe just say I expected this to be like this and I found this really complex or I found it confusing because we'd really like to gather that feedback so we can incorporate it into a larger plan for how to really improve the developer experience before we ship Drupal 8. Cool? Yay, all right. So pre-requisites, I had this on the screen before. You need a module that you want to port. You need a development environment with Drupal 8 set up. You need Git and if you have Drush, the master branch of Drush, that can also be really helpful because you can do things like clear the cache or do a site install, stuff like that. So if you don't already have those things maybe set those up while I'm talking for a little bit and then you'll be ready to go when we get to the hands-on part. So once again, this lab is BYOM. We call it bring your own module. So picking either your own module or someone as familiar module that maybe you need to be available on Drupal 8, you can do that as well. And if you don't have one and you just came here to learn Drupal 8, that's fine to pick the Pants module which we'll talk about later. How many people here are, your project maintainers, you have your own first class, full URL project on Drupal.org that you came here to port? Nice. Nice, that's great. So about half. How many people here don't have their own module on Drupal.org but they have a module that they really care about being ready on Drupal 8 and would like to help with that? Okay, cool. So like a third. And then the rest of you all are you like people who just came here to learn something? Okay, cool. Also who has maybe a custom module for a site or your shop that you're trying to port that's not on Drupal.org because it's probably a couple of people? Okay, yeah. You don't have to throw like private code with passwords on Drupal.org but we encourage you to put your code out there even when it's not ready because even having a start on it is better than nothing and we'll define success today by having something done. You're not gonna get your whole module ported in an hour and a half, it's gonna take a little longer but you should at least have it started and then on Friday in the contribution sprints you can kind of carry on from there with an even bigger pool of people. So yeah. So let's talk about the state of Drupal 8. I wanna kind of blow through this. Dries sort of already talked about it. So feature development began in March of 2011. We had a feature freeze in December of 2012 and then there was a period of time where even though we weren't accepting new features we were polishing up the existing features and that sort of lasted till February of 2013. Then we had this period of time between then and API freeze to sort of kind of rejigger things, clean things up. We entered API freeze in July 2013 and now we're in a phase of the release called API completion and what that means is that we were done adding new APIs to Drupal 8 for the most part unless it's something fairly minor. Now we're trying to clean up the existing APIs better, integrate them together, fix the developer experience with Drupal 8 and those kinds of things. And then we'll start rolling alphas and betas and RCs and all this kind of stuff and then we'll release Drupal 8.0 when it's ready. So what does API completion mean to you? It means that APIs are freezing but they're not frozen. So you're gonna do some work today and that work may or may not survive the rest of the Drupal 8 development cycle but it shouldn't change too materially. We've been mostly renaming stuff and things like that. What the core development team is actively trying to do right now is knock that list of critical bugs and tasks down to zero. When we hit zero we release a release candidate and then that's at the point where we ship Drupal 8 once we release a couple of those. So I wanna make people aware there are still API changes hiding in those critical issues. Here are some of them. Right now you'll notice your module still works if you're using old hook menu or variable get or things like that but that will not survive the remainder of the Drupal 8 release cycle. Eventually those backwards compatibility layers will be removed. So it's nice now to port your module because you get a little bit of a cushion but just be aware that those things are under active discussion and or removal for the remainder of the release. We'll break the APIs if we have to to fix major development experience problems or major performance problems. So you know essentially just keep an eye on those kinds of things. And we have a couple of resources here for API change tag and there's a big list that Jess made of it goes in a much more detail on the stuff that's still outstanding. So with that out of the way, let's do some first steps. So this is gonna be hands ony thing. Yay. The module we're going to use as an example in our walkthrough and our thing is called Pants module which you may or may not care about but it's a useful module because it sort of has an answer key for like how to port from seven to eight so it can be useful to use as a reference. So I'm just gonna walk through that module real quick and show you what it does. Actually, let me finish this first. Anyone guess what my admin password is? Okay, so here's a seven Drupal installation and I have this thing called the Pants module and essentially what the Pants module does is it lets you set a flag on your user profile that says your Pants status is either on or off. Okay? So you can turn your Pants off in which case your Pants will turn off and then you'll just say Pants status is off or you can say, okay, I've turned my Pants on and then you put your Pants on and it'll show you a little picture or alternate living some text. It's a dumb module, that's all it does but it's actually useful because it can expose you to a lot of Drupal APIs. So for example, this Pants status field is actually like a field API field like what used to be called a CCK field. We also have this nice view that shows you recent Pants stages and that's actually a view from Views module. We have a nice block that has an Ajax callback so if I wanna quickly change my Pants status without having to go all the way into my user profile to do it, I can just change my Pants on and off like that. I can sit here and click on this all day, it's really fun. I cannot stand up here and take my Pants on and off though because that would be criminal. So the other thing I can show you that this does is it defines a configuration page. Wow, that was cool, one sec. Sorry, I'm having some memory issues in my local environment. The other thing it does is define a configuration page so the administer Pants configuration page where you can say what is the Pants type you wanna use here. So you can say when people have their Pants on I wanna show MC Hammer Pants or you could say nope, I wanna show Bell Bottoms instead and then I'm gonna go back to my user profile and reload, well, turn my Pants on and then reload. Then I'll see, I show Bell Bottoms in my user profile. So it's a dorky little module but in the process what it defines is it defines a user permission to figure out who has the ability to administer Pants. It has an Ajax callback so you can see how that sort of thing is done. It also defines a form, specifically a configuration form where it saves different settings. It finds a field that you use on an entity so it's actually a really good introduction to all of the major API changes in Drupal 8 just by virtue of being a silly little module. So Alex will be going in a lot more detail into what the code is underneath that but I just wanted to kind of expose that to you so you see how that works. Cool? Questions on the Pants? Oh, let's see in action. We did that already. I'm leaping way ahead of myself, alright. So the first thing we want to do and we want everyone to do this right now is in your Drupal 8 site, which I know you all have because I had the prerequisite slides up, right? Yes, Angie, we totally have that, okay. We want you to clone your module from Drupal.org into your local environment. But the key thing is, you remember how it used to be that you'd say, you put your modules in sites, all modules, everybody knows that, don't be stupid, right? Nobody puts their modules into slash modules at the root because that's a new thing to do. Well, we changed that in Drupal 8. So now that is where you put your modules, so let me show you this. So if you have your Drupal 8 site, and it's 8, you can see that there is a core modules directory and that's where you find node and user and all that stuff. Don't do that, don't change anything in core. However, the modules folder that's at the top of the directory, that you do put your stuff in. So slash modules is a new sites, all modules, which is the exact opposite of what you're used to. Welcome to Drupal 8. Yay! It would work in the other directory. It would work in the other directory, it is true. The reason we changed that, by the way, is because we accepted it as an inevitability that everyone wanted to do that anyway, so we just went with what was easier for users, which I actually think is gonna be a good change once we get used to it. Yeah, anything underneath there is fine. So if you wanted to am in my... Yeah, so I'm currently in my root directory of Drupal 8. I'm gonna CD into modules. There's just a readme.txt in there, but yeah, if I wanted to make a subfolder here called contrib or wanted to make a subfolder here called bunny rabbits, either of those would be fine. Yeah, it doesn't enforce a convention either way. So I'm in, once again, I'm in my root modules directory in my Drupal 8 installation. I'll put the instructions back up, but I just wanna demo it so you can kinda see what I'm after here. Gonna go to the pants module. It'll be real cool to see if the internet holds up during this session. So I'm gonna go to the version control tab, which gives me nice copy and paste instructions and I'm actually gonna show the non-maintainer version of this. And I'm going to copy and paste the Drupal 7 version. So I wanna take the Drupal 7 version of my code and I wanna put it in my Drupal 8 site just as is, okay? So here's the command I copy and paste, which is get clone yada, yada, yada, yada. That's it, okay? So that's the first step and we'll give everyone like, say, two minutes to do that and if you don't get it done, it's fine. There'll be helpers running around to help you but everyone do this step right now, okay? So take your Drupal 8 site, take a Drupal 7 version of the module you wanna port and stick it in your modules directory, ideally from git so that later on we can push to it, okay? If you need help, raise your hand. We had one question that came up that I think would be useful to everyone to know and that's we're not getting rid of the sites all modules directory and if you're using multi-site, you'll still use site slash whatever your domain name is slash modules. It's just we added this in and it's sort of becoming the new best practice so I figured we'd start you off on the right foot, so. How are people doing? Everybody done with this? Few people? Okay, I think we're gonna move on and if you need help, that's no problem. We'll have a break after the code review and then we can go get everyone caught up so. All right, so you've got a copy of your Drupal 7 module in your modules directory. So now you wanna have an 8.x branch of your code, okay? So we're gonna create that right now and what that will do is it will go ahead and get everything done. If you don't own the project that you're doing, so for example, there were some people who said, yeah, I own my own module and this is what I wanna do. If you don't own your own module and you wanna use someone else's module and you wanna port it, there's some helpful sandbox instructions right here that Jess helpfully wrote up with pictures and everything is my understanding. Look at that. So if you follow these instructions, you can actually get a Drupaladorx sandbox where you could start your port of your module and then you can follow along with all the other instructions and you can commit code to it and stuff like that if you don't own the own module that you're working on. Trying to think if I should leave that up or not. Maybe I'll leave that up because I think everyone else knows how to do this. But for now I'm just gonna do the steps I told you to do, which is I'm gonna go into my Pants module directory, right? And I don't know Git. What did I say I was gonna do? Oh yeah, right. Okay. So I'm going to get checkout B for branch 8.x1.x. So that makes a new 8.x1.x version of my module. Even though I haven't changed any code yet, it gives me a place to do it. And then get push U origin. I don't know why. I just copy and paste. So you can copy and paste too from the version control tab. And then that will make, really? Yeah, that's not gonna work. Hold on. First part wrong. I do need to maintain your instructions. Sorry. Yeah, if you get that error, if you get a HTTP request failed because you got a 403 error, then you're trying to commit to a module you don't own. That's basically, I did that on purpose. So you could see the effect that happens when you, yeah. So get clone yada yada yada yada and then get checkout. Git is not subversion. I will remember that someday. But you know, I like to learn the right way to do things. Okay, so get checkout hyphen B, 8.x1.x to create the branch and then get push hyphen U origin 8.x1.x to make the branch on Drupal.org, okay? That's what it should do. Yeah, can I? That's what hopefully you see on your screen, okay? And then I think rather than leaving that up though, I'm gonna leave up the, maybe I'll leave the sandbox instruction. Well, they're not all gonna fit on the page. So yeah, I'm gonna leave this up, but I'll copy the URL of this. Yeah, I'll leave it on the slide. Also, I noticed you can't, whoa. I noticed that you can't really see this back there. So let me try, white it out and. All the things you find out when you get into the room. Whoops, see this. There we go. Okay, so let's take two minutes and do that. If you have questions, raise your hand. Maybe you don't need two minutes to do that. One minute to do that. But if you have questions, raise your hand. Anybody know any good Drupal jokes? I actually have one that came up on IRC, but it's hard to say verbally. Why did the Drupal developer quit his job? Or her job? Because he or she didn't get a raise, A-R-R-A-Y-S. Ah, ah. Who has an 8.x, 1.x branch? About the same amount of people who got the other thing. Who needs like 30 seconds? Okay, 30 seconds. I'm gonna give you 15 seconds. So now, we wanna go to the modules page and we wanna see what happens. This'll be very exciting, except that I already ruined it, but yeah, so now I've got my Drupal, whatever. I should disable EPC, but I'm not gonna do that right now. So to recap, I've got my Drupal 7 Pants module into my modules directory. And usually when I put stuff in my modules directory, I wanna turn on the modules. So I'm gonna go to the extend page, which is new in Drupal 8, extend, because nobody knew what a module was, except for people who work on Drupal, which is a lot of people. But anyway, point being, but this is new, watch this. I can search for PA, whoops, and it will limit the list of modules to things that have a PA in them. Whoa. But as you can see, I only see path, I do not see pants. So that's a problem for me, right? Why would that be? Dot info file, right, because dot info file is usually how you end up with this on there, right? Okay, so you might think to yourself, I can do this. I know what the problem is. The problem is this says core equals 7.x, right? So that's easy. I'm gonna soon change that to core equals 8.x, right? Come on, come on. So you do that, and then you refresh the page and go aha, Drupal 8, I figured you out, and then you find out. You find out, oh, I didn't do that. Okay. Shub, shub, shub, shub, shub, shub. You need a spoiler alert on you. Yeah, sure, that's a good point. I should probably clear the cache. Never hurts to try it, right? So I'm gonna clear the cache, development performance, gonna clear the cache, and I'm gonna see, by the way, I just fixed a bug that makes the cache clears take about seven seconds less than they used to, which is cool, but they still take a long time. We're working on it, all right. So clear the cache, going back to extend, which is being ridiculously slow for some reason. I'm probably gonna have to turn off APC again. There we go. PA, nope, wah, wah. Dang, right? Drupal 8 sucks. Let's all go home, okay. So no module for you, all right, and you know, but you had the right idea, right? Like info is how you register a module, so something is wrong with my info file, right? Something is wrong. I don't know what yet, because I didn't go to Larry Garfield's session, where he spoiled it for me. So we know it's an info file, so we should now get acquainted with our new best friend in the whole wide world, which is the list of changes on drupal.org. So what this is, is this is an old, how many people ported their modules from six to seven? Okay, and you remember that horrifically, endlessly scrolling handbook page that went on and on and on forever and made you want to shoot yourself in the face? Now it's 400 individual nodes that make you want to shoot yourself in the face, but they're searchable, which is cool. So if I search for info, I'm going to end up with a couple of things, but this is the key one we want to highlight here, which is that info files are now info.yaml files, okay? So this is a big change in drupal 8. So when you find a problem, you get an error, you're not seeing something showing up, this is your workflow, as you go to this page, you do a keyword search for something related to that, and then you find it. And so each of these change notices they're called, they have a nice, they tell you when it was introduced, so it was introduced in 8.x, they tell you what were the issues that discussed why this change was made, so if you want to go lynch the people who changed it to yaml, you can find out why they did that, and they had very long discussions. And then it will show you a little bit of a high level of what has to happen, and then almost always they'll show you before and after code examples. So this is showing you Bartik.info file before, so you have things and little things and an equal sign, and then it'll show you it after. And so primarily the after is you put colons in, and you, anything that's an array instead of using the brackety thing, you now actually put on a new line and indent a little bit, stuff like that. It's all in this page, 193.5708, and you can find out all about that there, as well as why we did that, yes. No, it's necessary, it's part of the yaml parsing thing. So yes, you do have to do the indentation. I'm sorry, Doug. I want to say, is it two exactly? Yeah. And by the way, for the links in this presentation that Andy just rattled off, if you go to dhcx.org slash pants-lab, there are links you can click there, so you can open them on your laptops rather than typing. Yeah. So why doesn't, why doesn't Angie fix her slides for a second? It's right at the bottom of the, oh, you mean for the change notifications? D8cx.org slash pants-lab. And I wrote it on the whiteboard, but no one can see that. It's in the green marker and it's dark up here. It is dark in here. All right, so everybody take three minutes and update your yaml file, okay? So, and that primarily involves a few changes. You want to remove any references to files equals because we don't do that anymore. We'll talk about what we do do instead. You can remove dependencies on modules that are moved into core. For example, Ctools module, like largely got moved into core. And then the key thing is you want to rename your file from module.info to module.info.yaml. And you're also going to want to insert a new key which is type module in your info file, otherwise it won't come up. And no matter how many times you clear that cache, you can keep clearing it, it still won't happen. So, two things, info.yaml, type module, and then change all your equal signs to colons and then just watch the array syntax, make sure you're indenting and putting little hyphens. Ready, set, info. And then raise your hand if you need help. One thing that came up in the back is that if you, if you weren't logged into Drupal.org when you went to the version control tab, it will have given you anonymous checkout instructions, in which case you're going to get that 403 error I demonstrated. So you have to log in in order to get the right command to copy and paste that knows that you are you. So if you're getting that error, log in to Drupal.org, copy and paste that command instead. We also have some people that are getting white screens of death, which is always fun. And as soon as I have an answer on what to do about that from Gabor, I'll tell you how to proceed. Yeah. Also you'll notice in the slide, there's a red line for dependencies C tools. So if your module has dependencies on other country modules that don't have an 8x version yet, you know, one thing you can do is what we did in PANTS, which is just remove the dependency. And that will at least let you enable your module. But then of course, if your module then calls functions that other country module provides, then that'll be broken. So then you can decide what to do about that. You know, either in the case of PANTS, we rewrote PANTS to not have to depend on C tools. But in the case of, you know, your module, if you really wanna depend on the country module you depend on then, you know, you might need to wait until that module is ported. All right, I'm gonna move on. Cool. Info files, who successfully got an info file moved around and stuff. Good, okay. Several people. All right, so what could possibly go wrong? Couple of things that could possibly go wrong. One is if you forgot to change an equals to a colon, you'll get a scary error like that. The key thing there is unable to parse that line three or whatever it says, that's where your error is. So you have, you know, forgotten this. Basically it can't parse the syntax of the YAML file. Also if you forgot type colon module or you forgot to rename it to the info file YAML extension you'll also get an error. Or you won't get an error. You just won't see your module still. So check those couple of things. So step six is turn on your module and see what happens. I know I'm not. So, oh, I didn't update my, hold on. Oops, I need to do this. I think that's right. How does that look? Maybe we're room full of developers. Can I get a code review? Let's see if that is in the case. Reload. Yes, right. The thing I just said you have to do, it helps to do it. Okay, so. I was just seeing if you were paying attention. So thanks, the pants shows up. And I'm gonna save it and turn it on and wah-wah. Oh, well it turned on but it gave me an error of some kind. And now the fun part. I'm not gonna dig into that right now but basically what probably happened is something like this. Yes, did you just blow up your site? All right, awesome. So now is a great time to talk about common debugging techniques, okay? So in Drupal 8 there's a few different things that you should do. The first thing is actually read the error message. That's important. The debug function still works. You can debug a var to figure out what's happening there. If you have a white screen of death, oftentimes it's helpful to tail your PHP error log and find out what's happening there. So the location of your PHP error log will be different depending on what your environment is. But when there's a white screen of death, you can actually get into Drupal to check watchdog. So instead it's helpful to look in your PHP error log and oftentimes that's like a fatal error somewhere earlier than it can get output on the page. One way to work around this issue too is you can comment out hook install or hook uninstall so that when you turn on your module, no hooks are firing. That's a useful way to get around this. This is new in Drupal 8. So when you do something like enable a module, it compiles what's called a PHP container and that has basically a cache of all of your functions and classes and all this kind of stuff. If that gets messed up, that can cause a problem. So you can actually just remove everything in the PHP directory and your site's default files, blah, blah, blah. That's a new step sort of in addition to clearing the cache that you want to try in Drupal 8. Clearing the cache is always good. Uninstalling and reinstalling your module, if you can get that far is always good. And then finally, sometimes you just need to reinstall your site right now because we don't provide 8.x to 8.x upgrades until beta-ish. Those are some things that you might have to do. So if you're totally dead in the water, that's okay. We'll get around and we'll help you. But I want to go ahead and for the people who are not dead in the water, give them the one last step to do. You're taking a picture of that, cool. Which is commit and push your code, okay? So until everybody in this room by the end of the day, we hope we'll be able to have one commit on drupal.org that is 8.x and if you get more stuff than that done, that's awesome, you know, like kind of thing. And then what we'd love you to do is link to that code from the comments of the session so that we can go back and look and see who was here and what modules they tried to port and all that kind of stuff would just be really useful for us to have. So I'm gonna do that. I'm gonna get rmpants.info and there's probably a better way to do this, but I'm gonna get addpants.info.yaml. I'm going to get commit, adding or converting info to info.yaml and I'm going to get push. Put that stuff at the top of the screen and that's what you wanna do. You wanna remove the old info file, add your new info.yaml file. There's fancier people will get MV it or something. I don't know, but this is the basic thing and then commit your stuff and then push it to Drupal.org so that if it works, what you should see is on your project page. If you go to repository viewer here, what you should see is down in the list of heads, you should see an 8.x, 1.x head and if you go to the log, you should see that you've just done something and then you feel a huge sense of accomplishment. Yay, all right, so do people wanna try and do this and again, we're moving kinda slowly because I'm talking an awful lot so we'll do this for maybe like two minutes, try to get this done and then I wanna break to Alex so he can start walking through the rest of the code and what we'll do is if you already kinda know Drupal 8 and most of what Alex is gonna cover is review for you, that's totally cool. Just throw on some headphones and start porting your module because this is the end of the hands-on stuff, instructor-led hands-on stuff, but if you wanna listen to that, that's totally fine too and you can even start porting your module when you go home tonight or at the sprint or whatever, so. Whatever works for you. So let's take a couple of minutes and do those two things and please, please, please, please link to, even if you don't get your code up on Drupal 8 to link to, please at least like, you know, put, I'm trying to port this module, just be great to see what the modules represented in this room are so if you could do that, that would be really awesome. So two minutes, I'm gonna just gonna run back and for the primary, if you have a question. How many people have a log on Drupal.org that says you've committed to info YAML? Yeah? Applause for everyone, yay. That's great. And how many people remember to comment on the session? Okay, cool. All right, so now we wanna get into some of the Drupal 8 APIs. So this is gonna be more of a talky thing than a hands-on-y thing and this is gonna be Alex who'll be leading this part. And essentially what he's going to do by comparing and contrasting a Drupal 7 and a Drupal 8 module is walk through the major API changes of Drupal. So those include the move to object-oriented programming, the new routing system and how you define pages and forms, the new configuration system, how entities and fields have changed, twig, plugins and blocks and views. So some of these will apply to some people, some won't apply to others, so feel free to port your module while you're listening and if you have questions, raise your hand and we'll run around to help you. So Alex. How's the font for people in the back of the room? Okay, so I'm gonna start going through an overview of the PANth 7 module and the PANth 8 module and use that as an opportunity to go over the APIs that Angie just mentioned. So the one thing I'll mention is I'm gonna go over each of the APIs fairly quickly and it's just so that you have a chance to kind of like see it, get a high level. If I spend, say, a few minutes per API, you might not remember everything, but that's okay, my hope is that maybe you'll at least pick one thing out that you can actually apply today. So maybe, for example, if you haven't done a routing conversion yet, then maybe you can just work on that, but at least you'll have seen some of the other major APIs as well and if you already know the routing stuff and came here to get into some of the other APIs, then maybe there's something in this talk that will be useful that way. So I'm actually gonna show three things. The first thing I wanna show, sorry? Okay, so one thing is if you don't have to go right now unless you want to, but if there's on the PANTS project page, as Angie showed, you can get to the repository user, the repository viewer, there it is, thank you. I think you lose about 50 IQ points when you stand in front of a microphone, or at least I do. Yeah. Okay, so what I wanna show from the repository viewer is that there is the, that you can go to the, that there's the 8.x-prog branch and the 8.x-prog branch contains essentially every commit from contains every commit from the 7.x-1.x. So it's about 38 or so commits. And it's a total of about, yeah, like 38 or so commits and I don't know, 12 or so tags. And so the idea is that it has a history of step-by-step kind of what I was doing to get this ported. So what I'll do after this is I'll show the, just the Drupal 7 code and then the Drupal 8 code. But if at some point you wanna go through in detail, instead of doing like a full diff of the 7x and 1x, you could, if you want, follow it commit by commit. And I'll give the other warning here is if you do this, then I did the bulk of this a couple of weeks ago, as you see back in September 11th. And so there's a few things that if you follow commit by commit that were the right thing to do based on what Drupal 8.head was two weeks ago, which then has changed in the last two weeks. So there's one more commit here, which is chasing Drupal 8.x-head, which is just one additional set of things to reflect the last two weeks of head changes in Drupal 8. Okay, so the Drupal 7 module. So first of all, go through the layout of it. So we all know there's the .info file, the .module file. I was able to change up the font size for the code, but unfortunately the file browser portion is at a small font size, so I hope it's still semi-readable. But there's the .module file, the .install file. There's a .pages.inc and a .admin.inc. I think a lot of you are probably familiar with that, which is like to separate your pages and your pages.info file and sort of your administrative forms and pages and an admin.inc. There's also a pants.test file. That's where all the simple test coverage for the pants.module is. There's a .views.inc, which is, so when Angie showed the pants demo, there was the recent kind of pants history block, so that's done through a view. So the pants.module provides a pants history table and then the pants.views.inc file integrates that with views and then there's a views.default.inc. That is basically going into Drupal 7, building the view and then using the Ctools exporter to export it and then put it into code. The code is not visible at all. Okay, let me up that font size on that. Is that visible at the back of the room? Or should I go a larger font than that? Okay, I'm getting thumbs up in the middle and a thumb up towards the end. Okay, great, thank you. So those are an example of some of the files that are in here, you know, the views and the views.default. There's also something in here that's using Ctools plugins. How many, can I get a show of fans of people who in their Drupal 7 module have used Ctools plugins? Great, wow, okay. More than half. So when Angie showed, there's the ability to select which pants type, you know, so like is it, you know, when people are wearing pants, is it, you know, sort of the none pants type versus the bell bottoms versus the MC Hammer. So that's implemented using Ctools plugins. So I have my, you know, following the Ctools convention, I have my plugins directory and then my within there, my pants type directory. And then I just have my, you know, MC Hammer.inc and bell bottoms.inc has plugins. So that's sort of the layout of the Drupal 7 module. And then I'll take a quick tour of the code. So within the dot, actually I'll go with the install file first. So within the install file, there's the, you know, hook schema, which defines the pants history table. Within, there's a hook install. So within hook install, I'm creating a field and a field instance. So that's my pants status field, which I'm adding to my, you know, user entity. And I'm making it a, you know, so the field name pants status and a type list Boolean. So list module in Drupal 7. It provides the field type that I'm using, which is the Boolean field type. And I can just here, just make my specific field. I can also, you know, set it to locked, which means I don't want people in the UI editing this field, right? Because I'm writing code against this field, that's expecting it to be a particular way. So I don't necessarily want it to be user configurable. Alternatively, if I wrote my code to be more robust so that it would work if the user configured more things about it, that would have been great too. So that's the dot install. So that's how I'm doing the, the hook install is just making that field. Within the dot module. So I'm defining a couple permissions. I am, then I have my hook menu. So this is basically how routing works in Drupal 7, is if I have my configuration form. So that's admin config people pants. And I give it a page callback, which is Drupal get form. And the page argument of pants settings. Similar, you know, since it's in the dot admin adding file that, you know, I specify that through file. And then also my Ajax callback, you know, pants change, you know, percent user. So that should be fairly familiar. The way, you know, I have blocks. So the recent pants block that's done through a view. So I don't need to define that in my code, but the change pants block that lets me toggle it through the Ajax link. I need that block. So I implement hook block info and hook block view to do that. Then I need to hook into user stuff, right? So, so it's a field. So, so field API takes care of, you know, making it available on the user profile page and letting them, you know, change it through the widget. That's all great. But the one piece of functionality that I want to add to that is every time that it gets changed, I want to put, I want to log that to my history table. So that's my, so I do that via hook user pre-save. And so I just sort of compare here, you know, my original pants status is, you know, I take my account object. It has, you know, arrow original. So from my original, can I get, you know, my pants status and then, I'm sure a lot of you are familiar with this, getting field values, you know, getting field values in your code. Takes a lot of typing, you know, because it's pants status, language none, zero value. Note I'm assuming here in language none that it's a non, you know, localizable field value, but maybe, you know, if I wanted to integrate with multilingual sites, maybe I want my pants status to be on or off depending on what language I'm using. Probably not, but other fields I might need to figure out what language code to put in there. One of the things I'll be showing in triple eight is how some of the multilingual integration has gotten easier. So, you know, once I finally, you know, through that, all that code, you know, figure out what my original pants status was and what my new pants status is, then I can say, well, if they're not the same, then log that in my history table. So that's hook user pre-save. I also implement hook user view. So the reason for hook user view is normally field formatters are the thing that's responsible for, you know, putting things, you know, displaying stuff, but in the case of the Boolean field type, you know, the formatters that are available for the Boolean field type aren't very fancy. So here I can just implement, you know, hook user view and kind of override what like the default formatter does with something that calls my own custom theme function. I'm gonna have plugins. So if you're familiar with the Ctools plugin API, that means that I have to sort of implement hook Ctools plugin type and hook Ctools plugin directory. So I sort of, you know, do that sort of Ctools plugin integration. Where can I find plugins? I'm also using views. So in Drupal 7, with the views API, I have to, if I'm integrating something with views, I have to implement hook views API and specify which views API version my code is written to. So that's that hook. I have to register my theme function or in this case, my theme template, which is the thing that themes, you know, the pants status. This is the Drupal 7 code. So yeah, I'm gonna go through that and then go through the Drupal 8. And then I've got my, you know, pre-process hook for that theme function. So then, and I'll go through the rest pretty quickly. So now my admins, I think, so one of my page callbacks in that I registered in hook menu pointed to this pants settings form. So this is my basic pants settings form where I can choose whether for the site, for it to be no default pants types or bell bottoms or MC Hammer. So I create my radio group. I set the default value to, you know, the variable get function, right? This is how you do configuration forms in Drupal 7. And then again, if you're familiar with Ctools plugins, then to get my other options in here, I sort of iterate, I, you know, use the Ctools get plugin so that I can iterate through what that returns in order to add more options into my options array. And if some of this code is not familiar, that's fine. Let's see, similarly, my, you know, in my pages.inc, I have my page callback, which does my Ajax response for the change pants block. All right, let's give it a hand for Morton. All right, so the .test file, so this is where, you know, if you have simple test coverage. So one of the things in Drupal 8 is there's a lot of things that use object-oriented programming, which means a lot of classes. In Drupal 7, we don't use classes very much. Generally, for a lot of modules, the only place where classes are used is the tests because every test is a class. So, and depending on what you're doing with views, some stuff with views. Views itself uses classes everywhere, but. So here I've got my classes that represent my various tests. And, you know, so my views integration file, you know, hook views data. I won't go through all of this in detail, but this is basically, you know, if you're familiar with, if you create tables and you want those tables to be available to views, you implement hook views data. This is, again, the Drupal 7 version. And similarly, the views.default.inc, it's actually crazy long file, but no one ever reads this stuff, right? This is just, you make your view in the UI, you export it, you copy it here. And then the other files here, so my Ctools plugins, my Bell Bottoms and MC Hammer plugins. This is how Ctools plugins work. So with Ctools plugins, you can do things in a bunch of different ways. Ctools is extremely flexible, but if you follow the, within the Ctools module, there's the plugin example folder. So if you look at how the plugin example folder does it, it does it this way, which is you create a, you put one plugin per file, within that file, you define a dollar plugin variable, and you put things in there that are very similar to the kinds of things you would put into an info hook. So like the label and then various callbacks. So in this case, like what I'm calling the view enabled callback and the view disabled callback. I realized after I wrote this, that enabled and disabled is not the best name for showing pants on or off. Probably a better function name would have been, like view pants on, view pants off, but since the field was called pants status, I immediately was in the mode of thinking, oh, well that's enabled and disabled. So I've got my two functions, which is what should my, you know, what should my pants look like when the user has them on. So I'm returning here, you know, and a render array of type image and giving a path to the graphic I want to use. And then for disabled, just saying off. So this is just showing the Ctools plugin structure. So that's the Drupal 7 version. And now I'm going to go to the, switch to the Drupal 8 one. Spoiler alert. So again, starting with the layout of the file, a lot of it's the same. So instead of my .info file, I have a .info.yaml, I still have a .install file, I still have a .module file, and I still have a .views.ing file for the views integration. A couple of the new files that I have in here are .routing.yaml and .services.yaml. I'll get to what's specifically in there a bit later. Also, I moved, so in the Drupal 7 version, I had my pantstatus.tpl.php file right here at the root folder. In Drupal 8, the convention has gone to where these now go into a templates subdirectory. And also, they're in twig now. So instead of pantstatus.tpl.php, it's pantstatus.html.twig. You'll notice also in here, we have a config directory. So one of the things, as you know, that configuration lives in files, and so the module can supply the default configuration file. And so that's what pantstatus.tpl.yaml is, and I'll get into what the others are in a bit. There's also, if you'll notice, a configuration schema directory. So this is, it can be a little intimidating when you look at it at first, but it's a really useful file. So you don't have to start with it. You can actually port your module without it. And your module can work without the schema file just great. But one of the things that the schema file does is it basically identifies everything that's in your configuration files. And by providing some of those mappings, like identifying that my pant's type setting is of type string. And if I had other things, I could say type text or type path or there's a whole set of documentation on what the different types are. Then by doing this, it actually allows like configuration translation to work. So I might get into more details about this in a bit, but I'll just point out that if you see a schema directory in like for example, Drupal 8 modules, it's there to sort of define the structure of the configuration. And in theory that can have many uses, but the use, the one use case we know it has is to support really great UIs for being able to translate any configuration in your site. Yay, multi-lingual initiative. Do YAML files understand the constants? I think the YAML syntax understands constants, but the YAML parser we're currently using, I don't know if it does. We're using a fairly limited YAML parser and there's been talk about using a more full featured one, but that hasn't happened yet. Okay, so then the one other directory that's in here is the lib directory. So the lib directory is where all of your object-oriented classes go. So, and there's a lot more of them. So, there's the lib directory and then as of today within the lib directory, there's a directory that's literally called Drupal and then beneath that a directory that's the same name as your module. That, those two, the literal Drupal directory and the name of your module directory, we're hoping in about a week or two that we won't need those directories because we're switching from the PSR0 standard to what will hopefully become the PSR4 standard. So for now, as of today, there's within lib, there's Drupal and then the module name, but those two directory levels will hopefully go away within a week or two. Within that, we have a structure that is up to your module to define. You can define whatever set of subdirectories in here is useful for organizing your files, but core follows a certain set of conventions. The conventions that core follows is that, well actually there's two directories that are not up to you. The test directory and the plugin directory, those are like, that's not convention, that's like, it has to be that way. The others of annotation, controller and form, those are by convention, but that's the convention that core uses. And so forms go in the form directory. So for example, what was my, what in Drupal 7 was my pants.admin.inc file in Drupal 8 is a class inside of my form directory. Similarly, controller is for all of your things, you know, all of your pages basically that aren't forms. And so like my Ajax callback, which was in my pants.pages.inc file in Drupal 7, becomes my, so basically the function that was my page callback in Drupal 8 becomes a class in the controller directory. The word controller by the way is, that's from MVC terminology, right? So MVC terminology is model view controller. Drupal isn't a 100% perfect MVC framework. I don't even think a 100% MVC framework is necessarily perfect, but some of the terminology from MVC is being adopted. So that's where the word controller comes from. And then there's some other, so oh, I want to open up the test. So within Drupal 7, I just had my pants.test file. And I had all of my classes there, or I could have had multiple.test files. Sort of you could decide which classes you put into which files. In Drupal 8, we're following sort of the newest PHP standards which is that, you know, one class per file. So if I have three tests and therefore three classes, they each go into their own file. So here's my configuration test and my Ajax test and my UI test. So the question is, is that a standard? One class per file is a, well, it's actually both the PSR0 and the PSR4 standard. So, and what that allows is it allows, one, I think it's actually a really good convention. I think it's a great way to organize files. Yeah, if it work otherwise. So in, we're using a standard autoloader. So we're using Composer's autoloader. So if you're using Composer's autoloader, which we're doing, then that's, you have to do it that way. If you require, if you decide you wanna put multiple classes into one file, then, right, but if for whatever reason you wanted to, then you would be responsible for loading that file. So you would have to do the require once of that file before you try loading the class. The plugin directory works actually very similar to like Ctools plugins. So with Ctools plugins, you had a plugins directory and then within that you had a directory for your plugin type. So it's the same thing here. We have a plugin directory, only different from Ctools is it's capital P for plugins with a capital P and singular. So plugin instead of plugins. And then the pants type directory, which is my plugin type and again, capitalized instead of lowercase, but otherwise, you know, same thing, one plugin per file. And you'll see here that blocks became plugins, which I'll get into in a bit. Okay, so any sort of any questions on just file layout before I get into some of the contents of the files? Yep. Oh, okay, yeah, so the question is, what are the different YAML files and are they required to be in certain places? So there's two kinds of YAML files that we have. There's YAML files that represent configuration and when I say configuration in the Drupal sense, I mean things that generally there's a UI to edit, right? So that there's, in principle, a configuration user interface, it's something that can be edited by the site administrator. And also in some cases, there might be configuration that there isn't a UI for, but the other aspect of configuration is that it can be deployed. So anything that we call configuration in Drupal is something that you can take those YAML files from, say, your staging site and import them into your production site and Drupal will import them and write, it's just like features, but better. So YAML files that are not in the config directory are not deployable in that way. And in particular, YAML files that are not in that config directory, they're not configuration in the sense that they're not things that change, they're not something that the administrator of the website is meant to change. They're essentially part of your code. They're just like your code. They're just written in YAML because YAML is a nice syntax instead of like a PHP function that returns an array. So the examples of things, so for example the .info.yaml file, right, is a great way to provide information about your module and then the others in here, the routing and the services, it's a way to declare things that in Drupal 7 you would have declared by implementing say an info hook that returned an array, in this case a few of those have moved into YAML files and those have to be where they are. So they both have to be at the root directory and named your module.routing.yaml or your module.services.yaml and there's a few others that will be documented eventually what they are is still being in flux. Okay, so I'll go through the, I guess the, actually I'll go through the same thing I did last time, which is the .install file first. So within the .install file, the hook schema hasn't changed. Yay. So my pan history table, absolutely identical definition as in Drupal 7. Hook install, what you do, I mean the fact that hook install exists hasn't changed, still named hook install. What you do within hook install may or may not be different, depending on what your module does. In this case, it's quite different than the Drupal 7 version. The Drupal 7 version of pant module within hook install created a field and created a field instance. So in Drupal 8, that's configuration. So that's what this is here in this YAML file called field.field.user.pantstatus.yaml. That's my field. So what in the Drupal 7 version, I passed to field create field that I just put into this YAML file. And then same thing for the instance. There's actually two ways you can make default config files for things like say fields and views. So for fields, and actually you can do this. So for fields, I happen to do it based on just specifying like the minimum that's needed, right? So just specifying that what I, in Drupal 7 would have passed to field create field or field create instance. And then during the import process, the configuration system pretty much figures out everything else. Just like what field create field and field create instance used to do. It's like the module that defines what these configuration files are for. So for example, field module knows what it expects within field configuration files. It can provide defaults. So that's one way is sort of the minimalistic approach. The other way you can do it is you can just make the thing you wanna make in the UI and export it. So that's actually what I did with views, right? So views instead of just trying to figure out what is the minimal information I can put in here, I just made my view and then it generated the YAML file and then I just copied the YAML file into here. So that's kinda neat, the configuration system, those are two different ways you can specify your default files. So going back to the dot install. So I don't have to make my fields. But this is now sort of a concept that's specific to a field API, which is within field API in Drupal 7, sort of all of the information that all of the information about the field was sort of attached to the field kind of configuration. So that included like how to display it both on the, essentially what formatter to use on the display side and what widget to use on the edit side. That was sort of part of the field and the instance configuration. The transition to Drupal 8 and trying to make our, as part of configuration management, trying to make our configuration files better structured. We decouple that. So the configuration of the field is just the information about the field from the standpoint of data modeling and the configuration of what it should look like when it's being displayed in a particular view mode or what it should be edited like when it's in a particular form mode. That is now a separate piece of configuration and so that's what these functions are doing is it's just setting that. So I won't get into this in more detail unless there's maybe questions later about it. This gets into the nitty gritty of field API which probably not everyone cares about. Okay, now going back to the .module file. So permissions have been really changed. Hook menu. So hook menu has changed. So hook menu in Drupal 7. You specified two things in it. You specified, it was used as a way to map a URL to PHP code that would have to run. So a URL to, or a Drupal path which is sort of equivalent to a URL to the page callback that would have to run. That concept of mapping a URL to PHP code that runs, that's called routing. And so hook menu in Drupal 7 gave you the ability to supply routing information. So that all moved into this routing.yaml file. Okay, so this is using symphony. So we're using the, in Drupal 8, we're using the symphony routing system. So we're using the symphony sort of format for routing. And one of the reasons we're doing that is because for web services to implement RESTful web service, like implementing RESTful web services in Drupal 7 was difficult for a lot of reasons. And so like services module and RESTWS module had lots of things they had to do to sort of accommodate how Drupal 7's custom routing worked. When we were looking at what other projects were doing, we saw that symphonies router actually does a lot of what we needed to make things like services module and REST module way simpler. So it's great that we were able to just use that router and it just meant that in our routing.yaml file, we had to learn their syntax. But the nice thing is symphonies routing syntax is really well documented on symphonies website. So here I have my two URLs. So I have my pants, my pants settings form, which I give a particular path. And then I specify that the form is a particular class. And then there's this requirements key where I can specify what permission is required. And then there's various other things that I could have specified here if the requirements was based on something other than a permission. In this one, the leading slash there. Is that needed? I don't, it's good. So the question is, is this leading slash? So I'm here, I'm specifying the class to use for my form. So I'm using a class that's namespaced. So the class name is pants settings form, but it's within Drupal slash pants slash form and does it need a leading slash. PHP is sometimes ambiguous as to when things need a leading slash or not. A lot of times it lets you get away with that one. It's generally good practice to have it. Yeah. Sure. Yep. Great question. So the question is, why is it that in some places we use forward slashes and in other places we use back slashes? So the reason is because we use forward slashes when we specify things that relate to URLs because HTTP convention is that URLs are separated with forward slashes. Here we're using back slashes because we're specifying a class in a namespace in PHP for whatever reason decided that namespaces are delimited by a backslash. What's that? So the answer is that PHP chose the backslash delimiter because they couldn't use the forward slash delimiter because the forward slash already had meaning in PHP. Yeah. Yeah, they're out of here. Okay. Yep. Sorry. Yep, another question back there? Yep. Okay, so the question was if you have classes like the pants module, which is a contrib module, is why are the classes that it defines in the Drupal slash pants namespace? And the reason is, so yes, that is the convention we chose. We said, we're gonna put every Drupal contrib module into the Drupal namespace and then the module after that. And the reason is because if it's a contrib module it's going to live on Drupal.org. And so we just decided that the name Drupal is not just Drupal core, but the name Drupal is everything that you can get through Drupal.org. And so essentially that's the sense in which Drupal is the vendor. Even though you might be the author of your particular class, once you put it on Drupal.org, Drupal's like the vendor of it, right? Maybe you stop being the maintainer, someone else becomes the maintainer. If, yeah. So then the question is, so what happens if you're writing a custom module that you don't plan on putting on a Drupal.org? So Drupal already essentially assumes that you're picking a unique namespace for your module. It's not like on your website you can have two modules named the same thing. So you can, for your custom module, put it in the Drupal namespace as well, especially because maybe it's your custom module now, but maybe eventually you'll put it on Drupal.org. However you could, if you know it's your custom module and you know you will never want to associate it with the Drupal as a vendor, then you could actually put it in your own namespace, but then you'll have to then write some code to essentially register that namespace with the auto loader that Drupal uses. Okay, so the question is, do you still namespace things like with the Drupal slash pants in front of it? There was a comment in Larry's session earlier about that we'll be moving to PSR4. That's actually a great question. So what's not changing is class names, right? So the class will still be, the name of the class as far as PHP is concerned will still be Drupal slash pants slash form slash pants settings form. If you, what is changing hopefully next week is how that class maps to the file that it's in. So the class as far as PHP is concerned is still Drupal slash pants slash form slash pants settings form, but right now that class lives in the file that's lib slash Drupal slash pants slash form slash pants settings form. And what will change in a week is that the Drupal and pants directories won't need to be there, but the class will still be qualified to the Drupal pants namespace. The reason why the directories won't be necessary anymore is because we're already within the folder structure of the pants module, because we're already in the folder structure of the pants module, obviously we're in the Drupal pants namespace. So that's why we'll be able to get rid of those two directories. Is that, was that the question? Okay. Yes, yes, yep, so let's see if you, so for example, and like, yeah, so for example, if you, again, if you're, you know, within PHP 5.3 because you have to refer to classes and they're fully qualified sense, the convention that we use is we have a bunch of view statements at the top of the file, which, so that then later in the file we can use them by their shorter name. So the use statement at the top of the file will still be fully qualified. So the fact that we're taking directories out doesn't change any of the code, which also means if you port your module before, you know, like now, like, none of that code will have to change. When we remove those directories, you'll just have to move the files, you know, two levels up. And one more. Okay, so the question is, will hook menu go away eventually and I'll answer that right now, which is so, so right now we still have hook menu but the scope of what hook menu is responsible for is less. So because we've moved everything routing related to the routing file, all that's left in hook menu is providing the information for a menu in the sense of a visible menu, a set of links that get rendered to a page that can be clicked. Yeah. Okay, so the question is, what should we do with menu routes that don't need to appear in any visible menus? And so yeah, so notice that in my routing file, I actually defined two routes. I defined a pant settings route and a pants change route. So the pant settings is the configuration form and pants change is the Ajax callback. So the Ajax callback is an example of something, I don't need that to appear in a menu and that's why in hook menu, it's not there. So if you don't need it to appear in a menu, you don't need it in hook menu. But if you do want it to be in a menu, so for example, like admin config people pants, I actually want that to be in a menu. Then I put that in hook menu and I tell it what route it's using and then the only other information I supply is information that's necessary for the rendered menu. So generally like the title of the link and then the description. There's a good possibility back to your question about what happens with hook menu. There's a good possibility that this reduced hook, so what hook menu has become, which is much more limited than what it was in Drupal 7, will very likely get renamed to a different hook name. So instead of hook menu, it'll probably be something like hook default menu links. But that hasn't happened yet, but it probably will in the next month or so. Yeah, the question is can we remove title and yeah. So yeah, the question is, will title and description stay in hook menu and what we already have in Drupal 8 is the ability to specify a title in the route. In which case, so the reason that's important is because the title serves two purposes. So there's the title that you want to set the page to, like the thing you wanna put in your H1 tags or in your head title when you go to that page. So that title has to be in the route because when you go to URL, what you want your actual page title to be is that needs to be in the route, but what you want the title of a menu link to be in a menu, if it's the same, then you won't need it within hook menu because the system will be smart enough to say, well, let's default the link to whatever the page title would be if I went to that URL. But if you wanted it to be different, if you wanted to render your menu with a different link title, then what becomes the page title when you click that link, you would still be able to put title within hook menu to specify that as an override. Yes, yes. So the observation here was that I'm specifying the route name to pan settings and then when I go to, the route already knows what path it's on. So why are we duplicating that information as the key? And the answer is that's actually changing. So there's a patch in the queue to change that. Ah, okay, so the question is if you're, so I think the question is that within the route, so the YAML file is great for defining things that are static, like for example, if I have specifics things that I want, but YAML doesn't support a looping structure. I can't do whatever, for I equals one to 10, define a bunch of paths based on a loop or based on other PHP logic. So how do we do that? And the answer is there's a, there's a event, there's essentially a route build event and a subscriber that you can implement. So there's basically PHP class that you can implement where you can do dynamic routes. I won't show that here because it's, I think, a little out of scope, but there is a way to do that. So the question is can you set callbacks? You know, what's the similarity or differences to how you set callbacks? And it's different. So for, like in Drupal 7, what you would do is you would say page, if you were doing a form, you would say page callback is Drupal get form, right, because Drupal get form is the name of the function that gets a form. And then page arguments is the form ID. So in Drupal 8, you specify a form and it has to be a class, right? It's not a function, it's a class. Right, so if it's not a form, then for things that weren't formed, so you would just say page callback in whatever your function is, what you do instead is instead of saying underscore form here, there's actually a couple of different things you can set. There's underscore controller and underscore content. The more common one is underscore content. In fact, this one ideally would be underscore content here as well, but there's still a bug in the AJAX system. Typically, it would be underscore content and then the value of underscore content, what you would set it to would be a class, you know, colon, colon method name. So instead of it being just a global function, it would be, you know, a method in a class. But other than that, it's the same. Yeah, so the question is, when do you use content, when do you use controller? Underscore content is the much more common one. Underscore controller is where you want to take over the entirety of what's returned. So for example, if you're doing like an autocomplete callback, you know, or other fancy stuff, but typically if you're just returning content that you want to be shown in HTML with all of the blocks around it, that's underscore content. Underscore controller is like you're basically saying, I'm gonna take over absolutely everything that's being returned to the browser. The question of whether AJAX fits in that, like AJAX in the sense of Drupal AJAX. It's in between state right now, but things like an autocomplete where all you're returning is the autocomplete matches, right? That's not something that you're gonna render. That's something you're providing for JavaScript to interpret as data. That is clearly an underscore controller. I think I'll move on just to get through this faster and leave more time for hands-on stuff. Okay, so that's routing. I'll now actually show the configuration form. So here's my configuration form and actually what I'll open up is, okay, so object-oriented programming. One of the great things about object-oriented programming is you can define interfaces, right? So in Drupal 7, whenever you build a form, you have a function that corresponds to your form, right? So the function is named the same thing as the form ID, which is the thing that you pass to Drupal GetForm. And that's what defines the form, the actual structure of the form. And then you also have to implement an underscore validate, that same form name, underscore validate, and that same form ID, underscore submit. So there's like three functions that you generally have to implement in order to make a useful form, and you just have to know that. So in Drupal, one of the great things about object-oriented programming is PHP provides this concept of an interface, which means you can essentially document what is expected of forms, right? So here I have my form interface, and I have build form, validate form, and submit form. And then also what's new, GetForm ID, the reason for that is because since my form is no longer a function, I can't just get the form ID by that function name. There's actually an issue right now being debated about if we wanna make GetForm ID easier. But so anyway, that's my, so now instead of just happening to know that to make a form, you need a form builder function and then a validate function and a submit function, the interface now tells you that. So if you're using an IDE where you can see interfaces or once we get better class hierarchy documentation on Drupal.org, when you browse the API docs on Drupal.org, you'll see, oh, I'm building a form. What's the interface for a form? Great, that's what I need to implement. Now, in this case, I'm building a configuration form and so instead of building it from scratch, I can actually extend it from config form base, which lets me do a couple of convenient things. So I have my build form function and so in the Drupal 7 version, the way I got my, I called variable get in order to set the default value of the radio group that I'm defining. And in Drupal 8, variable get is going away because that's not deployable from staging to production. So part of the configuration system is I'm gonna get it through config and the way I can, we're still working on some of the ways to do it, but one of the ways to do it when you're in a configuration form is this arrow config factory arrow get is how I get my configuration object. I could also call Drupal colon colon config and anyway, I'm gonna skip over the details of you. There's still some, from a developer, Angie mentioned we're still trying to get the developer experience right for Drupal 8 now that we have the basic architecture in place like how can we make for the best developer experience, whether calling this arrow config factory arrow get is good developer experience or not is being debated. So maybe there'll be an easier way to do it, but this is how we can do it now. Once I have my configuration object, so that configuration object essentially represents the contents of the file that's in the YAML and I can now just call get on that. So for example, once I have my configuration object representing what's in my pants.settings.YAML, I can now say dollar config arrow get pants type which is a particular variable or key within that YAML file. So that's building the form. So instead of C tools plugins, I'm using the Drupal 8 plugin system. I'm actually gonna skip over the details of that right now. And then the other thing I need to do is I need to implement my submit functionality. In Drupal 7, if you are building a simple settings form, you didn't, in Drupal 7, if you were building a simple settings form, you actually didn't have to implement your old submit function because Drupal 7 tried to, if the configuration stuff was being put into the variable table, like if you were getting it from variable get and setting it with variable set, Drupal 7 had this ability to sort of automatically look at what's in your form and kind of call variable set on everything. And if you ever opened up your variables table, it ended up being polluted with a ton of stuff that you actually didn't want. So in Drupal 8, for various reasons, we decided we're not gonna have that auto magic and instead it's your responsibility to save your configuration as part of the submit handler of the form. So which you can do the same, where you get the config object, you call set on it, you save it, done. Oh, okay, so yeah, so the way you get the config object is you ask the config factory to get pants.settings, then you're gonna call config set, pants type, that's the key within the ammo file that I wanna set, and then the value I'm gonna set it to is what got submitted as part of my form. Oh, oh, sorry, you said left, I'm sorry. Okay, okay, okay. So that's base, that's configuration. Let's see, what else can I show? So entities, I think will be the next thing that I'll show, which is, so the entity API is totally different in Drupal 8 than in Drupal 7. There's actually a lot to the entity infield API that got changed, I'll just show one part of it. Which is the part that's relevant to Pants Module. So the part that's relevant to Pants Module is that we were implemented in Drupal 7, we were implementing cook user pre-save, and you remember, because we want to log into our custom history table if there was a change, and the way we got data out of a field was, we had to do dollar user or dollar account, arrow, pant status, language none, zero value, and instead that got a bit easier, where now we can just say dollar account, in this case we want to get the original one, so dollar account, original, pant status value. So we don't have to specify language none, we don't have to specify zero. We can just, so not have to specify language none, that's because sort of the entity system and the multilingual system already make sure that the object knows what language it's supposed to be in. And then in this case we're bypassing the zero because a lot of times you have single valued fields and whether you have a single valued field or a multi valued field, if you sort of don't specify, if you want the second item you could do pant status, one, if you want the second item, but if you want the first item you can just leave that off. So that makes it easier to sort of work with single valued fields. And the reason this is possible is because you'll notice that the signature specifies that my account object also implements an interface. So all entities, in Drupal 7 entities were objects that were just standard class objects. In Drupal 8 entities like dollar user, dollar node are objects that are classed objects. They have a particular class which means they have a particular set of methods on them and they have an interface that they conform to so you can type into them and then figure out which methods you can call on them and they can therefore hide implementation details. Like they can, one of the great things about arbitrary programming is they can automatically know what language they're supposed to be in rather than having you specify that every time you access a value. And let's see, a lot of, so that's actually, that's most of entities and I guess I can get back to plugins. So plugins. Okay, so remember the plugin in Drupal 7 if you were doing a Ctools plugin had like a dollar plugin variable at the top and then a bunch of functions. And then the plugin array at the top had to map, like has defined certain magical key names and then map what function, contain the implementation for that key name. So in Drupal 8, now we can use classes so essentially we can just implement a class. Again, we can say that it implements a particular interface which means the interface knows that the interface documents that what you need is a view enabled and a view disabled function or if I named it better, view pants on, view pants off. So instead of those being like magic key value pairs, it becomes defined in PHP through the interface and then I can just implement my methods on this class, view enabled and view disabled. So that's, so all of the magic function kind of key to function name is just replaced with methods on classes. But the part that got a little trickier is instead of having a dollar plugin variable at the top for the other stuff like the label, the stuff that's not provided through a method, that's now done through an annotation. So that's kind of what that is. So that's kind of plugins and blocks are an example of that plugin, which you'll probably run into right away if you're doing your module. That's probably the first plugin you'll have to deal with. So blocks in Drupal 7, you did with hook block info and hook block view. So blocks are now our plugin. So instead of, so there's no more hook block info and there's no more hook block view. Instead, you create a block. You can implement block interface or extend block base. And then you can then look at the inner, you look at what the interface requires and figure out what you need. So you need to implement the build method, which is the equivalent of what hook block view used to do. So everything that hook block view used to do, you just do inside of the build method of the block. And then everything that hook block info used to do, you do through the out block annotation. Okay, so I know that was really, really fast, but I guess I could maybe take a few more questions and I also wanna make sure to leave enough time for you to pick one of these things to start cranking on. So can you repeat the first part of the question? Oh, okay. Okay, so the question is what's the, I mentioned something earlier about singular versus plural plugins. So I'll answer that question first. So in, so again, if you were doing stuff in C tools, if you were doing plugins in C tools, then the convention in C tool for your plug, was within your module directory, if you were supplying plugins, is you would have a directory named plugins, lowercase p s at the end. And then within that you would have your, plugin type name, which also was lowercase. And therefore if your plugin type had multiple words, it was separated with an underscore. So like lowercase pants underscore lowercase type, right? And then within there, you would just have your dotting files. So the way that's changed in Drupal 8 is the dotting files became classes. So bell bottoms dot ink became bell bottoms dot PHP. And so therefore, the B's would be capitalized because PHP naming convention is when you have a class name, you usually title case it instead of lower casing it. And then the other thing is the directory names also are following that same convention, which is the directory that it's in instead of being plugins is plugin. And then pants type instead of being, lowercase pants underscore lowercase type is uppercase pants uppercase type. So just, you know, so that's it. There's no different kinds of plugins. It's just if you're moving things that were C tools, plugins in Drupal 7 to Drupal 8 plugins, that naming convention has changed. The second question is what's exportable, what's not? So one of the great things about Drupal 8 is the configuration management system. All configuration is exportable. Just config. All configuration is exportable, which means any piece of configuration, anything there's a YAML file for is, well, sorry. Anything there's a YAML file for in the config directory is exported, is exportable, and therefore deployable from one site to another, which is great. It's not like in Drupal 7 where it's like, well, if you have features module enabled and some configuration was exportable and others wasn't. It's like every configuration is exportable in Drupal 8. And then what's not exportable is things like content, but there's the REST module, which lets you, you know, get essentially, you know, get node one as like adjacent string, and then also put that to another site. So you can, via the REST module, you could actually do content staging, you know, via just sort of doing, but you need it there, you know, there will probably be like a content deploy module that's written in Drupal 8 to handle content deployments, yeah. There are also some things that you have, you know, there are some things in Drupal 8 that might be in your Drupal 8 database that are neither config nor content. You know, neither config in the sense of YAML files nor, you know, content in the sense of content entities. So for example, like the band module has a table of IP addresses that you're banning, right? So anything like that is not exportable by default. I mean, unless the band module happens to provide that. Any other question or do you wanna get coding? Or actually just if you wanna get coding, get coding, but if you do have other questions, well let me ask, for people who are coding, would you rather that any more, that additional questions be asked sort of through the microphone or quietly here to the side? Okay, who would rather questions continue over the microphone? If it's better, okay, raise your hands if you'd rather do questions over the microphone and raise your hand if you'd rather we stay quiet and let you code. All right, questions over the mic. Any other? Okay, yeah, so the question was, you know, like this annotations business, you know, the thing that in C tools was a dollar plugin variable at the top, which was actual PHP code and now that moved into a class annotation which looks like a comment and it's hard to debug because the annotation parser that we're currently using is very finicky. Yeah, so one thing is we're actually working on improving the annotation parser. We're using doctrines, we're actually contributing some of those improvements upstream back to doctrine. So hopefully it'll be a little bit easier to debug at least in terms of like if you get one thing wrong it doesn't white screen. We're also trying to implement some better error handling where even if the annotation parser isn't happy at least like throws an exception and we can catch it and do something like that. The other aspect of it being hard to debug is, you know, the IDE doesn't really help you with it. Yeah, that kind of sucks. So, you know, we had a lot of debate around, you know, the two best options for how do you provide metadata, how do you provide the label of your plugin, right? You know, the two options that we've worked looked at is annotations on the class and, or YAML files. And YAML files would have had the advantage of, you know, you can open it up in a YAML editor, you know if your syntax is right. The disadvantage though would be that your, the metadata about your plugin, you know, the label of your plugin is in one file and the behavior of your plugin is in another file. And if you have lots and lots of plugins that's annoying. So that is what we do for routes, right? So like route controllers are classes in one file and the information for how you connect that to a URL is in a routing.yaml file. So we sort of accepted the YAML approach for routing but chose the annotation approach for plugins. We're probably gonna continue to have some discussions around do we wanna leave it like that? Do we wanna standardize on one, standardize on the other or make it so that people, you know, each module can choose which one it does. You know, there's all, it's sort of weighing a whole bunch of like pros and cons on one side against pros and cons on the other side. Yeah. So the question is can you do annotated routes? Not currently, though there's been requests to allow for that. So that's, you know, we'll see. Yeah. Okay, whenever I answer these questions I was like, you know, we'll see. We means all of us, right? So like all of these issues, all of these things are being debated in the issue queue. Everyone can participate, so. And actually, and this is, and it's, you know, one of the reasons we're doing this lab is because, you know, the more, you know, the more developers like you are actually running into these things with your module, the more likely it is that you will participate. You know, so that's what we're hoping, is that you'll participate in these discussions so that like what Angie mentioned is we have a period of time over which we can try to get the developer experience optimized. So that'll happen, you know, that's the process for how to optimize it, is figure out what you don't like, find the issue, comment on it, and we'll try to come up with something that works. I think I do want to give people a chance to code, so I'll get away from the mic, but feel free to come up and we can keep chatting. And thank you, oh wait, one more. Oh, if you have a, meaning it's available to everyone, or do you mean it has some other kind of access control on it besides permission? Okay, so yeah, if you're doing it, if it's available for everyone, it's instead of underscore permission, within requirements instead of, you know, underscore permission colon a permission name, it's just, it's underscore access colon true. Thanks everyone.