Plugins in symlinked directories?

When I develop plugins I test them on multiple versions of WordPress by symlinking my plugin directory in the different wp-content directories. This is great since I only have to edit the files once, but it breaks an important construct to generate references to resources in my plugin: __FILE__ refers to the physical plugin location, not the one in wp-content. How should I solve this?

My directory structure looks like this:

Read More
  • /path/to/wordpress/development/dir/
    • plugin-development/
      • monkeyman-rewrite-analyzer/
        • monkeyman-rewrite-analyzer.php
        • js/
          • monkeyman-rewrite-analyzer.js
    • versions/
      • 3.1/
        • wp-content/
          • plugins/
            • monkeyman-rewrite-analyzer as a symlink to the above plugin
      • 3.1-multi-dir/
        • wp-content/
          • plugins/
            • monkeyman-rewrite-analyzer as a symlink to the above plugin
      • 3.1-multi-domain/
        • wp-content/
          • plugins/
            • monkeyman-rewrite-analyzer as a symlink to the above plugin

If I want to enqueue the Javascript file, I should use plugins_url( 'monkeyman-rewrite-analyzer.js', [base file] ), but using __FILE__ here will not work, because the actual file path will be /path/to/wordpress/development/dir/plugin-development/monkeyman-rewrite-analyzer/monkeyman-rewrite-analyzer.php, not /path/to/wordpress/development/dir/versions/*/wp-content/plugins/monkeyman-rewrite-analyzer/monkeyman-rewrite-analyzer.php, so WordPress cannot strip the first part out and generate a URL relative to the WordPress installation.

Related posts

Leave a Reply

4 comments

  1. I currently use a trick to get the WordPress-relative file location: wp_get_active_and_valid_plugins() returns the file paths, and wp_settings.php loops over them and includes the files. So the global $plugin variable will refer to your current plugin (of course only when the plugin is loaded, so I save it in a prefixed global variable):

    $monkeyman_Rewrite_Analyzer_file = $plugin;
    

    Because plugins can also be loaded as must-use or network plugins and these loops use other variable names, the complete code looks like this:

    $monkeyman_Rewrite_Analyzer_file = __FILE__;
    if ( isset( $mu_plugin ) ) {
        $monkeyman_Rewrite_Analyzer_file = $mu_plugin;
    }
    if ( isset( $network_plugin ) ) {
        $monkeyman_Rewrite_Analyzer_file = $network_plugin;
    }
    if ( isset( $plugin ) ) {
        $monkeyman_Rewrite_Analyzer_file = $plugin;
    }
    

    The fallback is still __FILE__, so if someone changes the loop variable name in the future my code should still work for 99% of all installations, only my development setup will fail and I can release a new version with ease.

  2. $_SERVER["SCRIPT_FILENAME"] works if you use it right. You just have to use it to set a base path, and then include your files using a path relative to that base path.

    Something like:

    $plugin_dir = dirname($_SERVER["SCRIPT_FILENAME"]);
    $myFile = $plugin_dir."/includes/js/myJavascriptFile.js";
    

    Note, this is more useful when you don’t have access to wp-blog-header.php yet (i.e. in processing an ajax-based form request)