Tag Archives: plugins

Getting started with WordPress plugin development

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.

Selectively deprecating WordPress plugins from Dashboard > Plugins

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.

TimThumb problems and solutions for WordPress theme developers

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 timthumb-config.php file).

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 (wp-content/uploads and wp-content/blogs.dir).

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:

<?php define( 'FILE_CACHE_DIRECTORY', dirname( __FILE__ ) . '/blogs.dir/1/timthumbcache/' ); ?>

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:

    	<?php
    	if ( file_exists( dirname(__FILE__) . '../../global-timthumb-config.php' ) ) {
    		require( dirname(__FILE__) . '../../global-timthumb-config.php' );
    	}
    
    // Load the out-of-the-box TimThumb utility
    	require( dirname(__FILE__) . '/thumb.php' );
    	?>
    	

    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 get_option() and 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:

    	<?php
    
    // Load the plugin tools, conditionally just in case
    	if ( !function_exists( 'do_action' ) ) {
    		require( dirname(__FILE__) . '/plugins.php' );
    	}
    
    if ( file_exists( dirname(__FILE__) . '../../global-timthumb-config.php' ) ) {
    		require( dirname(__FILE__) . '../../global-timthumb-config.php' );
    	}
    
    // Load TimThumb
    	require( dirname(__FILE__) . '/thumb.php' );
    	?>
    	

    Now in this example, thumb.php wouldn’t have to be an out-of-the-box TimThumb instance. It could be filled with wonderful do_action() and apply_filters() goodness. And your global-timthumb-config.php or 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.

New WordPress plugin: Unconfirmed

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

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.

BuddyPress Docs


Flattr this

BuddyPress Docs is a powerful and flexible tool for collaborative editing in BuddyPress.

BuddyPress Docs features:

  • Full integration with BuddyPress Groups Docs can be activated on a per-group basis, creating a Docs tab. Doc access, by default, is inherited from group privacy settings. Doc authors, as well as group admins and mods, can override these default settings so that visibility, editing, and commenting of a given doc can be more restrictive.
  • Full integration with activity streams Whenever you create, edit, or comment on a Doc, an activity item will appear in all relevant activity streams. These activity items obey group privacy settings, so that edits in private groups are private, etc. New dropdows in sitewide activity filters allow you to view Docs activity selectively. Full activity integration means that the plugin can be coupled with a plugin like BuddyPress Group Activity Subscription for fine-grained activity notification.
  • Front-end, rich editing BuddyPress Docs has full rich-text editing, powered by WordPress’s own TinyMCE editor. Because it’s the WordPress editor, users will experience the power and ease of use they’ve come to know from the Dashboard. Because it’s on the front end, users don’t ever need to leave your BuddyPress environment to edit Docs.
  • Doc tags With full taxonomy support, BuddyPress Docs lets your users tag and organize their content however they’d like. Doc lists can be filtered by tag for easy navigation. You can see at a glance how many times a tag has been used in a given group (and, in an upcoming release, sitewide).
  • Easy sorting and search When viewing Doc lists, you can sort by a number of criteria, making it easy to find what you’re looking for. There’s also a search box, which is smart enough to limit searches to specific group contexts dynamically.
  • Comments Leave comments on docs just like you would on blog posts.
  • Protections against overwrites To make sure that users don’t overwrite each other’s work, BuddyPress Docs only allows a single user to edit a Doc at a given time. To make sure that others aren’t blocked from editing by those who leave leave Docs open and then forget about them (ahem), there is a timeout and autosave after 30 minutes of idle time.
  • Developer goodies Built by the person who has (probably!) built more BuddyPress plugins than anyone else in the world, BuddyPress Docs is designed with extensibility in mind. do_action() and apply_filters() is everywhere. Add-ons like taxonomy and hierarchy, and integration pieces like groups (and the upcoming profile integration), are totally modular. BuddyPress Docs uses WP’s internal APIs wherever possible: custom post types, custom taxonomies, and more. Templates have been abstracted out to make theme overrides easy. And – inline documentation EVERYWHERE! Feedback from developers is welcome: ongoing development lives at http://github.com/boonebgorges/buddypress-docs.

Lots more development is coming! User profile integration, BuddyPress Documents upload integration, and more!

NOTE The plugin is listed as requiring WordPress 3.1 and BuddyPress 1.3. While I have been developing against the BP 1.3 trunk, it should work fine with BP 1.2.8 as well. However, do NOT use the plugin with WP 3.0.x, as it will expose private group Docs.

Instructions

  1. Upload the bp-group-reviews directory to your WP plugins folder and activate
  2. Activate Docs on a per-group basis in the group admin section

Download the plugin here.

BuddyPress Docs has been downloaded 26,474 times. Are you using this plugin? Consider a donation.

Version history

1.0-beta – March 1, 2011
Initial release