July 20, 2016

Today’s sponsor is Network Solutions. If you are looking for a managed hosting platform with an emphasis on security, consider their product, Secure WordPress. Your plugins will stay updated and you won’t have to worry about malware. Even better, their tech support is available 24/7, so your questions won’t have to go unanswered. You can learn more at getnetsol.com/applyfilters.


This week, we’re hearing from Pippin and Brad about what they’ve been up to, and both will talk about one of their respective blog posts that have gone up recently.

Pippin’s Update

Pippin’s main update is that Restricted Content Pro 2.6 went live. It was a smooth release, and it has a few great new features. First, they rebuilt the user interface and how content restriction is set up. There is new metadata and APIs, and they’ve replaced PDF invoices with HTML to help save space during downloads. Finally, they’re using Drip Content, a new add-on that will eliminate the problem of people signing up for one month of the program, downloading all of the content, then cancelling.

Brad’s Update

Brad has recently released the version of 1.6.1 Migrate DB Pro. Most of the differences are bug fixes. It’s now WordPress 4.6 compatible. They’ve launched automatic renewals. Perhaps one of the most important fixes is that the version number is now in the name of the file to make it more usable with JavaScript.

Other topics that are discussed include:

  • Pippin explains his post, “The Monster That Is a Poor Database Schema.”
  • He talks about the importance of an abstraction layer.
  • Brad explains his post, “Hey, WordPress Developers, Your Clients Should Own Their Plug-In Licenses.”
  • He discusses the pitfalls of developers using their own licenses for plugins on client sites.

Links and Resources:

If you’re enjoying the show we sure would appreciate a Review in iTunes. Thanks!

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 65. This time Pippin and I will be talking about what we’ve been up to and we’ll be covering some of the articles we’ve recently written and kind of going into detail on some of those topics. But first–

I registered my first ever domain name in 1999, 17 years ago. Back then there was one place to register domain names, a company called Network Solutions. Many of you probably already know this, but did you know that Network Solutions also has a WordPress hosting platform? They do.

It’s called Secure WordPress. It’s a managed WordPress hosting platform with an emphasis on security. They automatically keep WordPress core and your themes and plugins up to date. They have daily backups. They provide malware scanning and removal. And they put your site behind a data center class firewall to protect against zero day hacks and DDoS attacks.

They have expert tech support available 24/7 via chat and phone. Network Solutions takes care of keeping your site locked down and up to date, so you can focus on your business. Visit GetNetSol.com/ApplyFilters today to get started. And now back to the show.

Okay, Pippin. What have you been up to, man?

PIPPIN: Well, once again, kind of like just about every other week, we’ve got a couple of plugin updates that went out. This week was in the Restrict Content Pro land. We pushed out Restrict Content Pro 2.6, which I believe I had mentioned we had released the beta in the last episode, and so that update went live a few days ago. So far it’s been a pretty smooth release.

We have pushed a couple of very, very minor point releases since then just to fix a couple of small issues. This is one of the big updates that we’ve been working on for about four or five months now, and we’re pretty excited to get it out. It doesn’t have a ton of new user facing features, but it has a lot of improvements behind the scenes that, in the long run, will make a very significant difference.

A couple of the main things that we did is we rebuilt the user interface for how content restriction settings are setup on posts and pages. Let’s say that you write a tutorial or you write a blog post, and you want to restrict that to paid subscribers, there’s an interface on the edit screen for the posts on how you do that. It’s always been a little bit of a confusing interface. It’s never been super smooth, and some of that is just because, as the plugin developed over time, we added new features to it. We added new ways to restrict content. We just kind of piled them on.

Anyway, we decided to look at that interface, throw it all away, and rebuild it from scratch with we thought was a new, much better interface. Which, in the long run, will hopefully do two things, primarily. Number one, it will reduce friction for new users and make it more intuitive for them to set up the plugin for the first time. As most people are familiar with, the first impression that somebody has of a product, of a person, of a thing has a very long-lasting impact on their long-term opinion of it. And so with this being one of the very first parts of the plugin that users interact with, we felt it was very, very important that we give it some more attention.

BRAD: You’ve redone the UI. What does the process look like? How do you guys iterate? Does someone do mockups, or do you just start right away with code? How does it work?

PIPPIN: There’s a few different ways we would do it, and there’s no set in stone or standard way. In this particular case, my team member, John, and I. John is the primary team member that works on Restrict Content Pro. He actually flew into Kansas a few weeks ago, and we spent a week working together onsite. One of our goals was to come up with this new UI while we were both in the same place.

BRAD: Whoa! You were in person, so what did you do? Used a chalkboard or you went old school?

PIPPIN: No, we did it a little bit differently. He used it on his computer. I used it on mine, and I put together a quick proposal, actually just coding up an HTML mockup and said, “Hey, John. Take a look. What do you think?” Then he had some suggestions, made some tweaks, and then repeat that through out the day.

Then once we had kind of put together what we felt was a decent UI, we then sent that off to some of our other team members who are not even necessarily involved with Restrict Content Pro but are familiar with it, and so they were kind of our test users, our test case to say, “What do you think of this UI? Does this make sense to you?”

Okay. Now we sent it to somebody else who was very familiar with the old UI and said, “Now does this make sense? Is this an improvement?” We spent about three or four weeks doing that.

Hopefully, in the long run, it will turn out to be a positive. We think it will. The second goal is that if you make users happier, you give them a better experience from the get go. Not only are they more likely to be long-term customers, they’re also going to open less support tickets.

One of the number one support tickets that we would get prior to the 2.6 release, a customer would come to us and say, “This content that I’ve restricted is still accessible to non-subscribers. What’s going on?” In almost every instance it was due to the restriction settings being configured incorrectly. We decided the fact that this happens all the time, it is not user error. It’s a product error, and we need to fix that. That was part of the goal as well.

A couple other things that we added to it is just some polishing, things like making the whole admin area fully responsive, adding a few additional features to some of the payment gateways, for example like Stripe checkout, which is the modal window that Stripe offers. It has some really nice integrations with Bitcoin and a couple other payment processors like bank transfers and Alipay – Alipay being the number one payment processor in China. We added support for those or, specifically, we added support for Alipay and then some other refinements.

Then there were also some improvements behind the scenes, three primarily. One being we added metadata to subscription levels and payment records, which is something that we’ve needed for a long time, primarily at the subscription level because let’s say, for example, Affiliate WP has an integration with Restrict Content Pro. One of the things that site owners want to do a lot of the time is to set up custom commission rates on different subscription levels.

You can say anybody that an affiliate refers to the gold level gets 20%. Anybody that you refer to the silver level, you get a 10% commission, et cetera. Prior to 2.6, we didn’t have any good way for other plugins to store metadata on subscription levels, so you had to kind of figure out your own way to do it. Store them in the WP options table or come up with something else. And so we’ve introduced metadata of APIs for those two, which will make it a lot easier for us to introduce new add-ons in the future.

BRAD: I’m curious how Restrict Content Pro integrates with Easy Digital Downloads because it looks like Restrict Content Pro is pretty much an e-commerce system kind of on its own, right?

PIPPIN: Yes and no. It’s kind of funny, and this happened entirely by accident, but we get that question a lot in both RCP and EDD support. Usually it’s people coming and asking, “Hey, how do they integrate?” because the natural assumption is that they are directly integrated with each other because they come from the same company.

The truth of the matter is that they’re actually completely independent platforms that just happen to be built by the same team now. They were both built to serve different purposes, and those purposes have slowly kind of moved together to overlap a little bit.

There are some very distinct differences, like for example Restrict Content Pro, you would never sell products through it. You might sell access to one product, but probably not multiple products. One of those reasons is that members are limited to one subscription. You don’t have five subscriptions through Restrict Content Pro as a customer. You have one. What you sell needs to be within those confines.

BRAD: Right. I was kind of thinking like it might make sense to share payment gateway stuff, like the Stripe library or whatever, the Stripe add-on. There’s got to be quite a bit of overlap in that.

PIPPIN: There definitely is.

BRAD: Yeah.

PIPPIN: There’s feature overlap. There’s library overlap. There’s lots of overlap that there can be. Right now we’ve chosen to keep them almost completely separate because they are distinct platforms and neither one of them requires the other, and we want to keep it that way.

What we’re working to do is to make it a little bit more seamless. And so if a site is running both of them, there’s shared interfaces. There’s some shared features, et cetera. But that’s a slow process. Right now it’s pretty minimal.

BRAD: Right. Makes sense.

PIPPIN: My favorite feature in 2.6 is not really a feature, but is a change. We used to have PDF invoices, so if a customer had a payment record, they could download a PDF invoice for that. We ripped it out – or sort of. We replaced it with an HTML invoice. Have you ever looked at the size of PDF libraries?

BRAD: They’re large.

PIPPIN: Monstrous. One of the problems that we used to have a lot was somebody would buy Restrict Content Pro, and then they’d try to upload it to their site. They’d get an error that says the file size is too big because, on tons of shared hosting, your maximum file size is one, two, three, or four megabytes. Because of the PDF libraries, the Restrict Content Pro file size unarchived was 12 megabytes. Once we removed the PDF libraries, now it’s like 1.5 or less, and it’s just because those PDF libraries are so enormous. And so we said we’re moving away from the PDF libraries. We’ll move to HTML versions only, and we’ll dramatically reduce our footprint.

BRAD: Right.

PIPPIN: We’re very excited to have that finally done.

BRAD: You’ve got a logo in the invoice that people can add, I’m assuming?


BRAD: Yeah. If people upload just a regular GIF, PNG or whatever, those are generally 72 dots per inch when printed, so there should be like a hint there that they either have to upload a much larger size and then you can resize it to be smaller so that when it prints it comes out clear and crisp. That’s something I ran into, I think–

PIPPIN: That’s an excellent point.

BRAD: Yeah.

PIPPIN: Something I had not considered.

BRAD: Yeah. Yeah, I think I ran into that when I was billed ten years ago or something when I was building the invoices for the Web hosting company that I was running at that time. Yeah. Yeah, if you just print a regular image off a Web page, it comes out fuzzy because the dots per inch is very low for Web.

PIPPIN: Makes sense.

BRAD: Yeah.

PIPPIN: The last thing that we’ve been doing was also related to RCP, and that was a new add-on, a new professional add-on that’s available to the professional and ultimate license holders for dripped content. One of our number one feature requests ever since 1.0 has been the ability to have dripped content. And so, as of Tuesday, that is now available and we’re pretty excited for it.

BRAD: What is dripped content exactly?

PIPPIN: Sure. All right, so let’s say that you have a membership website, and somebody subscribes to your paid plan. They now get access to all of your content. Well, that usually works fine for most sites.

BRAD: It’s a little overwhelming though.

PIPPIN: Yeah. It can be overwhelming because suddenly you just have this massive library of content, assuming it’s a large site. But there are also some disadvantages to it.

Let’s take my brother’s website for example. CGCookie.com is a large membership website. When you buy a subscription, you get access to a whole bunch of courses. You get access to file downloads and things like that.

A perpetual problem that CGCookie and every other large membership website faces are customers that come in, buy an account, download all the resources, copy all the courses, and cancel their account. Then they’ve paid whatever the monthly fee is or the yearly fee and kept all of that content and then possibility redistribute it. One of the ways that you get around this is dripped content.

Dripped content is the idea that instead of getting immediate access to everything, you get access to stuff on a schedule. Let’s say that you could set it up on a category basis, and so you could have your categories first month, second month, third month, fourth month, et cetera. You subscribe to an account and, in the first month, you get access to this category of content. Once you get into your second month, you get access to this content. Then on the third month, you get access to this content. It’s a way to delay the access to the content based on when a customer registers. It automatically fixes that problem of somebody subscribing, downloading everything, and canceling.

It does another thing, and it fixes the problem, the overwhelming problem that you just mentioned at first. Let’s say that you sell access to music lessons. Okay. If you are a beginner guitar player, you want to start at the basics. Then you might go to intermediate. Then you might go to advanced. That’s not going to happen in one day. That’s not going to happen in a week. It might happen in a couple of months. More likely it’s going to be a year or so.

And so, you could set it up so that the drip content basically follows a flow of when you should be working through these courses. You could say these are weekly courses. You should work through one lesson per week. And so, once you subscribe, you get access to your first lesson. Next week, you get access to your second less. You get your third lesson, your fourth lesson as time progresses. It’s just a natural progression through the courses.

BRAD: I like that.

PIPPIN: It’d be another good use case for drip content.

BRAD: Another thing that might be neat is if people could mark a lesson as completed and then the next one would be sent to them. You know what I mean?

PIPPIN: That would be cool.

BRAD: Or unlocked or whatever because I find, even with drip emails, you see these all over the Internet now. You submit your email address, and then they start sending you emails every day. Oftentimes you don’t have time to read them, so they just kind of stack up in your inbox. Then it just becomes overwhelming, and you’re just like, “Screw this. I’m not reading these,” because it’s just like this huge, daunting task. Whereas, if after I’ve finished reading the email I could click a button and it would queue and maybe send the next one to my email address or something, for me that would be better, anyway. It wouldn’t be so overwhelming.

I think that is a feature in Drip. I think you can pull that off with their new features.

PIPPIN: In GetDrip?

BRAD: GetDrip.com, yeah. Drip, the app, I guess. Anyways.

PIPPIN: We’re pretty excited to have both of those things done. They are two of the overall project of slowly rebuilding Restrict Content Pro into a full, premier, membership plugin, and we’re making progress. We’ve got a few more coming in the next couple of weeks, so I’m sure the next episode I’ll have something else for you that’s RCP related.

How about you? What have you guys been working on over there at Delicious Brains?

BRAD: Well, we just released version 1.6.1 of Migrate DB Pro, so just a minor release, but there are quite a few improvements in there, in addition to bug fixes. We’ve done some adjustments so that it works with WordPress 4.6, which is, I think, beta 3 right now. Specifically around Shiny Updates, the new, in place updates system.

PIPPIN: Did you have to make changes so that your add-on updates or your pro version…?

BRAD: I think it’s the pro version. I’m not actually even sure. I just read the change log.

PIPPIN: Hey. Look. It’s awesome when you’re running a company and then you realize that, like, you used to write every line of code that goes out. Then you used to review every line of code. At a certain point you don’t have to. And, at a certain point you can’t. That’s great.

BRAD: Yeah. At a certain point you’re just reading the change logs like everyone else.

PIPPIN: “What’s new, Brad?”
“I don’t know. I’ll have to read the change log.” Love it.

BRAD: Yeah. We did do this strange little thing. I figure I should explain it. You’ll notice. Well, you may not notice, but our JavaScript files have version numbers in the name of the file now. The version number is the version of the plugin.

The reason for that is that some people, their JavaScript was not updating when they would update the plugin. Usually the way that cache is busted is that WordPress adds a query string to the end of the JavaScript URL. For some reason, for some platforms, that wasn’t actually busting the cache.

We said, “Let’s take this a step further and change the file names every time we build a new version of the product.” Hopefully that will. I can’t imagine that’s not going to fix the problem, but who knows. Have you guys ever run into that issue?

PIPPIN: All the time.

BRAD: Yeah.

PIPPIN: The query string that it appends to try to bust the cache works in some environments. Okay. Let’s be fair. It works in most environments.

BRAD: Most. Yep.

PIPPIN: But there are definitely some where it doesn’t work. And so, like in our recent, in the RCP 2.6 release and also in the EDD 2.6 release, we added tool tips. We’ve had several reports from people saying, “Uh, your tool tips are broken,” and it’s because the CSS file had not refreshed even though our CSS file has the EDD version number appended to it, meaning that it should have busted the cache, but it simply didn’t. And so then they had to go in and bust the caches to get the new CSS to show up.

BRAD: Right.

PIPPIN: Yes, we see it all the time.

BRAD: If I was to guess what the problem was, I think, if I remember right, Varnish, by default, ignores query strings when it does its caching. I could be wrong about that, but I’m pretty sure that was the case.

PIPPIN: Okay. Here’s a question for you then. If you’re changing the version number on the files, that means the actual file name itself is changing.

BRAD: Yep.

PIPPIN: Are you doing anything to remove the old versions?

BRAD: Well, they should be removed. Like when WordPress updates the plugin, it should blow away the entire directory and then replace it with whatever is unzipped, right?

PIPPIN: I don’t believe that’s true. I believe it does a merged.

BRAD: What?! Really?

PIPPIN: I’m pretty sure it does a merge.

BRAD: This is all news to me.

PIPPIN: We can check. Hey, if anybody knows, ping us on Twitter.

BRAD: Yeah. Yeah.

PIPPIN: I’m pretty sure it does. The reason being that we used to have, so EDD has moved files around quite a few times in our “Includes” folders. I remember a couple of distinct cases where, like for example, we renamed one of our payment gateways. I would log into a customer’s site who had updated from the old version to the new version, and they had both versions of the file in there, the old version and the new one.

BRAD: Yeah, but they might have been doing something crazy.

PIPPIN: No, this is something that we would see a lot.

BRAD: That’s weird, man, because I’m almost certain that it blows them away because, for our site, for DeliciousBrains.com, we still manage the plugins in Git. So when I need to update a plugin, I update it locally, commit it, and then push. When I do that, I see a bunch of deleted files.

PIPPIN: Okay. Well, you could be absolutely right.

BRAD: I’m almost certain. Anyways, we’ll look into that.

PIPPIN: I’d like to know for sure.

BRAD: Yeah. Anyway.

PIPPIN: I know it definitely used to be a merge. It may not be one any more.

BRAD: Yeah. Yeah, I could see that causing some problems, especially if there are security issues with a certain file.

PIPPIN: Right. Well, and the other thing that made me think about this is, let’s say, if they’re using a CDN. Is their CDN bandwidth being taken up by those old files? Obviously they’re tiny files, but it’s more the principle.

BRAD: Yeah. The CDN could very well continue to serve the files. If you updated the plugin, you’d still have to blow away your CDN cache.

PIPPIN: Yeah. Right.

BRAD: That’s very likely that the CDN would still serve the old files indefinitely until you actually purged it, assuming you have a time to live that’s super long, which you should if you’re using a CDN.

What else? We’ve launched automatic renewals.

PIPPIN: How is that going so far?

BRAD: Pretty good. We’ve got, the last time I checked it was like 65 people have opted in, I think.

PIPPIN: You guys launched it, I assume, all new purchases are automatic renewals?

BRAD: All. All new purchases. Then just recently, a couple days ago, I’ve launched email, so 90 days before your license is to expire, I send an email that says something to the effect of consider enabling automatic renewals and then you don’t have to worry about missing out on your discount.

PIPPIN: I just logged into my Delicious Brains account, and I see a really big, nice green notice at the top that says, “To enable auto renewals for your license, add a credit or debit, debit card or PayPal account.” Very nice.

BRAD: There you go. Yep. That’s part of our user experience flow. When you click through that email, you will automatically get logged into My Account. If you’re not logged in, it’ll just log you in. Then you’ll see that. You’ll see that right at the top – bright, bright green. Hopefully that’ll help people sign up just so that they don’t miss out on getting that discount because the way it works for us is that we offer 30% off until your expiree date. Then it drops to 20% off your renewal after that date.

We’ve had quite a few people just say, “Oh, I forgot. I totally missed it,” and they only get the 20%.

PIPPIN: Well, I just went ahead and completed the auto renewal process, and that was very smooth. I like it.

BRAD: Awesome. Yeah.

PIPPIN: I like the option that you guys have of turning them on or off. It’s very nice.

BRAD: Yes. Yes, and then you get to select. You can add as many payment types as you want: PayPal or Stripe or credit card, I guess. Yeah, we’re pretty happy with it. It took quite a bit of effort.

PIPPIN: Right, because that’s all custom built, right?

BRAD: Yeah. It’s pretty much all custom. It is all custom built. Yeah.

PIPPIN: The beauty of it being custom built is that you can make that flow really, really nice. As you know, being a product creator, there are always certain limitations that a product will have when you have to try to cater to a wider audience.

BRAD: Yes. Exactly.

PIPPIN: And so the fact that you guys can build this custom makes it so you can build a very smooth, nice system. I like it a lot.

BRAD: Yeah, yeah, yeah. Exactly. That is the big advantage of not releasing this as a product.

PIPPIN: At the same time, if anything breaks, guess who has to fix it.

BRAD: Yeah, exactly. On that note, for example, our Stripe add-on for WooCommerce and our PayPal Express add-on for WooCommerce are a bit out of date because, to update those, so the code is heavily dependent on those add-ons. And so to update those add-ons, they’ve changed a bunch of things, so we have to change our custom code as well. It’s a hassle. That’s what we’ve signed up for. Every time these dependencies update and change a bunch of stuff, then it creates a bunch more work for us. That’s the downside, but I knew that going in.

Anyways, should we move on? You wrote a blog post titled The Monster That is a Poor Database Schema or Thoughts on Resolving Poor Database Schema Designs.


BRAD: What was it about?

PIPPIN: Well, the main premise is a poor database schema. Let’s say that you build a product, and you don’t think about your schema very well, either because you just don’t do it or because you don’t have the experience yet to tell you why you should have thought about the schema carefully. The point is that once you have a poor database schema for a product, especially if it is a larger product and you have a whole lot of data in it, resolving problems that stem from those poor early decisions can be very, very challenging, especially if you want to try and do it in a very smooth, frictionless way.

For example, Easy Digital Downloads has a couple of things that we really, really hate in the database schema. Those are there because the plugin was originally built, number one, four years ago, and I knew significantly less then than I do now. Two, it was built to be a much simpler, much more minimal product than it is today. When originally building it, I had no plans for it to be what it is today, and so there were decisions made, or perhaps decisions not made, even, in the very, very early days of EDD that have now had long-term consequences.

And so, basically, if you have a poor database schema, it can be a monster that is always standing at your back. It’s always kind of creeping in and leaving its effects somewhere or other. If you’re trying to introduce a new feature, you want to build more efficient queries, you want to improve performance, whatever you want to do, if you have a database schema that is poorly structured or has certain aspects to it that are not great, they can be difficult to get around.

BRAD: What are some examples of this in EDD right now?

PIPPIN: Sure. The main example is the fact that purchase records are stored as a post type in wp_posts.

BRAD: Mm-hmm.

PIPPIN: It’s asinine that that’s where they’re at.

BRAD: What kind of problems has that caused recently?

PIPPIN: Sure. The biggest problem that storing payment records in the post table creates–and I guarantee you this happens to WooCommerce, this happens to EDD, and happens to anybody else who has decided to store payment records there if they have achieved any kind of scale–and that is scaling. Scaling is brutal, primarily when it comes to trying to do reporting.

Storing data in the post table is fine. You can store millions and millions and millions of rows, and most of the time WordPress would be okay as long as the host is okay. We know this for a fact. We know that WordPress.com, as an extreme example, has millions and millions and millions of rows in the post table, and that’s fine. We know lots of sites that have millions of rows in the post table and that’s fine.

It’s not the amount of data that is inherently a problem. It is the way that you want to interact with that data. It is the kind of queries that you want to run on that data.

Payment records, for example, we want to be able to do queries to say, “Okay, what are the earnings for the last months? What are the earnings for this time period? How many sales has this customer made? How many sales of this product are there? How many sales are refunded? What was the average refund rate in this time period?” You want to be able to do queries like that.

The post table does not support those very well at all with the primary reason being that a lot of that extra data that you need to store, let’s say that is the purchase total, maybe the customer associated or the product that was purchased or all of these other pieces of information are stored in post meta. The moment that you want to start querying those, you have to start doing joins across the posts and the post meta table. A few joins are usually not a problem. But when you start getting into really complex queries, you’re looking at five, ten, who knows how many inner-joins on post and post meta, and it makes things extremely inefficient.

BRAD: Yep. Even if you did have an optimal database schema, if you’re a high traffic site or you’re a site like let’s say Amazon, you have records, like order records at that scale, like massive number. Maybe that’s an extreme example, but let’s say you’re a pretty good sized e-commerce store. You’re probably not even going to run reports in production. You’re probably going to have a slave database and have a reporting tool hooked up to that and be running.

PIPPIN: Mm-hmm, or you’re pulling data out when records are created so that you can put them into a reports system.

BRAD: Yeah. Yeah, something like that. That’s because you don’t want to affect the performance. Reporting is taxing anyways, right? But like what you’re describing just makes it even worse. It’s a multiplier.

PIPPIN: Mm-hmm.

BRAD: Yeah.

PIPPIN: The blog post just kind of acknowledges that once you have a poor database schema, it’s going to cause you problems. Then we went and looked at a few different angles of it. One is, okay, why did this happen? One of the answers is it’s quick and easy in the beginning.

When you’re just starting out a project, sometimes you have no idea where that project is going to go, and so you just throw something together that works. Oh, and then you get a new feature, and so you build that on. Then you build that on. Sometimes things progress a little too quickly before you take the time to really plan out how you want to build it. It’s one of the reasons why things like this happen.

Then I went and looked at a few other things like, okay, how do you actually resolve this kind of problem? Let me ask you this. What would happen if tomorrow we just said, “We’re going to rewrite EDD, and we are going to put it inside of a custom table. We’re going to rebuild the entire database schema, and we’re going to launch it tomorrow”? We’ll just pretend that there’s a magical upgrade routine that moves everything to the new schema. What’s going to happen?

BRAD: Everything is going to break, probably.

PIPPIN: Right. Well, one of the main reasons being that EDD, just like many of the other e-commerce plugins, has been built as a platform that other people build on top of. And so we have this database schema inside of the plugin that we use internally and that our add-ons use. We could build a new schema, and we could update all of our plugins to use that new schema without a problem.

The problem comes in is that we don’t know how many of those 50,000 active websites have custom code running on them. We don’t know how many other plugins are built by other people that are interacting with our database schema. We have no idea how many people’s code we’re going to break if we change that schema. That’s where the real problem comes in. That’s why you can’t escape a bad database schema easily. There are ways to get around it, but it has to be a slow process. That’s where kind of the final point comes in, and that’s about building an abstraction layer.

Okay, since we’re using the wp_post and the post meta table, that means that we have helper functions provided by WordPress: get_post_meta, wp_post, and a few other ones for pulling data in and out of the posts and post meta table. Those are great because they’re super easy to use. They also mean that let’s say that you write an EDD plugin and you want to retrieve a little piece of metadata, and so you just call get_post_meta. Guess what happens when we move that data and it’s not in post meta any more. Your call breaks. And so the idea of an abstraction layer is that even if you depend on originally WordPress helper functions, you should make sure that you have your own classes and helper functions that wrap all of those so that you can change the internal storage of the data without affecting how that data is retrieved.

BRAD: Right. Instead of get_post_meta, you would call get_download_meta or get_product_meta.

PIPPIN: Right.

BRAD: I guess you would have to prefix it with EDD_ too.

PIPPIN: Yeah. For example, we have payment records, and they’re stored in a post type of EDD payment. You can use the wp_post class, or you could use get_post_meta to retrieve any of that metadata, but we don’t want you to do that. We don’t want anybody to do that. Instead, we want you to use our EDD payment class that has all of these different helper methods in it for getting the various pieces of metadata. That way if you’re using EDD payment, we can change where the data lives behind the scenes and you’ll never know. That’s the way that you have to resolve a poor database schema is, first, you have to have that abstraction layer in place. Once you have the abstraction layer in place, then you can start moving away and moving to a better schema.

BRAD: This is really great advice for anyone who is, early on, building a WordPress product or just thinking about it because now is the time to do this.

PIPPIN: Don’t wait until later.

BRAD: Yeah. It’s more work, but it’s a lot easier now than it will be later to change it. You’re changing; you’re adding this abstraction layer to EDD now, but you’re going to have to wait a while.

PIPPIN: Oh, yeah. We’re going to have to wait a year or more before we can really actually change anything. EDD payment, for example, was introduced in–shoot, I don’t even know what version it was introduced–2.5, I think. I think it was two major versions ago. We’re only just now really seeing some add-on developers update their plugins with it. Honestly, that’s even after we’ve blogged about, we’ve reached out to a bunch of developers and said, “Please use this. Please update to it,” because the next thing that we want to do is move payment records to a custom table. We cannot move payment records to a custom table until we’ve got the majority of people updated to use the new abstraction layer.

BRAD: Right. Have you ever thought of writing some kind of scanner or something that people could run to try to find uses of things that you’re deprecating before the update?

PIPPIN: I don’t think we would run it as a scanner for customers to do, mostly because I just don’t think that’s something that should be their responsibility. Our goal, if we do it right, is that every user and every customer will be able to update seamlessly without it ever being a problem.

I think what we would do instead is we would get a copy of every single EDD plugin that we’re aware of, and then we will grep it and we’ll find instances of get_post_meta and things like that. Then we’ll reach out to all the authors and say, “Hey. Here’s how you get an update. Here are the guides on using the new abstraction layers. Please do it. Here is the timeframe. We want to make this as smooth as possible.”

BRAD: Sure. That makes sense. I guess I was more referring to custome code.

PIPPIN: Well, right.

BRAD: That’s why I was saying if you could trigger a background process that would just scan their custom code, like their theme, their active theme code and the plugins that they have active that you don’t recognize.

PIPPIN: I gotcha.

BRAD: Just scan those for any hooks into your stuff and anything that’s deprecated. Then it could just show up as a little notice that says, “Hey. We’ve noticed you’ve got some code here that’s probably not going to work.”

PIPPIN: We’ve identified a potential problem.

BRAD: Yeah. Yeah.

PIPPIN: Yeah, that’s definitely a possibility.

BRAD: It’s a lot of work.

PIPPIN: I saw Jonathan Christopher at SearchWP does that very well.

BRAD: Yes. Yeah, that’s right. I just thought of it because I just saw WP Engine has a PHP7 scanner. Someone told me that Migrate DB Pro is tripping up. Than scanner is throwing–

PIPPIN: We have a bug report for EDD too.

BRAD: Yeah, but here’s the thing. All of the ones for Migrate are false positives. We’ve already checked them because we’re actually searching because we do support other versions of PHP, so we do need to check certain things in those other versions. For example, safe mode. We don’t support.

PIPPIN: That’s exactly what tripped ours up.

BRAD: Yep. If you do an ini_get_safe_mode, then it’ll trip that up.

PIPPIN: But it does. But it still works. It’s not an actual issue, right?

BRAD: Yeah.

PIPPIN: It’s a false positive.

BRAD: Yeah. It’s weird that that trips it up. That’s not a critical issue.

PIPPIN: Well, what I think it is, is it’s not looking at that full conditional, so I would assume you’re doing something like if ini_get_safe_mode or if not ini_get_safe_mode, you can then set the time out or a couple of other options like that. Instead, what they’re looking at is they’re just seeing there’s an instance of get_safe_mode being called. That’s wrong. Basically.

BRAD: Yeah. Yeah, exactly. It’s kind of a dumb scanner, but their tool says that there are false positives. You will get false positives.

PIPPIN: Hey. No tool is perfect.

BRAD: No. Exactly.


BRAD: Yeah, except maybe — I’m sure there are some out there.

PIPPIN: Somebody has written a perfect tool, and it probably does one thing and one thing only.

BRAD: Yeah, hello world.

PIPPIN: Anyway, so that’s my blog post on database schema. If you do anything with databases, go give it a read. Let me know what you think. We’ll have a link in the show notes.

I believe you wrote a blog post that got a whole lot of traction recently, and it’s something that I’ve been super adamant about. That is that WordPress developers — I’ll just read the title instead. Hey, WordPress Developers. Your Clients Should Own Their Plugin Licenses. Give us a rundown.

BRAD: Yep, they should. End of story. I wash my hands of it.

PIPPIN: Enough said.

BRAD: No, so what I’ve found is that a developer will be working on a client site, and they’ll use their developer license. They’ll just plug in their license key. Once the site is delivered to the customer, they walk away, and then decide to become a surf instructor and stop developing. They let all their licenses lapse, and then the client can’t update their plugins, so they leave their plugins kind of out of date. Then a security — they get hacked. Their site gets hacked because of a security vulnerability in the plugin that’s been fixed a year ago.

I think that’s my concern with developers using their licenses for clients is that the clients don’t know about the license. They think it’s included with the site. They just don’t know. That’s kind of my beef with it. What are your thoughts?

PIPPIN: Well, first, I ran into this issue firsthand, oh, I think two years ago, maybe. It was the first time that I ever encountered it, and it was basically that same scenario where we had a customer.

BRAD: Someone became a surf instructor?

PIPPIN: I don’t know if they did that, but there was a developer. They bought a bunch of licenses, and then they used those on a client site or on a series of sites. Then that client came to us later asking questions and looking for support. Not a problem. We’re happy to support them, but we find out that all the license keys are expired or she doesn’t have them or he doesn’t have them. They can’t get a hold of the developer any more because they’ve gone AWOL.

We basically have to say, “I’m sorry. There’s not anything we can do unless we have a valid license from you. Unfortunately, the only way for us to look it up is to either know the website it’s being used on, know the customer email address associated with it, or know the actual license keys. If you don’t have any of those, like, too bad.”

Several times it’s resulted in the client having to go and purchase a new license key for themselves because the one that they had is expired and belongs to a different developer that they can’t get in touch with. There are a whole bunch of different variations of how that can play out, but it’s a very real problem.

I actually have an open support ticket right now with the exact same problem. The customer does not know their license key. They don’t know the email address that it was purchased with, and their developer is AWOL, but they would like help with an issue.

Unfortunately, we have to do our own. As a product owner, we have to do our due diligence and be very firm about, “We can’t help you if you don’t have a license key because scaling is a problem.” And so, until we can confirm a license, we can’t really assist. In order to confirm a license, we need to know that information. They would not be in that situation if they had either bought their own license or the developer had transferred it to them.

BRAD: Right. Yeah. I do want to make it clear that I don’t feel like WP Migrate DB Pro really fits into this category because it’s a tool. It’s a developer tool. If a developer walked away, the customer could just delete WP Migrate DB Pro and their site would work fine. It’s really for plugins that are integrated into the functionality of the site itself that if they deleted the plugin, the site would probably break or whatever. I think, for any kind of utility plugin that can be deleted, maybe this isn’t that important.

PIPPIN: It’s definitely going to apply in certain cases, but it’s not as prominent.

BRAD: Yeah. Exactly. I’ve considered following Flywheel’s example, which is that they allow you to create a link for your clients so that that’ll bring them to the site and just give them a payment form and just fill in their payment information, and kind of all the rest is taken care of, like picking the license and filling in any other details that need to be filled in. That’s done for them. I really like that idea that developers could just give their clients a link to fill in their billing details.

PIPPIN: I love that.

BRAD: It’s been on our to-do list for a long time, but we would love to do that eventually.

PIPPIN: It’s a really cool feature that kudos to anybody who can build that for their product or their service. But it is one of those that will almost always be a nice to have. Simply being that there’s almost always higher priorities than something like that because it doesn’t affect every customer. It affects 1 in 100 or 1 in 1,000. But the unfortunate thing is that when it affects a customer, it affects them really greatly.

BRAD: Yeah, exactly. Like you were saying, it’s not really fair to the plugin author either, right? It puts us in a hard spot when people come to us for help and they have no idea why we won’t help them.

PIPPIN: Unfortunately, they’re a victim of the circumstances. It’s not their fault.

BRAD: Exactly. I hate to tell those people, “Well, you’ve got to buy a license.” It sucks. Yeah, do it for us too.

PIPPIN: Yes, please.

BRAD: Should we wrap it up?

PIPPIN: Yeah, let’s do it.

BRAD: Cool.

PIPPIN: I think we’re getting close to an hour, so you guys don’t want to listen to us that long.

BRAD: Yeah, that’s right. All right, well, I guess we’ll talk to you guys next time. Thanks for listening.

PIPPIN: Yeah, thanks for listening. You can check out all of the links to all of the blog posts in the show notes.