Problems Detecting WordPress MU in Plugins with PHP’s __FILE__

| January 5, 2010

I’m a fan of symlink-type deployment scripts such as Capistrano, which is in heavy use in Pressible. It’s not perfect, but it’s how we deploy most of our non-MU code (plugins, themes, etc.). The basic premise of these scripts is that code is copied from your SCM system into a staging directory, and once everything checks out, a symlink is replaced to make the new code active. Any web server pointed at said code will then always be accessing a path that includes at least one symlink.

If you are using such a script, problems can arise in PHP when using the magical constant __FILE__, which reports the absolute path to the current file. __FILE__ will actually contain the “true” location of the file regardless of whether or not it was accessed via a symlink. (There is some discussion about whether or not this is a bug or a feature of PHP.)

For many applications in WordPress this isn’t terribly consequential. The important exception is plugins that need to detect whether or not they are running as a site-wide plugin under WordPress MU. One common method of doing that is the following (taken from the WP reCAPTCHA plugin):

if (basename(dirname(__FILE__)) == "mu-plugins")

The plugin expects wp_recaptcha.php to be at the root level of your mu-plugins directory and therefore that dirname(__FILE__) will return the MU-identifying information. The problem is that if wp_recaptcha.php is a symlink to a deploy location, this method becomes unreliable. For instance, we might have deployed our version of the plugin to /deploy/wp_recaptcha/current/wp_recaptcha.php

The solution is to avoid using __FILE__ for this purpose until it is “fixed”. A workaround that we came up with is to use the following conditional instead:

if(is_dir(WP_CONTENT_DIR . '/mu-plugins'))

After determining that MU is running the plugin, you can check if it is installed site-wide with the following additional check:

if(is_file(WP_CONTENT_DIR . '/mu-plugins/wp_recaptcha.php'))

If you know of a simpler or faster way we’d be very interested in hearing about it, as we perform this check at the beginning of almost all of the plugins we use. Much of this may not be necessary once MU is phased out in WordPress 3.0, so this is probably good enough for the time being; still, I’d rather not have to check two files at startup if at all possible.

Our fork of the WP reCAPTCHA plugin that contains this fix is over at GitHub and has since been pulled into the repository of record. Blaenk Denum, the developer managing the plugin, has said he’s working on refactoring the whole thing, so again this is just a temporary fix.