Hit a Moving Target in your WordPress Plugin

In recent changes to WordPress code, users are more than ever able to customize folder and file locations. [Edit: Refers to WordPress 2.6] The wp-config.php file can now be located one directory up from the one containing WordPress. The wp-content folder can be moved arbitrarily, as can (separately) the plugins folder. What’s a poor plugin author to do in keeping track of these ever-moving targets?

When those last two folders are moved, it is done by defining specific constants: WP_CONTENT_DIR and WP_CONTENT_URL for the wp-content folder, and WP_PLUGIN_DIR and WP_PLUGIN_URL for the plugins folder. In plugins it’s best to use these, except that they are not defined in a default setup, and don’t exist in earlier versions of WordPress.

The solution, fortunately, is simple: Check if they are already defined. If they’re not, then the folders are in the default locations and you can define them accordingly. Then just use the constants as normal. Here’s the code; just drop this somewhere in the beginning of your plugin:

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' );

There are a couple things to note:

  • By defining these, you might actually fix problems in other plugins — ones that assume these are defined and call them without checking.
  • I recommend not using the older PLUGINDIR constant at all. It is both obsolete and problematic. Use WP_PLUGIN_DIR instead.
  • You might be tempted to set WP_PLUGIN_DIR as something like dirname(dirname(__FILE__)). Don’t. First, it’s inefficient, as it unnecessarily calls dirname() twice. Second, I’ve seen (albeit unusual) situations where it caused problems*.

So. Not so complicated after all — it’s just one of those rote things that’s helpful to know. Use those four constants and you shouldn’t go wrong finding the right paths in WordPress.

*: Specifically, a plugin was being shared between two WP installs with a symlink. Running in the second blog the plugin was calling the directory of the first blog.
This entry was posted in Codecraft, Webcraft and tagged , , , , . Bookmark the permalink.

4 Responses to Hit a Moving Target in your WordPress Plugin

  1. kahi says:

    > You might be tempted to set WP_PLUGIN_DIR as something like dirname(dirname(__FILE__))…

    Before all other reasons you mentioned, this could create some new problems – like if another plugin would need the constant (then it would get it with unexpected value).

    I think plugin coders (mostly) know, that when they need to store some plugin-specific data, they should use variables or constant of specifically prefixed names, or store them inside the own class.

    And I also think that the names of new constants weren’t created too well. Instead of WP_PLUGIN_DIR and WP_PLUGIN_URL it would be IMHO more correct to make WP_PLUGINS_DIR_PATH and WP_PLUGINS_DIR_URL. (I’m interested in other’s opionions…)

  2. Stephen says:

    Well, theoretically the folder above your plugin’s folder is the “plugins” directory, so setting WP_PLUGIN_DIR to dirname(dirname(__FILE__)) should work. In practice, it doesn’t always.

    RE constant names, I have no problem with the ones they’re using. They’re consistent, which is nice. 🙂 My pet peeve is that ABSPATH has the slash at the end, but none of the other path constants do. ABSPATH is so deeply embedded it would be impossible to change at this point, short of just replacing it outright.

  3. Kahi says:

    Ah, I thought `dirname` returns name of the last folder in hierarchy (and you’re trying to get the path to the current plugin folder), sorry, I got your message completely wrongly. Now I see. 🙂

    Yes, trailing slashes inconsistency is sometimes annoying too. Anyway, I do not understand why not to *always* add trailing slash. Do you know any motivation for that?

  4. Stephen says:

    Just for clarity:

    $x = '/home/public_html/wp-content/plugins/myplugin/myplugin.php';
    
    //dirname($x) == '/home/public_html/wp-content/plugins/myplugin'
    //dirname(dirname($x)) == '/home/public_html/wp-content/plugins'
    

    Regarding trailing slashes, it’s a matter of preference, but a really good idea to be consistent within a particular project.

    Personally I prefer no-slash, for two reasons:
    1) It’s easier to add a slash when you need it than to take one off when you don’t.
    2) “$x/$y/$z/file.php” looks more like a path than “$x$y$zfile.php”

Leave a Reply

Your email address will not be published.