<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	xmlns:creativeCommons="http://backend.userland.com/creativeCommonsRssModule"
>

<channel>
	<title>willnorris.com &#187; plugins</title>
	<atom:link href="http://willnorris.com/tag/plugins/feed" rel="self" type="application/rss+xml" />
	<link>http://willnorris.com</link>
	<description>there&#039;s more to life than this</description>
	<lastBuildDate>Tue, 15 May 2012 21:57:32 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.4-beta3-20574</generator>
<creativeCommons:license>http://creativecommons.org/licenses/by-nc-sa/3.0/</creativeCommons:license>
		<item>
		<title>WordPress Plugin Pet Peeve #2: Direct Calls to Plugin Files</title>
		<link>http://willnorris.com/2009/06/wordpress-plugin-pet-peeve-2-direct-calls-to-plugin-files</link>
		<comments>http://willnorris.com/2009/06/wordpress-plugin-pet-peeve-2-direct-calls-to-plugin-files#comments</comments>
		<pubDate>Tue, 02 Jun 2009 20:05:45 +0000</pubDate>
		<dc:creator>Will Norris</dc:creator>
				<category><![CDATA[technology]]></category>
		<category><![CDATA[pet-peeve]]></category>
		<category><![CDATA[plugins]]></category>
		<category><![CDATA[wordpress]]></category>

		<guid isPermaLink="false">http://willnorris.com/?p=637</guid>
		<description><![CDATA[This is actually very similar to my first pet peeve of hardcoding the path to wp-content, in that it makes assumptions about where files are placed on the filesystem. Oftentimes, plugins need to handle certain kinds of requests, maybe for some specific protocol, or to handle an AJAX request. Some plugins will do this by [...]]]></description>
			<content:encoded><![CDATA[<p>This is actually very similar to my first pet peeve of <a href="http://willnorris.com/2009/05/wordpress-plugin-pet-peeve-hardcoding-wp-content">hardcoding the path to wp-content</a>, in that it makes assumptions about where files are placed on the filesystem.  Oftentimes, plugins need to handle certain kinds of requests, maybe for some specific protocol, or to handle an AJAX request.  Some plugins will do this by making an HTTP request directly to one of the files in the plugin&#8230; something like:</p>

<pre><code>echo '&lt;script type="text/javascript"&gt;
    jQuery.get("' . plugins_url('my-plugin/ajax-handler.php') . '");
    // do something with AJAX data ...
&lt;/script&gt;';
</code></pre>

<p>This is not a problem in and of itself, in fact it&#8217;s great that the plugin developer is actually using the <code>plugins_url</code> function!  The problem arises in the <code>my-plugin/ajax-handler.php</code> file itself.  <span id="more-637"></span> If that plugin needs to make use of any WordPress data or functions, then the developer is certain to do something very ugly.  You&#8217;ll know it when you see it:</p>

<pre><code>require_once('../../../wp-load.php');

// or sometimes you'll see...
require_once('../../../wp-config.php');
</code></pre>

<p>So what is this, and why is it so bad?  Well, the <code>wp-load.php</code> is a file provided by WordPress core that bootstraps the WordPress environment.  It loads in the <code>wp-config.php</code> file, loads all the common WordPress functions and classes, initializes the database connection, and gets everything in place to process the request.  These are all important things, and provides a lot of functionality that the plugin developer may need.  The problem is that in the <code>require_once</code> call above, the plugin developer is assuming that the <code>wp-load.php</code> file is in a directory exactly three levels up in the filesystem from their plugin directory.  In a standard WordPress deployment, this will be true and everything will work fine (for the most part).  But <a href="http://willnorris.com/2009/05/wordpress-plugin-pet-peeve-hardcoding-wp-content">as we&#8217;ve already seen</a>, WordPress allows deployers to move where their <code>wp-content</code> or their plugins directory lives, so the above code will break completely.  Yes, there are files in WordPress core that do something similar to the above, for example <code>wp-admin/admin.php</code>.  But these are safe for WordPress core files because they <strong>do</strong> know where certain files will be.  It is <strong>never</strong> safe to make this assumption from a plugin.  I think it&#8217;s pretty safe to say that if you have a <code>require</code> or <code>include</code> call that goes up more than a couple of directories (&#8220;<code>../../</code>&#8221;), you&#8217;re almost certainly doing it wrong.</p>

<p>A couple of points to emphasize before moving on: if your plugin files are <strong>not</strong> accessing any built-in WordPress functions, classes, or data, calling them directly should be just fine.  Also, if you&#8217;re doing <a href="http://codex.wordpress.org/AJAX_in_Plugins#Ajax_on_the_Administration_Side">AJAX calls on admin pages</a>, use the built-in functionality WordPress core provides.</p>

<h3>The Right Way</h3>

<p>So the right way of doing this is actually pretty straightforward conceptually, but in practice there are a couple of ways to do it depending on your needs.  The short answer is that instead of calling your plugin file directly, you must send the request through the standard WordPress request handling mechanisms.  This requires two things: constructing your request properly, and then hooking into the WordPress request handling code at the appropriate time to take over the request handling yourself.</p>

<p>All standard WordPress requests eventually get broken down to a request to <code>/index.php</code> with a bunch of URL parameters.  For example, when someone goes to your blog post at</p>

<pre><code>http://example.com/2009/01/hello-world
</code></pre>

<p>WordPress uses the configured permalink structure to break this down to</p>

<pre><code>http://example.com/index.php?year=2008&amp;monthnum=01&amp;name=hello-world
</code></pre>

<p>And from that, WordPress can determine which post the request is for, and serve that up accordingly.  So what we want to do is be able to construct a request along the lines of</p>

<pre><code>http://example.com/index.php?my-plugin=ajax-handler
</code></pre>

<p>and then hook into the WordPress request handling logic so that we can process this request ourselves.  Fortunately, WordPress provides an action hook for exactly that purpose, called <code>process_request</code>.  Functions that hook into this action are passed one parameter, an instance of the <code>WP</code> class, which encapsulates most of the specific parameters for the current request.  If we want to process only the requests which include <code>my-plugin=ajax-handler</code>, we would add something like this to the plugin:</p>

<pre><code>function my_plugin_parse_request($wp) {
    // only process requests with "my-plugin=ajax-handler"
    if (array_key_exists('my-plugin', $wp-&gt;query_vars) 
            &amp;&amp; $wp-&gt;query_vars['my-plugin'] == 'ajax-handler') {

        // process the request.
        // For now, we'll just call wp_die, so we know it got processed
        wp_die('my-plugin ajax-handler!');
    }
}
add_action('parse_request', 'my_plugin_parse_request');
</code></pre>

<p>If you&#8217;re following along at home, try accessing <code>http://example.com/index.php?my-plugin=ajax-handler</code>.  What happens?  Most likely, nothing at all&#8230; it still loads your normal blog index page.  So what went wrong?  In order to have the WordPress request handling code process custom URL parameters, we have to register them.  This is necessary for a number of reasons including security, performance, and also to ensure that WordPress doesn&#8217;t accidentally process something it wasn&#8217;t meant to.  Fortunately, registering a new query variable is very simple using the <code>query_vars</code> filter hook:</p>

<pre><code>function my_plugin_query_vars($vars) {
    $vars[] = 'my-plugin';
    return $vars;
}
add_filter('query_vars', 'my_plugin_query_vars');
</code></pre>

<p>This simply registers &#8216;my-plugin&#8217; as a valid query variable to be processed by WordPress, but says nothing about valid values for that variable.  So now try reloading the page, and you should be greeted with a simple styled page reading &#8220;my-plugin ajax-handler!&#8221;.  Now you just need to modify the <code>my_plugin_parse_request</code> function to actually do your custom request logic, and you&#8217;re good to go.</p>

<p>I mentioned earlier that there are a couple of ways to do this.  The one caveat to be aware of with the above approach is that you are hooking into the WordPress request processing logic <strong>before</strong> WordPress has processed the query itself.  WordPress&#8217;s query handling logic is responsible for examining the request and figuring out what page or post within WordPress the request maps to.  This is also what makes the <code>is_*</code> functions work: <code>is_page</code>, <code>is_front_page</code>, <code>is_feed</code>, etc.  If your plugin is actually doing things on normal WordPress page requests and needs access to these functions, then instead of hooking into the <code>parse_request</code> action, you should use the <code>wp</code> action.  You are still passed an instance of the <code>WP</code> class, so all you need to modify is the <code>add_action</code> call:</p>

<pre><code>add_action('wp', 'my_plugin_parse_request');
</code></pre>

<p>I would recommend that you <strong>not</strong> make this change unless you know that you need to.  Otherwise, you&#8217;re having WordPress perform a lot of logic that isn&#8217;t necessary (including hits against the database), potentially making the request take longer than it needs to be.  Though the difference is likely to be imperceptible, it&#8217;s just good practice to keep things as fast as possible.  And when dealing with custom request handling, you can keep things fast by hooking into as soon in the flow as possible.</p>

<h3>Additional Exercise for the reader</h3>

<p>If you don&#8217;t like the look of URL containing <code>index.php?my-plugin=ajax-handler</code>, and instead want something pretty like</p>

<pre><code>http://example.com/my-plugin/ajax-handler
</code></pre>

<p>that is certainly possible with just a little bit more work (see <a href="http://codex.wordpress.org/Function_Reference/WP_Rewrite">WP_Rewrite</a>).  The <a href="http://wordpress.org/extend/plugins/openid/">WordPress OpenID Plugin</a> does this to achieve nice endpoint URLs for the OpenID authentication protocol.  A word of caution with this however: if you want to make sure that your plugin works on the widest number of deployments, where you have no idea what their permalink structure is going to be, there is a bit more work that is necessary.  You can see the rewrite rules I setup for the OpenID plugin in the <a href="http://code.google.com/p/diso/source/browse/wordpress/openid/trunk/common.php">common.php</a> file.  There&#8217;s a lot of other stuff in there, and the rewrite code is a little confusing at parts, but it&#8217;s all there.  I will actually be changing this in the future to simplify things a bit, so avoid complicating matters unless there is a real reason to.</p>

<p>Further codex reading:</p>

<ul>
<li><a href="http://codex.wordpress.org/Query_Overview">http://codex.wordpress.org/Query_Overview</a></li>
<li><a href="http://codex.wordpress.org/Custom_Queries">http://codex.wordpress.org/Custom_Queries</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://willnorris.com/2009/06/wordpress-plugin-pet-peeve-2-direct-calls-to-plugin-files/feed</wfw:commentRss>
		<slash:comments>13</slash:comments>
		</item>
		<item>
		<title>WordPress Plugin Pet Peeve #1: Hardcoding wp-content</title>
		<link>http://willnorris.com/2009/05/wordpress-plugin-pet-peeve-hardcoding-wp-content</link>
		<comments>http://willnorris.com/2009/05/wordpress-plugin-pet-peeve-hardcoding-wp-content#comments</comments>
		<pubDate>Sat, 23 May 2009 22:50:31 +0000</pubDate>
		<dc:creator>Will Norris</dc:creator>
				<category><![CDATA[technology]]></category>
		<category><![CDATA[pet-peeve]]></category>
		<category><![CDATA[plugins]]></category>
		<category><![CDATA[wordpress]]></category>

		<guid isPermaLink="false">http://willnorris.com/?p=618</guid>
		<description><![CDATA[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 &#8216;wp-content&#8217;, 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 [...]]]></description>
			<content:encoded><![CDATA[<p>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 &#8216;wp-content&#8217;, and resides at the root of the primary WordPress folder.  However, since WordPress 2.6 (released July 2008), this location <a href="http://codex.wordpress.org/Editing_wp-config.php#Moving_wp-content">can be moved</a> by simply defining a constant in <code>wp-config.php</code>.  That&#8217;s precisely what I do on my website: my WordPress installation lives at <a href="http://willnorris.com/wordpress/">/wordpress</a>, while my content folder is at <a href="http://willnorris.com/wordpress-content/">/wordpress-content</a>.  I like having this separation of core WordPress files from the themes, plugins, and uploads I&#8217;ve added myself.  It also makes it easier for me to upgrade WordPress, since I don&#8217;t use the built-in upgrade system added in 2.7.  Any plugins that still hardcode the path of the <code>wp-content</code> folder break in often spectacular ways on my site.</p>

<p>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.  <span id="more-618"></span> So instead of including an image using something like:</p>

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

<p>you would have:</p>

<pre><code>&lt;img src="&lt;?php echo WP_PLUGIN_URL ?&gt;/my-plugin/images/logo.png" /&gt;
</code></pre>

<p>or even better:</p>

<pre><code>&lt;img src="&lt;?php echo plugins_url('my-plugin/images/logo.png') ?&gt;" /&gt;
</code></pre>

<p>Since these constants were added in WordPress 2.6, they obviously won&#8217;t work in earlier versions.  No problem, you can define them yourself in your plugin.  The WordPress Codex page <a href="http://codex.wordpress.org/Determining_Plugin_and_Content_Directories">Determining Plugin and Content Directories</a> 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:</p>

<pre><code>// 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' );
</code></pre>

<p>Everywhere else in your plugin, make sure that you use the constants, not the hardcoded path.  If the string &#8216;wp-content&#8217; appears anywhere in your plugin that isn&#8217;t defining one of the constants above, you&#8217;re doing it wrong.  If you also want to make sure the functions like <code>plugins_url</code> are available in older versions of WordPress, see the <a href="http://code.google.com/p/diso/source/browse/wordpress/openid/trunk/compatibility.php">compatibility.php</a> file the ships with the <a href="http://wordpress.org/extend/plugins/openid/">WordPress OpenID Plugin</a>.</p>

<p>So plugin authors, please go and fix this in your plugins.  Please?  Otherwise I can&#8217;t use your plugin at all on my site.</p>
]]></content:encoded>
			<wfw:commentRss>http://willnorris.com/2009/05/wordpress-plugin-pet-peeve-hardcoding-wp-content/feed</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
	</channel>
</rss>

