January 6, 2015

In episode 33 we discuss upgrade routines in plugins and what’s new in WordPress 4.1. This episode was recorded on December 19th as part of WordSesh, marking the first time we’ve done a video episode. If you’d like to watch and listen, head over to YouTube.

This episode was sponsored by WP Ninjas, the creators of Ninja Demo and the highly popular Ninja Forms plugin.

logo-nd-h-color

Show Notes:

Transcript
INTRO: Welcome to Apply Filters, the podcast all about WordPress development. Now here’s your hosts, Pippin Williamson and Brad Touesnard.

BRAD: Welcome to Episode 33 of Apply Filters. Today is a special WordSesh episode, and we’re going to be talking about upgrade routines and plugins and what’s new in WordPress 4.1. But first, Pippin, how about the sponsors?

PIPPIN: Once again, this episode is sponsored by the WP Ninjas. They are the developers behind Ninja Forms, as well as Ninja Demo and several other pretty cool little plugins. They’re some good friends of ours, and they’ve been very generous in helping us keep this thing going.

This is also the first time we’ve ever done a video episode, so this is a little different for us, but it should be fun. Why don’t we go ahead and get started? Brad, take us away. What have you been working on?

BRAD: Last Friday, we had a Core Contributor Day with Delicious Brains, Inc., my company. All the employees just spend the whole day working on Core, WordPress Core. It was just pretty fun just to kind of work on Core.

PIPPIN: That’s for the five for five, right?

BRAD: Yeah, well, that’s kind of what pushed me over the edge, for sure. I’d been thinking about it before Matt put up that thing, but that kind of pushed me over the edge.

PIPPIN: You guys spent the time working on Core. As a team, what did you guys work on for the day? Did you find anything interesting?

BRAD: Yeah, so one of the bugs I found was an interesting little bug. It was just a little performance bug, so the problem is with comments. When you list comments on the page, if there’s any metadata that you’re displaying, like comment metadata, it’ll do a select query for that comment meta for every comment. If there are 100 comments on the page, it’ll do a select query for each one of those. This is a bug that someone suggested be implemented four years ago.

PIPPIN: Oh, yeah. It looks like it came from … been around for a while.

BRAD: Yeah, it’s been around, so I kind of dug into it. It took a while to get my head around it. I probably, I don’t know, spent like over an hour trying to figure out what I needed to bring together, the best way to bring it together and make it happen. If you look — we’ll link up the bug in the show notes and the patch that I….

PIPPIN: I’m going to drop it into the chat too for anybody who wants it.

BRAD: Yeah, yeah, do that. It’s super small, and it’s really brief. It’s one screen.

PIPPIN: It’s funny. I was reading through that issue to … and as I was reading it, I was thinking this is a pretty large problem. I saw your patch, and it’s tiny. It’s so small; it’s awesome.

BRAD: I know. No one has reviewed it yet, so I hope it’s right.

PIPPIN: Yeah, we’ll see.

BRAD: But I’ve tested it, and it seems to work great. It cuts all those queries down to one query.

PIPPIN: That’s really cool.

BRAD: Instead of 100 queries, you get one query.

PIPPIN: That’s going to be a major improvement for anything that, if anybody is using plugins that add a lot of comment meta.

BRAD: Yeah.

PIPPIN: Or review plugins, for example. In Core, by default, there’s really very little metadata stored in comments.

BRAD: Right. Yeah, yeah, exactly.

PIPPIN: …it probably doesn’t affect people unless they have that.

BRAD: To test it, I had to actually make adjustments to the default themes because they don’t display any comment meta, right?

PIPPIN: Right.

BRAD: I had to actually add some in there to test.

PIPPIN: That’s pretty cool. I hope we’ll see some more progress there once a Core dev gets to review it.

BRAD: Yeah. What about, have you considered dedicating a day to Core?

PIPPIN: I’ve been meaning to. It’s been on my to-do list for about two years. I tend to go through phases where, one month, I’ll spend two or … or reviewing patches or trying to do some testing of patches, submitting. I try to do a lot with unit test. In the last couple months, I haven’t done hardly anything, but every now and then I get into a nice zone and get some done. I’m hoping to get back into it soon.

BRAD: It’s interesting to do it as a company because then you’re kind of on the hook, right? Everyone knows that it’s that day of that month and everything.

PIPPIN: Right.

BRAD: Everyone is kind of accountable to each other to make sure it happens.

PIPPIN: I’ve been wanting to also get our support team involved and get into the .org support forms.

BRAD: Oh, yeah.

PIPPIN: Especially after major releases.

BRAD: Is there a big need for that right now?

PIPPIN: There’s always going to be a need.

BRAD: Yeah.

PIPPIN: Especially any time there’s a major release, no matter how solid a release it is. When we’re talking about millions and millions of sites, there are going to be people with problems. There are going to be people with questions. And so every additional volunteer in the forms helps, right?

BRAD: Yeah.

PIPPIN: Is there always going to be a need? Yeah, probably.

BRAD: Cool, man. What have you been working on?

PIPPIN: The last couple of weeks, mostly this week has been focused on a new version of my Restrict Content Pro plugin, which is a membership plugin. It’s one of the three main plugins that I work on, but it’s probably the smallest of the three, which would be EDD and Affiliate WP. Anyway, they’re working on some big changes to it that have been really eating at me for a while that I’ve wanted to work on, and that is how the member data is stored in the database and also … payment integrations work with Stripe, with PayPal, et cetera. And so I’m doing a whole bunch of new changes. It’s actually great because it’s going to lead into the main subject for this episode, which is upgrade routines in plugins.

One of the changes that I’m making in this is, for the last … years that this plugin has been around, all of the information related to members, which would be things like the subscription level they’re subscribed to, their status, whether they’re active, they’re cancelled, they’re failed, et cetera, their expiration date. All of these different things are all stored in user meta. Well, on a small scale, that works just fine. But when you get into really, really large sites, it can start to cause problems.

I have a site that I actually work on quite frequently that has around 500,000 users in the database. Storing that much user meta can have problems. It’s more difficult when you start trying to query that information.

One of the changes that I’m getting ready to make and that I’m working on is actually moving all of that member data to a custom table in the database … structure in the exact way that I want with the proper schema, make things a lot more efficient. I should be able to make the plugin probably five or ten times more efficient than it is right now, and so this last week is kind of where I’ve been starting on those changes. The fun part of that is that I then get to write an upgrade routine that goes and migrates every single user in the database to that new schema, which could be 20 users, or it could be 500,000.

BRAD: Right.

PIPPIN: Lots of fun.

BRAD: Right, so are you going to tackle that? I know last week we discussed the upgrade routine that I implemented or we implemented in our Amazon plugin. Is that similar to what you have planned for this?

PIPPIN: Yeah, it’ll be pretty similar, at least based on what I remember from the upgrade routine that you did. The basic idea for what I’m going to do is actually two parts. One part of the upgrade is simply maintaining backwards compatibility for the old schema.

If someone tries to call “get user meta,” and maybe they’re trying to get the status or the … perhaps they built a custom plugin or they’ve done something and they call “get user meta,” I’m going to implement all the necessary hooks to maintain backwards compatibility so that when they pull that information, it still works even though that data no longer exists in the user meta table. That’s step one.

Then step two is actually moving the data from user meta to the custom table. That will simply be a batch processing script that will go through and do 50 or 100 users at a time. We’ll be able to continue going forever until all the users are done.

BRAD: Right. That’s just going to run on a cron in the background.

PIPPIN: To be honest, it’s probably going to run at the time you install the upgrade. I could actually do it either way. I could do it on a cron because, if the backwards compatibility is there, I can probably do it in a way that it actually doesn’t matter which table the information exists in.

But because cron is notoriously unreliable, in WordPress at least, the WordPress cron API, I think I want to do it all at once. That way, if something goes wrong, the person running the site knows that there’s an upgrade routine running and that if something dies, they can say, “Hey. The upgrade routine died,” as opposed to they were using their site and, randomly, all their user information is gone.

BRAD: Yeah. This is a pretty important migration, right?

PIPPIN: Oh, yeah.

BRAD: If this goes wrong, there’s trouble, right?

PIPPIN: Yeah.

BRAD: What if something does go wrong? Do you have fallback scenarios? What happens if halfway through it forks?

PIPPIN: My plan is to make it so that if it fails — let’s say it’s going through and it’s going to migrate 100,000 users, and it fails at 20,000; 20,000 that have been migrated and 80,000 that are still there. My goal is to just put in a blocker that says, “Hey, we failed for some reason. Use the old database until we can get the new one moved over.” No data will be deleted until we know that we know that we have the new database is complete because that way at least you can revert.

BRAD: Yep. Yep. That’s how Migrate DB Pro works, right? When it does the migration, it copies the tables separately with a different prefix. Then if all is good at the end, then it renames them in one quick operation.

PIPPIN: Right.

BRAD: Sorry. It drops all the existing ones and then renames the ones with the prefix, so if anything goes wrong halfway through, then you just end up with some tables that you can easily delete in your database.

PIPPIN: Right. Having a little leftover data at the end is a heck of a lot better than having missing data.

BRAD: Yeah. Oh, yeah, for sure.

PIPPIN: Yeah, so that’s going to be fun. That’s been this whole week and will be for a while. It’s kind of a slow process for me because it’s not my primary focus.

BRAD: Right.

PIPPIN: It’s what I decide to do when I’m tired of working on other things and I want to spend two hours on something else.

BRAD: Right. Interesting.

PIPPIN: Brad, you’ve done this, and I’ve done this. But for people that have never done this, how do you start this kind of upgrade routine? How would you go about it?

BRAD: Yeah. Good question. I think it really depends. You mean, how do you start the process? How do you start the upgrade?

PIPPIN: Yeah. Just for an example, you can’t just say, “Okay, here’s one big SQL query. Go modify 100,000 rows in the database,” because it will fail.

BRAD: Right.

PIPPIN: How do you lay that process out? How do you keep it going? How do you make sure it can run for 5 hours or 20 hours or 2 minutes?

BRAD: Yeah. There are a lot of considerations there. The first thing to decide on, I think, is whether it should automatically start, the migration should automatically start because, do you want your code to have to — do you want to have to write or have code that works with the existing data? Right? If that’s the case, then you’d have two sets of code: one that works with the old data and one that works with the new data. Then you’re waiting for them to upgrade to the new data schema. Then you can use the new code. That’s pretty complicated, right? Usually you just get them to upgrade the data right off the bat, automatically.

PIPPIN: Once you get the upgrade started, how do you actually go through processing that upgrade? You’re going to do it in a batch.

BRAD: Yes.

PIPPIN: You have to. Let’s say you have 100,000 records. You’re going to do 100 at a time, so what is that? Ten thousand steps, something like that.

BRAD: Yeah.

PIPPIN: How do you go through those steps to ensure that you don’t have a timeout?

BRAD: Yeah.

PIPPIN: What would you do?

BRAD: What we do is I know that most Web requests will work for around 30 seconds, but we err on the side of caution, and we say 10 seconds. What we do is we set a timer. Then we run it. Then, after ten seconds, we stop it. Then we do another batch after that.

Basically, it depends on how fast your server is running, your database, and all those things … how much gets processed in a batch. That’s the way we chose to do it. You can certainly do it other ways. You could just pick an arbitrary number, but that’s a little less safe, right?

PIPPIN: I actually really liked what you say about the timer because that’s actually the issue that I ran into. In all the ones that I’ve done, I do it on a certain number.

BRAD: Right.

PIPPIN: I say I’m going to do 100 users at a time. That works really well for most people, but occasionally you get into situations where a server can only do 50 or can only do 20, for a variety of reasons. But that timer, I like that idea.

BRAD: Well, the most common reason, if you want the technical server sys admin crap, it’s that if you have a PHP-FPM, with Nginx usually, the set time limit function in PHP, that doesn’t mean anything to PHP-FPM. It doesn’t obey that. PHP-FPM has its own timeout setting that’s in a config file on the server somewhere and it obeys that. That’s whatever your Web host has set it to. Like I said, it’s typically around 30 seconds. If it exceeds that, you get those gateway timeout errors that I’m sure everyone has seen.

PIPPIN: Super awesome.

BRAD: Yeah, and so that’s why I usually go with the timer now because we learned the hard way that doing a fixed number is….

PIPPIN: You also have to be careful with things like set timeout because they’re not always enabled on all shared hosts, which is kind of a problem.

BRAD: Right. I don’t know why they would disable that.

PIPPIN: I know it fails in safe mode, which is super obnoxious.

BRAD: Right. Safe mode is silly though, isn’t it?

PIPPIN: It is silly. It is silly. It’s … deprecated in PHP 5.5.

BRAD: Right.

PIPPIN: Something like that.

BRAD: Yeah, I think that’s right.

PIPPIN: They … which makes me really happy.

BRAD: I’m pretty sure we support it in Migrate DB Pro, but you get a warning that says things may not work out here.

PIPPIN: Nice. I just posted a link into the chat for anybody who wants to see it, and so this is actually a really cool script that Thomas Griffin released a few days ago for doing batch upgrades. It’s basically the same process no matter what kind of batch upgrade you’re doing. It’s the same kind of logic. There are a few little nuances here and there that change, but basically it’s the same thing where you’re going through and doing it in batches. That’s what I’m getting ready to do for Restrict Content Pro is I’m going to set up a batch processing script that will go through and move all of this customer data over.

We also just did this for Easy Digital Downloads a couple months ago when we released version 2.1. We introduced a brand new customer table where we moved all of our customer records from user meta to a custom table in the database, and we had to go through and migrate every single customer record. It worked really well. We had a really small number of failures, at least that we were aware of.

This script, the one that Thomas Griffin wrote, is very similar to what we did in EDD and what I’m going to do in…. It uses … combination of PHP and JavaScript. Basically each batch is triggered by ajax and by JavaScript, so it fires off an ajax request. That triggers a batch.

Then the batch returns … which triggers the ajax to say, “Okay, we’re done. Let’s do it again,” and it just keeps looping and looping and looping. You don’t have to worry about redirect timeouts because, if you get a lot of servers, if you try to redirect, say, five or ten times, it will say, “Oh, you’re going back and forth to the same page again, and I’m done. I quit.”

BRAD: Yeah.

PIPPIN: That helps avoid that.

BRAD: That’s how Migrate DB Pro works, actually. It uses ajax and just does one request, gets some kind of value back to start the next batch to know where to leave off the next batch. We’ve tested that solution quite a bit, and it’s worked quite well, so I think it’s the way to go.

PIPPIN: You can also do it — the way I did it first in Easy Digital Downloads was a little bit differently where, when you’re processing with ajax, which is the same way that Thomas Griffin does, the same way that WP Migrate DB Pro does, you actually load the page. It has…. It’s constantly showing you a progress bar, and so it sends a request. It returns a response from that request, updates the status, et cetera.

But I did one a little bit differently that also worked pretty well where it actually does reload the page over and over and over again. But what happens is you first go to the upgrades page, which then has a small JavaScript snippet on it. That JavaScript snippet triggers a redirect via the jQuery, a jQuery redirect, which goes to some action in PHP Defier. That PHP redirects back to the upgrade screen, which is essentially a success page. Then the JavaScript on that page ends up triggering the redirect again.

You have essentially created a redirect loop that’s not actually looping. It doesn’t trigger the redirect loop error. But that also works.

BRAD: One thing we have noticed, yeah, we’ve noticed a little bit lately is some servers are protecting against brute force attacks, like making a bunch of requests one after the other. If your ajax requests finish quickly and start, and fire the next one quickly, sometimes the server will ban you.

PIPPIN: Oh, awesome!

BRAD: You do have to be careful of that. We’re actually thinking of adding a delay, basically slow down your migration setting, so that if that’s a problem that you’re having, you can actually add a delay between each ajax request. It’s just something to watch out for.

PIPPIN: That’s pretty awesome.

BRAD: It’s pretty uncommon. We’ve only got a few reports of it in the last six months or so.

PIPPIN: It’s one of those edge cases that’s kind of entertaining when you run into. I’m sure that was a harder one to track down.

BRAD: Yeah, yeah. Yeah. I don’t even remember what the heck we did.

PIPPIN: Cool. We’ve got about 25 minutes left, so let’s go ahead and jump into WordPress 4.1. We’re going to look at some of the developer changes in 4.1. If anybody has questions about upgrade routines in the database, feel free to post them in the chat. Ping us on Twitter. Post comments to anywhere you can find us. We’re happy to answer them.

BRAD: Sure. I haven’t done my homework at all on WordPress 4.1.

PIPPIN: Surely you’ve installed it already.

BRAD: I have. I’ve tested the surface, the toys. I’ve played with the distraction-free editing or distraction-free writing stuff.

PIPPIN: I will say that is really nice.

BRAD: It is super cool, right? It just makes so much more sense that it just works. You don’t have to hit a button to go to another screen and then exit out of that screen. It just kind of happens.

PIPPIN: Yeah. It’s super slick. If you haven’t checked that out, go take a look at it. It’s one of the main features in the WordPress 4.1 release post on…. David Bisset, on Twitter, said something pretty funny about it. He said the new distraction-free writing is so great in 4.1. Basically, my family hasn’t seen me in 24 hours because I’ve just been writing.

BRAD: Nice.

PIPPIN: It’s pretty sweet.

BRAD: Yeah.

PIPPIN: There are a few developer-oriented changes in 4.1 that are really cool. There’s a couple of minor ones and then some that make me really, really happy. The first one is the new title tags. Have you seen that, Brad?

BRAD: I have not. What’s that about?

PIPPIN: This one, I really like it simply because I feel like this is probably something that should have been there a long time ago because it would have saved a lot of headache in theme development, so I’m really glad that we finally have it. Basically, the title tags, which is the title that displays in your browser, is now an officially supported function in WordPress, so there’s an actual function that just outputs those title tags, sets up the title tags, et cetera.

If you have ever done theme development or you’ve ever looked into themes, you are probably aware that there are thousands of different ways that themes have come up with adding the title tag to their header.php files. There are so many different ways. Some work really, really well. Some don’t. There’s an official title…. And if you want to support it in your theme, it’s done through the theme support API, so you simply say add_theme_support title tag.

BRAD: Okay. Let me think. I’ve always used just WordPress SEO to manage my titles, so I’ve always had the standard, whatever it is, WP_title, or whatever.

PIPPIN: Right.

BRAD: The usual one that I put in there. That’s always just worked with WordPress SEO plugin.

PIPPIN: Right, which is does.

BRAD: How does this help me?’

PIPPIN: The big thing is that this is also — I hope I get this right. To be honest, I haven’t dug into the source enough to know for sure on this one. They’ve introduced a number of functions along with it for archive titles, for example, that will display the title for taxonomy archives, for post type archives, for tag archives, et cetera. What it’s going to end up doing is it’s going to create much more consistent titles in themes.

BRAD: Right.

PIPPIN: Instead of each theme coming up with their own way, like if you’ve ever seen — a lot of themes will do this. I know my current theme does. It has a function that hooks into, I think WP Title is the filter, and it goes through all these conditionals. It says if it is tag, do a title like this. If it’s a post type, do a title like this. If it is taxonomy, do this, do this, do this. This is going to help get rid of all of that fluff.

BRAD: Okay, okay, gotcha.

PIPPIN: Along with those, they’ve also introduced new template functions for, like, post navigation, which is get the post navigation, the post navigation, and post plural, which will be awesome for official pagination, which will be nice because pagination is another thing that’s been done in so many different ways in tons of different themes, plugins, et cetera. This is just going to create a little bit more consistency for it.

BRAD: Yeah, it sounds all right.

PIPPIN: It’s going to be sweet.

BRAD: Yeah.

PIPPIN: Yeah.

BRAD: What’s next? Complex queries, yeah, this looks pretty cool.

PIPPIN: Yeah, this is awesome. I’m going to post a link to this in the chat for anybody who wants to read up on it. This is a major shout out to Boone Georges because he is a madman that has done amazing things. First of all, this is amazing.

BRAD: And that’s coming from Pippin. I mean —

PIPPIN: Hey, I can’t even tough this stuff. This stuff is nuts. In 4.1, Boone introduced, I think, 250-plus new unit tests, which is awesome, specifically around queries. But there are three major changes to queries that are pretty awesome, or three different types of queries that are changing. We have WP Day Queries … WP Meta Query. All of these are the main query classes that can be used for querying complex data from the database.

If you want to find a list of posts that have a particular piece of post meta, you can use that. If you want to find posts that are within a particular date range or match a specific date or after a specific date, you’re using a date query, even if you don’t realize it. If you want to query posts that are related to a specific taxonomy in a post category, in a post tag, and in some custom taxonomy that you’ve registered, then you’re using a tax query.

What these have all supported for a while, the ability to say have I … and/or statements. Let’s say … related to geo location, so we’re going to store a city. We’re going to store a zip code. And we’re going to store a state. For one particular post, you might say the city is Miami and the state if Florida. Then in another one you have the city is Augusta and the state is — I have no idea where Augusta is. I think there’s an Augusta, Florida.

Anyway, you have … and so, for a long time, you’ve been able to say, “Okay, give me all posts that are in Florida or are in Kansas.” Or you could change it so you can say, “Give me all posts that are in Florida and have a city of this.” So you could have and/or statements.

Now what you can do is you can have nested statements. You can say, “I want all posts that have a city of Miami and a state of Ohio, and all posts that have a city of Augusta and a state of Maine.” What you can do is now you can have basically a big “or” statement, so it matches this one or this one. Then, inside of each one of those, you can have an “and” statement. You can say, “This city and this state. This city and this state.” And so anything that matches this bubble or this … and so you can do that with meta queries, tax queries, and day queries.

BRAD: Yeah. Just check out the link in the show notes or in the chat because there’s a little snippet of code here, and it’s super clear that it’s —

PIPPIN: It’s a lot easier to read than it is to explain.

BRAD: Definitely. Yeah, it takes about three seconds to realize this is cool. You can nest these relationships. That’s pretty cool. Yeah.

PIPPIN: Apparently I’m having some problems with my video freezing, so … who is seeing that.

BRAD: Eh, what are you going to do?

PIPPIN: Oh, well. What can I do? Then there was one other big change to complex queries that’s pretty cool, which is related to WP Comment Query. Comments have had a technically support for custom comment types for a long time, so you could have a ping back comment, a track back comment, or a standard, just blog post, comment. It used to be a little tricky if you wanted to say, “Query them by a specific type.” Now it’s a lot simpler to do that, so there’s a lot better support for custom comment types.

Then there are also some additional parameters that they’ve added that allow you to say, “I want all comments except for those that are in this list of IDs,” or “I want all comments that match this list of post IDs.” Let’s say you have 50 posts, and you need to go get all of the comments related to those posts. You can easily do that now.

BRAD: That’s pretty cool.

PIPPIN: Pretty sweet. Definitely a nice change.

BRAD: I wonder if you’re going to start to see people using comments and comment meta more for other things that satisfy that data structure. I’ve seen a few examples. I know WooCommerce uses them for order notes.

PIPPIN: They use them for order notes, and I believe they also use them for product reviews.

BRAD: Oh, I didn’t know.

PIPPIN: I may be wrong on the product reviews.

BRAD: Yeah. Do you use guys use them in EDD?

PIPPIN: We do. We use them for payment notes, and we have an extension that does it for product reviews.

BRAD: Cool. How has that worked out? Are there issues with it?

PIPPIN: Well, yeah. There are some pain points, which is one of the reasons why these changes to comment query make me really, really happy. For example, right now let’s say you register a custom comment type, which you don’t actually register it. You just include it into the arguments when you store it into the database. But if you do that, it’s automatically going to be displayed along with other comments. If you have a recent comments widget in your sidebar or on your dashboard, those comment types are going to be included.

Oh, Mike Jolley in the chat did just say product reviews are comments.

BRAD: There you go. Confirmed.

PIPPIN: Yes. If you have these notes that you’re storing on order data in the comments, those might contain more private information, maybe things like transaction IDs or maybe private notes left by a store admin or something like that. You really don’t want them to be publicly available, especially think about RSS feeds. You definitely don’t want them showing up in RSS feeds for comments or, with the new json API coming, you don’t want them to be publicly available there.

If you want to exclude those, right now you have to do some kind of nasty stuff. You have to alter some database queries and say, “Don’t touch these ones if we have a payment note, an EDD payment, or anything like that.”

BRAD: Oh, right. You’re probably hooking into the posts_where filter and those ones.

PIPPIN: Yeah. We do post_where, comments_where.

BRAD: Yikes!

PIPPIN: I think there are three that you have to do if you want to exclude them from all defaults, which is kind of annoying.

BRAD: Yeah.

PIPPIN: In 4.1, there’s better support for just excluding those by default. I’m not sure if this actually went in or not, but this was proposed in a ticket that Core should only display default types, so it will only ever display comments, ping backs, and track backs. If you have a custom comment type, it’ll just be hidden by default unless a plugin enables it.

BRAD: Cool.

PIPPIN: I don’t remember if that actually got in or not, but it was definitely proposed.

BRAD: The next feature in 4.1 is log out everywhere. I don’t really know what that is, but let me guess. You log out of WordPress, it logs you out of every account that you’re logged into on the Internet. Is that?

PIPPIN: No. It’s not.

BRAD: That might be….

PIPPIN: That one is totally different. That might be a problem. This is kind of cool, and I’m going to see if I can actually pull this up real quick and do it local. If I can, if I can replicate this real quick, I might share my screen. I’m going to fail though. Okay, I’ll just tell you what it is.

What it is is the ability to — it’s like session management. When you are logged into your user account on a site, that’s your session on that site. Let’s say that you then leave that computer. You go to your laptop, and you log in again. You now have two different sessions logged into that site.

Now, what you can do is it will actually tell you if you’re logged in somewhere else, and you can say, “Kill all other sessions. That belonged to me.” It’s just a little button on your profile page, if you go to your profile in the WordPress admin, and you’re logged in somewhere else. It will say, “Log out other sessions.”

Oh, you know what? Actually, I think it shows at all times, so I can click it, and it just let’s me do it, which is pretty cool. It logs you out everywhere else.

BRAD: This is a new UI change, right?

PIPPIN: Yeah, it’s a new UI change.

BRAD: Okay.

PIPPIN: Here’s an example of where it’s really cool, where it’s great. Let’s say you go to a coffee shop, and you use a public computer.

BRAD: Yeah.

PIPPIN: You leave yourself logged in, and you forget about it. Then you realize, two hours later, crap! I was logged into my site, and I don’t want someone to do that, so you simply log in again. You go there, and you click “log out,” and you’ll be logged out on the other computer. That’s pretty cool.

BRAD: Yeah, it’s a nice feature, for sure. I noticed. This must have been an incremental improvement in 4.0 too because we’ve noticed, with Migrate DB Pro, now when someone migrates the user meta table, it logs them out if they’re logged in on the other side.

PIPPIN: Yeah, it was a new class they implemented called WP Sessions, I think.

BRAD: Yep. There’s new data that they put into the user meta table that has some information where, if you remove that record in that table, it’ll log you out everywhere. I think that you could have done this previously by editing the database.

PIPPIN: There was no UI for it.

BRAD: There was just no UI for it, I think.

PIPPIN: Right, so the API that powers it was in 4.0, I believe, and now the UI is in 4.1.

BRAD: Yeah, so pretty cool.

PIPPIN: What else is new here?

BRAD: You’ve got to tell me about plugin recommendations. It sounds really cool.

PIPPIN: Oh, yeah.

BRAD: Have you looked into it?

PIPPIN: I have a little bit. I followed the track ticket on it, so it’s pretty cool. What it does, now WordPress.org is constantly aggregating data and keeping track of what plugins are frequently used together. If you have plugins on your site, and you then go to add a new plugin, it’s actually going to look at those plugins and say, okay, these are the other plugins that people use with the plugins that you have installed, frequently.

Where this gets really cool — allow for this to pop up just because I’m not sure how long the data has been aggregating, but let’s say that you’re using an e-commerce plugin, whether it’s EDD or WooCommerce or Jigoshop or anything like that, and there’s free extensions to that plugin in the repository. You go to click “add new” and go to search, and you’ll be able to go find extensions a lot more easily that are directly related to that Core plugin because they’re frequently installed together, which would be kind of cool.

BRAD: Right.

PIPPIN: I haven’t played with it enough to kind of see how good the recommendations are. I have it open right now.

BRAD: Probably, I’m going to guess, it’s not Amazon quality yet. That would be pretty impressive though.

PIPPIN: Probably not, but okay, so here’s a quick shout out that it worked well, apparently. “I have Affiliate WP installed,” which is my affiliate plugin.

BRAD: Yep.

PIPPIN: “And I go to recommendations, and two of the free WP add-ons that are in the repository show up.”

BRAD: Nice.

PIPPIN: There we go.

BRAD: Pretty cool. Do you have any idea how they’re doing it on the backend?

PIPPIN: I don’t. I haven’t seen the API for it.

BRAD: A mystery black box.

PIPPIN: Yeah, I don’t know if, when you install the plugin, if it sends a query that says, “Hey, here’s all the plugins I have.” But I’m sure that you could dig into the Core installation API and figure it out.

BRAD: Yeah.

PIPPIN: Let’s see.

BRAD: What else?

PIPPIN: There are a couple of other things that are new in 4.1 that are pretty nifty.

BRAD: Yeah.

PIPPIN: Customizer API.

BRAD: Customizer API, yeah. I tend to ignore these things because they’re theme related. I don’t do a lot of work with themes, so I was just like, eh.

PIPPIN: I like to pay attention … and I don’t usually play with them as much. But the Customizer API does have a cool feature in it now that allows you conditionally show or hide sections and panels based upon the page that you’re previewing. Let’s say that you have settings in the Customizer for your theme. Now this can apply to plugins as well, so this is pretty cool because you can build settings pages for your plugins.

BRAD: Oh, interesting.

PIPPIN: I haven’t really done, but I’ve seen people that have done it really well. But let’s say that you are previewing the homepage in the Customizer. Then you have settings that only apply to the homepage, so you can show those settings in Customizer. Then you navigate over and show a static page somewhere else or something else, some other page on your site where those settings related to the homepage really don’t apply any more, and so you can hide them by default. The API now supports that, so it’ll create really a lot better settings panels for the Customizer that are much easier to navigate for the user because they’re only seeing stuff that actually applies to them right there.

BRAD: Cool.

PIPPIN: Instead … screen, you have a live version of what applies to what you’re seeing right now, which can be very cool.

BRAD: Oh, that is neat. I think I’ll have to take a closer look at that now that I know it applies to plugins.

PIPPIN: Definitely. I’ve been wanting to build a setting screen in a plugin for it just to do it. I haven’t really had a reason to yet because I haven’t had a plugin that needs it, but I would like to.

BRAD: Yeah. Then, of course, 2015 has been released with 4.1 as well.

PIPPIN: I like 2015 a lot. It is a pretty, pretty theme. There is one thing that I kind of like and dislike at the same time about it. First of all, the theme itself is beautiful. It requires WordPress 4.1. It … because of the new template tag functions that they’ve introduced.

BRAD: Oh.

PIPPIN: One great thing about that is that it’s taking that movement, encouraging people to upgrade and helping be the–don’t know–model to say, “Hey, let’s do it this way,” which is great.

BRAD: Yeah.

PIPPIN: I don’t know if I would prefer that they had done some backwards compatibility so that someone on 4.0 could still use it. I don’t know. In some ways that’s almost making a concession and saying, “Okay, well, whatever.”

BRAD: “Come on, man. It’s 2015. Get with the program.” That’s what they’re saying, right?

PIPPIN: I do. 2015 is a vertical theme, so all the menus and stuff are now on the left or the right side. There is no top menu, and it’s a nice layout. It’s really clean.

BRAD: Yeah, I like it. You know one thing I found? When I was doing the Core dev, I was using 2015 to work on that comment, the comment performance bug. I was using Query Monitor, right?

PIPPIN: Yeah.

BRAD: Query monitor spits out a panel that shows all the queries and how long they take to run and all that stuff. I was using that, and you know the bar, the fixed panel on the left in this theme?

PIPPIN: Yeah.

BRAD: Yeah, it overlays it.

PIPPIN: Ah! It works too well.

BRAD: I had to switch to 2014.

PIPPIN: Isn’t Query Monitor written by John Blackbourne?

BRAD: It is, ironically.

PIPPIN: I imagine that will probably get fixed up pretty soon then.

BRAD: Yeah.

PIPPIN: John Blackbourne, for anybody who doesn’t know, was the lead for WordPress 4.1.

BRAD: Yeah, that is a sweet plugin though, man. That’s really the first time that….

PIPPIN: I use that plugin all the time.

BRAD: Yeah.

PIPPIN: It’s been amazing for me.

BRAD: Yeah.

PIPPIN: One of the reasons I like 2015 so much is because it’s the closest to 2012, and 2012 is my favorite theme that’s ever been released for a standard theme because it’s so clean. It’s so easy. It’s a perfect development theme for plugins because it doesn’t have a lot of styles. There’s no flashiness to it. It’s just great for doing development. 2015 is the same way.

BRAD: Oh, well, I think —

PIPPIN: And 2013 —

BRAD: I think we’re about close to out of time here, Pippin.

PIPPIN: We’re getting super close.

BRAD: Yeah.

PIPPIN: Yeah. 2013 … so far. Yeah, so we’re pretty much out of time. Anybody, we’re listening; where are these questions? I’ve got to find them.

BRAD: Oh, in this chat, in the chat notes?

PIPPIN: Yeah. Brad just gave us a note that says we’ve got a couple of questions in the chat room. I’ve got to find them.

BRAD: Oh, no! It’s like it’s a heap or a stack.

PIPPIN: There we go. Oh, nope. Okay, well, if anybody has a question, go ahead and post it right now in the chat room, and we will see what we can do to answer it. We have five minutes left.

Questions – there we go. See if we’ve got anything. Query Monitor is … and if you’re a developer and you’re not using Query Monitor. Question: Do you keep upgrade routines in Core forever … them forever?

BRAD: That’s a good question.

PIPPIN: Leave it in forever. My favorite. One of my favorite features in WordPress Core is that you can install version one-point-something and it will upgrade to 4.1 flawlessly.

BRAD: Right. Yeah. I don’t know. I think I’d have — yeah, I don’t know. Part of me wants to get it out of there at some point just for the OCD part of me, right?

PIPPIN: I think it’s the same question of do you deprecate. If you deprecate a function, do you eventually remove that function completely?

BRAD: Yeah.

PIPPIN: Yeah, so there are good arguments for both.

BRAD: Yeah. I think upgrade routines can probably stay in forever.

PIPPIN: Yeah, I would usually keep them in. Brad, why don’t you answer this one? “In this context, using ajax for an upgrade routine would be great, except it would break in WP-CLI.” Ooh.

BRAD: Ah, yes. Good point.

PIPPIN: Any upgrade routine would break in CLI if it does redirects.

BRAD: Well, if you code it right, and you abstract your code enough, and separate the ajax from the functions that are handling things, you can still use the CLI. The CLI can still fire off remote requests to an ajax endpoint.

PIPPIN: Ah, true.

BRAD: That’s what we do for Migrate DB Pro. We have the CLI add-on, and that’s what it does.

PIPPIN: I’ll have to look for your code for that because, I’ll be honest, off the top of my head, I can’t even think of how to do that.

BRAD: Well, see, the thing about our CLI add-on, it’s our first version, so don’t expect too much. We definitely need to — we kind of shoehorned it in there, and we could definitely clean that up, so keep that in mind.

PIPPIN: Where did you get your glasses?

BRAD: Oh, MSNBC.

PIPPIN: Nice!

BRAD: No, Warby Parker, if that’s a serious question.

PIPPIN: That answer actually doesn’t mean anything to me. I have no idea what that is.

BRAD: WarbyParker.com, you can order glasses, and you can order a bunch, try them on, and then send them back for free.

PIPPIN: That’s cool.

BRAD: Yeah. They’ll send you the frames without the lenses, and you try them on. See if they work for you, and then send them back

PIPPIN: Oh, nice. Okay, I have heard of services like that. I just haven’t heard hat one.

BRAD: Yeah. It’s pretty cool, man. The, not optometrist, but the people that fit the people for glasses, optician, they hate Warby Parker because it’s killing their job, man.

PIPPIN: I bet.

BRAD: Yeah.

PIPPIN: There are a couple other questions left in the chat, but we are out of time. If you would like to get your question answered, feel free. I might stick around in the chat for a little bit. I’ve got another session coming up here in a couple of hours for the plugin roundtable. You can also ping us on Twitter. Brad, how do they find you?

BRAD: @BradT on Twitter. And you?

PIPPIN: @PippinsPlugins. Everybody, thanks for chiming in.

BRAD: Thanks, everybody.

PIPPIN: Enjoy the rest of WordSesh.