Tag Archives: WordPress

Git, WordPress plugins, and a bit of sanity: Scatter

A few months ago I made a tool called Scatter to help automate deploys and keep them separated from code. This weekend I completely rewrote it in Ruby (from Python) and added some new features (install it with gem install scatter_deploy). One of those new features is shared deploy scripts, which turns out to be a really handy way to deploy WordPress plugins from Git to WordPress.org. I made a 5 minute screencast that shows the process of deploying and updating a WordPress.org plugin without ever touching SVN.

First, a bit of background. WordPress.org’s plugin system uses Subversion. I use Git for all of my projects. While there are a bunch of ways to communicate between the two systems, they’ve all been varying degrees of annoying for me. For a while I was using this workflow from Boone Gorges based on git-svn. It had some big problems though — it’s slow, and it causes huge problems when you try to do things in Git that SVN doesn’t understand (like use submodules). As a result, even Boone doesn’t actually use that Workflow anymore. I also considered this workflow from Daniel Bachhuber, which basically handles the problem by creating two repos in the same “place”. That felt very manual and error-prone though.

When I added support for shared deploy scripts in Scatter, I decided to use that to automate this whole plugin process. I started with Ben Balter’s plugin deploy script and made a few small changes to (1) add some safety checks and (2) build in assumptions that fit Scatter’s process. The result is that I can now run scatter -s wp from anywhere inside a WordPress plugin Git repository, and have everything just work. You can see some more details in the Scatter Deploy Examples readme.

This is not the only thing that Scatter does — it’s a more general deploy tool — but it’s one of the use cases that I think is pretty cool.

The Challenge for WordPress Plugin Businesses

A few days ago Pippin Williamson wrote a post about the WordPress plugins business. It’s worth reading, but I’ll paraphrase its main ideas:

  • WordPress plugins are getting more powerful and sophisticated
  • Plugin-based businesses are growing
  • Requirements that used to fall to custom themes are now being solved more granularly with plugins

I agree with these ideas in general. Plugins are certainly getting more powerful and mature. The best examples of this are the plugins-as-platforms that are becoming significantly more popular, like BuddyPress and Pippin’s own Easy Digital Downloads.

At the end of his post, Pippin makes a prediction:

If you are on the edge about entering the world of commercial plugin development, now is the time.

Here’s where I disagree. We got to talking about it on Twitter earlier and I decided that I’d rather take a few extra characters to explain my opinion.

@ I don’t think WP consumers are sophisticated enough yet to support plugins businesses on the scale of theme businesses
Evan Solomon

First, I’ll start with a premise. The WordPress theme market is a success. It has high end agencies like 10up and Range, consumer-facing marketplaces like ThemeForest, developer ecosystems like Genesis, and great tools like _s. The commercial WordPress theme market is large and growing.

Conversely, the commercial WordPress plugin market is significantly smaller and I think will face a much more difficult path to success.

Themes have a natural source of demand because the easiest thing to understand about a website is the way it looks, which is the primary thing a theme controls. Most technical products have consumers that are much less knowledgable about the products than the creators, and often the creators that win are the ones that market the products in a way that matches the consumers’ understanding of it — even when that understanding is drastically flawed. Themes fit this model perfectly because of the natural tendency to express what you want in your website primarily by its interface.

Plugins tend to be much more abstract. I think understanding a plugin often requires understanding how it works in addition to what it does. The reason is that plugins are a lot less standardized and are naturally suited to do a lot more things, so basic descriptions of what they do are likely to cause more confusion than they solve. In addition to doing a wider variety of things, plugins also tend to do them in a relatively granular way. While you can only have one theme, you can have countless plugins and plugins can interact with (and even require) each other. Again, to make sense of that you need a deeper understanding of the system than just a list of features — you need to be able to make sense of how that interaction works.

In short, plugins are complicated, and complicated things have a smaller market for natural demand, even if they’re ultimately a better solution for customers.

That brings us to customers. WordPress’ greatest strength and source of growth is its usefulness to non-technical people. It can be hard to remember, but in the not-too-distant past it was nearly impossible for a non-technical person to make their own website. While I think it’s still probably not an awesome idea for a lot of people to do it, it’s now incredibly easy and a lot of that is due to the WordPress ecosystem. Despite this being one of WordPress’ greatest strengths, it’s also one of its biggest problems because it creates a market full of people who often don’t really understand what they’re doing. This lack of understanding has actually been a real value to the commercial theme market because its resulted in themes being the hammer to an “every WordPress problem is a nail” syndrome. Themes are often chosen irresponsibly and forced to solve ill-suited problems — see every theme that bundles 15 image sliders and 25 shortcodes. When presented a WordPress requirement, it’s incredibly common for the solution to start with a trip to a “premium theme” website, almost regardless of whether a theme is a logical way to solve the problem.

There are obvious reasons this benefits theme businesses. Similarly, there are obvious reasons this hinders plugin businesses. Here are the assumptions I’m making:

  1. WordPress theme businesses are, in aggregate, a success
  2. Theme business success has been significantly driven by customers’ overfitting WordPress demands to theme solutions
  3. Plugins require sophisticated customers that can think about problems granularly and understand multi-part solutions
  4. The conditions that drive #2 also hinder #3

As I mentioned to Pippin on Twitter, I’d like to be proven wrong. I think a growing plugin market is important to WordPress. There are some outliers, for sure. Ecommerce plugins, an example Pippin chose, are an early success story, as are some strong brands. This might even be a good thing for customers because it’s harder to build a business with bad plugins than bad themes. And it’s certainly a good thing for those people and companies that have found a way to build successful plugin businesses. As a result, I think they’re a lot more defensible than theme businesses. But it’s bad for the market as a whole.

The plugin market needs more demand and more supply to grow to a scale where it can support more businesses. WordPress’ economic moat is driven significantly by the number of people that earn their income from it. That market creates a lot more people that are incentivized to improve WordPress than would otherwise exist. Right now that moat is mostly composed of the businesses that make themes successful — agencies, marketplaces, etc. WordPress would benefit greatly by expanding the pool to plugins, which is why I hope that I am wrong and Pippin is right.

Cogitate: A simple and readable WordPress theme

Over the weekend I wrote a new theme for this site, which I called “Cogitate”.

Cogitate: v. To take careful thought or think carefully about; ponder.

Cogitate is a child theme of the soon-to-be default WordPress theme, Twenty Twelve. It doesn’t change a ton, but I had a few goals with Cogitate that extended past Twenty Twelve:

  • Ridiculously readable text
  • Minimalism without sacrificing fanciness
  • Support a blog and an independent-but-consistently-styled front page

I just released the code on Github here: https://github.com/evansolomon/wp-cogitate

For now, it’s going to stay only on Github and not on WordPress.org for two reasons. First, since I wrote Cogitate primarily for my own use there are probably some parts of the WordPress Theme Review that it wouldn’t pass. Second, I used a couple of PHP features introduced after 5.2.4, which is the minimum WordPress requirement. You can see those in the dependencies section of the README.

There are still a few things that I want to clean up, but overall I’m pretty happy with the result. Twenty Twelve is a great parent theme to work from.

Commercial plugins & the GPL

Brandon Dove did an awesome presentation at WordCamp San Diego this year on running a commercial plugin business while working with and respecting the GPL. I’ve mentioned it to several people since then because it’s the most informative and logical approach I’ve seen to a common challenge.

I just noticed it was posted on WordPress.tv, so here it is.

WordCamp Denver 2012

I’m doing a talk at WordCamp Denver today called “Demystifying the Black Box of WordPress Core”. It’s a collection of (hopefully) useful knowledge and tools to help understand how WordPress core works, and some examples of how to use and navigate WordPress more easily. Here are the slides.

oEmbed in Comments

Last week I tried to embed a tweet in a comment reply here, and I was sad when I realized that comments don’t get the same oEmbed magic that posts do. I thought about making a core ticket to add this — and I still may do that eventually — but decided to make it a plugin first.

Over the weekend I wrote it, and earlier today I released oEmbed in Comments on the WordPress.org repository today. It’s also on Github.

It’s really simple. Once activated, if someone posts a comment with a stand-alone URL pointing to an approved oEmbed provider (like YouTube or Twitter) it will grab the media and replace the link with an embed. There’s no UI and no settings, just activate the plugin and it works.

If you search for this kind of thing, you may find an old plugin called oEmbed for Comments (lots of creative naming here). I originally thought I might just use that, but on closer inspection I didn’t like the way the plugin worked. It sort of used WordPress core’s oEmbed functionality, but it also rewrote a significant part of that on its own. On top of that, it hasn’t been updated in two and a half years, which isn’t a good sign.

In the end, I decided I’d be happier with something simpler and done from scratch.

WordPress themes on the command line: _sh

Last week we had a very fun hack day at Automattic. A couple Automatticians (Hugo and Konstantin) made underscores.me, an awesome and easy way to create custom forks of the _s starter theme that the Automattic theme team released earlier this year. Ian Stewart wrote a post about it on ThemeShaper and today I noticed an interesting discussion in the comments about forking _s from the command line. It seemed like a cool idea, so I spent a little while hacking together a Python script to do it, which I just released on Github.

I’m calling it _sh.

I wrote a detailed README, so I’m going to copy most of that here and let it play out the remainder of this post.

_sh (the _s shell)

_sh is a command line tool to generate forks of the _s WordPress starter theme. It uses underscores.me to create the fork, but lets you do it entirely from the command line.

It lives at https://github.com/evansolomon/_sh.


_sh is written in Python, so you’ll need to have it installed and have a way to interact with it on the command line, like in Terminal.app.

The easiest way to use _sh is to put it in a place that your PATH can access it. First, clone this repository.

git clone https://github.com/evansolomon/_sh.git /path/to/save/_sh

From the directory that you cloned _sh, you can run the setup.py installer script to create a symlink.

python setup.py

That will give you a prompt where you can type the directory that you want to link _sh to. Here I’ll set it up to live in my ~/bin directory.

Welcome to _sh.

Where do you want to symlink _sh? ~/bin


ln -s /Users/evan/code/_sh/_sh /Users/evan/bin


Assuming you’ve setup _sh to be accessible in your PATH, to use it you can just call _sh on the command line from anywhere.

When you call _sh you’ll get an interactive prompt that will walk you through setting up your theme. The new theme will get created in a child directory of wherever the command is run from. Here’s an example:

cd ~/code/themes && _sh

Once I run the _sh command I’ll get an interactive prompt with a few questions to setup my new theme. It’s hard to tell from here, but the introduction and questions all come from _sh, and the answers come from me, typed into an interactive prompt in Terminal. Most of these questions are optional; the only one you must answer is the theme’s name.

I'm going to ask you for some information about your theme.

You have to give your theme a name but you can leave the others blank if you want.

Let's get started.

Name? Stella and Mojo
Slug? stellaandmojo
Author? Evan Solomon
Author URI? http://evansolomon.me
Description? It's a theme named after dogs, because why the hell not.

At this point, _sh will make a request to underscores.me, download a ZIP file with my new theme, and unzip it. Then I’ll have a directory in ~/code/themes/stellaandmojo with my theme files.

That’s it, now I’ve got a new fork on _s with all of my customizations setup.

I updated the post to reflect the new setup.py installer.

“Premium Themes” are a lie

If you do almost anything with WordPress you’ll quickly find your way into discussion of “premium” themes. The name would suggest that these themes are the cream of the crop, vetted and verified as the themes to use to craft your soon-to-be-amazing WordPress site. The name lies.

Premium themes are just themes that are not free (as in beer). In Ryan Imel’s recent WordCamp SF talk called “The State of Themes” he suggested calling premium themes “commercial themes”, which I think is a good start to clarifying the real differences. I can’t count the people I’ve talked to that assume premium themes are good and free (as in beer) themes are bad. All things considered, it’s a rational assumption. Unfortunately it’s a really, really bad assumption and it leads to people having really bad experiences with WordPress that should have been avoided.

I am making a simple landing page for a project Beau Lebens and I worked on during a hack day at Automattic. I decided to browse Theme Forest and found a theme that, while not perfect, I came up with a way to tweak that I liked. I happily paid $8 and would have easily paid triple that for the time saved by not starting from scratch. In hindsight, it would have been a ripoff at half the price. Here’s the Skype conversation that followed, which really underscores how much I hate this theme.

Evan Solomon: this is very likely the worst $8 i’ve ever spent
Beau Lebens: you can just send me $8 if you like
Beau Lebens: i won’t even give you a shitty theme for it
Beau Lebens: then that’ll be the worst
Evan Solomon: this is way worse than just losing $8
Evan Solomon: it’s like spending $8 to get punched in the balls

This post really is not meant to pick on a particular theme, but the one I bought is called Under Construction page with twitter & pie graph. After reading the name, one wouldn’t have to work hard to argue that I got what I deserve.

Jokes aside — and there are many to be made — this is actually a substantive complaint. Let’s start with activating the theme. Here’s the first thing I saw:

Notice: Undefined index: id in /Users/evan/code/evansolomon.me/wp-content/themes/buddypig/var.php on line 6
Notice: get_settings is deprecated since version 2.1! Use get_option() instead. in /Users/evan/code/evansolomon.me/wp-includes/functions.php on line 2612
Notice: Undefined index: id in /Users/evan/code/evansolomon.me/wp-content/themes/buddypig/var.php on line 6
Notice: Undefined index: std in /Users/evan/code/evansolomon.me/wp-content/themes/buddypig/var.php on line 6
Notice: Undefined index: id in /Users/evan/code/evansolomon.me/wp-content/themes/buddypig/var.php on line 6
Notice: get_settings is deprecated since version 2.1! Use get_option() instead. in /Users/evan/code/evansolomon.me/wp-includes/functions.php on line 2612
Notice: Undefined index: id in /Users/evan/code/evansolomon.me/wp-content/themes/buddypig/var.php on line 6
Notice: Undefined index: std in /Users/evan/code/evansolomon.me/wp-content/themes/buddypig/var.php on line 6
Notice: get_settings is deprecated since version 2.1! Use get_option() instead. in /Users/evan/code/evansolomon.me/wp-includes/functions.php on line 2612
Notice: get_settings is deprecated since version 2.1! Use get_option() instead. in /Users/evan/code/evansolomon.me/wp-includes/functions.php on line 2612
Notice: Undefined index: std in /Users/evan/code/evansolomon.me/wp-content/themes/buddypig/var.php on line 6
Notice: get_settings is deprecated since version 2.1! Use get_option() instead. in /Users/evan/code/evansolomon.me/wp-includes/functions.php on line 2612
Notice: Undefined index: std in /Users/evan/code/evansolomon.me/wp-content/themes/buddypig/var.php on line 6
Notice: get_settings is deprecated since version 2.1! Use get_option() instead. in /Users/evan/code/evansolomon.me/wp-includes/functions.php on line 2612
Notice: Undefined index: std in /Users/evan/code/evansolomon.me/wp-content/themes/buddypig/var.php on line 6
Notice: get_settings is deprecated since version 2.1! Use get_option() instead. in /Users/evan/code/evansolomon.me/wp-includes/functions.php on line 2612
Notice: Undefined index: std in /Users/evan/code/evansolomon.me/wp-content/themes/buddypig/var.php on line 6
Notice: get_settings is deprecated since version 2.1! Use get_option() instead. in /Users/evan/code/evansolomon.me/wp-includes/functions.php on line 2612
Notice: Undefined index: std in /Users/evan/code/evansolomon.me/wp-content/themes/buddypig/var.php on line 6
Notice: get_settings is deprecated since version 2.1! Use get_option() instead. in /Users/evan/code/evansolomon.me/wp-includes/functions.php on line 2612
Notice: Undefined index: std in /Users/evan/code/evansolomon.me/wp-content/themes/buddypig/var.php on line 6
Notice: Undefined index: id in /Users/evan/code/evansolomon.me/wp-content/themes/buddypig/var.php on line 6
Notice: get_settings is deprecated since version 2.1! Use get_option() instead. in /Users/evan/code/evansolomon.me/wp-includes/functions.php on line 2612
Notice: Undefined index: id in /Users/evan/code/evansolomon.me/wp-content/themes/buddypig/var.php on line 6
Notice: Undefined index: std in /Users/evan/code/evansolomon.me/wp-content/themes/buddypig/var.php on line 6
Notice: Undefined variable: ts_portfolio_cat in /Users/evan/code/evansolomon.me/wp-content/themes/buddypig/var.php on line 12
Notice: Undefined variable: ts_blogpage in /Users/evan/code/evansolomon.me/wp-content/themes/buddypig/var.php on line 16
Notice: Undefined index: page in /Users/evan/code/evansolomon.me/wp-content/themes/buddypig/functions.php on line 98

That’s 28 PHP notices for those keeping score. It’s worth noting that at this point I still haven’t actually loaded a page running the theme. I noticed that there were quite a few errors (18) in a file called var.php. That’s notable because I’ve actually never seen a WordPress theme that had a file with that name. So I did what any developer would do when faced with a strange-sounding file generating lots of errors, I got a beer from my fridge. Next I opened the file.

I was surprised to find that the file was actually quite short. How short, you ask? 18 lines. 18. In a coincidence so incredible it made me question my own atheism, this file generated exactly one PHP notice PER LINE. Amazing, but far from the best part. The best part is that — ignoring comments, blank lines and PHP tags — I actually disliked every single line of the file. Even that is somewhat generous, because the file included a PHP closing tag, which you should not use. Thanks to the GPL I now have the right to redistribute this code, which I feel compelled to share with you.

Where to even start…

  • This code is running in the global scope already, because why the hell not, so there’s no need to global-ize $options
  • $options is possibly the worst name ever chosen for a global variable
  • …well, until we name one $value
  • get_settings() was deprecated in WordPress 2.1, which was released in January 2007. The function has actually been deprecated longer than it was valid.
  • Variable variables. Enough said.
  • Raw, un-sanitized database queries

So I hope we can all come to terms on the idea that this is a bad file. Maybe it’s not that important though, perhaps it’s used sparingly, right? Allow me two show you two lines from the theme’s index.php file. These are lines 10 and 96, and neither are inside of a conditional or any other code that would prevent them from running.

require(TEMPLATEPATH . "/var.php");
include(TEMPLATEPATH . "/var.php");

So you get this shit twice on every single page. Because — well, I have no idea.

Actually that’s a lie. Want to guess what functions.php does right before it ends with a PHP closing tag? Yup.

require(TEMPLATEPATH . "/var.php");

I guess at this point we might as well load up the actual theme. Upon visiting the front page, var.php outdoes itself by generating 47 PHP notices, for a staggering ratio of 2.6 notices per line of code.

I could go on, but I assume by this point you get the idea. This theme creates about a million global variables, does absolutely no sanitization of data, has SQL injection opportunities, misuses (or just ignores) countless WordPress core API’s, and who knows what else.

The point here isn’t just to criticize bad code. Everyone who’s written any code has written some bad code (though maybe not this bad). The point is that this is a “premium theme”. In fact, as I write this, it’s sold almost 1,000 copies and the feedback is almost universally positive.

Themes are a hugely important part of the WordPress ecosystem. For many people, their theme is synonymous with their site; they have no concept of the separation. For many of those same people, their site is synonymous with WordPress. If they have a bad experience with their site (or theme) that’s a bad experience with WordPress. And one of WordPress’ greatest strengths is how usable it is for non-experts. Those people need tools to make informed choices, and one of the tools that’s currently used most is the association of “premium” themes with high quality. It’s bullshit.

There are a few things I really hope this post can help inspire.

  • The WordPress community needs to take responsibility for communicating the idea that price is not a reliable predictor of quality. This isn’t to say that there are no good commercial themes, but it does mean that themes aren’t good just because they’re commercial.
  • The “premium theme” market needs to be more open. There are lots of very high quality companies and developers in the market, and they probably get hurt more by crap like this than anyone. They should be incentivized to educate users and educate each other, which starts with getting the code in commercial themes scrutinized the way the code in free themes is.

Simple function to add body classes in WordPress

I wrote this for one of our themes on WordPress.com and thought it might be useful to someone else. This is just a slight abstraction on top of the body_class filter in WordPress. We had a use case for adding body classes within theme files, and I wrote this as an alternative to adding function/filters to templates or adding more global variables.

The short saga of a W3 Total Cache victim

Before I start, I should say that the title is somewhat misleading — I’ve never actually installed W3 Total Cache on this site, or any other site outside my laptop for that matter. I have tested it a bit, and because of that decided not to use it. Someone in the comments of my post on Batcache, nginx and multisite asked me why I didn’t use it, and I decided to turn my response to that into a post.

Here is that comment, unedited. If you’d like to see it in context, you can check it out here.

To expand a bit on why I dislike W3 Total Cache, here is a short summary of my experience installing it.

First, because I know what’s coming, I made a new branch in my git repository.

Then I installed and activated W3 Total Cache. Let’s see what it did.

Oh, that’s interesting. That’s not the worst part though, the worst part is that because I am running Batcache it’s already broken my site. Here’s what the page you’re reading this on would look like if I activated W3 Total Cache on it.

Because of WordPress’ modular design, I’d hope to be able to fix this by deactivating the plugin. Not so much.

That’s what my repository looks like after the plugin is deactivated. Notably (though really, the whole thing is notable), it’s actually changed one file that wasn’t changed before, wp-config.php. What change did it make, you ask. Good question, I was curious too.

So after I deactivated W3 Total cache it decided to simply wipeout part of Batcache’s configuration. This sort of had the opportunity to be a good thing, because it had already broken Batcache to start with. Unfortunately they missed that parlay because they also edited wp-content/advanced-cache.php and destroyed the $batcache global, which means Batcache now throws a PHP notice because of an undefined variable.

That sucks. And if I were less responsible about versioning my code, I’d have a hell of a time getting my site back to a working state. I know a lot of people who love W3 Total Cache and I believe it does a lot of good things, but this is just a design I am not interested in working with.