 All right, we are live. Welcome everybody who is joining or has joined, should I say. Don't have my usual slide. Absolutely change that as you are joining. If you would like to code along with me today, there is an example plugin that I can share with you. That wasn't supposed to happen. And while you're doing that, I've just realized that I have a little sign on my door that says meeting in progress that I switch over. I haven't done that now, so I'm going to do that quickly. So I don't get interrupted. Okay, so I have put my do not disturb sign up. So while you are joining, please do consider downloading the plugin in the chat if you don't see it in the chat, we can share it with you. And then let us know where you're joining us from. I am joining you from a cold and wet Cape Town today. March, April is generally the start of our autumn season. Moving towards winter and Cape Town is usually wet and cold, not as cold as some parts of the world that have snow. Generally, to us cold is three degrees, four degrees. We don't hit subzero temperatures here. Thank goodness. We do have some parts of the country, the higher, higher, higher lying areas that show that. Let me get some folks and then we'll pop the link in the chat again. Some of the higher lying areas do get quite cold. They do get subzero temperatures but here in Cape Town where I am. It's generally just wet and miserable. And you have to wear layers to keep dry. So, yes, that's what we're moving towards. If you've never joined one of these sessions before welcome, my name is Jonathan. I live in Cape Town in South Africa. I am a developer educator at automatic. I've sponsored full time to work with the training team. The training team is a team of volunteers and contributors sponsored contributors unsponsored contributors from around the world who work on predominantly on the learn WordPress platform. I am one of I'm one of the content creators I do tutorials I do workshops like this, work on lesson plans work on courses. We try and help folks learn WordPress or learn how to code with WordPress. Should I say. If you want to let us know where you are from in the chat or what your weather is like. Welcome to let us know. Otherwise, we'll, we'll continue along today. So today we are looking at custom content and custom capabilities. In the last week's workshop, we focused specifically on roles and capabilities how to develop roles. At least how to assign capabilities to existing roles how to create new roles. Hi there Amy from Philadelphia glue me here today as well. Okay, that's interesting. It's always always find interesting to see how different parts of the world, what their weather is like. So before we get started, welcome everybody and big thank you to Tracy who is co hosting with me again today Tracy co hosted last week, and he's co hosting again today. Please let me know at any point in time if you can't see my slides. As I mentioned before we have picked up a few issues with folks not being able to see the screen share so if at any point in time you can see the screen share just let me know, and I will disable and re enable the screen share. So we are presenting in focus mode. But if you would like to enable your video so that I can see you you are more than welcome to your welcome to also leave it off. I don't mind. I've been doing these workshops for about a year now, just just short of a year. June I think will be I'm sexually check with my first workshop was. And I've gotten pretty, pretty used to talking to a bunch of names so I don't mind if you leave your video disabled. So as always welcome to ask questions you're welcome to post them in the chat, or unmute ask questions. You're welcome to interrupt me to ask questions if you if you need to. The only thing that I do ask is if you are going to interrupt me. If we could please make sure that that interruption is specific to what I'm doing on screen. If your question is unrelated to what I'm specifically working on at that time I do allow for pauses for questions tangential to what we're doing or somehow related in a different way. I don't mind you interrupt me as long as it's like maybe to explain something that I'm doing or to slow down or to pause on whatever we're dealing with at the time, but not to take us off into a different tangent. But I do allow time for those kind of questions in between the sections. Valerie says good morning from Oklahoma. Only Oklahoma references the musical so I don't know anything else than that. And Arthur welcome from Frankfurt Germany very cloudy in Frankfurt. I will be hopefully all going well I will be traveling to work camp Europe in June, which is happening in Athens this year from upstake and so if you are in Europe and you do plan on attending word camp Europe. Please do let me know somehow in advance and I would love to meet you. If you're joining the sessions from Europe or if you're joining the sessions from the US and you're planning on traveling to, to work camp Europe do let me know. I would love to meet with with as many folks as I can. Okay, one last check to make sure you've got the correct version of the plugin we're going to be working with today. Valerie says don't forget the covered rags and I seem to be sending this to the wrong chat so let me change that. So that is the plugin will be working on today will be going through the plugin in a second to explain what it's doing. But if you want to install that plugin please do so. As always, if I'm going to fast please do let me know. I've stayed away from the coffee today so I shouldn't start rushing off but if I do let me know. We will be posting the session to WordPress TV afterwards I need a sip of water my voice is starting to go a little bit. And if you're looking for more WordPress focused educational content you can go to learn a WordPress.org. You will find all the tutorials or the lesson plans or the courses and all future online workshops listed on that site. Alright, now that we've got the announcements out of the way let's talk about our learning outcomes today so as I mentioned earlier we are working with roles and capabilities this week as we did last week. If you didn't catch last week's session yet. That's not a problem, but if you're watching this now and you didn't see last week's session or if you're watching this as a recording on WordPress TV and you didn't know I don't want to log in. And you didn't see last week's session. It is this one over here. Let's code developing WordPress user roles and capabilities. So we covered last week. So you don't have to watch that to catch to understand this week session I do cover some of the things we covered last week but I do recommend giving that a watch if you get a chance. Today we're going to specifically be looking at how custom capabilities work within the realm of custom post types. So we'll discuss custom post types very briefly before we kick off and then we'll talk about how capabilities work within that scope. We'll be looking at the capability argument. Don't know why there's a hyphen there so let me take that out. We'll be looking at the capability argument of the register post type function, the capabilities argument of the register post type function those those two sound the same but they're two different two different things. And this should actually be I apologize this should be capability type. I'm going to have to update the slides and slide you. So we'll be having a look at the map meta cap argument of the register post type function, and we're going to figure out what all those things do and how they work. When we're working with custom post types and when we're creating roles for accessing those custom post types. Our specific objectives today. Just to kind of frame what we're going to be building. We're going to be looking at the test bed plugin that I've set up and just kind of diving into what that does some of it is based on the code we did last week. Some of it is new. We're going to be creating a specific custom post type called a story. So if you want to put the idea in your head we're building a website that allows writers to submit short stories. So we're going to create the custom the story custom post type to be able to save those stories. And then we're going to be creating the writer role to be able to allow folks to manage their own short stories. To be able to log in create stories edit their stories and publish their stories but only their stories. And we're going to be doing that by using the capabilities functionality of register post type specifically looking at the capability type argument, looking at the capabilities type argument and what it does. But then also looking at the map meta cap how that works and how it all fits together in one picture. So keep that idea in your head as we're working through that example. I'm going to pause for a second and just check if there are any questions before we get started if anybody still needs to install the plugin. I will go through the process of the plug in in a second on my test site. So if you're still installing that's fine but if anybody who needs a break or wants to grab a cup of coffee or whatever, and ask the perfect time to do it. I just, I just came out of a session. A work work related session where the facilitator was extremely comfortable with silence. And I was very impressed by the fact that she gave us one two three minutes where we were doing things and she was not talking. And I, I need to learn that skill because I struggle with the silence. If ever there's silence I tend to want to fill it with my voice, which is why I have these little poking bits in between. Okay. Stuart says so one zero zero to one zero two for this week, kind of. I'll dive into that in a second Stuart so bear with me, but yes we are jumping straight to one zero two and I'll explain why in a moment. Okay. As I mentioned we're looking at release one zero two of my example plug in this week. And to Stuart's question specifically, what I've done is I've created one point zero point zero which was the original test bed plugin that we built on last week. Then one point zero point one is the final outcome of what we did last week. And you can see that if you want to browse it on the GitHub repo. If you switch to the adding roles and capabilities branch, or you can download the plugin code on your side. And then you can see the code that we worked on and the things that we added that was from last week session. Let me share this whole, this whole GitHub repository with you so that you can browse through that if you want to. And two this week is specifically, let me show you what that code looks like the only real differences I've cleaned up some of the test code we were working with. And then right at the bottom, I'm not going to look at it now on screen will dive into it when we look into a code in the plugin, but we've got this learn in net function and then I'm registering the custom post type and that's where we're going to be doing most of our focus for today. If you have 100 installed on your tested environment from last week, I recommend deactivating that plugin first because it will remove all the roles and capabilities that you had installed, and then activating the 002 plugin. As I always recommend when we do these sessions if you have any of my previous plugins installed and active, I recommend deactivating them, because I tend to reuse prefixes. Because this is just example code. And so you might have conflicts if you have any of my other plugins installed. But the plugin we want to have installed today we want to deactivate any existing roles and capabilities plugins and delete them from the site. And then the one we're going to install is the zero one point zero point two, which I'm just going to install I've got it on my, on my desktop here. I'm going to open that up, and I'm going to install it. And you need to make sure that you've got the one zero two version installed and active on your site. So if I scroll down here there's roles and capabilities one zero two. So that is, that is what we should have and what I'm looking at the plugin code itself. Let's dive through that. I'm not going to go through all of it. I'm going to go through a lot of this briefly because a lot of this is just sort of setup code that we're using. But I've added and so last week we added the, or at least we started with the learn capability submenu page just which can see on screen right now. Today I've added a learn story CPT page and I'll show you what those pages do in a second. The admin page just renders the author role currently and explain why I'm doing that in a second. And then the render story admin page just renders specific data for the story capability for the story custom post type. Don't worry too much about what that does now this is really just like throw away code that I'm using for for the test example today. Then in an activation hook on the plugin. I've got the add custom caps function which is taking the editor role and adding activate plugins and update plugins these the capabilities we added last week to the editor role that allowed the editor to update and activate plugins. And then in the deactivation I'm removing those capabilities because as I recommended last week. It's always a good idea to have a cleanup procedure. It makes it easier to test your capabilities work the way they shouldn't alter them should they need to. And also to clean up if your plugin ever gets uninstalled. For those of you who weren't your last week or didn't watch the session roles and capabilities are stored in the database, it's not a live thing that runs when code is executed. So you trigger it in a plug in activation and you remove it in a deactivation as to recommended way of doing things. And I've got another activation hook which is adding a custom role. This is the assistant role that we added last week, and it has specifically the read activate plugins and update plugins capabilities. And then again I've got sorry I scroll too fast there, and then I've got a deactivation hook which is removing the assistant role. So this allows us to activate and deactivate this plugin and remove and add those roles, which is great for development because then you can clean out any changes you've made and make amendments to it. And we're going to be doing that today so it's a good idea we have these activation and deactivation hooks set up with callback functions to perform specific functionality. And then right at the bottom of the plugin I've got a function called learn a net or WP learn a net. This is hooked into the net action hook of WordPress so this will happen on both dashboard and front end. So here it registers the story custom post up so every time WordPress execution runs, it'll register this custom post type and then users can create things with this custom post up. You will see that I've given it the name story, and then the labels are stories plural because the plural of story stories, but that also becomes important later so so bear with me on that one. I've made it public for now. I want to show the user interface in the dashboard I wanted to be available in the rest API because I want users to be able to create things in the block editor. And then I want to support things like the title editor and custom fields so the default things that you might need for a custom post type. You've never seen register post type before don't stress too much we're not focusing on how register post type works, we will dive into the code in a second for specific reasons but effectively what register post up does it creates a custom post type with a specific name that we can then work with in WordPress. I'll show you what that looks like in my dashboard. You will see that I have the stories item in the menu here. And just as I can add and delete and edit stories. I sorry posts and pages pages are just a custom post type as well. I cannot add and edit and delete stories. So I can go in as an administrator. I can say let's just call it something simple like admin story. And I can say this is my short story. The end will keep it nice and short and sweet. And if I publish this, or at least I want to if I can want to I can preview this on the front end see how it will render on the front end. I can publish this. And I can make it live I can view the post. I don't know why that is doing that. Okay, I think I've done something wrong, maybe with my theme somewhere that should work but don't worry too much about that. It is now a live story that works it might be one of the settings that I've done wrong. I'll have to check on that one but don't stress too much about that we're not focusing on custom post types today. Okay. Any questions on the code that we looked at anything that that I've gone through that maybe you missed last week that didn't make sense to you that you're not sure of. Okay, before we continue the other two things that I wanted to show you with the admin submenu pages. So in the tools menu item there are two new submenu pages the first one is WP learn capabilities. And you'll see that all that is doing right now as it's showing the author object, and the author, or at least the author role object the WP role object so it's the author role, and it includes the authors capabilities and those capabilities are listed here. So certain ones are upload files, edit posts, publish posts, publish posts, delete posts and delete publish posts. These levels are for for things that we don't have to worry about today so don't stress about them. And then the read capability is the one that allows an author to access the dashboard so that's what that menu page does we'll dive into that in a second and we'll use it in a second. And then in the story CPT page I've coded this specifically so I want to show you this code. If you have a look at the render all back for that for that function and just move this up the way. I'm using the globals object or at least the globals array to get the post types so when the post types are registered they're stored on the globals array, and they're stored by the custom post type name. And then I'm simply just outputting the following properties of the story post type. I'm outputting the capability type value, the map meta cap value and then the story cap value or property at least. If that doesn't make sense to you now don't stress but I just want to show you what stored in in those fields for a story. And if you were if you were here last week some of this might start making sense to you when you look at it. But you will see that the capability type currently for the story is post. Map meta cap currently displays as one but this is actually true. So it's a true or a false, but when you render things on a front end that they're true or false values they they become one and zero. It's a it's a data thing so it's just about not too much. And then there is the array of capabilities and you will notice that it is effectively everything related to the post capability so edit post is mapped to edit post on the story capability. And so the list goes on. So what this effectively means is when you create a custom post type of story, it inherits the post capabilities, and you will see that they are basically the full list over there. Okay, so now is the time to pause if there are any questions around any of this. You're welcome to give me a shout otherwise we will get into how you can customize these capabilities for your story. To do that I'm going to open up some documentation items and share them with you in the chat if you'd like to get them open on your side. The first one we're going to look at. They don't seem to be any questions I'm going to go ahead so long and just have a few things. The first one I'd like you to have open is just the documentation on roles and capabilities. So these are the default roles and capabilities within WordPress. As you know there's, there's a set of 123456 roles, and then each role has a specific set of capabilities that are assigned to those roles. That's that the next one is the register post type documentation in the developer handle. And then what I would like you to do if you do have this open or you're welcome to just follow me on screen is if you scroll down and there's a little contents area on the right hand side here. It's down and it talks about the parameter here parameter detail information. If we scroll down further there the first one we're going to talk about is capability type. So I'm going to click on that. Okay. So the capability type is a string or an array. I'll show you the two different options now. And this is the string to use to build the read edit and delete capabilities. And this is an array to allow for alternate plurals when using this argument as a base to construct the capabilities and the example they use is story, which is perfect for our purposes. Ironically, I came, I came about story by myself and then I realized in the documentation they use story as well because it's the perfect example of singular and a plural is a slightly different spelling. I want to show you sort of step by step what making changes to capability type and then capabilities and then Mathematica does and how it interacts with things. And remember when we looked at the story custom post type, the default capabilities are all related to post. So that means any user role that has access to these capabilities related to post will be able to edit stories. So when I create, let's say a writer user for one of my writers, and I want to assign a capability to them or at least a role to them, then I'm going to also allow them to access posts and let me show you what I mean by that. So if I go into my user list over here, and I create a new writer, so we're just going to give him the user name writer. The email will just be writer at I'm working on learn press test. And I'm just going to give them a random name, not going to use real people this time. I'm going to keep the password simple so that I can remember it. And then I'm going to assign them to for example the author role. And if I add that user. The writer has all the author capability. So this is one of the reasons why the learn capabilities item in the menu starts with the author user. So let's have a look. That user can upload files, edit posts, edit publish posts, publish posts, delete posts and delete publish posts. So let's see what that means in the real world. So let's log out as the admin user. And I'm going to log in as the writer. There we go. I can add or edit posts. I actually can't edit them I can view them, but I can see what's there. And then I can go into stories and I can view the ones that belong to the admin user but I can add new ones for example. In posts I can add new posts now, I might not want the writers to have all this kind of access they can also see comments, they can see media they can see all kinds of things. It might not be ideal for my use case for me to want the users to be able to use the right to use to be able to do that. I want the writer users to only access their stories. I don't want them accessing any other users stories of example in this case the admin user. I don't mind them seeing it but I don't want to be able to edit it to be able to lead to that kind of thing. I want to be able to fine tune how the user assigned to that role can access information. So let's log out here again. And let's pop on over to this. So the first thing that I'm going to do is it's have a look at the story CPT now now that we sorry, you go back to the code. To do that, let's go back to register post type to do that you can use the capability site site and you can set the capability type and I can set it in this case to story. So let's start with that. So we're going to kind of go this baby step by step so what right now if you want to you can scroll down to the bottom of this code. And in this array of properties over here underneath the last one. You can hit enter and you can say, okay, but I'm actually just going to copy it from the documentation because I struggled to spell the word capability. This is a pro tip if you're if you're working with documentation, copy things rather than type them out makes your life a lot easier. And I'm going to assign it capability type and I'm going to assign it to the word story. So I want to show you what happens when I just do that. Before we move on. I want you to look at the learn CPT sub menu page, you'll see that they are count with me 12345678910111213 this 15 capabilities that have been mapped for the story custom post type. And we change it that numbers going to change as well and I'll explain why in a second. So, with this change that I've made of capabilities of story because this is happening on an internet action I don't have to activate and deactivate things this will just happen when execution runs. So I can just refresh things. So I'm just going to refresh the learn story CPT page that I'm already on. And you will see immediately that that list has shrunk. So now I've just got 123456789. That's how many capabilities I've got. You're probably wondering why and I'll explain that in a second so bear with me. But if you have a look the top three are edit post read post and delete post. And then below that they are edit posts, edit others posts, delete post publish post read private posts and create posts. Then you'll notice what's assigned to those things is for example, edit post is assigned edit story. So that means that a user needs to have the edit story capability in their assigned role for them to be able to edit story. If you have a look if you've got this running on your side at the moment. If you have a look at the menu suddenly your stories custom post type has disappeared. And that's because your admin user no longer has access to it as a story they just have access to edit post. So you will need to update your admin user to be able to for example view and listen edit stories. Okay, just bear with me we'll we'll do that in a second. So now we've got read story we've got delete story and then we've got edit stories. And the English teacher might if there's any English teachers in the group you'll notice that stories as well completely incorrectly. And that's because we didn't define a pluralized version of the word story. So this works fine. If your word can be pluralized with just an S so birds as a good example trees books. But the minute it's something like story or baby is another good example you know the pluralization is a different spelling, you need to tell WordPress what that pluralization looks like so let's do that very quickly. So you do that by changing this which is a string to an array. And you open close your brackets and inside of your regular first parameter is your singular name or your singular capability name, and your second one is your pluralized version of that. Now WordPress can use that to create the capabilities. So if we refresh the page now we'll see that the list number stays the same but the spelling is correct. It doesn't matter that much, I believe, but I like to have it spelled correct it's a personal thing but if you didn't do that it would just be store why is. The reason it might be beneficial to do it correctly as somebody extending your product might think it's stories SD or is, and you've left it as why is and there's confusion and there's a bug and people complain. So it's a good idea to make sure that the pluralization is correct. Okay. Any questions on that change, before we start looking at assigning capabilities anyway. Okay, don't seem to have any questions if you have questions while I'm talking you're welcome to leave them in the chat. I'll answer them when I pause, but let's go back to register post type. Now I want to scroll down and I want to show you it says example with book or array books books it will generate the seven capabilities equal to the set capabilities parameter. That's exactly what we've seen. Okay, but now what about those other was 15 so seven says like eight more. What about those. If you scroll down a bit further. And you'll see that it says here. If you look at the global's CPT name you'll see the following. So there's meta capabilities, which is the edit read and delete. Then they are primitive capabilities used outside of map meta cap. If you don't know what that means yet, don't worry we will get there. And then they are primitive capabilities used within side map meta cap. Personally, I would have liked it if these things were named a little bit better if it was like primary capabilities, and then second key secondary capabilities and then advanced capabilities or something. But that's how they've been defined. So also mark Andrew. So the top three are the meta capabilities. The next one, the next, the next list are all primitive capabilities and if you scroll down further. You can scroll down to the capabilities section. There's there's a whole piece of documentation here where it says here we go underneath capabilities says by default seven keys are accepted as part of the capabilities array. Edit read and delete these are meta capabilities, which are then generally mapped to corresponding primitive capabilities depending on the context. The capabilities would generally not be granted to users or also you would generally not grant edits post read post and delete post to a role. But then you have edit posts edit others posts publish posts read private posts. Those are the those are for primitive capabilities. And then you have additional capabilities below that read, delete posts, delete private posts published and on and on and on. And the full list of capabilities that are possible. And you will see that the way it works is you assign edit posts to edit and the capability type in our case story or stories. And understanding and remembering which ones give which access is something that takes a lot of practice in working with these capabilities. It takes diving into these capabilities, it takes more time than we have in this workshop. The top tip that I want to leave with you today is once you understand how you can assign and work with these capabilities. I almost want to give you a little bit of homework and say take the code at the end of this lesson or the end of this workshop, and then go and play with it and start assigning and assigning things and seeing what works and doesn't work so you get a good feel for how it works. So we're just going to stop there for now. And we're going to go back up to our capability list. So if you have this all set up if you have a look at where am I can't find my browser. If you have a look at the capability about currently you might think well for me to give my administrator user for example access I need to assign all of these stories, and you would be correct. So if we take this whole list. And I'm going to copy this out. And then we can start adding some code to our plugin to assign it so that our admin user can use it. Before we do that though because roles and capabilities are done on plugin activation to the database, we first need to delete. Sorry not delete deactivate the plug in so it rolls everything back, then make the change to the code and then reactivate so if you are following along with me, go into your plugin list deactivate the plug in so it runs the deactivation hooks, and then we'll have a look at the code. So what we're going to do now is we're going to scroll right to the top here. Right to the top right about line 60 in the code where I'm adding the plugin capabilities to the editor role. We don't need to use the editor role anymore so we're going to now assign some things to the administrator role. And I'm going to leave the function names the same but I'm going to change the role to administrator. And then I'm going to start adding capabilities now the capabilities that I copied were edit story read story delete story edit stories and on and on and on. So there's two ways I can do this. The one way is I can have something like this I can say at cap edit story at cap update plugins and then align per capability. So it's very long and boring number one. Number two it makes it difficult to manage if you want to add additional capabilities to this user role. So what you will generally find in the wild plugin developers that are using custom roles and capabilities. When they want to assign a mass amount of capabilities to a specific user role. They will do something like this they will create the capabilities as an array. You might see the array specified like this using the word array. The other way to do it is what is known as the short array syntax like that. Both work I prefer the more verbose way that's just my personal preference. And then what they will do is they will set up all of the capabilities in this array. So I'm just going to copy paste this a few times and then we can copy some things over. I will share this code with you in a second so edit story read story. Delete story then we've got edit stories. Edit other stories I might want my admin to edit someone else's stories. I might want to add them to delete stories I might want to add them to publish stories definitely. Read private stories, possibly it's an admin I pretty much want them to do everything. And edit stories there because so now you'll see that edit stories comes up twice. Because edit stories is mapped to both edit posts and create posts so we don't need to actually define it twice in this array so we can delete that one. And now what you can do is you can loop through the capabilities so you can say for each capabilities as capability. This is known as a for each loop in PHP. And I need to have my my dollar signs in front of my variables. And this effectively is going to loop through and get every single one of these and pop it into variable called capability in the loop. And then I can just use this role at cap code once. So I can say role at cap capability. And that will then loop through the list of capabilities and add the capability to that user role for each one of those in the list. Now the other reason this is, I believe more manageable is if I later on want to add additional capabilities to this user. I just need to add them to the array. I just need to add one string to the array. And the code will still fire loop through and add the ones that are needed. So what I'm going to do is I'm going to share this code in the chat quickly if you need it. Then I'm going to refresh and I'm going to show you the change. So if we hop back over to here, now you'll see on my, I don't know why I'm pointing at the screen like you folks are in front of me, but if you have a look at the menu on the left hand side, we don't see stories in the list. If we refresh the page. We still don't see stories. That's because the plug is not activated. So let me activate the plug in so that the code runs. And there we go. The stories have appeared again. So now as the admin user because I have access to do something with these stories. I can now see them. I cannot click on them. I can add them. I can do what I need to do. So that's the first thing I wanted to show you is that when you define a custom capability type to your custom post type, it's going to set up brand new set of capabilities defined by that capability type. And therefore any users who need access to those types need to have those capabilities added to their user roles so they can access them. Okay, that's step number one. I'm going to take another break if there are any questions or at least pause if anybody needs to catch up. And then we'll move on to the capabilities array. Just going to scroll down here and check my notes. Oh, yes, there was something else I wanted to show you before we before we move on. And that's how WordPress uses the register post type code to set up these things. I showed it down earlier. So let's do it now quickly. So if you go to the in your WordPress install, if you want to do this along with me, if you go to the WP includes folder. And you scroll down and find the post dot PHP file, which is down here somewhere. It's class feed formatting option. Here we go post. There it is post. So let's go to line 1694. So let's scroll down to 1694. There's probably a way you can go to line 1694 in VS code, but I don't know it myself. 168 here we go 1694. No, one, oh, no, I need to be one six, sorry. Very one seven here we go one six. So once it's one six seven nine as we're rich, the post type is originally set up. And then 1694 is where it is creating the new post type object. That's the code that runs to create the post object. So that we will find in the class WP post type file. So if we scroll up here class WP post type there it is. And if we scroll down to line 541. Here the post type is created. So it calls something called set prop so it sets all the properties of the custom post type. And if we go down to 541. We will see that it sets up the capability so here we go. So the first thing it does it does some backward capability checking with capabilities and mapping the meta cap and setting map meta caps true. Then it checks if map meta cap hasn't been set and then sets it to false by default. So if you if you haven't specified map meta cap it will make it false by default. And then it gets the post type capabilities based on argument specified and sets it to that cap value which is what we were looking at. And then lastly it sets the capability type to whatever the capability type is so it uses the capability type here inside this get post type capabilities and that's where those new capabilities are set up so if you pass in story and stories. This is the part where all this happens. I just thought that would be interesting to know how all that works. Okay. So now that we've got the, the capabilities to find we've defined our custom capabilities for our story. We now want to create our user role. So we want to create a writer user role. We want to give it the same capabilities we just gave the admin user so those edit story roles that we that we saw. So we would do by making use of the add role function that we used last week. I will just find it in the slides quickly for you and share that in the chat. So it is, I don't have a chair that's annoying. Give me one second. Add role. There we go. Valerie says, are you editing the code file settings or plugin. I'm editing the so I'm editing the plugin that I installed. So this, this was not the plug in this was just having a look at the WordPress core code. But what I'm editing here is the plugin that I installed on my site. If that answers your question. Sorry, I saw that was sent there. Okay, Stuart found the add role function. Okay. I'm going to just check is there is everybody happy with with where we are right now do I need to pause and wait for a bit was everybody good to go. Okay, so we've set our capability type on the custom post up to story stories. It has created those capabilities for us. We then went and assigned them to the administrator role so the administrator can access those stories and do whatever they need to. And now we want to create a specific role for writers so that we can assign it to that writer role so that that writer role can only handle stories. So if we have a look down here at the removing plugin capabilities from the editor role section, we can use we can reuse that code to to create the writer role and then assign the capabilities. Again, because this is all stored in the database. It is now a good idea to go back into my dashboard and find the plugin and deactivate it so now it's going to clear out all the custom roles and capabilities which is fine. For the purposes of what we want, because I want to make some changes to the code, working with the roles and capabilities is about the only time where you have to do this activate and deactivate of your plugin stuff, because it's storing it to the database. There are one or two other places that do that but roles and capabilities is specifically one of them. And I would also say that if you are somebody who uses WPC li you can also run the associated functions using the WPC shell command in WPC li that's what I normally do instead of this deactivation activation process. But deactivation and activation of the plugin is probably the easiest way to manage things. So what we can now do is we can take this code here this removing the plugin capabilities from the editor role and change it to. Sorry, not that one, not the editor role sorry. We want to change this to removing these capabilities for the administrator role. So we should have actually done that before we deactivated the plugin. So let me go back and activate the plugin quickly so it sets all that stuff up. And then I'm going to change this deactivation here and I'm going to use the same code for administrator. So I'm going to get the same role administrator role there. And I'm going to get the same set of capabilities. And pop it down in here and I should have done this earlier. And then I'm going to do the same for loop, but this time instead of adding the cap I'm going to remove the cap. There we go. So top tip if you're working with with roles and capabilities, make sure you set up your activation and deactivation before you start making changes so that when you deactivate it's doing the correct deactivations. Okay, so let me copy that code out and share it with you in case you need it. And then I will deactivate this plugin. So that I'm now clearing out my data my data is back to normal and now I can make some changes. Okay, is everybody up to speed with me there I want to make sure that I'm not going too fast for anybody so I'm going to take another break before we add our custom writer role. So let me know in the chat if you need me to slow down, or if you're happy with where we are. Okay, so just to recap. All we did for the custom post type was we added the capability type story stories so pluralize is correct. So that's in the function right at the bottom of the of the plugin. Then at the top towards the top of the plugin in the WP Lord add custom caps function which is hooked into the plugin activation. We got the administrator role and we added all the story capabilities that were created by setting up that capability type, and we loop through we added those capabilities to the administrator. So with the activation below it we made sure we got that administrator and removed all those capabilities just because we want to clean up the data. Before the plugin is removed from the site. Now we would like to create a specific role that can access only stories. And just below the administrator stuff that we just did there is the assistant role that were created last week. So the first one is the adding a custom assistant role. And the second one is removing the custom assistant role. So we're going to use this code to create the writer role. And you'll see that it uses the add role function let me get that that documentation for you I think I had it open up over here. We covered how ad role works last week. Basically you can create the role and assign capabilities at the same time. So I'm going to use this code and I'm going to simply change a few things I'm going to change assistant to writer, the first one, which is the name of the role. I'm going to send the change the second one from uppercase assistant to writer which is the readable version on the front end. This should really be a translatable string but I'm just leaving it as English for now. And then I want to assign those those capabilities. Now those of you who were here last week will remember that the read capability is necessary for the user to be able to access the dashboard menu and see those things so read needs to be there. And then the other capabilities that need to be there are from this list. So I'm going to copy this whole list out. And then we're going to kind of look at what might we need for this role. So remember I mentioned earlier about they wouldn't need the meta capabilities the edit story read story and delete story because those are not generally checked on users it's the primitives that are checked. So you wouldn't typically have edit story read story and delete story. You would have edit stories you want this user to be able to edit stories. Which also is mapped to Valerie's got a question I'll get I'll pause in a second Valerie, which also maps to create create stories Valerie you want to go ahead with the question. Are you are you muted Valerie. What do you need me to just to wait. Okay just hang on one sec. Valerie's asking me for the link to the plugins I'm going to grab that quickly I think it's in here. Let me just get a chair. There we go. If you need if you need any help with that let us know, but you can go ahead and install that one. Okay. If you need me to stop again Valerie you can just let me know but I'm going to continue along so long. So edit stories we might need edit other stories we probably won't need we won't want this user to be able to edit someone else's story so we can remove that one. Yes we want them to be able to lead their own stories yes we want them to be able to publish their stories. We probably don't want them to be able to read private stories. So those are probably the only pieces of functionality or capabilities that they might need that we're aware of. So we're going to set these all to true. And I want to show you what happens when we do that, because something interesting happens that is not necessarily ideal. Right there so add role writer writer, and then the array of capabilities. Okay Valerie I'm going to just share your your question with the general chat you're sending me a direct message but I'm going to share it with you. So, if that link only gives you a single PHP file that's a Mac OS specific thing. I know we've had this before where if you click on a link Mac OS automatically extracts the file I think to your to wherever you're downloading it. I don't, I don't see this happening on my side and I think that's because of a setting that I've done or something in the browser I think it's a safari thing. Can anybody else I know somebody else helped me with this once before. I think if you use a different browser maybe it'll download the zip file. Can anybody remember what that was and possibly help Valerie out with that way if you click on a zip file it just downloads and extracts the PHP file and not the zip file that can be installed. Anybody anybody out there I think it's a safari thing. If I'm not mistaken. Just see here. Yes, how to fix. I'm on a Mac and I had to use that specific link with the word download releases yada yada yada. As opposed to just this link I also got the same thing and I'm on a Mac but I'm that was in Chrome. So wherever that was I couldn't find the releases I wasn't sure where that was. So releases okay let me let me take you through to releases so this will be the tag here. I'm going to share this in the general chat so that everybody can see that so there's the releases there. And then if you click on releases you can go to 102. And then if you click on that one that should give you the, as far as understand the download. Let me know if you don't come right with that. Is that working for you. Okay. Perfect. Okay, awesome. As I say, I've stumbled across that one before I think it's specifically a safari thing. I don't use safari. I don't generally use a Mac it's a work machine so I have to, but this might be useful for you as well Valerie there's actually apparently a way you can fix this. So I will share this link with you as well. And then, and you'll be able to use that as well so thank you for shouting that out and letting us know that you that you're struggling with. I'm trying to remember. Oh yes. So that's what our writer code might look like. We might think edit stories delete stories publish stories that makes total sense. And that's our writer role setup. Then we should remember to remove the writer role and the plug in deactivation. So just below that I've got the deactivation hook with the remove custom role function setup. So we can just make use of that so we can pop in there, remove role writer. So just to make sure everybody's got this I'm going to share this code with everybody in the chat again. So there we go we're adding the writer role, and then inside the removal inside the deactivation have just below that will remove the writer role. What's interesting to notice and this is just on a little side note, you can register multiple deactivation and activation hooks you'll see I'm doing that here I'm registering one activation hook here. I'm using register activation hook, and then one deactivation hook there, and then another activation hook there and another deactivation hook you can register as many hooks as you need to. Some folks like to have all their activation hooks together and then all their deactivations. I tend to like to register the activation and deactivation together so I know what's turning on and off, but you can do as many as you as you might need to. Okay, so theoretically that should mean we have a role we can work with now. So if I go back into my plugins list, and I activate my plugin it's going to set everything up for me. So let's verify this first let's look at those tool settings those menu settings we created to make sure. So the first thing we might do is look at learn capabilities. We're not needing the author role we're needing the writer role. So let's actually go here we can now just go back into the code and change it because this doesn't require things to be stored to the database. So if you go right up not right up to the top but more or less to the top is the learn render admin page, we can just change this from author to writer, and you should really change the variable as well, you don't need to. It'll still work, but you should change the variable from writer role to author role just so that your brain knows what it is. And if we now refresh that page. And have a look at it there's the writer role, and there's the capabilities we specified we specified read edit delete and publish stories so that's working as we want to do the learn story CPT won't have changed much those will still be the same but at least now the capabilities are set the way we want them to. So now let's go into our writer user and change the role. So we go into writers into the user at least and we scroll down to the role selection, and we can now specify this as a writer role, and we simply save the changes. So let's update that user. That's all well and good. Now let's log out and test whether this user has the access they need. So I'm going to log out of this. I'm going to log in as writer and password. And there we go writer can log in writer can see the dashboard writer can see the stories writer can see the admin story but not edited which is what we want writer can add a story, which is what we want. However, when you add the story it breaks. Now, in my site it's breaking because I'm using the block editor, and the block editor requires a different set of capabilities. So using the classic editor it may or may not break as well. But basically what we've discovered is there's some additional capabilities that this user needs. Now there is a function inside of WordPress called map meta cap and this might sound familiar to you. And basically this maps a capability to the primitive capabilities required of the given user to satisfy the capability being checked. There's a capability somewhere that hasn't been mapped. So when map meta cap runs and checks against that capability a checks has this capability been mapped to this user role that I need to be able to view in the editor. And it goes no it hasn't and everything fails. So now we need to start digging into what is that capability and which ones do we need and it's a whole thing. So I'm going to start register post type. And I'll go back over here is that it has an argument related to map meta cap, and it's just called quite simply map meta cap. And what that does is that maps all the primitive capabilities both those used inside and outside of custom of the map meta cap function to the primitives and makes them all available to check against and then you can assign them to your users as needed. So what you will generally see in plugin development is you won't see I'm going to scroll down to the bottom here. You won't see the users using the capabilities array. What you will see is folks will use the map meta cap array, and they will set that to true. So there's two, there's two ways you can do this. Let me show you the one way. And then, and then we'll take it from there. So you might do something like this, you might say, I mentioned a copy this code out, we're not going to use it. You might say something like this, you might say, well, I need to edit additional things like maybe publish posts or whatever the case might be. So let me map those capabilities on the custom post type. And then you have to go digging in the documentation again. Okay, there's another capability that I'm missing. Let me add that to the list and etc, etc, etc. To bypass having to do all of this, you simply set map meta cap to true. And once you do that, I want to show you what happens. So with map meta cap set to true on the capability type story stories. Let's go and have a look in the dashboard. If we, where is my dashboard now, here we go. Let's go back one. I'm going to have to log out as the writer and log in as the admin so that we can see that menu page. And then if we go into the learn capabilities. It's the, here we go. So now if you look at the custom post type you will see 1234567891011121314 all 15 are mapped again for us, based on the fact that we've said story and stories. So this doesn't mean that the that users have access to these things it just means they're mapped and they're available. So if you, for example, like we have done, if you specify that your writer user can edit stories and publish stories. But they also need an additional capability to do something within the within the block editor to be able to work with stories. So because you've mapped the meta capabilities, the capability for store just, if you remember the second step back if you remember earlier with admin user, we created the stories capabilities but we still needed to add them to the admin user. So now because we've added edit stories and delete stories and publish stories if there's anything missing to be able to do what we need to do within the scope of these three capabilities, because the rest of them are maps. So if you look up can this user physically edit this based on edit stories. And then if there's an additional capability related to that it'll look that up as well. It'll all come back true and it'll be good to go. You'll notice that I'm still defining this writer can only read edit stories delete stories and publish stories, not other people's things not external stories not private stories just my own stories. So if there's anything missing that I need to do something within the scope of those three capabilities, they will now be mapped. So if I now log in as my, as my writer user it are, and I go password. Now I can go in and I can say yes, I want to add a new story. Yes, I can add a story. That's great. So now I can go write a story. This is another story, and I can publish this this is all good. So that's perfect and I can do you know whatever I need to do it's there, and it's all good. But notice, once it's published, I can't edit it. And that is because, and this is where things get fun. And that's because I haven't given it any kind of published capabilities. So let's have a look again at our story CPT. There is also the fact that I can edit published posts, for example, that I might want to be able to do. I might want to be able to delete published posts. So that I might want to add to my right to capability. I'm mapping the meta capabilities by using map meta cap. I'm basically saying, make sure that all the capabilities are available. But then I still only assign specific capabilities that I need. And if any of the meta capabilities are needed for that specific capability to work, they will run through the map meta cap function return is true and allow me to do that functionality. But because I have defined and this might be a good use case, I might want you writers to be able to submit stories, but once published, they can't edit it. So this might be a very specific use case. They can edit it, they can create it, they can edit it, they can delete it, but they can publish it. They can delete it before they publish it, but they can't delete it after it's published because I haven't allowed them to edit published or delete published. So I can still limit their capability set, but by mapping meta cap on the custom post type, I'm at least saying if anything is needed within that set any additional meta capabilities primitive capabilities beyond that set, allow them so that that functionality works. Okay, does anybody have any questions around all of that. I know it is it's a lot of a lot of knowledge to take in. It's difficult to define it in a very short space of time and understand how it works. And that's why my recommendation to you is to after you've done this after you finish this workshop, take the plugin code and play with all of this I have a look at the custom post and start with just giving the user read capabilities that right to roll just give them read and active deactivate give them read activate see what happens. Then start from the top give them edit post see what happens give them read post play with the combinations that you understand what they all mean and what they all do. And then play with all of the other capabilities. So if you have a look at the roles and capabilities list over here. You've got manage options manage plugins manage various things. Make sure you've tested them and you see how they work because unless you've got them in your sort of full knowledge your scope of knowledge, things can get a little bit tricky. Okay. That is where I'm going to end here today. The thing that I want to the thing that I want to end with is my top tip for working with capabilities. First make sure you set your correct custom capability types. So in other words make sure you set your singular in your plural, so that that all works as expected. Then use the always use the map meta cap argument you're not going to be exposing your site to any security flaws by doing so. So all it does is map the capabilities to the custom post up it doesn't actually set anything to anybody. As you saw earlier, the admin user, even though they had edit posts. They didn't have edit stories when we set up the capability type of stories. So you're not exposing things by setting these two arguments in your in your custom post type. So it's a good idea if you're going to be working with with user roles and capabilities on your custom post types to use these two settings. And then thirdly, then create your custom role. So this is what we did over here we did it a little bit backwards the way I showed you it. We created the role and then map the meta cap but then create your custom role that you're going to use, and then assign the capabilities that you think make sense. And see if it has all the functionality you need if it doesn't add look for and add those additional capabilities. Use your activation and your deactivation hooks to roll back the changes and install the changes again. So that you can work with these things and understand how they will work. Does anybody have any other questions around all of that before we close off today. Please let me know. While I finish off my last sip of coffee for the day. Okay, they don't seem to be any more questions. But as always, if you do have questions for me you are welcome to reach out to me afterwards. I actually, I don't know if it exists anymore but I bought this AM a. You're still welcome to post questions to me there. I don't even haven't tested it lately so let's see if it's still working. Let's see if it runs. Looks like it still works. So you're welcome to send me questions there you're welcome to contact me via email. It's just my name at gmail.com. You're also welcome to find me on the making WordPress slack. You can send me questions there. But thank you all for joining me today I hope you have learned something about how to manage roles and capabilities. And if you haven't please give me a shot and I'll do my best to dive into it with you. Thank you everybody for joining me enjoy the rest of your Thursday and enjoy the rest of your weekend.