WordPress Plugin Pet Peeve #1: Hardcoding wp-content

Perhaps my biggest pet peeves I run across with WordPress plugins is when developers hardcode the URL or path to the WordPress content folder. By default this folder is named ‘wp-content’, and resides at the root of the primary WordPress folder. However, since WordPress 2.6 (released July 2008), this location can be moved by simply defining a constant in wp-config.php. That’s precisely what I do on my website: my WordPress installation lives at /wordpress while my content folder is at /wordpress-content I like having this separation of core WordPress files from the themes, plugins, and uploads I’ve added myself. It also makes it easier for me to upgrade WordPress, since I don’t use the built-in upgrade system added in 2.7. Any plugins that still hardcode the path of the wp-content folder break in often spectacular ways on my site.

So what should plugins do instead? In order to make moving your content folder possible, WordPress 2.6 added a number of constants and functions which refer to the correct location of several often used folders. So instead of including an image using something like:

<img src="<?php bloginfo('wpurl') ?>/wp-content/plugins/my-plugin/images/logo.png" />

you would have:

<img src="<?php echo WP_PLUGIN_URL ?>/my-plugin/images/logo.png" />

or even better:

<img src="<?php echo plugins_url('my-plugin/images/logo.png') ?>" />

Since these constants were added in WordPress 2.6, they obviously won’t work in earlier versions. No problem, you can define them yourself in your plugin. The WordPress Codex page Determining Plugin and Content Directories includes 8 lines of code (plus 1 comment) that you can add to your plugin to ensure these constants are set, even in older versions of WordPress:

// Pre-2.6 compatibility
if ( ! defined( 'WP_CONTENT_URL' ) )
    define( 'WP_CONTENT_URL', get_option( 'siteurl' ) . '/wp-content' );
if ( ! defined( 'WP_CONTENT_DIR' ) )
    define( 'WP_CONTENT_DIR', ABSPATH . 'wp-content' );
if ( ! defined( 'WP_PLUGIN_URL' ) )
    define( 'WP_PLUGIN_URL', WP_CONTENT_URL. '/plugins' );
if ( ! defined( 'WP_PLUGIN_DIR' ) )
    define( 'WP_PLUGIN_DIR', WP_CONTENT_DIR . '/plugins' );

Everywhere else in your plugin, make sure that you use the constants, not the hardcoded path. If the string ‘wp-content’ appears anywhere in your plugin that isn’t defining one of the constants above, you’re doing it wrong. If you also want to make sure the functions like plugins_url are available in older versions of WordPress, see the compatibility.php file the ships with the WordPress OpenID Plugin.

So plugin authors, please go and fix this in your plugins. Please? Otherwise I can’t use your plugin at all on my site.

Comments and responses

Have you written a response to this? Let me know the URL:

I’ve run into this problem with a few plugins as well. I got tired of fixing plugin each time a new version of the plugin was released, so I added a few mod_rewrite rules to ensures that the requests ended up in the right spot.

I ended up adding those rules to my ‘WordPress in a separate directory from SVN’ post:

http://josephscott.org/archives/2009/02/installing-wordpress-as-a-subversion-checkout-or-external-in-a-subdirectory/

well, sure I could (or use mod_rewrite like Joseph suggests). But it would be much easier if people would just fix their plugins.
[…] do plugin WP-HOTWords. Na versão 4.4 as modificações são poucas, mas necessárias. Hoje descobri que eu papei mosca em relação as normas de plugins para a versão 2.6 do WordPress. Isto mesmo! A […]
I just recently discovered that my plugin is guilty of this offense. Apologies to everyone I've offended up to now. Thanks to your post, I quickly corrected the error.
@mattc: heh, no worries. I've wondered if calling this series "pet peeves" is too negative. Perhaps just "best practices" would be better? Glad to hear that it helped you fix your plugin though! :)