How to get your plugin removed from the directory

The following is a non-exhaustive list of things you can do to get your plugin rejected or removed from the WordPress.org plugin directory.

Yes, this is tongue-in-cheek. This is a list of things NOT TO DO.

  1. Give it a license that is incompatible with WordPress’ license.
  2. Host your plugin elsewhere, and only use the WordPress.org plugin listing as a pointer to that.
  3. Use base64 encoding to hide your plugin code or obfuscate HTML that you’re injecting into people’s blogs.
  4. Insert SEO spam links into people’s blogs (like <a href=”http://example.com/”>video poker</a>).
  5. Insert external links (like a credit link, <a href=”http://example.com/”>My Awesome Plugin by Awesome Sauce</a>) into their blog without explicitly asking their permission, or make the default option be to insert the link.
  6. Load portions of the code from an external site for no valid reason, or use any other trick to work around #3, #4 and #5.
  7. Harvest people’s e-mail addresses or require registration to activate the plugin.
  8. Explicitly state or imply that users of the plugin must pay you money in order to use the plugin.
  9. Make the plugin a “requirements check” or bootstrapper for some other plugin, hosted elsewhere. See #2.
  10. Make it do something illegal.
  11. Make it do something sneaky, underhanded, or otherwise dishonest or immoral. Maybe a plugin that disables all plugins by a plugin author you don’t particularly like. Harvest the user’s password. Use your imagination!

Again, this is a list of things not to do. It is not comprehensive. Be cool, think of how your plugin benefits its users, and write awesome plugins.

New Plugin – “I Make Plugins”

I have several WordPress plugins. They’re hosted on the WordPress.org plugin repository, but I also have a page for each plugin on my own site. I’ve found it tedious to have to update both places separately. Things get out of sync, or worse, I put off plugin updates because I loathe updating two places (with two different formats) with the same information.

The WordPress plugin repository has an API. Let’s use it! I Make Plugins is a plugin for WordPress plugin authors to let them easily showcase their plugins on their own site, solely by updating the plugin’s readme.txt file.

Adding a plugin is as simple as creating a new subpage of your plugin listing page, and giving it the name of your plugin in the repository. All the information comes from the API and is kept up to date.

Here is a nine and a half minute. boring-as-hell screencast with a full tour of the plugin.

I realize that writing a plugin for plugin developers is probably a futile gesture. Plugin developers are choosy people, and many may already have their own setup for managing their stable of plugins. I wrote this for myself — but let me know if you find it useful!

New in WordPress 2.9: Post Thumbnail Images

Many WordPress themes, especially those with “magazine-like” layouts, use an image to represent each post. It might just be on the front page. It might be alone, or alongside an excerpt. Until now, there was no standardized way to do this. Many themes would require you to tediously enter a Custom Field with the value being the URL you wanted to use. Often you had to do cropping yourself. With WordPress 2.9, theme authors can easily enable Post Thumbnail selection UI and call those image using simple template tags.

First, in the theme’s functions.php, declare that your theme supports this feature. This will enable the UI in the WP Admin.

add_theme_support( 'post-thumbnails' );

That will enable Post Thumbnail UI for both Post and Page content types. If you’d only like to add it to one, you can do it like this:

add_theme_support( 'post-thumbnails', array( 'post' ) ); // Add it for posts
add_theme_support( 'post-thumbnails', array( 'page' ) ); // Add it for pages

Simply remove the one you don’t want to support.

Next, you should specify the dimensions of your post thumbnails. You have two options here: box-resizing and hard-cropping. Box resizing shrinks an image proportionally (that is, without distorting it), until it fits inside the “box” you’ve specified with your width and height parameters. For example, a 100×50 image in a 50×50 box would be resized to 50×25. The benefit here is that the entire image shows. The downside is that the image produced isn’t always the same size. Sometimes it will be width-limited, and sometimes it will be height-limited. If you’d like to limit images to a certain width, but don’t care how tall they are, you can specify your width and then specify a height of 9999 or something ridiculously large that will never be hit.

set_post_thumbnail_size( 50, 50 ); // 50 pixels wide by 50 pixels tall, box resize mode

Your second option is hard-cropping. In this mode, the image is cropped to match the target aspect ratio, and is then shrunk to fit in the specified dimensions exactly. The benefit is that you get what you ask for. If you ask for a 50×50 thumbnail, you get a 50×50 thumbnail. The downside is that your image will be cropped (either from the sides, or from the top and bottom) to fit the target aspect ratio, and that part of the image won’t show up in the thumbnail.

set_post_thumbnail_size( 50, 50, true ); // 50 pixels wide by 50 pixels tall, hard crop mode

Now, you can make use of the template functions to display these images in the theme. These functions should be used in the loop.

has_post_thumbnail() returns true/false and indicates whether the current post has a manually-chosen Post Thumbnail (in the loop):

<?php
if ( has_post_thumbnail() ) {
	// the current post has a thumbnail
} else {
	// the current post lacks a thumbnail
}
?>

the_post_thumbnail() outputs the Post Thumbnail, if it exists (in the loop):

<?php the_post_thumbnail(); ?>

Those are the basics. How about some advanced stuff?

What if you want to use a small 50×50 hard-cropped image for the home page, but want to use a 400 pixel-wide (unlimited height) image on the post’s permalink page? You’re in luck. You can specify additional custom sizes! Here’s the code:

functions.php

add_theme_support( 'post-thumbnails' );
set_post_thumbnail_size( 50, 50, true ); // Normal post thumbnails
add_image_size( 'single-post-thumbnail', 400, 9999 ); // Permalink thumbnail size

home.php or index.php, depending on your theme structure (in the loop):

<?php the_post_thumbnail(); ?>

single.php (in the loop):

<?php the_post_thumbnail( 'single-post-thumbnail' ); ?>

That’s it! set_post_thumbnail_size() just calls add_image_size( 'post-thumbnail' ) — the default Post Thumbnail “handle.” But as you can see, you can add additional ones by calling add_image_size( $handle, $width, $height, {$hard_crop_switch} );, and then you use that new size by passing the handle to the_post_thumbnail( $handle );

If you want your theme to support earlier versions of WordPress, you’ll have to use function_exists() to keep from calling these new functions in those versions. I’ve omitted that code to keep these examples as simple as possible. Here would be the functions.php example with the wrapper code:

if ( function_exists( 'add_theme_support' ) ) { // Added in 2.9
	add_theme_support( 'post-thumbnails' );
	set_post_thumbnail_size( 50, 50, true ); // Normal post thumbnails
	add_image_size( 'single-post-thumbnail', 400, 9999 ); // Permalink thumbnail size
}

There is one caveat for this feature in WordPress 2.9 — it only works fully for new image uploads. We can’t yet resize images on the fly, although I’m strongly considering it for a future version. If you call the template functions on a post that has a Post Thumbnail that was uploaded prior to your theme having declared the new sizes, you won’t be able to do hard-cropping, and the box-resize will be done in the browser. As a temporary solution, Viper007Bond has a great plugin that will go back and create missing image sizes for you: Regenerate Thumbnails.

I’m looking forward to see what kinds of sites you can build with this feature!

How should “Post updated. View Post” links open?

We’ve gone back and forth on this. How should the “View Post” link that shows up next to the “Post updated” (or similar) text work? Should it open in the same window/tab, or should it open in a new window/tab?

The problem with this question is that the people who have really strong opinions in favor of opening the tab in the same window are all power users. They’re people like me. I don’t think I can give an objective answer on this, because manually opening a window in a new tab is a skill that I don’t even think about, I use it so much. I realize that’s probably not the case for many WordPress users.

We’re going to use the honor system on this, so be honest:

Do not vote in this poll if your mouse has more features than two buttons and a scroll wheel, and you know how to use them. Do not vote in this poll if you know what “middle-clicking” is.

I’m abstaining from voting, as my mouse has 7 buttons, one 4-way scroll wheel, and another two-way thumb wheel. 🙂

Excluding your plugin or theme from update checks

There has been a vigorous discussion going on regarding what data WordPress installs send to WordPress.org when doing update checks. Because WordPress (the software) doesn’t know whether a theme or plugin is listed in the WordPress.org repositories, it has to check them all, and let the repository sort it out. Some have expressed concern that private plugins developed for a single client could contain sensitive information in their headers, like contact information for the developer, etc.

If you, as a plugin or theme developer, would like to exclude one of your plugins or themes from the update array, the following code will do the trick.

For plugins:

function cws_hidden_plugin_12345( $r, $url ) {
	if ( 0 !== strpos( $url, 'http://api.wordpress.org/plugins/update-check' ) )
		return $r; // Not a plugin update request. Bail immediately.
 
	$plugins = unserialize( $r['body']['plugins'] );
	unset( $plugins->plugins[ plugin_basename( __FILE__ ) ] );
	unset( $plugins->active[ array_search( plugin_basename( __FILE__ ), $plugins->active ) ] );
	$r['body']['plugins'] = serialize( $plugins );
	return $r;
}

add_filter( 'http_request_args', 'cws_hidden_plugin_12345', 5, 2 );

Just change the cws_hidden_plugin_12345 string (two instances) to a namespaced function name for your plugin, and you’re good to go.

For themes:

function cws_hidden_theme_12345( $r, $url ) {
	if ( 0 !== strpos( $url, 'http://api.wordpress.org/themes/update-check' ) )
		return $r; // Not a theme update request. Bail immediately.

	$themes = unserialize( $r['body']['themes'] );
	unset( $themes[ get_option( 'template' ) ] );
	unset( $themes[ get_option( 'stylesheet' ) ] );
	$r['body']['themes'] = serialize( $themes );
	return $r;
}

add_filter( 'http_request_args', 'cws_hidden_theme_12345', 5, 2 );

Put this in your theme’s functions.php Again, just change the cws_hidden_theme_12345 string (two instances) to a namespaced function name for your theme. Do note that this will only hide the ACTIVE theme. This code doesn’t get run if the theme isn’t active. If you want to hide non-active themes, you’ll have to put this code in a plugin and instead of using get_option( 'template' ) or get_option( 'stylesheet' ) you’d hardcode the values for the inactive theme you want to hide.

Just a note: I don’t want the comments to turn into another battlefield for the update check debate. I’m putting my code where my mouth is and showing you how you can keep private plugins/themes from contacting WordPress.org if you so wish. Comments about this code are welcomed!

Using PHP5 object constructors in WP Widget API

Someone mentioned to me that they couldn’t use PHP5-style object constructors when using the WP Widget API. I looked into it, and it turns out it does work. Example:

class My_Widget extends WP_Widget {
	function __construct() {
		$widget_ops = array( 'classname' => 'css-class', 'description' => 'Description' );
		parent::__construct( 'css-class', 'Title', $widget_ops );
	}
	// Rest of your widget subclass goes here
}

The key is using parent::__construct() instead of $this->WP_Widget().

Interview with Deutsche Welle on WordPress Security

I recently did a short interview with Deutsche Welle about WordPress security. Listen to it here.

To expand on the topic, here are some of the details that didn’t make it into the final cut of the interview:

If your blog is compromised, you should install the latest version of WordPress, but first you should remove your old files. This is to prevent a hacker from leaving a back door (something like wp-give-hacker-access-forever.php in your WordPress directory. Just dropping the new version over the old version wouldn’t replace a new file that a hacker may have added, which is the reason for getting rid of the old files. Once you’ve done that (being careful to back up your wp-config.php and all your wp-content files), upload a clean install of WordPress. Restore your custom files. Next, look for any user accounts that weren’t there before, or that have higher access than they should. Sort that out. And lastly, scan through your theme/plugin files looking for backdoors or hidden links. This is mostly a manual process, but there are some common things to look for. Most backdoors use the eval() function, so be on the lookout for that!

The best way to keep your blog safe is to stay updated with the latest WordPress version! We’ve tried to make it as easy as possible to update (one-click!), and we have big plans for making it even easier in the future.

I’ve never had one of my WordPress blogs compromised, and I don’t do anything “fancy.” I just stay updated.

Reminder: if you’re using WordPress.com or another “hosted” blog solution, they take care of security updates for you. The only thing you need to worry about is choosing an unguessable, complex password.

TextMate WordPress Widget Snippet

I love WordPress’ sidebar widgets. I also despise coding them.

I love how they let me offload menial management tasks directly to clients, avoiding all the “Change this word to another word!” e-mails. But every time I code them, it seems to involve 15 minutes of Googling, copy-pasting from a previous widget, and looking at documentation.

So I created this TextMate “snippet” to make it easier:

class ${1:PREFIX_Name}_Widget extends WP_Widget {
	function $1_Widget() {
		\$widget_ops = array( 'classname' => '${2:CSS class name}', 'description' => '${3:Description}' );
		\$this->WP_Widget( '$2', '${4:Title}', \$widget_ops );
	}

	function widget( \$args, \$instance ) {
		extract( \$args, EXTR_SKIP );
		echo \$before_widget;
		echo \$before_title;
		echo '$4'; // Can set this with a widget option, or omit altogether
		echo \$after_title;

		//
		// Widget display logic goes here
		//

		echo \$after_widget;
	}

	function update( \$new_instance, \$old_instance ) {
		// update logic goes here
		\$updated_instance = \$new_instance;
		return \$updated_instance;
	}

	function form( \$instance ) {
		\$instance = wp_parse_args( (array) \$instance, array( ${5:array of option_name => value pairs} ) );

		// display field names here using:
		// \$this->get_field_id('option_name') - the CSS ID
		// \$this->get_field_name('option_name') - the HTML name
		// \$instance['option_name'] - the option value
	}
}

add_action( 'widgets_init', create_function( '', "register_widget('$1_Widget');" ) );

Just create a WordPress TextMate bundle, create a new snippet, paste in that code and give it a trigger like wpwidget. Then just type that trigger, press TAB, and you’ll be in the first field. Type, hit TAB to go to the next field. Places where you enter the same thing twice are handled—you only have to enter it once. There are some helpful comments that’ll guide you through the rest once you’ve filled out the basics. I find that with this snippet, I can code up a new widget in a couple of minutes, tops. This is definitely going to make it more likely for me to create a widget for a client instead of just cheating and editing their theme by hand myself.

Escaping API updates for WordPress 2.8

The WordPress escaping API functions have been updated. Escaping is a way of using untrusted text that “neuters” anything that could do damage. Escaping is used in WordPress to avoid SQL injection and cross-site scripting/script injection (XSS), among other things.

The old functions still work, so if you were using the old ones, you’re fine. The new ones just offer you an easier to remember, more concise, and more flexible way of securing your WordPress code.

Here’s an example. Say you wanted to translate a string, escape it for use in a quoted HTML attribute, and then echo it out. In WP 2.7, you’d have to do this:

<?php echo attribute_escape( __( 'Untranslated text' ) ); ?>

In WordPress 2.8, you can just do this:

<?php esc_attr_e( 'Untranslated text' ); ?>

Shorter, plus we killed the echo and the extra pair of parenthesis! But let’s break it down.

esc_ = 1, attr = 2, _e = 3

  1. esc_ is the prefix for the new WP escaping functions.
  2. attr is the context (in this case, attribute). The available contexts for 2.8 are attr, html, js, sql, url, and url_raw.
  3. _e is the optional translation suffix. The available suffixes for 2.8 are __, and _e. If you omit the suffix, no translation is performed, and your string is just returned.

More about contexts

  • attr means an HTML attribute.
  • html means text within an HTML node, but not within an attribute
  • sql is an alias to $wpdb->escape().
  • url means URLs for use in HTML attributes.
  • url_raw means URLs for use in redirects or storage in the database (does not entity-encode).
  • js means JS, for using PHP to populate a Javascript var.

More about suffixes

Suffixes work just like the function they’re named after.

  • __ translates the string and returns it.
  • _e translates the string and echoes it.
  • The suffix is optional. A blank suffix will just return.
  • Suffixes are currently only available for html and attr contexts.

Functions with translation suffixes also accept an option second parameter of a translation domain, for use in plugins.

Enjoy! Go forth and write more succinct code.

GigaOM Pro launches on WordPress and BuddyPress

2009 is the year of BuddyPress. It’s also the year where online content providers have to figure out how to make money outside of the flailing “get a lot of views, sell ads” model. For the past couple of months, I’ve been working on a project that tackles both of those things, and I’m really proud to present it to the world:

GigaOM Pro is a WordPress/BuddyPress-powered premium research membership site, focused on four initial verticals: Mobile, Green IT, Infrastructure, and the Connected Consumer. A network of independent analysts provide in-depth research papers and research notes, which subscribers can view on the site or download as PDF documents. GigaOM Network contributors provide “long view” posts — topic-focused long form posts. And each of the topic verticals has a curator who provides weekly updates on the topic, as well as a constant stream of curated links to relevant external stories. Subscribers can access all the content, comment on the content, have a profile on the site, and send messages to Analysts, Contributors, Curators, or other subscribers using the BuddyPress messaging system.

Here’s what it looks like:

GigaOM Pro home page
GigaOM Pro home page

The content is incredibly compelling. I’ve been especially impressed with the quality of the Long View posts. More than once when developing the site I would get distracted by one of these pieces and have to read the whole thing. The GigaOM writing staff and the analyst network are very talented people, and I think that $79 a year is a steal for this calibre of hyper-focused content and this sort of access to industry analysts.

From a technical perspective, it was interesting to create a site with such distinct content types. The Write screen for Curated Links looks nothing like the Write screen for Weekly Updates, or Research Briefs. The system makes heavy use of the category system, and custom WP_Query objects and loops. category__not_in, category__and and post__not_in are very powerful tools for getting the correct entries from the system.

Naturally, there are no core WordPress hacks — everything is implemented through plugins and the custom theme!

Let me know what you think. And don’t subscribe — I put in a lowball prediction in the internal betting pool for how many subscribers there are in the first week, and I think I’m going to lose. 🙂

Typographica relaunches on WordPress

Typographica, the excellent blog for typographical nerds, has just relaunched on WordPress with a great new design by Chris Hamamoto. Asked why they switched from Movable Type to WordPress, Stephen Coles replied:

For me, it seemed an obvious switch given WordPress’ wide adoption in recent years. We’ve often had trouble getting assistance with MT, whether it’s documentation or expert advice. Because WordPress is so common, the help resources and useful plugins are simply much more accessible.

WordPress’ killer features are its community and its marketplace: thousands of free plugins, thousands of free themes, and hundreds of agencies and freelancers providing every possible WordPress development and support service you can imagine.

Heading to SXSW, WordPress consulting availability in mid-May

Tomorrow I’m heading off to Austin, TX for the South by Southwest Interactive Festival. If you’re going to be there, and you’re a WordPress fan, make sure you say hi and let me know what cool uses you’ve found for WordPress! The best way to find out where I am or to get in contact with me is to follow me on Twitter. Ping me in an @message if you’d like to chat.

Also, if you have need of a WordPress guru, I’m back on the market! My contract with b5media has moved to a part-time arrangement, so if you’re looking for someone to figure out how WordPress and your company or product fit together, drop me a note or track me down while I’m in Austin. I have a really exciting secret project occupying my time until mid-May, but if you can wait a few months to start your project, we can start that conversation now.

Show all categories on the post editing screen

Isn’t it annoying when you have a site with a reasonable number of categories, say 15, and WordPress only shows you the first 8 in the category checkbox widget? Ugh, scrolling is annoying.

Try this super-simple plugin. It’s so simple that the plugin’s content is embedded into that link (seriously). There, now you’ll never see a scrollbar in the category widget. You’re welcome!

(Requires WordPress 2.7… upgrade already!)

Updated to work with WordPress 2.8.

Update: put it in the plugin repository. Download here.