 All right, everyone, welcome. Next up we have Take Back the Day, WPCLI, and here to educate us is Ryan Canner. Thank you, thank you everybody. Thank you everybody for staying till the end of the day. I know at this point you've probably been pretty worked over with WordPress information, especially if you've been sitting in this developer track all day, like I have, because there's been some really, really great talks today, lots of really good information, so your head might be exploding at this point. So we're gonna keep it a little bit lighter with this talk. It is technical, but we're not gonna get too far in the weeds here that your head's gonna explode for anybody in this room, depending on your experience level, it does not matter. So a little bit about myself, my name is Ryan Canner. I've been developing on WordPress for over 10 years now. I'm an ex-East Coaster, and I now live in Denver, Colorado, working for Media News Group, where I work on websites for newspapers, such as Denver Post, Mercury News, Press Enterprise, Orange County Register, to name a few. I'm also a freelance software engineer at a company called LotoPress, which is a full service WordPress agency out of Denver, Colorado as well, and I am the organizer of the WordPress Denver Meetup. So what is WPCLI, starting at the highest level here? Let me see some hands, who uses WPCLI on a semi-regular basis already? Okay, pretty cool. So my goal for this talk is for those of you that are already using it, is to inspire you to use it in a different way than you're already currently using it, and further integrate it into your tool chest and use it even more often than you do already. For the people who don't use it, I want to try and inspire you to start using it and to start automating some mundane tasks and just use it more than you currently are. So WPCLI, at the simplest explanation, is WordPress on the command line. It basically allows you to talk to WordPress without going through your browser. It's an open source project backed by the WordPress.org community. So it's underneath the umbrella of WordPress.org. It used to be just an independent project, but it got pulled under the WordPress.org umbrella a couple of years ago, and it's collaborated on in GitHub. It has a really nice API to extend it, to create your own commands and do other really cool things with. And it's available from WPCLI.org. So if you don't have it downloaded or starting from scratch, WPCLI.org is your starting place. So I want to talk about my journey to WPCLI Enlightenment. I previously used to work at an agency in Denver where I was the WordPress person. So a lot of you may be in that exact situation, or at least familiar with it, right, where you are the go-to person for anything and everything WordPress, whether it's someone lost a password or building a crazy site or integration or whatever. So I was in that position where I was the WordPress person. I had to handle lots of different duties related to WordPress, and my time got stretched really thin, really quickly. So I started turning to WPCLI to help me out, basically, to be a junior developer to me, basically. And I saw this tweet from Daniel Bakugir, and he ran this command, WPAtAllCoreUpdate, and I looked at what it was doing, and it was reaching out to all the sites and updating WordPress on all of them. At the time, I was managing about 100 WordPress sites myself. So Update Day was not a fun day. It was logging into 100 sites and clicking Update. So seeing this, I felt like a complete and total chump, and I decided on this day is that I wanted to dig into WPCLI and make it work for me. So I want to take you through a couple scenarios in this talk to hopefully spark some ideas of how you can use WPCLI and scenarios that happened to me where I used WPCLI to make my life easier. So the first thing that happened, I got an email from the CEO of our company, subject 911, disable Todd's login. Hi, Ryan, Todd from Marketing left the company today, and he's after all our clients. Can we please disable his login for all of our sites? First off, don't be a Todd. That's a real jerk move to do that, so don't be a Todd. So I thought to myself, all right, well, this obviously needs to happen right now. This guy had access to all 100 of our sites. So without WPCLI, I was forced to do the task of logging into every single one of these sites by hand, and this got really overwhelming really, really quickly. I mean, first of all, finding logins for 100 sites is a task of its own, and then going through individually to do all these things is a total pain. With WPCLI, I could run a command like this, WP at all, user delete Todd, reassign to user ID too. So I want to reassign all of this posts to another user rather than delete them out of the database. So this command looped through all of my sites and nuked Todd off the face of the earth. Take that, Todd. So this may seem like magic, but it's not, and it's actually really simple. So one of the most unheralded features of WPCLI, at least in my opinion, is their YAML configuration files. So up here is a WP-CLI.YAML file that contains the path and SSH access to all of my remote sites. So this way, if I need to run a command remotely on a remote server, I can access one of these sites by using what they're called aliases. So at site one, at site two, all those are aliases. And all of them are encompassed by the at all alias. So you can run WP at all, your command, and it'll loop through each one of these and run your command. So let's look at another example. I get a task from the PM at my company called environment creation. Hi, Ryan, we were ready to get started with development for whatever company. Could you get all of the environments for them created? I think, all right, cool, I got this. WordPress has a famous five minute install. But is it really a five minute install? Because to me, everything that needs to be done to set up WordPress across a bunch of different environments is download WordPress from WordPress.org, unzip it, create a database, or remember the credentials of that database somehow, dig through all of your notes, looking for those credentials, then copy the WP config sample file into WP config file and fill out all the credentials for your databases that you just found from your notes file, then go through the browser for the site and go through setup. Then my favorite step, add your personal email like auto filled from your browser for the admin of the site and then receive every single notification for that site till the end of time. So when you get a WordPress update or someone leaves a comment on that bakery site you made 10 years ago, you will get an email for it. Then you'll find your SSH credentials for your staging and production boxes. You'll SSH into both of those boxes and then repeat twice without messing anything up and hope that everything goes perfectly. Finally, you're gonna want to look at your favorite job board for a new job because at this point you're probably going insane. With WPCLI, I can do something like write a wrapper script like WP-install and pass a couple things to it like the URL of the site and the database I wanted to use and in about five seconds, I have a brand new WordPress install. And I'm even so lazy that it opens in the browser from the command line. Yes, I'm that lazy of a developer by the way. So let's look at the secret sauce behind this. I am not like a shell or bash, like Genie. Like many of you might know those people who can like write these crazy scripts that do these crazy things. I'm not one of those people. This is the entire script that did what you just saw. This is just literally the commands that come out of the box of WPCLI shoved into a script and then you just call the file, that's it. Like this is, I am confident anybody in this room could do this today, no problem. So another cool thing that the YAML configs can do for you is set default values to pass to your commands. So for me, I don't change the username and password to my local database all that often, if ever. So I set that in a local config file. I set DB user to root, DB pass to password, DB host to local host. I never have to remember those things of like does it have a password? Is it root? Is it not root? It's just there for me when I run this command locally. So I never have to remember this ever again. So the other thing that WPCLI is really good at is giving you a developer UI to debug problems in WordPress that don't have a UI. So UI-less features within WordPress, it will actually give a UI to and let you pick a part and figure out what's going on. So in this scenario, I might get an email from a client that I've written a cron job for to export some data into their system. The email saying, hi Ryan, we haven't gotten any new invoices into our system in the last two hours. Can you check to see if the cron job is stuck again? This is an artist representation of the cron being stuck by the way. So without WPCLI, I'm going into the database and looking at the cron option, which if you've never looked at it is this giant disgusting blob of computer garbage that is completely unreadable to any human being. With WPCLI, I can run something like WPCronEventList, which will give me a nice formatted table of all my cron jobs. And then I can force the cron job to run with WPCronEventRun and then the name of the cron. So that will execute the cron job right then and there. So while I'm going and digging through and figuring out why this cron job didn't fire, I can just send it off manually and please my client and then figure out whatever's going wrong in the background. So there's a couple of different UI list features within WordPress that WPCLI, it makes it a lot easier to deal with with WPCLI. One of my favorites is WP media regenerate. So if you're doing custom theming and you have custom image sizes, when you create a new custom image size and you need to recrop all of your photos, the current kind of developer thing is download like whatever AJAX thumbnail rebuild, right? And then it loops through all of your images and your image library, recrops them, and then you have to get rid of it before you ship it to production. But with WPCLI, you can run WP media regenerate and it'll just do that for you from the command line, no plugin needed. Also a transience, if you deal with a lot of object cache stuff, you can use WP transient delete in the expired flag and it'll just delete any expired transience. It's not as big of a deal anymore now that we're press added garbage cleanup, but it's still something you can do. Dealing with Cron is something really helpful. Daipi Cron event run do now is really helpful, especially if you have a site that you may be like moved over and the server's been down for a while and you just need to like catch it up. Running that will just run every single Cron job that's been overdue in the system for you. WP rewrite flush is another nice one. So rather than going to like the permalinks page and clicking save to like just magically flush all the transience without any feedback whatsoever, you can run WP rewrite flush and that'll take care of that for you. WP rewrite list is also really helpful if you're trying to debug some issues with like a incoming URL hitting the wrong template or something like that, really helpful for that. Also, if you're using an object cache, Daipi Cache flush will flush your object cache for you, which is another really nice one. So this kind of brings things full circle a little bit back to my original kind of getting to Daipi CLI enlightenment, right? Update day, it's a glorious day. It's the day you get those new features that you've been hearing about at Toxic WordCamps for years and years and years, but it can also be a really overwhelming day if you're like me and we're running a lot of sites. So using Daipi CLI can help you with that. Another thing, update day can also be really hectic if it's an update for a zero day vulnerability, right? Like these things happen in our community where plug-in authors sometimes push out bad code and I mean, it doesn't really happen to you often though it does, right? Things happen in software development. People push out bad code sometimes and it happens because we're all humans. But Daipi CLI can help you overcome these scary days of when you see that tavern post of some insecure plug-in that you know you have running on a lot of sites. And a lot of times those days feel like this, right? You have a vulnerability out there on a ton of sites and there's nothing you can do about it right now. It's gonna take some time to fix. Without Daipi CLI, we're back at logging into individual sites again. We have to figure out how many plug-ins we have of this bad version of this plug-in, right? On all these sites, we have to figure out which sites need to get updated to WordPress, which didn't get updated automatically. And going back to this, after using Daipi CLI, you feel like a caveman. With Daipi CLI, this becomes really easy. We're back to Daipi at all, core update. And then all it does is loop to all my sites and updates them to the latest version. Thank you very much. So as a developer, I get a task on update day or something or I'm being proactive. I know when update day is and I've carved out some time with my project manager telling them it's gonna take me all day and then I run this one command and I goof off the rest of the day or do something fun. Yep, that is the next slide. So the other thing it's good at is figuring out how big the issue is. So if I know that there's a vulnerability in Jetpack 4.2, I can run something like Daipi at all, plug and get Jetpack and I just want the version back and then I'm looking for 4.2, I get a couple, no Jetpack here, 5.1, 5.1, all right. Oh, one site has 4.2. And then I just let it finish and I see that only one site actually has an infected version of the plug-in so this isn't that big of a deal. I can go to that one site and make an update. So rather than immediately freaking out about a plug-in vulnerability, I can find out in minutes how big the issue is across my cluster of sites. There'll be time for questions at the end as well. Also these slides will be online if you need to reference them. So this is just to find out how big the issue is not actually updated. But there are other commands you can run for that. So another scenario could be for importing data. At my new job at Media News Group, a lot of the stuff we were doing now is spinning up new sites on WordPress from a legacy system. So a lot of things we need to do is import tons and tons of terms, users, posts, things like that. And WBCL, I can actually handle that quite a bit. So a lot of times we'll get something like this. Hey, Ryan, I have attached a spreadsheet of a few tags we would like to import into our site before launch. If you could have those imported by the end of the day, that would be great, right? How many times do we get client requests of, hey, could you do this by the end of the day without realizing the implementation details or how big the request actually is? So I'm gonna pop open this CSV in Excel really quick just to see what we're dealing with. And then I quickly realized that there's over 2,000 tags in this list that they want me to import by the end of the day. So without WPCLI, my initial reaction is like, oh, well, now we need to copy and paste 2,000 tags out of the spreadsheet into the Terms page. I'm gonna need a really good playlist, a bunch of coffee, or I'm gonna outsource this. With WPCLI, I can write a really quick script, something like, dopey import tags, and then pass it the name of the CSV. This is in real time, by the way. This is like actually how long it took to import 2,000 tags. That was like five seconds. And this is not a ton of code to make this happen. This is like five lines of actual functional code, like beyond ending braces and feedback. So WPCLI has a very robust API to extend it so you can actually add your own commands to it. So everything I've showed up to now is built into WPCLI. As soon as you install it, you have all those commands I've already showed you. But if you have custom functionality, you can actually implement it yourself. There's an add command method on the WPCLI class, and basically you pass either an instantiable function to it or an entire class of commands. There is much better documentation on how to do this on the developer docs for WPCLI. So I'm not gonna try and teach this to you up on stage because that's not the best way to consume this information, but it's just showing you how easy it is to do this. So this is actually one of my favorite scenarios. When I was working in marketing, we had a very overzealous client who was very obsessed with their website, which is a good thing. It's absolutely good to have a client who's very proud of their website, wants to keep moving it forward. But it made a lot of work for me. After the site went live, we made them a staging site, playground where they can go play around with things, but they had a habit of messing things up a little bit. So this was an email I was getting a couple times a week. Hi, Ryan. I was making a couple of small edits in the back end of our site today, and I think I got a little carried away. It no longer looks anything like this live site at all. Can you reset it for me today? Thanks. At this point, I basically want to throw my computer in the garbage because this may be the third, fourth time that this has happened this week. And without WPCLI, I need to start with reevaluating all of my life choices that have led up to this moment. Then I need SSH into the production server, take a database export, search or replace all the URLs, SSH in the staging server, import the database, and then I need to somehow remember, oh yeah, they have a production key that is pushing a bunch of data to very, very public places that we cannot push staging data to. Fun fact, they were running a bunch of video screens in the state of California, and they had a bunch of funny cat videos up there for a little while by accident. So with WPCLI, I can write a script, wp prodsync, this is gonna do everything that I outlined, but automatically for me, and I don't need to remember all of these things. So this is what the Bash Script looks like. Basically, it reaches out, it gets the URL of the production site, gets the URL of the staging site, runs a search or replace for me, takes an export, and then imports it into the staging site. And then remembers to clear out that API key so there's no more funny cat videos on all their video screens at the airport. So this is where local aliases come in. And so we talked earlier about the global wp.cli.yaml file. You can also have a wpcli.local.yaml file, and this is for single site specific information. So within this yaml file, I can create a production alias and a staging alias. So this yaml file actually lives inside of like the root of where your WordPress install. The previous yaml file that we were talking about could be in the directory above and will work for any commands that you're running across your sites. This will only work for one particular site. So I can define the SSH information for the production site and the staging site. And then that script can just grab all the information it needs from the environments and do this automatically for me. Another really nice feature of wpcli is the scaffolding capabilities it has. It can scaffold a lot of different things for you which can save a ton of time. So a common thing I would get is a task to, let's say, create a books post type and three new taxonomies. It would be something like, we would like to add a new books post type to the site to display our book collection. We would also like a few taxonomies to filter the books by. You're published, genre, author, and publisher. Without wpcli, I would probably copy and paste this code from the codex and then replace the names of everything and all the namespaces for translations and things like that. Or you could use a plugin with an admin UI to do this. You can use an online generator that may be out there, but again, you're still kind of back to copy and pasting. With wpcli, I can actually run these scaffold commands like wp scaffold post type. And then I can also use a prompt flag at the end of it which is a global flag that you can use on any command which will actually let you fill out all of the information for the command because I don't scaffold post types that often so I don't remember all the flags. So this will just ask me and I'll input the information right then and there. And then I'll just scaffold the rest of my taxonomies from here with the wp scaffold taxonomy command. And it's taking much longer than I thought. So then inside of my theme, I have a new taxonomies and post type folder where it's scaffolded all of my taxonomies and post types for me because this is like kind of a mind-numbing task to do by hand. So now this is just done for me. And I know no mistakes or typos have been made that are gonna leave to 500 errors that I'm gonna have to debug or anything. It's just done. There's a couple other useful scaffold commands that you should know about. If you use underscores quite a bit, you can scaffold an underscores theme straight from here with wp scaffold underscores. You can also scaffold a plugin which I actually use quite a bit. That gives you some nice starter files to start out with as well as like a full testing framework with wp scaffold plugin. You can also scaffold Gutenberg blocks which is really great if you're just getting into Gutenberg and don't wanna feel totally overwhelmed, you can wp scaffold block and it'll give you like a working example out of the box. So you can go in and tinker with it and see what it actually does. Which has been really helpful for me, a PHP developer, to figure out how this thing actually works. Again, you can also scaffold plugin tests. You can scaffold them into an existing plugin. So if you're getting into unit testing, I highly recommend using what comes from wp scaffold plugin tests. It's actually quite nice, runs on wp unit and is very minimal upfront work for you to do to actually get up and running with unit tests. All right, so now I wanna go through a little speed round of some commands that have come up that I've found really helpful but don't necessarily need like a full explanation I think. Something really helpful, delete all the spam comments on your site. So if your site gets a ton of spam or just randomly gets attacked, I've actually had instances where like it's locked up the admin completely. So your options are kind of go through the database and write a SQL query to do this or you can do something like this. W comment delete and then you can actually compose two commands together. So wp comment delete accepts a space separated list of comment IDs to delete. And wp comment list with the format IDs flag will return a space separated list of IDs. So the second command will actually populate all the data for the first command. So there's a lot of different ways you can get really creative with WPC-LI commands when you start getting into more advanced things, you start putting things together and then you can actually do some really powerful things. This is something that actually happens to me quite a bit. As a freelancer, I often work on sites that I did not build. So a lot of times when they wanna add a feature to a site or something and I get a database export and all of their code and stuff, I don't actually have a user on that site. So when I spin site up locally, I don't really have a way to get in. One option is you can go through the database and then type in your password, MD5 hash it or whatever. Or you can run the AP user create and give yourself an administrator role on the site rather than jumping through a bunch of hoops. You can immediately get access just like that. You can also create a bunch of posts for testing. This is helpful if you are a theme developer for sure. Also, if you're in the stage with your client where you don't actually have content from them yet, but you've started development and you just need to kind of populate the site with something to test things, you can use WP post generate and it will generate 100 random posts on your site. And then there's account parameter to kind of control that and you can create them in any post type you want, whatever you wanna do. There's also generate sub commands for most of the major object types within WordPress. So you can do the same thing with terms, users and I think that's it. Oh, and comments. So if you wanna test like 100 level deep comment threading for whatever crazy reason, you can do that with this. So really nice rather than copy and pasting lorem ipsum text like 50 times to test pagination on your blog role. Something like this is super, super handy. You can also enable WP debug and this is something that would be a really good candidate to wrap just in your own shell script. So if you wanted to toggle WP debug on and off, there's a WP config set sub command where you can control all the constants in your WP config file. So further than just the WP debug constants, anything that's in there. But in this instance, you can just, you know enable WP debug on your site. If you want to, you can wrap this with a shell script, like I said, and that's a really quick way to do that. This is a really handy one if your site has been hacked and you need to reset all your user passwords. If you have a ton of users on your site, I know on some of our sites we have somewhere near 5,000 users. So resetting all of those passwords you can reset the salts, that will take care of some of it. But if you want to be really crazy about it, you can run something like WP user reset password and then just pass all the user IDs to it and it'll just loop through all your users and reset all their passwords. It'll send them an email so that they can go reset their password. So you don't have to take care of that communication yourself either. WordPress just does it for you. Something really handy if you've been hacked. You can also run a recount on all of your terms. If you deal with a lot of content, do content migrations or deal with a very, very sticky object cache, you could run into weird situations where the term count does not match what the actual term count is. So DP term recount and then pass all the taxonomies to it will run a recount on all of your term counts which is pretty nice, especially if you're working on a really big site. So let's wrap things up now. So why should you use the OAP-CLI? My last ditch effort at trying to convince the unconvinced. As you can see, it allows you to control multiple installs from one place which can be extremely powerful if you're managing many, many sites. It allows you to automate monotonous simple tasks and frees up your time to do much more interesting things. It gives you an easy way to do bulk operations, like deleting users, migrating data, doing imports, things like that. It also provides an easy way to touch some hard to control and hard to reach places in WordPress like transients, crown jobs, things like that. Finally, I think the most important point is that it's consistent and it's repeatable. A lot of these things that I've shown you with OAP-CLI, you can absolutely go into your database and do today. You can download a plugin to do it today. The thing that makes OAP-CLI incredibly powerful is that once you've started using this tool and save up all of these snippets of things that you know fixes a certain problem, if that problem ever comes up again, you know how to fix it. You have your snippet, you have your pre-written shell script, or you have your custom command that fixes that particular issue. You don't, however, have that database SQL query that you ran seven months ago that you've completely forgotten at this point that may be so far buried in your history you're never going to find again. So that's where the power of OAP-CLI really comes to show. I also have some helpful resources on here. I know the Wi-Fi is not great, but you can grab this talk and go to any of these resources. WPCLI.org again is kind of the homepage for that. There's also incredible developer documentation at developer.wordpress.org, CLI commands. There's the GitHub for WPCLI. There's also a package index which I didn't really touch on during this talk, but essentially you can create plugins for WPCLI that are called packages. The package index has been deprecated, but it is a good place to find these packages because there's not a really good way to search through GitHub and find them. And you can also create your own packages if you come up with something that solves a very common problem, you think. There's also a link to, Daniel Bakuber has a post on advanced OAP-CLI tricks. So if you are a more advanced user, I definitely recommend you check that out. There's a lot of cool stuff in there that you probably don't know about. I also have another presentation called WPCLI from A to Z that is a little bit more technical. It gets into custom commands quite a bit more. And that's at my slides.com slash code pro kid slash WP dash CLI dash AZ. So that's all I've got. Thank you so much for staying here. I can take some questions. So the great thing about WPCLI is search in a place is that it does serialize search in a place. So if you've ever done a straight like VIM search replace on a database and things don't go really well, it's because if you have URLs inside of serialized strings in your database, it changes the string length. So you need to use a serialize search in a place and this does that. Yep, yeah, there's also like fine tune controls on it that can like skip certain tables and yep. Yeah, it's fantastic. Yes. So it's basically just like in the animal file you right. It's like dash the name of the alias and then it's indented one level and then each alias under there. So we do that a lot where we have like certain clusters of sites like we have a Northern California group or whatever and that's like NorCal just references the aliases from there. Yes, so at all is the default alias that comes and it will run all the aliases you have defined. So you don't have to create your own at all group and then put everything under there manually. It just will grab all of your aliases for you. But yeah, you can define more fine tune groups from there. Yeah, yes. It depends on your custom command. The way I write them is as like the first argument to go in, you give it a path. So you can put it wherever and then you just feed it the path to the thing. And basically the example I gave was like very short and didn't like check if the file actually exists. But like I'll say like if is readable this thing otherwise like throw an error. But yeah, usually you feed it a path to the actual CSV. Yeah, okay, yes. Sure, so the question was about if WPCLI has capabilities to handle rollbacks and basically to verify that like nothing horrible has happened and take backups and things like that. So okay, so there's a lot of different things you can do. There are packages out there to do straight up just take a backup, take a snapshot. I think 10 up actually has a package that does exactly that. Beyond that, there is a verify checksums check that is built into WPCLI for core. I know they've been working on it for plugins and themes as well. And that will check the hash checksum locally versus what is on like the wp.org servers. So that can be like something like I've set that up to run like nightly across all my sites where it'll make sure like nothing's been hacked basically. So you can do stuff like that. Yeah, did that answer your question? Yeah, so there's a couple of things with that. I would, if you're looking for like a cheap and easy backup system, I would wrap some of the commands just like with a shell script and point like a server cron at it. And like that's like a two cent backup solution basically for you. Also I've seen some good stuff. There's on my resources page there's this WPBulletGuides. They actually have a really cool example of checking to make sure a plugin update is not going to fatal your site and reverting it. And basically what it does is it's a shell script that runs through all of your active plugins or plugins that need an update and it will store the old version of the plugin. It runs the update. It checks to make sure that there's no 500s on the site. And if there is, it will revert the update for you, which is pretty cool. It's actually like a very simple shell script too. It's like 20 lines long, which is pretty cool. If you go to that Guides WPBullet, it's in that category like on the first or second page. Any other questions? What's up? Multi-site, media regenerate. So multi-site gets a tiny bit hairy. There are guides on developer docs that show you how to interact with multi-site and how to run through every site in a multi-site. Basically there's a WP site command. So the first thing you do is you basically query that, you get all the sites back and then you loop through it and inside of that, you can run your command. Yep, and then you just pass it right in. So it's actually pretty cool and it works for like everything. So like once you create the script, you can just like call the thing and pass it. Yeah, it's, yeah, yeah, it gets super powerful. Yeah. Well, I think that's all we have time for today. Thank you so much for staying. I really appreciate it. Thanks everyone for coming. Look forward to seeing you all tomorrow. Registration starts at 9 a.m. I believe the first session is 10 a.m. And if you're looking for anything to do here in the downtown area, there is a local guide on the website. Check that out. Thank you.