 All right, we are live. Welcome everybody. As you are joining, if you would like to get your local development environment ready, if you're going to code along with me today, you can download the plugin that we'll be working on. It's a very simplified plugin today. There's no major coding or anything like that. I'll paste the link in the chat for those who want to get hold of it. And then you can just let us know in the chat where you're joining us from around the world. I feel like I've been doing this for almost a year now and I feel like I need to start having a better introduction or something. So I'm going to start listening to radio DJs and listen to how they start their shows and come up with some kind of catchphrase or something. The phrase that always is in the back of my mind when I think radio DJs are Robin Williams and Good Morning Vietnam, but I don't think that's going to work for an online workshop. So for those of you who don't know me, my name is Jonathan. I am from Cape Town in South Africa. Currently a developer educator at Automatic and I'm sponsored full-time to work with the training team, the WordPress training team. And the training team is the team within WordPress that manages the Learn WordPress platform, learn.wordpress.org. We create tutorials. We create lesson plans for folks who want to present at meetups and WordCamps. We do these online workshops. We create courses. And so this is what I do every day. Welcome to Mary from, I'm not going to try and pronounce that because I probably am going to make a mistake, but welcome, Mary. It's Monomony. Monomony, thank you, Tracy. Okay, so while folks are getting installed and set up, let's get through some announcements quickly. First of all, welcome and thank you to Tracy, who is co-hosting with me today. Thank you, Tracy. Tracy is joining us from Reno, Nevada. I hope I pronounced that correctly. And he's joining us super security this morning. So I appreciate having him joining. If you can't see the slide right now on screen, I am presenting my screen, and this is an announcement slide with the title announcements. So if you can't see this slide or if you can't see any of the stuff that I'm presenting today, please do let me know. And then I will deactivate and reactivate the screen share, which usually fixes that problem. As always, we are presenting in focus mode, but if you would like to, please feel free to enable your video. I don't mind either way. I am quite comfortable going on, foraging on ahead or forging on ahead, should I say, without interaction with folks, but if you would like to, you're more than welcome to. As always, you are welcome to ask questions. You're welcome to either post your questions in the chat and I do allow for sessions in the chat where I pause and grab a drink of water or something and take a look at the chat and see what questions are happening. Or you're welcome to unmute and ask questions. I do ask if you want to unmute to maybe just use the raised hand feature in Zoom or just unmute and say, excuse me, just so that we know that you're there. Jean says, I'm from Northwest New Jersey and she gives me some glowing praise. Thank you, Jean. I appreciate it. I've really enjoyed putting these sessions together for everybody. I've started getting to a point where I'm seeing folks coming back for these sessions, folks like Jean, folks like Tracy, folks like Lisa, Adrian. So it's always fun to see folks come back and we share more information together. So I enjoy putting them together as much so I hope you enjoy watching them. Then to move on to the further announcements, as I said earlier, if you want to get your local install ready, you're welcome to do so. You can download the plugin and install that so long. I will go through a quick plugin installation when we get started anyway. Very importantly, if I am going too fast, please do let me know. I do tend to get excited about what I'm doing and I start talking really, really fast. So if I'm going too fast and you've got the automatic transcriptions on and it's going too quickly for you, please let me know and I will slow down. We will be posting this session to WordPress TV afterwards so that if you miss this or if you have to leave, I will be uploaded there. Okay. Close captioning. That's the other term for what the transcripts are. Close caption. All right. So today we're going to be looking at roles and capabilities within WordPress. We're going to be, first of all just doing a quick sort of overview of how roles and capabilities work. Most of the time, if you're creating users in a WordPress site, maybe even just an admin user, you've interacted with the administrator role and you understand maybe some of the capabilities that role has. So we're just going to do a quick overview of how that works within a WordPress environment. We're then going to dive into how and where the data around roles and capabilities are stored and how you can, when you're writing code, if you want to enable the capabilities, check how you can do that. We have covered it before in previous sessions, but we'll dive a little bit deeper into that today. And then we're going to look at how you can assign capabilities to an existing role. So we're going to take a specific role and we're going to beef it up with some additional capabilities in the code. And then we're also going to talk about how you can create a custom role and then assign capabilities to that custom role. So in terms of that, that might be you needing to create a role for a specific type of user. And we'll talk about an example when we get there and I'll show you how that works. The nice thing about today's code is it's very, very simple, adding and managing roles and capabilities in this way is very straightforward to do. Next week, we're going to be diving a little bit deeper into some more advanced topics around roles and capabilities. But this week is very much just sort of introduction and foundational concepts around how we can write and create them. Our objectives for today, we're going to set up and review the testbed plugin that I've shared with you. It's very short and sweet, so that won't take long. Then we're going to just do a quick review of roles and capabilities. I'm going to share some documentation with you that you can read later. Then we're going to actually have a look at where the user roles are stored in the database and how WordPress sets that up. And then we'll get onto the assigning specific capabilities to specifically the editor user. So we're going to beef up the editor user with some admin specific capabilities. And then we're going to create an assistant role. So an assistant to the administrator, which will have some specific capabilities assigned to that. And I'm going to show you how to do that. All right, I'm going to pause there for a quick sip of water. If anybody has any questions before we get started or if anybody still needs to set anything up, otherwise we can get going. All right, so let's have a look at the plugin itself. I'm pretty sure I have the plugin on my desktop. If I don't, I will quickly download it. It's not a very big plugin. So I'm going to just add it through the plugins and new functionality within WordPress. I'm going to click on the upload plugin button. I'm going to choose file and hopefully find the plugin. I don't have it on my desktop. That's embarrassing. I thought I had, I must have moved it. So let me quickly download it from my own link. There we go. That'll download my desktop and then I can install it. And there we go. And it is a very small plugin. It doesn't have a lot of code in it. I'm not going to activate it just yet. I'm just installing it. If you've activated it, it's up at the end of the world but I'm not going to activate it just yet because I want to have a look at the code itself first. So the plugin, here is my learn press test bed that I've got. And here is the plugin folder itself and here is the plugin file. And you will see that it only has two functions in the plugin code. Of course at the top of the plugin, there is the plugin header which just has the name and the version number. And then there are two things that I'm setting up. The first thing that I'm setting up is an admin sub menu page using the add sub menu page function. I'm hooking my custom learn sub menu function into the admin menu hook. That's the right hook to use when you want to create an admin sub menu page. And all I'm doing is I'm creating this WP learn capabilities sub menu page in the tools menu. Now I would mention if you are, if you have installed any of my other WP learn plugins like learning plugin security or learning rest API or those kinds of things, I do recommend disabling them from your WordPress site because I tend to use the same prefix for my example code. So you might have some conflicts. So make sure you've only got the roles and capabilities one installed and if you want to have it activated. This then sets up a sub menu page which uses the WP learn render admin page callback function to actually render the page content which is the next function in this plugin. And all this plugin is doing is it's getting the editor role. So we'll talk about that function later, but just for now, believe me when I say it's fetching the editor role, it's returning that role objects into this role variable. And then I'm simply echoing out the contents of that role object. If you don't know what an object is in PHP, don't worry too much about it right now. It's just basically a collection of information or a collection of data. You can have arrays or objects in PHP and the roles just happen to be of a type of object. So let me activate this plugin and show you what it does. I'm going to paste the plugin link in the chat again for those who are joining a little bit late today. So if you are joining and you would like to install this plugin on your site, there is the link there. Let me activate this plugin now. And as I say, for now, all it is doing is once the plugin is activated, if I hover over the tools menu item, there is a WP learn capabilities menu item, sub menu item. And if I click on that, it outputs the role object. So there we see WP role object. The name is the editor role and that's because I'm fetching the editor role in the code. And then the next item is the list of capabilities and then it shows all the capabilities. The reason it looks like this with the funny brackets and the squares and the square brackets and the double equal to arrow signs and all of that is because of the print R function that I'm using in the code. This is a very common function that developers will use just to output a variable. It's not something you'll generally see in a production environment because as you can see, it looks very ugly in my opinion but it's handy for checking things when you're busy developing. So doing a sub menu page like this and this is unrelated to roles and capabilities. This is just a little developer trick if you want. When you first start developing with WordPress, sometimes you might need to output something, some data in the database or you might need to test something and installing that or plugging it into an admin sub menu page in the tools menu like this is a very straightforward way of getting to that data. So it's what I tend to use for these kinds of things. Okay, that's just the plugin test bed. It's not super important for our learnings today but that's what it does and how it works. Let's move on to roles and capabilities. So I'm going to grab this link and pop it in the chat and then we'll open it and we will review what roles and capabilities are. So in a WordPress site, you have a user and I'm sure you've all seen WordPress users before when you create a new WordPress site it asks you to set up the first administrator user and it tells you to make sure you use a super strong password but your users are not, your user object or your user data if you will is not the thing that stores whether that user has access to different parts of the WordPress dashboard or not. That is defined by the roles and capabilities. So in a default WordPress sites I'm going to scroll down and I'm going to zoom this in a little bit because this is quite small on the documentation page and this is actually not the document that I want it's the other one that I wanted so let me get that one as well and I'll paste that into the chat and we'll open that up. So this is the one where I want us to really be this is much better looking with big text and lots of useful information but in a default WordPress install you will have the following user roles. You will have the super admin role and this is specifically to a multi-site so you will only have the super admin available to a multi-site. If you've ever worked in a multi-site the super admin is the person that can install the plugins and then network activate them for example but if you're not working in multi-site then you will have the administrator as your top level user and then below that on all types of WordPress installs you'll have the editor, the author, the contributor and the subscriber. These aren't specifically users these are roles. So these roles exist when WordPress is installed. The first time you install WordPress it sets up these user roles and I want to show you where this is set up. So you're welcome to navigate to this file with me or you can just watch it on screen. If you go to the, I just wanna check my notes here very quickly, make sure I'm in the right place. Yes, if you go to the WP admin includes and then it is the schema.php file. So the location of it is WP admin in your IDE that you've got your WordPress site open, WP-admin then the includes folder and then go and look for the schema.php file. That's the one over there. And then if you scroll down quite a bit I'm going to just do a search for roles, populate roles. The function is called populate roles. It's on line 712 on my WordPress install. So you'll see there is populate roles 160, 210, 230, 250, 260 these are all WordPress version numbers. So every time, well, maybe not version numbers you'll see the 160 is applied to 2.0.0 so it's not exactly version numbers but these are basically functions that have been added so that we, so that user roles and capabilities can be updated on WordPress updates. So the very first one, sorry I scrolled down too quickly there the very first one is populate roles 160 and it adds the initial roles and capabilities since WordPress 2.0.0 And you'll see there at the top it adds the administrator role, the editor role the author role, the contributor role and the subscriber role. Don't know what that noise is I apologize if you heard that I think there are some children running around outside. Then once it's created the roles then it adds the capabilities to the role. So here it is saying get the administrator role and then add the switch themes capability and then add edit themes and add activate plugins and add edit plugins and so on. And so forth. All this code is effectively doing is creating an array in PHP and then storing that array to your database. So when you run the role add cap functionality it goes and fetches the array from the database gets the administrator roles list of capabilities and add switch themes to it that's all it effectively does. So let me show you what that data looks like. If you have a local way of opening up your database I use PHP my admin in the browser you can use things like table plus if you're in WordPress you can install SQL buddy but don't worry too much about doing that now you can just watch along what I'm doing here. And if you go to the options table which in a default WordPress install might be WP underscore options or if you've changed your prefix your prefix might be different to mine mine is using the default WP underscore and you go and search for the in my case WP underscore user options field or a key or meta or however you want to call it. No, not user option, user options. Let me try that again. WP user options. Now why doesn't that come up? Let me try a different way of doing this. And it's not, it's not user options. It's user roles. There we go. Okay, so there it is WP user roles. I'm going to make this a little bit bigger as well. So the option name is WP user roles and then you will see that inside the option value field if we make this a little bit bigger it's got this whole chunk of data there. Now what this is known as this is called a serialized array. I'm going to open up an unserialized page which is just called unserialized.com and I'm going to paste that data in there and then I'm going to click VAR export and I'm going to click on unserialized. I'm going to paste this unserialized.com link in the chat if anybody wants to do this themselves later. And if we scroll down, there we will see the array. So let me make that a little bit bigger as well because it's already quite, there we go, we should be able to see it now. So there's the array there and we'll see that the array contains as the top level key the name of the role so administrator, then inside of that it has another array with a name which is the human readable version so in this case administrator and then it has an array of capabilities and then it has switched themes, edit themes to make plugins, da, da, da, da, da and that's also true. And that is how the roles and capabilities are stored in a WordPress database. So when you add a capability to, for example the administrator role, it actually adds that item to the array of capabilities. Then when WordPress, everywhere in the WordPress site when it needs to check against the capabilities of the user, it uses something called the current user can function. So I'm gonna paste that into the chat as well and we'll open that up. And what this function does is you pass a capability string to this function. So for example, if we wanted to check whether this user has the capability to switch themes, you would say current user can switch themes, you'd say if current user can switch themes and then what WordPress does is it goes and it fetches the serialized array from the database. It unserialized it, so it turns it into a normal PHP array. It then fetches the user from the database and checks what user role is assigned. So if our user was an administrator, it would get the administrator role and then it scans through the serialized array of data through the capabilities to check whether switch themes is in that array. And that's the process that it does every time you call current user can. So it's not specifically assigned to the user. It doesn't do like a user checkup. The mapping of the capabilities is not stored in another table somewhere. So every time it runs current user can, it logs into the database, gets that data, pulls it out and checks against it. What WordPress does also do is it caches the array of data so that it doesn't have to pull that data from the database every time. So what it'll do is it'll run the first time, get that option into a cache somewhere, into what's known as a transient. And then when it needs to do any kind of current user can checks, it'll rather check against the transient than the actual pulling of the data in the database. It's important to understand how all this works because when you want to add or remove capabilities, you need to realize that every time you run the function to either add a capability or remove a capability or add a role with capabilities or remove a role capabilities, you are writing to that serialized array. It basically gets the array, makes the updates it needs to and then pushes that array data back to the database. And the reason that's important is because you might think that you can in the course of normal execution, simply add a capability somewhere along the line and then it'll just work and that's not the case. So we'll talk about that in a second and we'll talk about how you can work around that. But I just thought it was important for us to understand where that data is stored, how it is stored and what it means for us for plugin development. Okay, we're gonna take a break there if anybody has any questions around all of that and how that all works. And if we don't, then we can move on to actually adding some capabilities. Out of interest, did anybody here, children running around and screaming at the top of their voices when I mentioned it earlier? I'm just curious to know whether my mic picked that up or not. If you did, it's just funny to me. Basically says no, good mic. Okay, Mary, did you have a question? Yes, so in these, there seemed to be, you know, the people trying to hack in, come and go. And so this week I've had a lot of people trying to hack in. So I've walked down the temps and stuff and I don't have a lot of people that access the site. Does it matter if I have a strong password if I keep changing it? Because it doesn't let me change my username. So you're asking, do the capabilities matter or you're asking, does it matter if you keep changing your password? Well, capabilities is I understand that if I have someone else helping me and I let them in, then they're gonna have roles and capabilities. But then I'm, yeah, I am also asking, does it matter if I change my password if it's a good password? So that's an interesting question. Thank you for that. I would say that if you keep getting hacked, then definitely keep changing your password. The thing, the thing with temps, it's just attempts, attempts, oh, I see this, yes, yes. I'm not getting hacked. But I, you know, I keep get, but then sometimes when I want to do my monthly updates for the customer, then I'm locked out for, you know, two hours or whatever. Got it, got it. So I'm going to preface this by saying, I'm not a security expert number one. So take my advice or my opinions with a grain of salt. I can probably direct you to some security experts who might be able to answer this better than me. My understanding of website security is if you keep getting attempts, you might want, because when it comes to security, and please forgive me if I make any assumptions about your sites. I'm trying not to make assumptions about your site specifically. I'm talking about just sites in general. Folks who lock down or want to secure their sites from hacking attempts, they tend to think about doing it at the PHP level. And by that, what I mean is they install plugins that, you know, secure their sites. That's unfortunately not the best way to secure a site. The best way to secure a site is actually at the server level. So I would say that if you are regularly getting these attempts and they're preventing you from, you know, accessing your site and needing to do things, then a good first step might be to chat to your web host and find out what they're doing on a server level to prevent those things. There's things like fail to ban that can be installed and various other things that can be installed at the server level to prevent, because if you can stop the attacker from even attempting to hit your PHP, your WordPress site, then you stand about a chance of not being locked up. Number one. Number two, as it comes to passwords, I'm going to share, I probably shouldn't do this. I've actually done this publicly before and nothing bad has gone wrong with it. So I probably shouldn't do this, but I might as well, why not? I've actually used a, so let me preface this by saying I have switched to a password manager. So all of my logins are managed in my password manager. Some folks who have joined my previous workshops would have seen that I've logged into places in my password manager handles it, so I'm not sharing any passwords publicly. But before that I followed, and I'm going to share this because this is a useful conversation. This is an XKCD comic. You'll see I've actually got it there, password straight, I've searched this comic quite a few times. And there's actually, this is actually a very good, I've spoken to security experts within automatic, the company that I work for. And they said this is actually a very good way to manage password strength. It's more difficult for hackers and crackers and people like that to guess or crack four common random words than it is something with non-Jabrish base words and later replacements and all those kind of things. So if you have to physically remember the password, then try and use that as an option. There's another site that I can share with you. I think it's just called how secure is my password? And this will actually, I think it's this one. Yes, howsecureismypassword.net. This will actually tell you how long it would take a computer to hack your password. It's a nice tool to use. I've pasted it in the chat. But then finally, after all of that conversation, my other recommendation is use a good password manager. One password is the one I use. You can actually see it up here at the top of my screen. Let it generate randomized passwords, let it manage your passwords, then there's way less chance. And in terms of passwords for sites, I would say that if you have a very good strong password, then you shouldn't need to have to change it that often. If you're keep getting those hacking attempts, those attempts at brute force, then you maybe need to look at what your security setup is. And if it's not at the server level, it needs to be prevented more at the server level and at the PHP level. I hope that's helpful. As I say, if you would like to, I can after this call, maybe connect you with some other security folks. Thank you that answered all my questions. Okay, excellent. All right, I'm going to move on. Okay. Right. So let's get on to our next objective. So we have set up and reviewed the plugin. We have reviewed WordPress roles and capabilities. We have inspected the user role serializer race. We did the first three in one shot, that was great. Now we're going to learn how to assign admin-specific capabilities to specifically the editor user. So in this example, I want to give the editor user. So let's have a look at the editor user's capabilities first. You'll see that the editor user's capabilities you'll see that an editor that actually defines it in this document as somebody who can publish and manage posts, including the posts of other users. So because WordPress was originally a publishing platform before it was more of a CMS that was kind of around content and posts. So if we have a look at the editor user and I'm not going to expect you to see this here but if you've got this open on your side and you scroll through this, you will see that the editor user can't do anything with plugins. And under most scenarios, that's probably a good thing. But for our specific example use case we want to give this editor user the ability to add and update plugins for whatever reason, hypothetical scenario. So to do that, I'm going to hop over onto my plugin code. I'm going to close the schema file. I'm going to go back into my plugin. And the first link that I'm going to share with you is the add cap method. So the add cap method we did see before when we were looking at the schema. It's effectively a method that exists on the role class. So a class is a PHP set of code that can do certain things. Every single role when WordPress executes every single role is loaded as an object. And that's what we saw when we looked at this in the menu. So you can get that object and you can do things with it. And so what you do to assign capabilities to an existing role is you first get the role using the get role function, which I'm going to also share with you now. So let's pop get role into the chat. I don't think I've done add cap. Let me do add cap as well and get role. So get role will fetch the role object for the role that we want to work with, excuse me. And then we use the add cap to add the capability. So let me show you what that would look like. So I'm not gonna hook it into any kind of activation hooks yet. I just wanna show you what the function would look like to get the editor role and then add the cap. So we would say something like role editor or you can call the variable whatever you want. I'm gonna actually just call it editor role. And we would say get underscore role and then we would pass in the name of that role. So in our case, we can actually just check the object array that I'm sorry, at least the object that I might put into the screen here and the name is editor. So that's nice and simple. So if we pop that in there and we say get the editor role. So that will fetch the object. This is exactly the same code you'll see I'm doing here in the render add and page. I'm just changing the variable name. And then once we have the editor role, we're then going to use, so this is a normal single, it's a minus sign or a hyphen if you want arrow. This is used when you want to assign properties to objects in PHP. So we're actually gonna call the function, the add cap function. So that's what that looks like. So whenever you see this kind of notation, this single arrow here, it's usually either accessing a property on an object or calling a method of that object. A method is just a function on an object. And then we can give it the capabilities we want to say we want to add to this roles. If we have a look at the roles and capabilities and we scroll all the way up to the admin capabilities and we look for anything to do with plugins, where is it now? Then we will see is the activate plugins option. So we can just apply that role, sorry, that capability to the editor role just like that. We can just say add cap, add capabilities and then pass in the activate plugins capability. The other thing that we want to do for this role is we want to give it the ability to, sorry, we want to give it the ability to update plugins. And I'm not gonna search in the docs for this one, but I'm just gonna pop the code over here. So here it is update plugins. That's the capability for the ability to update plugins. And that's what our code will look like. Now, as I mentioned, we can only do this once. We have to do this when the plugin activates because then it writes it to the database and then makes it available to the rest of WordPress execution. We can't do things like hook into a net hooks or admin a net hooks or anything like that. We have to do it when the plugin activates so that it writes into the database and then is available for the rest of the time that that plugin is activated. The other reason we do it on plugin activation is if we do it on a net hook, so we could do it on the net hook and then the first time that plugin code runs it'll add the capability, but then future times when WordPress executes that a net hook's gonna run every time it's gonna keep running this code and nothing's gonna change and we're just adding execution time to our dashboard. So it's always recommended to use what's known as the register activation hook, which I will share with you now. Here we go. So this is very similar to hooking into a net or a WP action hook or whatever the case may be, but this one will only fire when the plugin is activated. So you pass in the file name which is a special PHP constant we're gonna use to do that and then the callback function to fire. So let me show you what that might look like. So we're going to say something along these lines. We're going to say, and usually what I like to do is I like to register my activation hooks right at the top of the plugin just because I know they're gonna happen once and I wanna kind of see where they are. So I would say register activation hook. Here we go. Then I need to pass in the current file name and the cool thing in PHP there's a constant called underscore underscore file in uppercase underscore underscore and that constant just means the current file that I'm inside of. So that works perfectly. And then after the comma I need to specify the callback function that's going to run when the plugin is activated. So we'll go wp-learn and we'll say activate plugin or whatever the case may be. Let's actually make it wp-learn. Let's say add capabilities, add caps, that's a good option. Then I need to define that function. So wp-learn add caps and then I can take this code that I have at the bottom here and I will share this final code with you once I have it working. I can pop that in there and I've done something wrong here. I've coded this incorrectly. I've used the wrong brackets in the wrong place, apologies for that. So it's normal brackets just before and after add caps and then the curly braces to open up the function and this is what a code might look like. So I registered activation hook. I pass in the file name which I'm using the file constant so that means this file. If I had another plugin file that I had my add learn caps function and I would pass in the path to that file but for this case, this is perfect. Then I specify the callback to run and then I can create that callback and put the code inside it. So let me pop this into the chat and let's see what this does. Now we have already activated this plugin but the reason that I've got this plugin showing you the editor role in the dashboard is because currently the editor role capabilities we can see they manage comments, categories, links and if we go right down to the bottom of this list the last two items are edit private pages and read private pages. When I deactivate and then reactivate this plugin the activation code should run. It should then get the editor role and apply and add these two capabilities to the editor capabilities list and we should then see it if we have a look at the menu. So let's see if that works. So in my plugins list, I'm going to deactivate then I'm going to reactivate the plugin. So that should now apply those changes. And the reason I wrote this code with the admin menu is because it's easier than going into the database to get it. So it's just easier to go to tools and then go to learn capabilities. There's our editor role and let's see if it's applied those capabilities. There it is right at the bottom. We've got activate plugins and we've got update plugins. So those capabilities have been applied. Okay, any questions on that code? What it does? How it works? Before we move on to another good step to do when applying capabilities. I'd also like to just mention to Mary that you've given me a great idea for a topic on what to do if you can't access your website. So I'll make a note of that and see if we can do that in the future. I had that happen once, but I got around it. Thank you. That would be a great topic. No problem. There's a lot of different ways to manage it. So I'll definitely make a note of that. Okay. So while we're talking about plugin activations and adding capabilities and removing capabilities I want to mention that it is a good idea to also learn how to use the registered deactivation hook and remove the capabilities from your roles when you're developing them. I'm going to add the deactivation link to our reading list. These are all linked in the resources of the slides. So you can also grab them there. But the deactivation hook works exactly the same as the plugin activation hook. You pass in the file in the callback and it'll then run that function when a user deactivates the plugin. There are two reasons this is a good idea. Number one, if you're building a plugin to be distributed to client sites maybe you're selling plugins maybe you just build custom plugins for your customers and you want the database to be cleaned up of any changes you make. If you register a deactivation hook which removes the customization you've made to the user role when the user deactivates the plugin it will do those cleanups. Unfortunately, it won't trigger if the user goes into their web browser sorry into their web hosts and browsers and just deletes the files but at least you're implementing something that'll allow them to have a little bit of a cleanup process. The other good reason it is to do this is if you're testing capabilities and we're going to do that in a second and you'll see where it comes in handy you might want to run your plugin code and then realize, oh, I've actually left out a capability that I thought I didn't realize that I actually needed. And therefore the ability to deactivate and run the deactivation code which removes all the changes you've made to then rerun them with the additional changes to make new updates is very, very handy. Because if you don't have that happening you can't make those changes and then you'll have to go into your database and un-serialize arrays and edit it yourself and it just becomes a nightmare. So my developer top tip today is if you are doing things on activation like we are doing today it's a good idea to also register the associated deactivation hook and then have a separate callback function which effectively reverses the changes you've made. So we're going to remove the caps and here we will just, this is quite similar to what we've already done. So it'll be WP learn remove caps. We will again get the editor role and just as there is an add cap function on your website, just as there is an add cap function on your role object there is also a, sorry, method there is also a remove cap method. I think let me just check my notes. Yes, remove cap, remove cap and we just pass in the same capability string as we did for the add cap. So remove cap activate plugins and remove cap update plugins. And I'm just trying to see why this is giving me, all right, because I haven't specified function in the front unit. Here we go. So let me pop this into the chat as well so that folks can see that. And so what that's going to do is when I deactivate it's going to remove those changes reset my data back to what it was. If I, let's say, and this actually happens to me while I was preparing for this talk. I forgot to add activate plugins capability. So I just had update plugins, ran the plugin activation and then my editor user couldn't activate plugins and I couldn't figure out why. And then I realized, oh, I needed to add activate plugins. Now I have no way of making that change. So I had to go into the database and reset things and that's why it's a good idea to have your deactivations. So now, if we deactivate the plugin it will remove those capabilities or reset the editor user back to normal and we will then be able to see those changes. So let's actually do this as a test together. If you are coding along with me, you're welcome to try this out but I will show you this very quickly. So I'm actually going to create this editor user. I'm going to first go back to my plugins and I'm going to deactivate so that it just clears it out back to normal and then I'm going to activate it again so it sets it up so it's all nice and fresh. I'm then going to go into my user's list and I'm going to, I've already got the editor user. So let me delete this one. I don't worry about content. I'm going to delete Assistant as well. So I didn't clean up my data before we started today. I apologize. Okay, so let's create the editor user. So we're going to just call the editor, let's say we'll make it Tracy because Tracy's my co-host today. I'm going to use Tracy's name. I hope you don't mind Tracy. I'm going to say Tracy at learnprest.test. I think it was Rhoads if I'm not mistaken. And just for the sake of testing today I'm going to just make the password very simple and then I'm going to apply the... Oh, hang on, where is the editor user? Oh, there it is. There's the editor user and I'm now going to add my new user. So I've got the editor user there. Now I'm going to log out and I'm going to log in as the editor user and we will see instantly there is a plugins list in the option there in the menu. So this user can go in and add edit plugins. What I don't recommend doing is deactivating this plugin now because it will register the deactivation hook, remove this capability from this user role and therefore this user won't be able to get back anyway. So what we'll have to do is we'll have to leaving that as is. I'm now going to leave the editor user with those capabilities they have. I'm going to log out as the editor and log back in as admin and I'm now going to deactivate that plugin as the admin user. So what this will do is this will remove those capabilities from any users that are editors. In this case, it's Tracy's user in my local site. So let's deactivate that. And then let's log back out and log back in as the editor user and see the change. So now we should see that the plugins option in the menu has been removed because the capabilities were removed. So it's a nice way that you can take existing user roles and you can change them as you need to. It's a perfect way to say, well, certain types of roles I want to give them certain access, certain types I don't. And then if you do it with this deactivation on the plugin, you can very quickly remove that access as well. So if you realize that some changes, you're the admin of the site and you realize that some capabilities you've given were incorrect. If you have that deactivation, you can just deactivate to remove those capabilities and then review your code and make changes as you need to. Okay. So that's adding. Mary says Tracy, did you run in and change anything? Unfortunately for Tracy has no access to my local site over the internet. So I'm safe. Okay, I'm going to pause there again if anybody has any questions around adding capabilities to existing roles. And then we'll move on to adding, creating custom roles with specific capabilities. Well, I run out of water. All right. So it is possible not only to add existing capabilities to existing roles, it is also possible to add a custom role, to create a custom role and then assign only specific capabilities to it. Now, this one we're going to approach from a slightly weird position. I'm going to kind of show you how to set it up with the base capabilities, but then what happens if you don't add a certain capability to it and why? And then I'll show you how it all works. To do that, we're going to have to register both the activation and deactivation hook. So if I start going too fast with the code and you need me to slow me down, please just let me know, but I'm going to try and step through it as cleanly as I can. But the function that we're going to be working with is quite a nice function. It's just called add role. And you might remember this when we were looking at the schema earlier, the schema PHP file uses add role to set up the initial default roles and capabilities. And the nice thing about add role is we don't have to add the role and then use get role to get the role and then apply the capabilities to it that way. You'll see that the third, so there's three parameters you can pass to add role. There's the role, the name, the string. Another string which is the display name, so the human readable format. And then there is an array of capabilities that you can pass to it. So just using that single add role, you can set up your new role with its capabilities from the word go. Okay, so let me show you what that would look like. So I'm going to use the same activation hooks. I'm just going to copy the register activation hook and move it down here so we can see what's happening on screen. I'm going to put some white space in here so that folks can focus on what we're looking at. There we go. And this time, instead of WP learn add caps, I'm going to WP learn add role. And then we're going to create the function WP learn add role. Okay. And then we can get rid of all of this and we're just going to use the add role function. So it's add underscore role. We open the regular brackets. I like to do my parameters when it's a lot of information one at a time. You can also have it across one line. That's just fine. I just like it this way because it's a little bit more easily readable. So the first parameter is the role name. All underscore one word. If it needs to be two words, you have to hyphenate it. There must be no spaces or anything. For our example, what I'm going to create is I'm going to create an administrator assistant to somebody who is assisting the administrator in specific tasks. In this case, the specific tasks are they can add and activate plugins. That's it. They can't do anything else. They can't do posts. They can't do themes. They're just the plugin manager if you will. And if you are following any of my live streams, you will notice that I was building a question AMA plugin and this would be perfect for that. You create a question manager and all that question manager can do is manage those questions. So for the name, I'm going to say assistant. That will be the name that is stored in the database for this role. The second parameter is the human readable, what do they call it in the documentation? They call it the display name. And effectively, this is just what's stored in that dropdown when you assign the role to the user. So I'm just going to keep it very simple as assistant with an uppercase A. If you are building a plugin that needs to be translatable, you should use your translation functions for this. If you don't know about translation functions, I did do a workshop on this a while ago. I'm going to share that very quickly because I just thought about it now. If you go to WordPress TV and you search, I think I was doing it in the scope of block themes if I remember correctly. And it was localization, localize a localization. I'm not going to find it now, am I? Pretty sure it was a let's code session that I did. Let's see if I can find it very quickly. Let's do a let's code and let's go newest. And you watch, I'm not going to find it now. Rest API, it was sometime last year. Let's just switch my name. I can't remember the name. Oh yeah, I think you mean my name. This is probably easier if we go let's code because then it's specific to what I was doing. I'm not going to find it now. I'll find it and see if I can add it to the comments. Yeah, if you search by my name, it's going to be a whole bunch of other stuff that I did before I started working with the trading team. So that might even be more difficult. Anyway, I'll find it and add it to the comments in the meetups.com chat, but there is a video about it. I'll try localization like that. Anyway, not going to find it now, but there are functions that you can use to make your strings translatable. We're not going to worry about those. For now, we're just going to leave it as English. And then your third parameter is your array of capabilities. So in this case, we want to give this user the same capabilities we did the editor user earlier. So it was the activate plugins and it was the update plugins. Now the one difference here is when you define this array, you need to define the key as the array, the capability that you want to set. So in this case, activate plugins and then the value of that array key is true. So if you're working in PHP arrays, you use this special array assignment operator. It's the equal sign and the greater than sign. And this is how you specify array key and values. So the key is the capability name and the value is true. So that we're saying, we're setting this capability to true for this role and then we do the same for update plugins. So there it is there. Okay, I'm going to copy this out into the chat if anybody needs to see that. And then at the same time as doing this, I'm also going to register, excuse me, the deactivation hook so that it cleans up that role when the plugin is deactivated. So it's going to register deactivation hook. We'll just say remove role. And just as there is an add role function, there is also a remove role function. I'm going to find that documentation now. I don't have it linked. It'll probably be pretty easy to find. If I just search remove role, it's the first one to come up. And there it is there. Paste that in the chat. And that just requires the string, the role name to be removed. So that's nice and straight forward. So remote role, remove role. So we say function, remove role. And then we can just simply say remove role and pass in assistant. So this will be nice for cleaning up and for testing and for those kinds of things. And I'm actually doing this for another specific reason which will become clear to you in a minute when we test this. Okay, so that is our activation and our deactivation for adding and removing the assistant role. If you're coding along while you're doing that, I'm going to show you what this is going to do because we're going to hit a little bit of a bug. I'm doing this on purpose, but I want to show you what happens if we just code it like this. So we create the assistant role and we assign it the activate and update. Tracy says it's a typo in deactivation. Thank you for that. Perfectly correct on that one. Deactivation. Let me actually just copy this one over here. There we go, much better. Thank you for that, Tracy. Okay, let me copy that again so that folks have the updated version. Let me show you what this does. So the first thing I'm going to do is I'm going to deactivate. Well, first I need to log out as Tracy and I need to log back in as my admin user. Then I'm going to deactivate this plugin so that it clears out. It really is deactivated. That's fine. So it cleared out everything I needed to do so I'm happy with that. So let me activate it. Okay, so now it's activated. So now I should see that two things should have happened. Number one, I should see that my editor user still has the update and activate plugins capabilities, which it does. At the same time, I'd like to make sure that the user roles are created and we can do that in the plugin code that I've already shared with you. So if you go down to the WP Learn Render Admin page code, we can now get the assistant role and we can output the same content. So let's do that. So let's set up two roles here. So let's say edits a role, which I'll get the edits a role and then let's say assistant role, assistant role and that will get the assistant for us. So there we go there and then we can just take this section of course here, the pre opening and close code. I don't know why that's on my second line there. We just take this line as it is and we can pop it in there and we can update this to say print R the editor role and print R the assistant role. So I'm going to paste in, this is the updated code for the function WP Learn Render Admin page. If you would like to do this on your side, that's what the code looks like. So it gets the editor role and the assistant role and then just outputs their data into that page. So let's see what that looks like. So there we go. So we've got the editor role on top. It still has the activate plugins and update plugins capabilities. And then there's our assistant role, which is perfect. And it has the activate plugins and update plugins capabilities. You'll notice that it outputs the value as one because in HTML and PHP land true and false become one and zero when output to a screen. So now we're happy that the role has been created. The capabilities have been set up for the role. Now we can assign this role to a user. So I'm going to create a new user and I'm going to name this user after my son. He's going to be my assistant. LearnPress.Test and Ethan Bossinger. And I'm going to give him a very simple password. And then I'm going to assign him to the assistant role. So that means Ethan will only be able to update and install and activate plugins. So that's exactly what I want. I want to confirm the use of the weak password. That's perfectly fine. Let's add that user. Okay, Ethan has been added. I said his username is uppercase, which I don't usually do, but that's fine. I'm going to just remember that. So now I'm going to log out. And I'm going to log in as Ethan and I'm going to see what happens. So the first thing you'll notice is we do have the admin toolbar at the top of the screen. What you'll notice though is we don't have an option to access the dashboard. So even though this user has the capability to activate and update and install plugins, they don't have the capability to actually what's known as read the dashboard. So if we have a look at this original roles and capabilities page, there is a, I'm going to find it here quickly. There is a read capability. And this basically just allows access to the dashboard. So whenever you're creating, sorry, my phone is about to ring and I'm just making sure it's not, it's not important, great. Whenever you're creating a custom role and you need that user to be able to access the dashboard, you always need to assign the read capability to them by default. You can't just say, just activate and update plugins without read. They need access to the dashboard. So somewhere in the WordPress execution, when the dashboard is loading, it checks, can the current user, does the current user can read? If not, don't load the dashboard option. So we need to add that. And now if we just added read to the role, it wouldn't update, it wouldn't make those changes. So that's where the deactivation and activation process comes in. We can now add, make the change to our code. So we go back to the array of capabilities on the assistant role and we enable the read capability. And I will paste that updated code for you in the chat. And now we have to clear out the role and then re-edit. And that's where the activation and deactivation becomes very handy. So if we go back to the plugin, we're going to have to do a couple of things. Number one, I'm going to have to log out as this user and log back in as admin. And then I'm going to have to deactivate the plugin, which will clear everything back to normal. And then I need to activate it. Now, I just want to mention, there are other ways to do this. You could manually edit the serialized array in the database. You could possibly, if you're comfortable with using something like WPCLI, you could do this on the command line. You can use something like WPShell, which allows you to execute functions from the command line. That's another way of doing it. But if you don't have access to those tools, this is a very straightforward way to roll things back and make them happen again by deactivating and reactivating your plugin. Okay. So now the assistant user should have applied the new roles. Let's test that by going into the learn capabilities admin page. So there's the editor. It still has activate and update plugins. There's the assistant role. It now has read, activate and update. So that should be working. So let us log out. And let us log back in. And now we should be able to see, we can access the dashboard. Great. We can go to plugins. Great. And I want to show you this. Watch what happens now. If I deactivate this plugin, what's gonna happen? The deactivation is going to run. It's going to remove the capabilities. And it's going to redirect me to an error page because suddenly my user doesn't have access anymore. So also be careful with what capabilities you assign and let folks know with great power and all that. Because if a user deactivates the plugin that runs your things for you, or for them at least, they're gonna lock themselves out. I now have no way of getting back to this. So I'm going to try and just go back and log out. There we go. And if I log back in as the admin in the password, my password, you will see that that plugin was deactivated successfully. But because that user now didn't have the capabilities to go back to the plugin list, it caused that error. So another way around that is maybe give them a different capability. Maybe give them a capability to maybe view the posts or whatever, then at least it can redirect somewhere. But that's something to be aware of when you're working with custom roles and capabilities. Okay. Any questions around all of that while I have my last subject? All right. There don't seem to be questions at this point in time. If you're watching this later on WordPress TV, Gene says that's pretty cool. I know I love this kind of stuff myself. If you're watching this later on WordPress TV and you want to see how all this code works, as always, I do have it as a repository, public repository on my GitHub profile. I'm going to share the link in the chat now, but basically you just go to my profile, which is github.com slash Jonathan Brossinger. And then it's wp-learn-roles-capabilities. The main branch is the code with just the admin submenu page. But if you switch at the top here to your branches and you go to the feature adding roles capabilities branch, which I will pop into the chat as well, you will see the final updated code with the activation hooks for adding the capabilities to the editor role, as well as the hooks and functions for adding the custom assistant role with the custom capabilities. Next week, we're going to look at how we can customize all of this even further. We're going to look at how custom capabilities work on a custom post type level and how you can actually create roles that only have access to specific custom post types. And we're also going to look at how you can define custom capabilities and then use it in your plugin. So that's the plan for next week. Otherwise, if anybody else has any questions, Stuart says it's one thing, controlling user access over at the editor level, there are sole challenges. Yes, no, I agree. And that's maybe a whole conversation about what you give folks and how you give folks access and all those kinds of things. All right, that's my bit for today. Thank you all for joining me. I hope that you've learned something about how to manage custom roles and capabilities. As always, if you have questions, you're welcome to send them through to me either via my email, which is my name, JonathanPostinger at gmail.com. You're welcome to find me on the various social networks. I have yet to find somebody else with my name, so you can generally just search my name and you'll find me. If I ever do find another Jonathan Postinger, I will jump for joy, but I have yet to find one so far. But thank you all very much for joining me and I hope you enjoy the rest of your Thursday and the rest of your week. Bye-bye.