<?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>Will Norris &#187; plugin</title>
	<atom:link href="http://willnorris.com/tag/plugin/feed" rel="self" type="application/rss+xml" />
	<link>http://willnorris.com</link>
	<description>Thoughts on Identity, OpenID, WordPress, and Life</description>
	<lastBuildDate>Tue, 26 Jan 2010 16:25:05 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	
<creativeCommons:license>http://creativecommons.org/licenses/by-nc-sa/3.0/</creativeCommons:license>
		<item>
		<title>WordPress Plugin Pet Peeve #3: Not being extensible</title>
		<link>http://willnorris.com/2009/06/wordpress-plugin-pet-peeve-3-not-being-extensible</link>
		<comments>http://willnorris.com/2009/06/wordpress-plugin-pet-peeve-3-not-being-extensible#comments</comments>
		<pubDate>Thu, 04 Jun 2009 15:53:25 +0000</pubDate>
		<dc:creator>Will Norris</dc:creator>
				<category><![CDATA[technology]]></category>
		<category><![CDATA[pet-peeve]]></category>
		<category><![CDATA[plugin]]></category>
		<category><![CDATA[wordpress]]></category>

		<guid isPermaLink="false">http://willnorris.com/?p=671</guid>
		<description><![CDATA[So this is one that is incredibly easy to implement, and yet goes a really long way in keeping people happy with your plugin. The very reason that WordPress has a plugin API is because they know that different people want different things from their blog. Some people are satisfied with just the core functionality [...]

<div class="related-posts">
Possibly related posts:<ul><li><a href='http://willnorris.com/2009/06/wordpress-plugin-pet-peeve-2-direct-calls-to-plugin-files' rel='bookmark' title='Permanent Link: WordPress Plugin Pet Peeve #2: Direct Calls to Plugin Files'>WordPress Plugin Pet Peeve #2: Direct Calls to Plugin Files</a></li>
<li><a href='http://willnorris.com/2009/05/wordpress-plugin-pet-peeve-hardcoding-wp-content' rel='bookmark' title='Permanent Link: WordPress Plugin Pet Peeve #1: Hardcoding wp-content'>WordPress Plugin Pet Peeve #1: Hardcoding wp-content</a></li>
<li><a href='http://willnorris.com/2007/11/new-wordpress-plugin-fullfeed' rel='bookmark' title='Permanent Link: New WordPress plugin - FullFeed'>New WordPress plugin - FullFeed</a></li>
</ul></div>]]></description>
			<content:encoded><![CDATA[<p>So this is one that is incredibly easy to implement, and yet goes a <strong>really</strong> long way in keeping people happy with your plugin.  The very reason that WordPress has a <a href="http://codex.wordpress.org/Plugin_API">plugin API</a> is because they know that different people want different things from their blog.  Some people are satisfied with just the core functionality that WordPress provides, but most people want a little more.  Perhaps they are using WordPress as a photo blog, and need better support for handling that kind of data.  Perhaps they need WordPress to integrate with some other system, or pull in data from elsewhere.  Whatever their needs, there is no possible way WordPress could address them all in the core package.  And even if they were to try, people have different ideas on how the same feature should be implemented, so there would be no way to please everyone.  And unless your plugin is very simple, I can pretty well assure you that some of your users probably want it to do something more than it does today, or do it in a slightly different way.</p>

<p>The very same mechanisms that makes WordPress extensible can be used to make your plugin extensible as well.  Most of the time this will mean action and filter hooks.  As a plugin author, you are no doubt familiar with how these hooks work, since your plugin is using them to hook into WordPress.  But what some newer developers may not realize is just how easy it is to provide your own hooks to extend the functionality of your plugin.</p>

<p><span id="more-671"></span></p>

<h2>Where to add hooks</h2>

<p>When you&#8217;re getting started with your plugin it may not be obvious where to add hooks, and that&#8217;s okay.  If you already have a number of people using your plugin, then perhaps you may have already received requests from people wanting to add some kind of functionality to the plugin or change how something works.  Oftentimes these changes are appropriate to add directly into your plugin, and you are most certainly encouraged to do so when it makes sense.  But sometimes the request represents an edge-case&#8230; something that one individual is wanting to do, but is very likely <em>not</em> going to be useful to most people using your plugin.  Even worse, making such a change may be confusing or even undesirable by other users.  In these cases, see if you can provide the appropriate hooks to allow people to extend your plugin to suit their needs.</p>

<p><a href="http://wordpress.org/extend/plugins/extended-profile/">Extended Profile</a> is a good example which provides quite a few hooks for people to extend.  One of the core features of the plugin is that it allows you to output an hCard Profile on a page, like I have on the front page of <a href="http://willnorris.com/">willnorris.com</a>.  The plugin provides most of the common hCard attributes that we thought an individual might be interested in like name, website, address, telephone number, etc. To collect this data from the user, the plugin extends the standard WordPress Profile administration page.  But we knew that users might already have a different plugin capable of providing this data, or that they may want to pull the data form some other source. Additionally, the <a href="http://microformats.org/wiki/hCard">hCard microformat</a> supports a number of other attributes that we didn&#8217;t include in the plugin.  In order to support these use-cases, we used a combination of action and filter hooks (mostly filters, in our case) to allow the hCard profile to be supplemented, or outright replaced. This is actually how I added the &#8220;Last Seen&#8221; geo data to my hCard, which pulls data from <a href="http://brightkite.com/">Brightkite</a>.</p>

<p>As a general rule of thumb, action hooks are used to alert other plugins that you are at a particular point within a process.  Perhaps that you&#8217;re about to begin doing something, or that you&#8217;ve just finished doing something which other code may care about.  If you&#8217;re printing things to the screen, an action hook may be a good place to allow other plugins to print things as well at a very particular point in your plugin&#8217;s processing.</p>

<p>Filters are intended to allow other pieces of code to actually modify something that your plugin has done.  As mentioned above, the Extended Profile plugin makes heavy use of filters to allow other plugins to modify various aspects of the generated hCard before it is printed to the screen.  In fact, the plugin hooks into its own filters in order to provide most of the functionality, just like any other plugin would.</p>

<p>That last point is worth underscoring: <strong>hooks are not just for other plugins to use, you should be using them yourself</strong>.  WordPress makes extensive use of its own actions and filters, just take a look at <a href="http://core.trac.wordpress.org/browser/trunk/wp-includes/default-filters.php">default-filters.php</a>.  This has a number of benefits &#8212; it allows you to keep your own code fairly clean and modular, but perhaps more importantly it allows other plugins to actually <em>remove</em> functionality they don&#8217;t want using the <code>remove_action</code> and <code>remove_filter</code> methods. When it comes to making your plugin extensible, being able to remove functionality is just as important as the ability to add it.</p>

<h2>How to add hooks</h2>

<p>Adding new action or filter hooks is deceptively simple &#8212; there is no registration of hooks, you simply call <code>do_action</code> or <code>apply_filters</code> as needed.  A simplified version of what happens in the Extended Profile plugin might look like this:</p>

<pre><code>function get_extended_profile($user_id) {
    // start output buffering
    ob_start();

    // call the action hook which actually builds the profile
    do_action('extended_profile', $user_id);

    // get buffered content
    $profile = '&lt;div id="profile"&gt;' . ob_get_contents() . '&lt;/div&gt;';
    ob_end_clean();

    // filter everything before returning
    return apply_filters('post_extended_profile', $profile, $user_id);
}
</code></pre>

<p>Here you can see both a custom action and filter being used, first to build the profile and then to filter it.  When adding hooks to your plugin, its important to think about what data those hook functions may need in order to do something useful.  For example, functions which hook into the &#8216;extended&#95;profile&#8217; action need to know the ID of the user the profile is being built for so that they can fetch the appropriate data.  The same user ID is also passed to the &#8216;post&#95;extended&#95;profile&#8217; filter for the same reason.  With filters it&#8217;s important to remember that only the first parameter passed into the hooking functions gets filtered.  You can certainly pass other data as well to provide context, but only the first one is filtered (which is actually the second parameter passed to <code>apply_filters</code>, since the first one is the filter name).</p>

<p>The real beauty of WordPress action and filter hooks is in how lightweight the entire system is.  Calling a hook that has no registered functions returns almost immediately.  And registering a function to a non-existent hook has basically no overhead, and absolutely no consequence&#8230; the function simply never gets executed.  While you should certainly think through your plugin and add hooks at the logical points, don&#8217;t worry too much about adding too many.  Consider this: on a standard, out of the box WordPress installation with no plugins activated, a page load can easily cause over 1,000 calls to <code>do_action</code> and <code>apply_filter</code>.  Having your plugin add in a handful more is not going to have any kind of adverse effect on WordPress performance, and you will potentially make your plugin users much happier.</p>

<h2>Custom Constants</h2>

<p>Another way to expose additional functionality within your plugin is through the use of custom constants.  This is generally most appropriate to enable advanced functionality that you don&#8217;t want to expose through the normal WordPress option pages.  For example, suppose you have a plugin which makes API calls to some service.  The URL for that API endpoint is constant, but you might want to allow it to be overridden for testing purposes.  Use a PHP constant for your API URL, but check to see if it is already defined:</p>

<pre><code>// near the beginning of your plugin
if ( !defined('MY_PLUGIN_API_URL') ) {
    define('MY_PLUGIN_API_URL', 'http://api.example.com/service'); // default value
}

// throughout the rest of your plugin, always use the constant
file_get_contents( MY_PLUGIN_API_URL . '?user=joe' );
</code></pre>

<p>In this way, the API URL can be overridden by defining the constant in <code>wp-config.php</code>:</p>

<pre><code>define('MY_PLUGIN_API_URL', 'http://testing.example.net/test-service');
</code></pre>

<p>This is not as common as using action and filter hooks, but is still useful especially when you want to ensure that other plugins are not able to manipulate the value.  Unless you do some additional checking, you never know what functions may be hooking into your filter or what they&#8217;re going to do with the value&#8230; in fact that&#8217;s kind of the point, you&#8217;re not supposed to know or care.  But in cases where you want to allow the user to define a custom value, but also ensure that other plugins don&#8217;t manipulate the data in any way, constants are the way to go.</p>

<p>A final note if you do end up adding hooks or constants to your plugin.  Because so many plugins <strong>aren&#8217;t</strong> able to be extended in these ways, it is well worth drawing attention to the fact in your plugin&#8217;s readme.txt.  You can even go so far as to document all of the extension points as I did <a href="http://wiki.diso-project.org/wordpress-openid-api">with the OpenID plugin</a>, but you don&#8217;t necessarily have to.  Just pointing out that hooks exist is often enough, developers can quickly scan your code for them.</p>


<div class="related-posts"><p>Possibly related posts:</p><ul><li><a href='http://willnorris.com/2009/06/wordpress-plugin-pet-peeve-2-direct-calls-to-plugin-files' rel='bookmark' title='Permanent Link: WordPress Plugin Pet Peeve #2: Direct Calls to Plugin Files'>WordPress Plugin Pet Peeve #2: Direct Calls to Plugin Files</a></li>
<li><a href='http://willnorris.com/2009/05/wordpress-plugin-pet-peeve-hardcoding-wp-content' rel='bookmark' title='Permanent Link: WordPress Plugin Pet Peeve #1: Hardcoding wp-content'>WordPress Plugin Pet Peeve #1: Hardcoding wp-content</a></li>
<li><a href='http://willnorris.com/2007/11/new-wordpress-plugin-fullfeed' rel='bookmark' title='Permanent Link: New WordPress plugin - FullFeed'>New WordPress plugin - FullFeed</a></li>
</ul></div>]]></content:encoded>
			<wfw:commentRss>http://willnorris.com/2009/06/wordpress-plugin-pet-peeve-3-not-being-extensible/feed</wfw:commentRss>
		<slash:comments>9</slash:comments>
	<creativeCommons:license>http://creativecommons.org/licenses/by-nc-sa/3.0/</creativeCommons:license>
	</item>
		<item>
		<title>WordPress plugins - development version</title>
		<link>http://willnorris.com/2007/12/wordpress-plugins-development-version</link>
		<comments>http://willnorris.com/2007/12/wordpress-plugins-development-version#comments</comments>
		<pubDate>Fri, 07 Dec 2007 16:52:46 +0000</pubDate>
		<dc:creator>Will Norris</dc:creator>
				<category><![CDATA[identity]]></category>
		<category><![CDATA[technology]]></category>
		<category><![CDATA[plugin]]></category>
		<category><![CDATA[wordpress]]></category>
		<category><![CDATA[wp-openid]]></category>

		<guid isPermaLink="false">http://willnorris.com/2007/12/wordpress-plugins-development-version</guid>
		<description><![CDATA[I&#8217;m always hesitant to tell people to &#8220;grab the latest version of wp-openid from subversion&#8221;. That is often either followed by questions of &#8220;What is subversion?&#8221;, requests for help getting subversion to work, or the person whose bug I&#8217;m trying to fix doesn&#8217;t test the change because they don&#8217;t want to deal with subversion. Not [...]

<div class="related-posts">
Possibly related posts:<ul><li><a href='http://willnorris.com/2007/09/wordpress-openid-20-coming-soon' rel='bookmark' title='Permanent Link: WordPress OpenID 2.0 (coming soon?)'>WordPress OpenID 2.0 (coming soon?)</a></li>
<li><a href='http://willnorris.com/2007/02/new-wpopenid-r13' rel='bookmark' title='Permanent Link: new wpopenid (r13)'>new wpopenid (r13)</a></li>
<li><a href='http://willnorris.com/2007/10/new-openidnet' rel='bookmark' title='Permanent Link: New OpenID.net'>New OpenID.net</a></li>
</ul></div>]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m always hesitant to tell people to &#8220;grab the latest version of wp-openid from subversion&#8221;.  That is often either followed by questions of &#8220;What is subversion?&#8221;, requests for help getting subversion to work, or the person whose bug I&#8217;m trying to fix doesn&#8217;t test the change because they don&#8217;t want to deal with subversion.  Not that I can blame them&#8230; Windows and pre-Leopard Macs don&#8217;t ship with a subversion client, so it really is a bit of work for the end-user.</p>

<p>Somehow, I completely missed the fact that wordpress.org addresses this by providing a zip file of the latest trunk code in subversion in addition to whatever you designate as the latest stable release.  On the plugin page, click on <em>Other Versions</em>, then on the <em>Development Version</em> at the bottom of the page.  For wp-openid, that is <a href="http://wordpress.org/extend/plugins/openid/download/">here</a>.  I imagine many other plugin authors knew about this, but it was news to me, and very welcome news.  So if you&#8217;ve been holding off testing some new changes I&#8217;ve made because you don&#8217;t want to mess with subversion, you now have an easy alternative.</p>


<div class="related-posts"><p>Possibly related posts:</p><ul><li><a href='http://willnorris.com/2007/09/wordpress-openid-20-coming-soon' rel='bookmark' title='Permanent Link: WordPress OpenID 2.0 (coming soon?)'>WordPress OpenID 2.0 (coming soon?)</a></li>
<li><a href='http://willnorris.com/2007/02/new-wpopenid-r13' rel='bookmark' title='Permanent Link: new wpopenid (r13)'>new wpopenid (r13)</a></li>
<li><a href='http://willnorris.com/2007/10/new-openidnet' rel='bookmark' title='Permanent Link: New OpenID.net'>New OpenID.net</a></li>
</ul></div>]]></content:encoded>
			<wfw:commentRss>http://willnorris.com/2007/12/wordpress-plugins-development-version/feed</wfw:commentRss>
		<slash:comments>13</slash:comments>
	<creativeCommons:license>http://creativecommons.org/licenses/by-nc-sa/3.0/</creativeCommons:license>
	</item>
		<item>
		<title>wp-openid 2.0 released</title>
		<link>http://willnorris.com/2007/11/wp-openid-20-released</link>
		<comments>http://willnorris.com/2007/11/wp-openid-20-released#comments</comments>
		<pubDate>Sat, 10 Nov 2007 02:04:12 +0000</pubDate>
		<dc:creator>Will Norris</dc:creator>
				<category><![CDATA[identity]]></category>
		<category><![CDATA[technology]]></category>
		<category><![CDATA[openid]]></category>
		<category><![CDATA[plugin]]></category>
		<category><![CDATA[wordpress]]></category>
		<category><![CDATA[wp-openid]]></category>

		<guid isPermaLink="false">http://willnorris.com/2007/11/wp-openid-20-released</guid>
		<description><![CDATA[I&#8217;m sure people are tired of me talking about how soon this will be released, so I promise I&#8217;ll shut up now. I&#8217;ve just tagged version 2.0 of wp-openid, a WordPress plugin which allows you to use OpenID for authenticating users and commenters. There are a number of really cool features we just weren&#8217;t able [...]

<div class="related-posts">
Possibly related posts:<ul><li><a href='http://willnorris.com/2008/07/wp-openid-220-released' rel='bookmark' title='Permanent Link: wp-openid 2.2.0 released'>wp-openid 2.2.0 released</a></li>
<li><a href='http://willnorris.com/2007/09/wordpress-openid-20-coming-soon' rel='bookmark' title='Permanent Link: WordPress OpenID 2.0 (coming soon?)'>WordPress OpenID 2.0 (coming soon?)</a></li>
<li><a href='http://willnorris.com/2005/07/shibboleth-13-released' rel='bookmark' title='Permanent Link: Shibboleth 1.3 released'>Shibboleth 1.3 released</a></li>
</ul></div>]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m sure people are tired of me talking about how soon this will be released, so I promise I&#8217;ll shut up now.  I&#8217;ve just tagged version 2.0 of wp-openid, a WordPress plugin which allows you to use OpenID for authenticating users and commenters.  There are a number of really cool features we just weren&#8217;t able to get into this release, so that just means more to come in the next version.  Go <a href="http://wordpress.org/extend/plugins/openid/">download it</a> and have fun.  Release notes, screenshots, FAQ, install instructions, etc can all be found there.  I&#8217;ll probably be unplugged most of the weekend, so try not to break anything too bad. ;)</p>


<div class="related-posts"><p>Possibly related posts:</p><ul><li><a href='http://willnorris.com/2008/07/wp-openid-220-released' rel='bookmark' title='Permanent Link: wp-openid 2.2.0 released'>wp-openid 2.2.0 released</a></li>
<li><a href='http://willnorris.com/2007/09/wordpress-openid-20-coming-soon' rel='bookmark' title='Permanent Link: WordPress OpenID 2.0 (coming soon?)'>WordPress OpenID 2.0 (coming soon?)</a></li>
<li><a href='http://willnorris.com/2005/07/shibboleth-13-released' rel='bookmark' title='Permanent Link: Shibboleth 1.3 released'>Shibboleth 1.3 released</a></li>
</ul></div>]]></content:encoded>
			<wfw:commentRss>http://willnorris.com/2007/11/wp-openid-20-released/feed</wfw:commentRss>
		<slash:comments>49</slash:comments>
	<creativeCommons:license>http://creativecommons.org/licenses/by-nc-sa/3.0/</creativeCommons:license>
	</item>
		<item>
		<title>New WordPress plugin - FullFeed</title>
		<link>http://willnorris.com/2007/11/new-wordpress-plugin-fullfeed</link>
		<comments>http://willnorris.com/2007/11/new-wordpress-plugin-fullfeed#comments</comments>
		<pubDate>Wed, 07 Nov 2007 23:05:23 +0000</pubDate>
		<dc:creator>Will Norris</dc:creator>
				<category><![CDATA[technology]]></category>
		<category><![CDATA[atom]]></category>
		<category><![CDATA[plugin]]></category>
		<category><![CDATA[rss]]></category>
		<category><![CDATA[wordpress]]></category>

		<guid isPermaLink="false">http://willnorris.com/2007/11/new-wordpress-plugin-fullfeed</guid>
		<description><![CDATA[Update - thirteen minutes after I posted this, Carsten pointed out there is another plugin that does this exact same thing (and is in fact named the same!). Go check out cavemonkey&#8217;s plugin. I noticed an interesting phenomenon this last week &#8212; Mint recorded a 400% increase in page hits on Tuesday, the day after [...]

<div class="related-posts">
Possibly related posts:<ul><li><a href='http://willnorris.com/2007/03/livejournal-syndication' rel='bookmark' title='Permanent Link: LiveJournal syndication'>LiveJournal syndication</a></li>
<li><a href='http://willnorris.com/2009/06/wordpress-plugin-pet-peeve-2-direct-calls-to-plugin-files' rel='bookmark' title='Permanent Link: WordPress Plugin Pet Peeve #2: Direct Calls to Plugin Files'>WordPress Plugin Pet Peeve #2: Direct Calls to Plugin Files</a></li>
<li><a href='http://willnorris.com/2009/06/wordpress-plugin-pet-peeve-3-not-being-extensible' rel='bookmark' title='Permanent Link: WordPress Plugin Pet Peeve #3: Not being extensible'>WordPress Plugin Pet Peeve #3: Not being extensible</a></li>
</ul></div>]]></description>
			<content:encoded><![CDATA[<p><strong>Update</strong> - thirteen minutes after I posted this, Carsten pointed out there is another plugin that does this exact same thing (and is in fact named the same!).  Go check out <a href="http://cavemonkey50.com/code/full-feed/">cavemonkey&#8217;s plugin</a>.</p>

<p>I noticed an interesting phenomenon this last week &#8212; <a href="http://www.haveamint.com/">Mint</a> recorded a 400% increase in page hits on Tuesday, the day after I made two blog posts about OpenID.  Now it&#8217;s not unusual for the hits to go up after a new OpenID post since I&#8217;m part of the <a href="http://planet.openid.net/">OpenID Planet feed</a>, but never like this.  Since these were slightly longer posts, I included a <a href="http://codex.wordpress.org/Customizing_the_Read_More">more-tag</a> so that only the first paragraph or so was shown on my index page.  I do this not to artificially increase my page-views (I don&#8217;t run any ads), but simply to keep the front page somewhat lean.  Unfortunately, WordPress also clips the post content in your syndication feeds, even if you have selected the option to show the full text.  In fairness, the admin page is very clear that it will cut off posts, but there is still no option to disable this.  So since I included more-tags in my posts this week, everyone who subscribes to the OpenID Planet feed had to click through to my website in order to read the rest of my posts.  I personally hate summary feeds, and I certainly didn&#8217;t mean to do that myself, sorry folks.  So last night I whipped together a little WordPress plugin that, when activated, will ignore more-tags when full-text syndication feeds are enabled.  It&#8217;s a little bit of a weird way to do it, but until wordpress-core changes to include more-tag splitting as a filter on <code>the_content</code>, there&#8217;s no elegant way of doing this.  <strike>For now the plugin can be found on my local project page, but I&#8217;ve requested a project space on wp-plugins.org.</strike></p>


<div class="related-posts"><p>Possibly related posts:</p><ul><li><a href='http://willnorris.com/2007/03/livejournal-syndication' rel='bookmark' title='Permanent Link: LiveJournal syndication'>LiveJournal syndication</a></li>
<li><a href='http://willnorris.com/2009/06/wordpress-plugin-pet-peeve-2-direct-calls-to-plugin-files' rel='bookmark' title='Permanent Link: WordPress Plugin Pet Peeve #2: Direct Calls to Plugin Files'>WordPress Plugin Pet Peeve #2: Direct Calls to Plugin Files</a></li>
<li><a href='http://willnorris.com/2009/06/wordpress-plugin-pet-peeve-3-not-being-extensible' rel='bookmark' title='Permanent Link: WordPress Plugin Pet Peeve #3: Not being extensible'>WordPress Plugin Pet Peeve #3: Not being extensible</a></li>
</ul></div>]]></content:encoded>
			<wfw:commentRss>http://willnorris.com/2007/11/new-wordpress-plugin-fullfeed/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
	<creativeCommons:license>http://creativecommons.org/licenses/by-nc-sa/3.0/</creativeCommons:license>
	</item>
	</channel>
</rss>
