 I'll make two announcements real quick before I start this. One, there is code in this presentation, so if you're not comfortable with that, I just want to put it out there ahead of time. Two, you can find the slides to follow along, because I know sometimes following this code is a little bit, when it's on screen, can be a little difficult, so the slides are already at the URL there. And third, I want to make a thank you to Doug Stewart, if he's still in the room, for giving me an awful lot of ideas that I've incorporated into this talk. So he's one of the organizers here. If you see him, thank him for me, please. And with that today, we're going to talk about extending WPCLI. There we go. Before I do that, I also want to add one more thing, is that I do work for TenUp. If this type of thing with WPCLI code and all that fascinates you, we are hiring. I'm sure none of you have heard that before, but it's true we're actually hiring at TenUp. So check it out if this type of thing interests you. So I'm going to start out today with talking about what is WPCLI. Many talks that you see on this topic tell you how to use it, how to create posts, and really, there are an awful lot of talks about what it is. So I'm not going to get too deep into what it is for this talk, but I will cover the basics. WPCLI is simply a PHP script that interacts with WordPress in the terminal command line. So you can, it's like kind of going into Homebrew or something like that. You can actually install this with Homebrew if you're on Mac, or you can install it with various package managers on Linux and things like that. It's a PHP script. It's so it is running on the same technologies as WordPress, but it's not actually a plug-in for WordPress. You're running it from your computer, and that's a very big distinction as we go forward. In addition, because it works on your local server as part of your development environment, it's not actually part of WordPress itself, and that's another big distinction, especially in a talk like this, where we're going to talk about extending it and what the other things it can do. So while, yes, it is PHP, you download actually what they call a FAR file, which if you've ever downloaded old Java software five, six years ago, you always got those jar files. Well, PHP has its own very similar packaging system called FAR, P-H-A-R, which is actually how WPC-LI runs. So it runs completely independent of WordPress itself. It just acts on WordPress. And it allows you to work on pretty much all parts of WordPress. You can work on content. You can work on users, settings, plug-ins, themes. Just about anything you can do through WordPress is available as exposed to WPC-LI's interfaces, so which makes it a very powerful tool. It is a simple API, which makes it easily indefinitely extendable. Oftentimes when we see these talks, we'll talk about how to remove Hello Dolly, sorry Matt, or something like that from WordPress, and a lot of the basics on things that you can do with just core. And out of the box, that's pretty much what it works on. It's going to work just directly on core. What we're talking about here though is extending it for plugins, themes, or other software. So what we can do with a command then becomes pretty independent, because we can extend this into a plugin. I actually write a number of plugins that are nothing but CLI commands for TenUp. Or a lot of the plugins I've written in the past, I built better WPC security. I was the original developer on that, and I themed security. So it had a very large WPC-LI interface on it. If anybody works with Elasticsearch, TenUp's Elasticpress plugin, it has been entirely WPC-LI driven, which meant there was no interface at all in the dashboard. All your configuration, all your indexing had to be done through WPC-LI, and that's still true up until a few weeks from now. But you can also do things like write to a log with it. So for things like debugging, or if you're trying to trace something on a production server, if you're trying to get information out of WordPress, that can be very handy. You can enable or disable options. You can write to other software. You can interact with other APIs or manage cache, handle security functions. You lock yourself out of WordPress. You can actually reset a password. One of the nice things about it is there is no, because you're already assumed to have privileges to run from the terminal, it actually removes a lot of the authentication, a lot of the barriers that are present, a lot of the roadblocks that you're gonna find as you actually work within WordPress. So if you lock yourself out, you forget your password, you have to go through the reset password function, you wait for the email, you play all those games. Because WPC-LI assumes that if you're on the server, you can actually, it's too late to try to stop you from doing anything, right? You're beyond WordPress, so it's gonna already authenticate you, and you can run these things like changing passwords, adding users, getting yourself in or out of trouble very quickly with plugins and with other things with WPC-LI. Some examples of this. ElasticPress is one of the ones I've already listed. We have sites that we've worked on. 85,000 posts are often what I test up to 250,000 posts when I test elastic press functions. And we can actually, because WPC-LI's the speed of WPC-LI, we can index those in just a couple of minutes. Where when we try to do that when you add the GUI, when you add JavaScript, when you add the whole PHP WordPress stack on, it's gonna slow it down quite a bit. Mune and Monit plugins. Mune and Monit are server technologies, and this is actually one of the things I've been involved with, and Doug had given me a lot of ideas for when I started with TenUp. Mune and Monit, if anybody's used Linode or a number of hosts, they always give those real 10-year-old-looking graphs of CPU usage and things like that. That's an application called Mune. And what it does is it simply reads text files. So what we've done then is taken WordPress, and set things like how many users are there, how many posts are there, how many comments are there, and spit them all back out to Mune via WPC-LI, and let Mune take that data, it writes Mune plugins, and then Mune can graph. So if you're a customer of ours, you can see in various spots how many users you have on your site, or if it's a large blog, how many comments are in there, and you can watch your trends go that direction as well. So it integrates very well with these server softwares. I've used it with various instances of WP fail-to-ban in the same way, or writing things. There is a very good WP fail-to-ban plug-ins, fail-to-ban being a technology. We've all used things like Brute Protect with Jetpack, or we've used iThemE Security to keep people out of our sites, and they're very good technologies. We can actually take it down to the server level a little bit. And WPC-LI can expose some very nice things to help with that. Cron jobs that can check if users have done certain things, or people that you don't want, or disabling certain people, things like that can all be done through WPC-LI, avoiding any kind of load, and moving things back off of it. Or just like that, clearing, especially iThemE Security. I know you guys have used iThemE Security, we log a lot of things. So you can clear logs, you can clear lockouts, you can interact directly with a second plugin, completely independent of core. We've used it to compare staging sites, compare screenshots of staging to production sites. Phantom.js is a great utility as you migrate sites. What it does is it's a headless JavaScript browser that just goes out to a site, takes a screenshot. It'll go out to a second site and take a screenshot and tell you a percentage of how different they are. And you can set warning levels to say, hey, if it's more than 20% different, let me know. We can do that through WPC-LI. We've written scripts that'll actually, as we move sites, compare site, it'll go out, it'll check both sites, and it'll say, hey, something messed up. You know, maybe it's a cache error, all the little things that can go wrong with a site migration. But using WPC-LI is a very quick and very automated way then to be able to handle on migrations in a much more sophisticated fashion, if you will. We can disable and handicap users through fail-to-ban, as I mentioned, and you can also offload heavy tasks. One of the benefits of WPC-LI is it doesn't run everything in WordPress. The front end, of course, is not loading. There's all sorts of things that are just, you know, at the very basic level, you're just simply not loading because you're running through the terminal. So very heavy database tasks, such as elastic search. Very heavy if you had bulk post generation. If you're importing maybe some sort of scripts from external sources or data from external sources, WPC-LI becomes a very efficient way. In some cases, you know, we talk about REST API a lot this weekend. In some cases, WPC-LI might even be more efficient based on data sizes, because you don't have the overhead of the HTTP requests in many cases. You can actually run this behind an HTTP request and even eliminate the overhead there. So things like SSL overhead and that wouldn't necessarily apply, allowing you to process hundreds of thousands of content entries or 10 content entries very quickly. So that's what it can do. Again, when we talk about this, we often talk about, most of these talks extend that, well, here's how you open a user. Here's how you do something else. I'd rather see people start using it for more of their own work. So we're gonna instead, we're gonna write a new command. I really debated making this HelloDolly instead of HelloWorld. I figured this might be a little bit more recognizable. But as we write a command, we're gonna write a couple different versions of HelloWorld that'll hopefully illustrate some of the concepts that WPC-LI is using. Whenever we, the one thing that every command has to do, and the only real interface it has to have with WordPress is this add command. WPC-LI, add command in the name of the command. So if you're using WPC-LI, you type WP is probably what you've aliased it to. And you say WP plugin is one of the common ones people use it for. Plugin is this registered command here that we see on the screen. In this case, the command is Hello, and it takes only two arguments, the name of the command and the class that we're gonna extend it to. So here we have a Hello command that extends to a class called HelloWorld command, which is very, very simple. Class HelloWorld extends to WPC-LI. It has a function called invoke, which for PHP developers, this is basically construct. Instead of underscore, underscore construct, for your constructor, here we're gonna use underscore invoke, which basically makes your plugin command, the Hello command, run its own command. So when you just say Hello, you don't need any subset. Again, if we were installing a plugin, we would say WP plugin, add. Well, the add is a sub-command. To just run WP plugin, we would have to run the invoke command. And in this very simple one, all this would do is print out HelloWorld. So WPC-LI, we're gonna give it a success message that just says HelloWorld, a very simple string. And that's an entire WPC-LI command. We go to our terminal, we go to vagrant, whatever you guys are running to run it, type WP Hello or whatever alias WPC-LI to, and all you're gonna get out is a Hello, it's gonna spit HelloWorld back out to you, just like everything you ever done in any kind of code school tutorial or something like that. It's a very simple, very complete command. And that's really all it takes is a success message, some sort of output as simple as HelloWorld. But of course we can also extend that a bit. One of the real benefits becomes options. Namely, HelloWorld is boring, so we can change this a little bit. What I've done here is it's the same, we've started class HelloWorld command, we're extending the same class, we're still doing the same invoke method, but now I'm passing it two parameters, args and associate, associate of args. If you've ever done any kind of Java class or C++ class or anything else, this probably looks very similar to you, very, very familiar. args is a list of just words or numbers or just a list of items after WP-Hello. Associated args is where we can name it. So if you're actually using, if you've used WPC-LI and you say WP-Plugin install and you have to give it a name. So either, a lot of times it might have an ID for some of these commands. If we're getting a post, dash, dash ID, dash, dash, whatever the argument is, those are your associative args. And in the case of plugin install, and if we just list the plugin name, that would be a standard argument. So we can take a look here at what this actually does. So if we have arg zero, this is just a simple array. It takes every argument, every non-dashed word after your WP command and spits it as one of the args back in an array. So we look at arg zero, if it's not there, then we look for associate args. In this case, we say one called name. And both of these are specified, I'm gonna highlight this row right up top here. Notice the square brackets run and that means they're optional. So we can either put somebody's name here or we can put dash dash name equals. The first one is args, the second one is associate args and they're passed right back. Here we're just checking for them and if one of them is set, use it. If there's first one set, use that. Otherwise, try the second one. And otherwise, we're just gonna go back to name equals world. So when we were to actually run this, here's back to our success command. Always sanitize output, even in WPCLI please. When we go back to it, we could type WP hello chris now or WP hello dash dash name equals chris. Or we could just still do WP hello and we're gonna either have the hello world or it's gonna come out as hello chris or whatever you stick in that argument. So it's very easy to pass data back. Post IDs, user IDs, database information, extra commands that you wanna run. Your log tables and your personal plugin, whatever it might be. Theme functions that you wanna change. Maybe this is a way you're, for some reason you wanted to change a widget. You have a thousand widgets in there and we all know how slow that screen can seem. So maybe this is a way you can pass text back to a widget in your theme without, just kind of save yourself a little bit of time. But there's a whole lot of things that you can do just with using these arguments. And we can take that even further though too. Here's our hello world and we have sub commands. Like I said before, we have invoke. And notice there's no more invoke this time around. So we have hello or public function world that just prints hello world. And we have one that's name with the same args or arg zero. In fact, this one just takes arg zero. Notice no more square brackets. If I don't pass it a name, it's gonna yell at me and say, hey, you did this wrong, try it again. That's the only difference. You have to specify the synopsis to tell it what commands to say. Otherwise who's gonna say I don't pass it JavaScript equals or HTML equals or something else. So the synopsis line specifies, oops, this is a problem I don't use a presenter when I stand so close, I apologize. The synopsis actually specifies and limits what you can put in there. And like I said before, on the previous page, we had the square brackets which made them optional. Now for this command, we don't have the square brackets. So this is a required command. And it works very similar. Now we type hello world, so it's a sub command. Very similar WP plugin add. It's a sub command of the plugin command. Or here's WP hello name and Chris. And it does the exact same things. It's gonna spit out hello world or it's hello Chris. Very similar to what we've done before. Just a slightly different way of handling it. This is very handy because if you have, your plugin is Acme super plugin and it does 5,000 things. You probably don't wanna come up with 5,000 different classes to cover every single command that you might have to work with. You have seven database tables. Maybe you don't want seven different commands to handle each table. That can get a little bit unwieldy. So instead what you can do is you can assign sub commands at this point. WP Acme super plugin, do this. WP Acme super plugin, do that. And these sub commands then work underneath to just basically kinda organize your command a little bit. So it's a way to keep this data simple. It's a way to keep the interface simple and hopefully keep your users a little bit happier and maybe your own sanity a little bit happier. When you're doing these, there are some things, that's the most basic command. That's our hello world. That's a couple different versions of hello world that you've probably seen just about any language you've ever touched. Because this is WPCLI and this is WordPress, of course there's always tricks and trade and various things we can do to help with this. One of the biggest ones is don't automatically register your commands. WPCLI sets a very good, I can't think of the word, I'm sorry, I'm drawing it like the constant here, the WP underscore CLI constant to set whenever it runs. So rather than trying to load, if you have a command with 50,000 sub commands, that's a lot of code, that's a lot of processing, don't try to load it automatically. Wait until WPCLI looks for the commands and then do your add command. Just like we did before here, we're registering it, but now we're checking to make sure, hey, is this actually WPCLI that's trying to get to it? I have slowed down a few sites by avoiding this, so it's definitely, the bigger the command, the more handy, the more you're gonna notice this type of thing, but it's definitely one of the tips you wanna use. Also, you gotta be careful with things like success and failure with WPCLI, they're not treated the same. In all my examples I've said success, we wanna print hello world, that's a successful message, but we can also print an error. And you guys have seen this anytime you've run anything in the terminal, it spits back something in red, probably, or whatever colors you have your terminal set to, when it says, sorry, something's wrong. We can spit this back, WP plugin deactivate X plugin, well, X plugin's not there, we're gonna have a problem. The catch is when we spit an error back in WPCLI, and this is something I've seen a lot of people, a lot of plugins make the mistake of, by default WP error actually stops it, whereas WP success keeps going. I can send a hundred success messages, but unless I change my error message, I can only send one. So it can be very frustrating at first going, oh, well, it failed on this one, but it could still keep working. So you have to watch what you do with this, in this case we can change WPCLI error, and there's a second command, which is exit, and set it to false, by default that's true. We can change it to false, and then we can make sure that even if we hit an error, hey, that user wasn't there, but you said create a post, and whatever your basic command was, whatever your plugin does, it'll allow you to keep going, which can be very handy, you do not have to exit just because you see an error. Another big one that you see, and you actually, I should say you see, but actually you don't see this on a lot of plugins that even use WPCLI, and it's kind of a pet peeve of mine, is output format. WPCLI, by default, most everybody uses error and success, and that's a great way to spit out a message. But if you're processing 250,000 posts, do you want an error message or a success message for every post? Just the refresh rate of your screen's gonna kill a lot of your advantage that you had by starting it, so there's a few things we can do. First, we can spit out the data in a JSON format. It has a built-in table formatter, so instead of trying to recreate the wheel and spit out your list of users in a format that somebody's gonna look at and go, where is what, it'll actually handle that for you. It has CSV output. It can give you a list of just IDs, and it has just a count format, all very standard built in, and it does this all through the format items. Is it a utilities class? Format items, it's a little bit hard to find documentation yet on this, which is why I want to bring it up as a point. But tell it what kind of format you want, table. JSON, in this case, I'm passing it, get users, and I'm passing it what I want the fields to be. ID, user, whoops, user list. All these different fields that we can pass it, and it's gonna spit them out in the format and request it. Now I have a JSON file I can pass back to my other application. No playing with WP, send JSON, no playing with JSON in code, no playing with any of that other stuff that can, if you're not careful and get you into trouble, it just handles it for you. Same with the table output. That's probably the biggest one I see people misuse. They recreate their own tables and wind up with a couple hundred lines of code for a table that now you can't read because you didn't test it on somebody else's machine and all this and that. They have a very solid table output that can really help you keep track of what you're doing with this. And in that same line, especially if you're doing something like 250,000, it actually has its own progress bar built in. There's a good friend of mine who's a developer who, the 250,000, I actually give him an example because I was just using his plug-in the other day to generate mock data, like the Ipsum data. And it spit out a line for every single plug-in. It's like, hey, can we get a progress bar on this? The progress bar not only give you a progress of how many percent that you have, so if you have 1,000 posts, every 10 posts, now you got 1% done, 2% it'll go along like that as long as you keep feeding the data back to it, but also tell you how much time. So if it knows there's 1,000 total and it's taken 10 seconds to do the first 10, it'll tell you how many minutes you have left, how many seconds you have left, which from a user point of view, this is usability on the command line. This is something that's gonna help it make it, you spit the bigger the data and the more handy this gets is the bigger the data. This is gonna make sure that people don't think their processes are stuck, people don't have problems like that. CLI has one of those neat advantages in most cases by default, there's no timeout. So if you're not telling people how far along things are and you're processing a lot of data, you're accessing a lot of remote APIs, it's really easy to think that your computer's locked up, the process is frozen, something's broken, try again. The progress bar can take care just about all of that for you. So even if it's a little bit of data, if it's a lot of time that you're gonna spend, you gotta go out to whatever API, it's a three minute return, use a progress bar. It'll tell your users how far it's gone, but more importantly, how much it's got left to go. Keep them knowing that the thing's working. Make sure nobody realizes that it's broken or something like that. And finally, one of the biggest things that are often missed is unfortunately there still isn't much documentation on that yet and is, I say use the force, but use the utilities file. The formatter was under utilities, if you looked at that. But there's also some very other, there's a number of handy functions. Locate WP config, where did they put the WP config file? If they're using the skeleton, is it in the WP folder? Is it somewhere else and linked to? So it's automatically, it'll take care of that for you. There's rate to CSV. I said you can do CSV output, but maybe you just wanna save it as a file. It'll handle all that for you. You don't have to play with F open. You don't have to play with F puts. You don't have to play with F gets or any whatever you wanna handle your files. It just handles the CSVs for you. It'll handle an editor. If you are doing, let's say you are doing a widget. You have a thousand widgets. We know how slow that screen is from my previous example. You can actually open, use this launch editor for input. It'll open the user's text editor where they can then change whatever they need to change, put in the content they need to put in, save the file, and WPCL, I'll pick it up right from there. It's a very good way to handle if you, for some, you know, with Calypso, now a lot of that tension is given to REST and that's great. Think of this as last year's REST in some ways. You can actually, if you wanted to really do it, I'm not sure why you wanted to, but you could actually blog through Adam or something, set up a command. Once you save your file in Adam, you can, or Sublime or whatever editor you want, you can blog right from there, save it, and it'll go right back to WordPress for you. It'll handle all that input. It'll handle the file save. It'll watch the files for you. No playing games with where anything's saved or how anything's handled. It's all built in. Things like parse URL. One thing we put in a lot on these things is URLs. PHP has parse URL. This adds sanity checks to it. Make sure it's actually a URL, handle it correctly, things like that. So instead of just a simple spit back what the domain is, spit back what schema it is, spit back where the path is, WPCI'll take that a bit further, use it, because you'll save yourself a lot of problems later when somebody puts in something weird that shouldn't be there. It'll handle that for you and it'll spit back the appropriate error, the appropriate response based on what it wants to do. And of course, probably if I looked around the room, most of us have Macs, but this'll handle Windows too and it'll check. Because most of us are used to using terminals, ZSH, Bash, whatever it might be. You can actually run the check that is Windows. So guys like Eric Mann and that can probably use this pretty well. I'm sorry, I can't, I'll call him out, he's sitting up here. But it'll actually check if it is Windows for you. So all the differences in the Windows from the file handling to things like that can be very quickly checked and accounted for to handle things like where our file outputs, how our file's input handled, different things like that, just by checking as Windows. So you now know, not only if you're running on Mac or, you know, IE or all the checks we put in the CSS, but it'll automatically account for the biggest difference that we're gonna see with WPCLI implementations, which is a NICS system, Mac, Linux or whatever, or is it Windows? Comes in very handy, especially on a plugin. And most importantly with WPCLI and the thing that if anybody's in here who just works in DevOps or anybody here works in systems, one of the biggest things that are very handy with it is it doesn't actually need a plugin. You can write your command in a class, you can save it anywhere on your computer, just don't just clone your GitHub repo in a standard spot. Add a file in it that call it require or something like that and there's actually a command for, anytime you execute, there's a global WPCLI argument called path and you can tell it where the class is and it'll run that command from anywhere. It'll launch the WordPress from where it is, if you run WP just like it normally would, but it'll go out and get your command from anywhere so it doesn't even have to be a plugin, it doesn't have to be part of your implementation. So if you're integrating with Ansible, Puppet, Chef, something like that, you can actually write your commands as part of your deployment script, you don't have to worry about where the sites are. So for things like Triple V, varying vagrant vagrants, map one folder, put your commands in it, just add the path variable. When you alias your WP, you can add the path variable. Now you don't have to worry about where these things are anymore. So if you have a handy set of 15 tools you want to use, just map once. Don't try to sit there and every time you set up a site, you have to reinstall the plugins and all that. This completely removes it. So it's very, very good, very handy when it comes to dealing with systems. That's what I have as far as a number of tips. These talks are always funny because 25 minutes isn't a lot to teach everything but hopefully we got some hello world and maybe some ideas as to where things are going and if anybody has any questions, I'd be happy to entertain. I was curious, you mentioned the invoke method. Are there any other like magic methods within WPCLI? That, you know, I mean, for instance, so like if they type dash dash help, is that just gonna show like a synopsis or is there a separate like underscore underscore help magic method or something like that where you could do stuff or, you know what I mean, so. There are others. I don't want to answer what they are because I cannot off the top of my head remember what the other methods are. For help and specifically there's actually not. It's all part of the PHP header. So when you write your file doc where I said synopsis, you can actually have example. You can have a description and all that would come up. That's where your help text comes from. It's not coming from a function itself. So it's just gonna process. You're keeping your stuff together at that point. Keeps your code together a little bit cleaner. I can't answer the other one because I just don't wanna answer that wrongly at this point. Cool, thank you. Sure. Five more minutes anymore? All right, thank you.