Better admin menu handling for post types in WordPress 3.1

There are about a dozen major features lined up for WordPress 3.1. My main tasks for 3.1 centered around improvements to custom post types. Since we’re in late beta stage, I wanted to offer a summary of all the cool enhancements soon coming to a site near you.

I started with a post on our development blog what I wanted to see, and asked others to chime in and share their “pet bugs, peeves, and workarounds.” The end result cemented what needed to get done for the cycle. There were many small incremental improvements, but a few stood out, which I’ll be covering in a series of posts this week.

Hiding the admin menu

In 3.0, when you register a post type with show_ui, you’ll end up with a top-level admin menu page, with submenu pages for edit, add, and any taxonomies.

Sometimes though, this isn’t ideal. Perhaps you’re using the user interface as a read-only display of logged information, or your post type works great as a specific subset of another admin menu, like slideshows under Media. Continue reading Better admin menu handling for post types in WordPress 3.1

CSRF attack strikes Twitter

I mean, who didn’t see this coming?

Twitter allows a URL to send a tweet. Many sites and retweet buttons and such rely on it. No POST, no nonce, nothing. Just a simple HTTP GET triggers a tweet. Clearly, someone was going to exploit this eventually.

Authentication is not the same as intention. You can’t just determine that a user is allowed to do something, but also that they intended to do something. When intent is not established, and especially when the form can be submitted via a GET request, it makes these kinds of exploits child’s play, as you can see by the complete exploit code below. It’s called a cross-site request forgery, or CSRF (or XSRF).

How do you determine intention? You’ll want to avoid accepting information over GET, but really that does nothing. Next step would be to check the HTTP referrer, but those can be spoofed. Since that isn’t foolproof, then you need to use something like a nonce check, like what we use in WordPress. For Twitter to secure the site from a CSRF vulnerability, they’ll be breaking a lot of embedded tools and buttons on many, many sites, so for now, they’ve apparently disabled the share endpoint that was exploited.

For the WordPress developers out there, probably the best read out there is this post by Mark Jaquith, from four years ago. It still applies as if it was written yesterday. For the non-WordPress developers, it’s still a great read as it explains what’s really going on, how WordPress prevents it, and why intention is important (if that isn’t obvious enough).

Once again, Twitter users are victims, thanks to the lack of basic security practices.

Update: Check out TechCrunch’s coverage. They quote a certain commenter who explained the issue. 🙂

Here’s the exploit:

<script type="text/javascript">
var el1 = document.createElement('iframe');
var el2 = document.createElement('iframe');
el1.style.visibility="hidden";
el2.style.visibility="hidden";
el1.src = "http://twitter.com/share/update?status=WTF:%20" + window.location;
el2.src = "http://twitter.com/share/update?status=i%20love%20anal%20sex%20with%20goats";
document.getElementsByTagName("body")[0].appendChild(el1);
document.getElementsByTagName("body")[0].appendChild(el2);
</script>

Rethinking template tags in plugins

Some plugins offer their own template tags that the blogger can add to their theme where they’d like to display it. Some may even be loaded with an array of arguments to further customize the options. We’ll stick to a simple myplugin_related_posts() template tag as an example throughout.

Usually, these plugins can’t or aren’t willing to take advantage of hooks, such as appending information to the post content, or widgets. That’s okay, especially so when they also offer those alternatives, but also include a theme template tag.

I want to rethink this process. Some bloggers are weary of modifying templates, some plugins’ instructions are plain dangerous, and some bloggers would love to take advantage of a plugin, but it doesn’t allow much flexibility with its output.

Take this as an example:

// Add this to your theme
myplugin_related_posts();

But, what happens when myplugin is deactivated? That function suddenly no longer exists, and the blog blows up. Of course, most plugin authors realize this, and encourage this instead:

// Add this to your theme
if ( function_exists( 'myplugin_related_posts' ) )
    myplugin_related_posts();

Not bad, but clunky. How can we do this better?

Using Hooks for Template Tags

Dion Hulse blew my mind away when he mentioned this method to me a few months ago. Sure, all developers use hooks on a regular basis, but the ingenuity of using a hook as a template tag was too good to resist.

As an example:

// Add this to your theme
do_action( 'myplugin_related_posts' );

Wow, how cool is that? Look ma, clean code! And no fatal errors! Now all the plugin author needs to do is add their existing template tag to that action:

add_action( 'myplugin_related_posts', 'myplugin_related_posts' );

And, if the plugin author doesn’t provide that, then you can do it yourself in your theme’s functions.php, right next to perhaps other filters and actions that modify or add to the hundreds of template tags built into WordPress.

What’s to stop you from adding arguments?

// Add this to your theme
do_action( 'myplugin_related_posts', array( 'count' => 5 ) );

Or, what’s to stop you from removing, replacing, or adding additional callbacks to the same hook?

If the template tag returns a result and needs to be echoed, you can attach the tag to a filter instead:

echo apply_filters( 'myplugin_get_related_posts', '' );

There are a handful of reasons why I really like this method:

One, it requires no effort for the plugin author to passively support this, as most template tags can already be used as callbacks. To actively support this, they can include an add_action call in their plugin, for the times the hook exists.

They don’t need to require the use of a hook, of course — the widget, template tag, hook, etc., all can be supplied, and the user can choose what to use.

Two, administrators can do this themselves by tying the template tag to a hook on their own. They may need their own wrapper function to support more complex tags, but it’s generally worth it.

Three, if the hook doesn’t exist in the theme, then the plugin’s add_action doesn’t do anything. The converse is that if the callback doesn’t exist, then the action hook doesn’t do anything. No fatal errors.

Four, it encourages plugins and themes to play nice with each other through clean, flexible, and robust methods.

Of course, the template-tag-as-a-callback method is only for those situations where the tag needs to be placed in a particular spot. There’s nothing stopping you from taking the template tag provided by the author and simply leveraging the existing hooks system to append the HTML to the post using the the_content filter.

Leverage the WordPress plugin API and reap the benefits.

In WordPress, prefix everything

I recently read a tutorial on digwp.com, a site run by Chris Coyier and Jeff Starr, and noticed that the functions were called rather generic names, such as custom_css_hooks, save_custom_css, and insert_custom_css.

I sent a message to Chris via Twitter: “It’d be nice to see digwp.com prefix functions used in tutorials. Promote best practices instead of condoning bad behavior?” He replied, asking for more information. When I began to write an email to him, I found that there was actually rather little that has been written on the subject, besides two lines in a large Codex page on writing a plugin. I could have sworn I’ve seen other blog posts, but I couldn’t find one — so here is an attempt.

It’s a simple concept. Anything you create in the global namespace has the potential to conflict with a theme, another plugin (including one you wrote), and WordPress core itself. Thus, prefix everything with a unique-enough character set. For example, all functions I write always start with “nacin_”, and I make sure that my functions are unique across all of my plugins. Even when I send a code snippet over the wp-hackers mailing list, I use nacin_ or myplugin_.

I would recommend the same to digwp.com — use digwp_ as a prefix, and try for them to be unique across all tutorials (within reason, of course). It promotes best practices and prevents accidentally teaching bad behavior. Their goal is to be a resource for plugin developers — many tutorials supply code snippets with the intent that they are studied, reused, and refactored. If two developers use code from a tutorial and decline to rename the functions, their plugins will be incompatible with each other.

Functions are only the beginning. One trick is to use a class to encapsulate your functions as class methods instead. When initializing your class, if you wish to assign it to a global variable, make sure that is unique too. Here are some examples:

function nacin_custom_css_meta_box() {
   // ...
}
function nacin_custom_css_save() {
  // ...
}

Using a class, a preferred method by many (myself included):

class nacin_custom_css {
    function init() {
        // ...
    }
    function save() {
        // ...
    }
}
$nacin_custom_css = new nacin_custom_css();

Clearly, the class method is very clean. You can name methods after after hooks and action verbs, working within that namespace as if it is a blank slate (because it is). Classes are very helpful in WordPress plugins even if you are not using object-oriented concepts.

At one plugin competition (I would say it was WordCamp NYC 2009, but I can’t find a link) referenced by Ozh Richard in the comments, multiple plugins by the same author could not even be run on the same blog, since they conflicted with each other. Don’t do that. If you have the same function in two different plugins, consider wrapping both in a function_exists check, that way both plugins can use whichever is defined first. Some do that with every function or class they define, just as a precaution. Fatal core errors from redefinition of functions will take a blog down real quick.

Prefix Everything

With custom post types getting super-charged in WordPress 3.0, along with better support for custom taxonomies, more plugins are going to be creating strings that sit alongside one another in the database. If they conflict, the results can be quite unexpected.

So, here’s a thought — prefix everything. Instead of creating an “event” or “twitter” post type, create “nacin_event” or “nacin_twitter” instead. Same with taxonomies. Meta box identifiers. Widget identifiers. Slugs on menu pages and subpages. Any callback or identifier you need to use, make sure you have it properly namespaced.

(Edit:) In the comments, Dougal Campbell also brought up namespacing options (and a related proposal). Though I neglected it in my laundry list, that is also very important. Same goes for transients, as well as metadata for users, posts, comments, and networks. You can also take advantage of serialization in these cases, and store arrays of options together, instead of polluting the options table (and increasing queries in some cases).

This all applies to themes, too — Twenty Ten uses the twentyten_ prefix throughout, for both functions it uses, and action hooks it adds in the theme. We also wrap most in a function_exists check, but that’s actually to allow those functions to be replaced by a child theme.

Use Common Sense

Above all, just make sure you avoid things that look too generic. Google recently released a plugin that prefixed every function throughout, except one — the callback tied to the activation hook. The function name? install(). I died a little that day.

Of course, if every other plugin author is properly prefixing their functions, then that function won’t conflict with any of them. I would leave the lack of a prefix to core — only some of our functions use the wp_ prefix. And, of course, avoid the wp_ prefix.

This isn’t just theoretical. We broke a plugin in 3.0, as a plugin was defining a function called get_admin_url(), which we added. That’s way too generic a name to assume we won’t add one like it — we’re at 4,000 functions and counting in WordPress. (I sent them an email and they said they would release an update — we try to play nice too. We’ve also renamed a function we had introduced, because it conflicted with a BuddyPress function.)

Another plugin is the Publish2 plugin, which uses publish2_ and p2_ interchangeably. Normally that might be fine, but there’s also the wildly popular P2 theme from Automattic, and the theme also uses p2_. I’m not aware of a naming conflict yet between them, but on the safe side, I sent a message to the Publish2 plugin developer giving him a heads up and suggesting that he standardize on publish2_.

In some ways, it’s about future-proofing. The bigger picture is that your plugin should do one thing and do it well, and allow other plugins to work with it side by side. When you’re a small fish in a big ecosystem, realize you’re not alone and play nice with others.

5 Ways to Debug WordPress

Many plugin and theme authors don’t take full advantage of some really helpful debugging tools in WordPress. Here’s a quick run-down of five cool tools for debugging:

1. WP_DEBUG

define( 'WP_DEBUG', true );

It’s no secret I love this constant and everything it stands for. Define it in wp-config.php and you’ll start seeing PHP notices and also WordPress-generated debug messages, particularly deprecated function usage.

(Added June 27, 2010: You may wish to check out my Log Deprecated Notices plugin.)

There’s also WP_DEBUG_DISPLAY and WP_DEBUG_LOG, which enable you to log these to a wp-content/debug.log file. I’ve added some inline documentation that describes these both well. Some use WP_DEBUG on a live site and just make sure it gets logged.

WP_DEBUG will often reveal potential problems in your code, such as unchecked indexes (empty() and isset() are your friend) and undefined variables. (You may even find problems in WordPress itself, in which case you should file a bug report.)

2. SCRIPT_DEBUG

In the admin, WordPress minimizes and concatenates JavaScript and CSS. But WP also comes with the “development” scripts, in the form of dev.js and dev.css. To use these instead:

define( 'SCRIPT_DEBUG', true );

3. SAVEQUERIES

The WordPress database class can be told to store query history:

define( 'SAVEQUERIES', true );

When this is defined, $wpdb->queries stores an array of queries that were executed, along with the time it takes to execute them.

The database class has additional error and debugging tools, which are documented on the Codex (though when in doubt, check the source).

4. The ‘all’ and ‘shutdown’ hooks

There’s an ‘all’ hook that fires for all actions and filters. Example usage:

add_action( 'all', create_function( '', 'var_dump( current_filter() );' ) );

You’ll be surprised how many hooks get executed on every page load. Good for troubleshooting and identifying the right hook.

There’s also a ‘shutdown’ hook you can use in combination with, say, SAVEQUERIES, and write the query information to the database. It’s the last hook to run.

5. Core Control

There are plenty of great developer-oriented plugins out there, but I’m not sure any list would be complete without Dion Hulse’s Core Control plugin. It is comprised of five modules covering Filesystem methods, HTTP methods, HTTP logging, Cron tasks, and upgrades. A must-have.


This list is by no means exhaustive, just some quick hits to get you started. What tools do you use?