I got an email with the following question, and figured I may as well answer publicly. The question comes from someone who’s an experienced programmer, but has never worked with WordPress before.
[…] I wondered if you had some helpful advice on learning the basics of WP plugin development. I’m mostly hoping there are frameworks/libraries that the community is currently using.
I don’t know of a widely-used library of general WP plugin development tools. Partly this is because WP itself partially qualifies as a “library”, insofar as it provides ready-to-use functions for saving data to the database, URL routing, template loading, user management, etc. And partly it’s because the architecture of WP is so wide open that it’d be difficult to build a more generalized library that covered even a majority of the possible modifications you might make to stock WordPress.
That said, here are a few useful tools that I know of:
- The official WP documentation on writing a plugin is good for learning about plugin manifests as well as a top-level overview of the aspects of plugin development.
- The official Plugin API page is also a good starting point. It explains WP’s hook system, which is the foundation for plugin development.
- Pippin Williamson has written a series called Plugin Development 101 that features a set of video tutorials on common plugin development techniques. Costs a couple bucks, but Pippin is a smart dude and I’m sure the videos are a really good way to get started.
- There are a couple of tools that can be used to generate boilerplate and basic file setup for plugins. The ones I know of are https://github.com/tommcfarlin/WordPress-Plugin-Boilerplate and the
wp scaffold plugin command in WP-CLI.
- The book Professional WordPress Plugin Development is very solid, and a good investment for those who like to learn this kinda stuff through books.
My #1 piece of advice to people getting started with WP plugin development is to find a plugin that does something sorta like what they are trying to do and to reverse engineer it. For me, this is far faster and more practical than any hello-world tutorial or sequential set of lessons. YMMV.
If anyone has other suggestions, please feel free to add them in the comments.
On large WordPress MS installations where site admins are allowed to manage their own plugins, the list of plugins tends to get crowded over time. Sometimes you introduce a plugin to the network and admins start using it, but some time down the road – a year or two later, even – you decide that you want to deprecate that plugin (maybe to replace it with another one, etc). However, migrating users of one plugin to another plugin is a logistical and technical tangle, and sometimes the best medium-term strategy is to allow existing users of the plugin to keep using it, but to prevent admins from activating it in the future.
Here’s how we’re doing it on the CUNY Academic Commons. In the gist below,
$disabled_plugins are the plugins that we don’t want people to activate in the future. In most cases, however, we do want people to be able to deactivate the plugins, so by default, we don’t filter plugins if they’re active. However, we also have an array of
$undeactivatable_plugins, which cannot be activated or deactivated.
Props to dev team member Dominic Giglio for writing part of this.
My last post on using Git with wordpress.org/extend is one of the more popular resources on the web on the subject. But since writing it, I’ve changed my workflow a bit more. So, instead of writing a new guide, I added an addendum to the old one. Enjoy!
TimThumb is popular PHP script for dymanic image resizing, and is often included in WordPress themes and plugins. It caches its processed images for performance reasons; its default cache directory is called
cache, one directory level up from the script itself. TimThumb itself helpfully allows users to define a custom cache directory with a constant (
FILE_CACHE_DIRECTORY) as well as a mechanism for loading this custom configuration (an optional
This setup provides plenty of flexibility when you’re using TimThumb on a one-off site for a client. But when TimThumb is packaged with a theme or plugin, this method of configuring TT not very helpful. Take the case of WooThemes, which uses TimThumb in all of its themes. We use a number of these themes on the CUNY Academic Commons, where I keep tight reins on file permissions. Our Apache user can’t write to the subdirectories of
wp-content/themes/, which means that the versions of TimThumb in this directory can’t use the default cache location.
The problem is that there’s no easy way to fix this in a global way. Creating a
/cache/ subdirectory in each of these theme directories and chmodding them to something more lax is out of the question in my scenario. After all, I already have a directory where Apache can write files: the WP uploads directories (
But configuring TimThumb to put its cache in one of these places is difficult to accomplish globally. The obvious solution is to create appropriate
timthumb-config.php file in each of the theme directories in question. This stinks, though, because it means that my modifications will have to be reapplied each time I upgrade the themes. In fact, what I’ve actually done for the moment is a variation on this: I created a centralized
timthumb-config.php file, in a centralized location (
wp-content, in my case), containing a single line:
I wrote a short script that crawled over every one of my WP themes, and if it found an offender (in my case, any theme with ‘WooThemes’ in the Author tag), create a symlink to the global config. I’ll be including this script as part of my more general deployment scripts.
Of course, this is all extremely inelegant. There are a few things that the theme developers could have done to account for my sort of situation:
Stop putting a copy of your shared utilities (the “framework”) in every theme directory. I understand why the theme shop might make this architectural decision – I’m sure that the vast majority of their theme sales are to people running the theme on a non-networked, single site. But it causes a lot of problems for Multisite networks that offer many themes to their users: a single change in the framework means updating all themes, which becomes a real pain if the theme dev’s autoupdater also isn’t working properly. Allow your framework to be installed as a network-activated plugin, or at least dropped into the
wp-content directory. Better still: You can continue to ship the framework files with the themes, but only load them if the pluginified version is not found. That gives you the best of both worlds.
Now in the case of TimThumb, this schema wouldn’t have solved the problem. But it would have meant hacking a single file, rather than 50 different files spread out through my installation.
Put a wrapper around TimThumb, to allow more flexible placement of the config file. For instance, create a file called mytheme-thumb.php, which looks like this:
Then point all of your TimThumb-generated
src attributes to mytheme-thumb.php, instead of directly at TimThumb. This way, if a global config is found, it’s loaded first, otherwise it falls back on a local timthumb-config.php file, as specified by TT itself.
Pluginify TimThumb before using it In a perfect world, you would have the flexibility of WordPress behind TimThumb: the ability to store your cache location to the database, for example, or to filter the location using
apply_filters(). I did a bit of testing to see just how much overhead this would add. In my tests, TimThumb used about 700KB to load a simple picture. To load WordPress using the
SHORTINIT constant (which loads just enough of WP to get things like
apply_filters()) takes about 2800KB. So loading WP SHORTINIT + TimThumb would take about 3500KB, or about 5x what it takes to load the same image using TimThumb alone. This wouldn’t be so bad with aggressive caching, but it’s probably too much sacrifice for a script that may get called several times on every single page load.
So here’s another idea: Just drop in
wp-includes/plugins.php. I once heard someone say that a great way to improve any PHP package is to include this file, and I think they’re right.
plugins.php is self-contained (it doesn’t require the rest of WP), and it only adds another 50-100KB of overhead. Let’s take our mytheme-thumb.php file again, but add some plugins.php goodness:
Now in this example,
thumb.php wouldn’t have to be an out-of-the-box TimThumb instance. It could be filled with wonderful
apply_filters() goodness. And your
timthumb-config.php file wouldn’t just define constants – you could have full-fledged PHP functions, using WP’s hook infrastructure.
This means maintaining a fork of TimThumb, but it could be a great resource for WP theme developers.
If you’ve ever been responsible for supporting an installation of WordPress Multisite with open registration, you know that the activation process can be a significant source of headaches. Sometimes activation emails get caught by spam filters. Sometimes they are overlooked and deleted by unwitting users. And, to complicate matters, WP’s safeguards prevent folks from re-registering with the same username or email address. This can result in a lot of support requests that are not particularly easy to handle. Aside from reaching manually into the database for an activation key, there’s not much the admin can do to help the would-be member of the site.
The Unconfirmed Dashboard panel
My new WordPress plugin Unconfirmed eases this problem a bit, by providing WPMS admins with a new set of tools for managing unactivated registrations. (By naming it “Unconfirmed”, I fully expect that the plugin will join some great movies and books in the pantheon of Important Cultural Objects.) Unconfirmed adds a new panel to your Network Admin Dashboard (under the Users menu). When you visit the Unconfirmed panel, it gives you a list of all pending registrations on your system. The list is easily sortable by registration date, username, email address, and activation key. For each unactivated registration, there are two actions that the admin can perform. “Resend Activation Email” does exactly what it says: it sends an exact duplicate of the original activation email, as created by the WordPress core activation notification functions. “Activate” allows admins to activate a pending registration manually, which will trigger the activation success email to the user.
At the moment, Unconfirmed is compatible with WordPress Multisite (aka Network mode) only. In the future, I may expand the plugin to work with non-MS installations of WP. Unconfirmed works with BuddyPress, too. The plugin was developed for use on the CUNY Academic Commons.
Download Unconfirmed from the wordpress.org repo or follow its development on Github.