<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss 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:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" xmlns:rawvoice="http://www.rawvoice.com/rawvoiceRssModule/" version="2.0"><channel><title>WPCandyWPCandy » Categories Archives for  Tutorials</title> <link>http://wpcandy.com</link> <description>A blog all about WordPress. Yes, we're a bit meta.</description> <lastBuildDate>Thu, 31 May 2012 22:07:41 +0000</lastBuildDate> <language>en</language> <sy:updatePeriod>hourly</sy:updatePeriod> <sy:updateFrequency>1</sy:updateFrequency> <generator>http://wordpress.org/?v=3.3.2</generator><itunes:summary>A blog all about WordPress. Yes, we're a bit meta.</itunes:summary> <itunes:author>WPCandy</itunes:author> <itunes:explicit>no</itunes:explicit> <itunes:image href="http://wpcandy.gooroohq.com/files/powerpress/podcast-larger.png" /> <itunes:subtitle>A blog all about WordPress. Yes, we're a bit meta.</itunes:subtitle> <image><title>WPCandyWPCandy » Categories Archives for  Tutorials</title> <url>http://wpcandy.gooroohq.com/wp-content/plugins/powerpress/rss_default.jpg</url><link>http://wpcandy.com/category/teaches</link> </image> <atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/wpcandytutorials" /><feedburner:info xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" uri="wpcandytutorials" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><item><title>Dear theme developers, this is how you add scripts in WordPress themes</title><link>http://wpcandy.com/teaches/how-to-load-scripts-in-wordpress-themes?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=how-to-load-scripts-in-wordpress-themes</link> <comments>http://wpcandy.com/teaches/how-to-load-scripts-in-wordpress-themes#comments</comments> <pubDate>Tue, 15 May 2012 03:09:34 +0000</pubDate> <dc:creator>Brian Krogsgard</dc:creator> <category><![CDATA[Tutorials]]></category> <category><![CDATA[Themes]]></category><guid isPermaLink="false">http://wpcandy.com/?p=38637</guid> <description><![CDATA[There are a lot of themes out there. And a ton of them are not &#8230;  <a
href="http://wpcandy.com/teaches/how-to-load-scripts-in-wordpress-themes">Continue reading <span
class="meta-nav">&#8594;</span></a><div
class="tentblogger-rss-footer"><p>You just finished reading <a
href="http://wpcandy.com/?p=38637">Dear theme developers, this is how you add scripts in WordPress themes</a> on <a
href="http://wpcandy.com" title="WPCandy WordPress community news">WPCandy</a>. Please consider leaving a comment!</p><p></p></div>]]></description> <content:encoded><![CDATA[<p><a
href="http://wpcandy.com/?p=38637"><img
src="http://cdn.wpcandy.com/files/2012/05/scriptsenqueue.jpg" alt="properly enqueue scripts in WordPress  themes" title="scriptsenqueue" width="600" height="264" class="aligncenter size-full wp-image-38644" /></a><br
/> There are a lot of themes out there. And <em>a ton</em> of them are not including javascript files properly. So theme developers, please pay attention: this is how to include scripts in your themes properly. And guess what? It&#8217;s really easy.</p><p>Let&#8217;s lay some groundwork:</p><ol><li>This example would go in your functions.php file.</li><li>This example assumes your theme is a parent theme.</li></ol><p>In this example, I&#8217;m registering four scripts, and enqueuing two. I&#8217;ll explain it afterward.</p><div
id="gist-2698599" class="gist"><div
class="gist-file"><div
class="gist-data gist-syntax"><div
class="highlight"><pre><div class='line' id='LC1'><span class="cp">&lt;?php</span></div><div class='line' id='LC2'><span class="cm">/*</span></div><div class='line' id='LC3'><span class="cm"> * WordPress Sample function and action</span></div><div class='line' id='LC4'><span class="cm"> * for loading scripts in themes</span></div><div class='line' id='LC5'><span class="cm"> */</span></div><div class='line' id='LC6'>&nbsp;</div><div class='line' id='LC7'><span class="c1">// Let&#39;s hook in our function with the javascript files with the wp_enqueue_scripts hook </span></div><div class='line' id='LC8'><br/></div><div class='line' id='LC9'><span class="nx">add_action</span><span class="p">(</span> <span class="s1">&#39;wp_enqueue_scripts&#39;</span><span class="p">,</span> <span class="s1">&#39;wpcandy_load_javascript_files&#39;</span> <span class="p">);</span></div><div class='line' id='LC10'><br/></div><div class='line' id='LC11'><span class="c1">// Register some javascript files, because we love javascript files. Enqueue a couple as well </span></div><div class='line' id='LC12'><br/></div><div class='line' id='LC13'><span class="k">function</span> <span class="nf">wpcandy_load_javascript_files</span><span class="p">()</span> <span class="p">{</span></div><div class='line' id='LC14'><br/></div><div class='line' id='LC15'>&nbsp;&nbsp;<span class="nx">wp_register_script</span><span class="p">(</span> <span class="s1">&#39;info-caroufredsel&#39;</span><span class="p">,</span> <span class="nx">get_template_directory_uri</span><span class="p">()</span> <span class="o">.</span> <span class="s1">&#39;/js/jquery.carouFredSel-5.5.0-packed.js&#39;</span><span class="p">,</span> <span class="k">array</span><span class="p">(</span><span class="s1">&#39;jquery&#39;</span><span class="p">),</span> <span class="s1">&#39;5.5.0&#39;</span><span class="p">,</span> <span class="k">true</span> <span class="p">);</span></div><div class='line' id='LC16'>&nbsp;&nbsp;<span class="nx">wp_register_script</span><span class="p">(</span> <span class="s1">&#39;info-carousel-instance&#39;</span><span class="p">,</span> <span class="nx">get_template_directory_uri</span><span class="p">()</span> <span class="o">.</span> <span class="s1">&#39;/js/info-carousel-instance.js&#39;</span><span class="p">,</span> <span class="k">array</span><span class="p">(</span><span class="s1">&#39;info-caroufredsel&#39;</span><span class="p">),</span> <span class="s1">&#39;1.0&#39;</span><span class="p">,</span> <span class="k">true</span> <span class="p">);</span></div><div class='line' id='LC17'><br/></div><div class='line' id='LC18'>&nbsp;&nbsp;<span class="nx">wp_register_script</span><span class="p">(</span> <span class="s1">&#39;jquery.flexslider&#39;</span><span class="p">,</span> <span class="nx">get_template_directory_uri</span><span class="p">()</span><span class="o">.</span><span class="s1">&#39;/js/jquery.flexslider-min.js&#39;</span><span class="p">,</span> <span class="k">array</span><span class="p">(</span><span class="s1">&#39;jquery&#39;</span><span class="p">),</span> <span class="s1">&#39;1.7&#39;</span><span class="p">,</span> <span class="k">true</span> <span class="p">);</span></div><div class='line' id='LC19'>&nbsp;&nbsp;<span class="nx">wp_register_script</span><span class="p">(</span> <span class="s1">&#39;home-page-main-flex-slider&#39;</span><span class="p">,</span> <span class="nx">get_template_directory_uri</span><span class="p">()</span><span class="o">.</span><span class="s1">&#39;/js/home-page-main-flex-slider.js&#39;</span><span class="p">,</span> <span class="k">array</span><span class="p">(</span><span class="s1">&#39;jquery.flexslider&#39;</span><span class="p">),</span> <span class="s1">&#39;1.0&#39;</span><span class="p">,</span> <span class="k">true</span> <span class="p">);</span></div><div class='line' id='LC20'><br/></div><div class='line' id='LC21'>&nbsp;&nbsp;<span class="nx">wp_enqueue_script</span><span class="p">(</span> <span class="s1">&#39;info-carousel-instance&#39;</span> <span class="p">);</span></div><div class='line' id='LC22'>&nbsp;&nbsp;</div><div class='line' id='LC23'>&nbsp;&nbsp;<span class="k">if</span> <span class="p">(</span> <span class="nx">is_front_page</span><span class="p">()</span> <span class="p">)</span> <span class="p">{</span></div><div class='line' id='LC24'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="nx">wp_enqueue_script</span><span class="p">(</span><span class="s1">&#39;home-page-main-flex-slider&#39;</span><span class="p">);</span></div><div class='line' id='LC25'>&nbsp;&nbsp;<span class="p">}</span></div><div class='line' id='LC26'><br/></div><div class='line' id='LC27'><span class="p">}</span></div><div class='line' id='LC28'><span class="cp">?&gt;</span><span class="x"></span></div></pre></div></div><div
class="gist-meta"> <a
href="https://gist.github.com/raw/2698599/6ca9b6642af4ef795b77ee919147b09b431548bb/enqueue-scripts.php" style="float:right;">view raw</a> <a
href="https://gist.github.com/2698599#file_enqueue_scripts.php" style="float:right;margin-right:10px;color:#666">enqueue-scripts.php</a> <a
href="https://gist.github.com/2698599">This Gist</a> brought to you by <a
href="http://github.com">GitHub</a>.</div></div></div><h3>Now let&#8217;s break it down</h3><p><span
id="more-38637"></span></p><p>We are using an action hook called wp_enqueue_scripts(). It&#8217;s your best friend. This hook ensures that your function is registering and enqueuing scripts in the right place and only on the front end.</p><p>We&#8217;ve prefixed our function. Because, you need to <a
href="http://nacin.com/2010/05/11/in-wordpress-prefix-everything/">prefix all the things</a>. Use a prefix that makes sense, but isn&#8217;t &#8220;wp&#8221; or something else that could be used by core or other plugins. Your full initials, sitename, etc. are good possibilities.</p><p>As a sidenote, I recommend adding the action in your own <a
href="http://justintadlock.com/archives/2010/12/30/wordpress-theme-function-files">theme setup function</a>.</p><p>We&#8217;re registering the scripts with <a
href="http://codex.wordpress.org/Function_Reference/wp_register_script">wp_register_script()</a>. <em>Read that page</em>. Get in the practice of providing every parameter of the function every single time you register a script.</p><ol><li>Handle &#8211; A name this script will go by. This is how you will enqueue it the short way, or if your user has a child theme and doesn&#8217;t want your script, they can <a
href="http://codex.wordpress.org/Function_Reference/wp_dequeue_script">dequeue it</a> with this handle.</li><li>Source &#8211; The path to the file. I used <a
href="http://codex.wordpress.org/Function_Reference/get_template_directory_uri">get_template_directory_uri()</a>, which is a WordPress function that finds the parent theme directory. Never, ever, hard code the path with /wp-content or anything else. Use this function. It works. It&#8217;s great. If you are registering your script in a child theme, use <a
href="http://codex.wordpress.org/Function_Reference/get_stylesheet_directory_uri">get_stylesheet_directory_uri()</a> instead. It&#8217;s the same thing, for child themes.</li><li>Dependencies &#8211; These are the scripts your script depends on. You may recognize my scripts I&#8217;m loading. They&#8217;re two different slider scripts. They both depend on jQuery. You can pass multiple dependencies in this array, if necessary. For the script called &#8220;info-carousel-instance&#8221;, it relies on the &#8220;info-caroufredsel&#8221; script. Therefore when I enqueue &#8220;info-carousel-instance&#8221;, WordPress will know it needs to enqueue &#8220;info-caroufredsel&#8221; as well, if it hasn&#8217;t been enqueued already.</li><li>Version &#8211; The version of the script you are loading. If you update your script, you can bump the version, and when you change the version here, WordPress will be sure to load the new one, and reset any caching that&#8217;s been used on the previous version of your script.</li><li>Load in footer &#8211; If you set this to true, your script will be loaded in the footer, and therefore after much of the rest of the page has loaded. I always do this for things like sliders, because that way my slider script won&#8217;t prevent more important things on my page from loading. Just think about what you&#8217;re loading when you consider whether or not to do this.</li></ol><h3>wp_enqueue_script()</h3><p><a
href="http://codex.wordpress.org/Function_Reference/wp_enqueue_script">wp_enqueue_script()</a> will enqueue scripts.</p><blockquote><p><a
href="http://dictionary.reference.com/browse/enqueue">Definition</a>: to place something into a queue; to add an element to the tail of a queue (line).</p></blockquote><p>This function simply puts the script it is enqueueing in line to be loaded onto the page. WordPress is also smart enough to know if a script you are trying to enqueue has already &#8220;been through the line&#8221;, if you will, and won&#8217;t load the same scripts more than once. Whenever you see a website loading jQuery mutliple times, you now know why &#8211; they aren&#8217;t enqueueing, or at least not properly.</p><p>I&#8217;m enqueueing two of my four scripts. My carousel instance and the home page flex slider instance. The carousel will be loaded on every page, and the flex slider only on the homepage, as that&#8217;s the only place it&#8217;s used. If you don&#8217;t <em>need</em> a script on every page, don&#8217;t load it on every page. You can use <a
href="http://pippinsplugins.com/wordpress-conditional-tags-overview/">conditional tags</a> inside the wpcandy_load_javascript_files() function, around the instances of wp_enqueue_script() that are to be loaded conditionally. Automattic&#8217;s <a
href="https://github.com/Automattic/_s/blob/master/functions.php">_S theme</a> also has good examples of loading scripts with conditionals (like a script for comments &#8211; a common one to load this way).</p><p>wp_enqueue_script() takes the same arguments as wp_register_script(), but if you register your scripts first, you can just call them by the handle in wp_enqueue_script, as my example above shows.</p><p><a
href="http://codex.wordpress.org/Function_Reference/wp_enqueue_script#Notes">As of WordPress 3.3</a>, you can even enqueue scripts in specific page templates. It will load the script in the footer automatically! For instance, I could have enqueued the &#8220;home-page-main-flex-slider&#8221; script directly in the template part with the slider code.</p><h3>Register vs. Enqueue</h3><p>In our function, we&#8217;re registering four scripts, and enqueing two. Registering a script makes it available for use. Enqueuing actually pulls the script to the theme. You can register without enqueuing. But to load the script on the page, you need to enqueue. If you register the script as I show, you can then enqueue it by its handle alone. If you don&#8217;t register it ahead of time, you&#8217;ll need to provide the full parameters in the enqueue function.</p><p>The reason I register all of my scripts in this function is simple: it helps me keep track. Sure, I could just enqueue them all in this function with conditionals, but sometimes conditionals get confusing, and I like to take advantage of the ability to enqueue in templates, because it&#8217;s simple. I could also skip the register function for the scripts I enqueue right away, but again, I do it for organization. I register them there, together, so that I know what I&#8217;ve got and I know what I&#8217;m loading on every page versus in specific places. I also tend to make notes in comments by the register function to note where I&#8217;m enqueuing, if not immediately.</p><h3>Notes</h3><p>To load scripts in plugins, <a
href="http://codex.wordpress.org/Function_Reference/plugins_url">plugins_url()</a> will replace get_template_directory_uri() for the path, and your function would be in your plugin file instead of functions.php. To <a
href="http://justintadlock.com/archives/2011/07/12/how-to-load-javascript-in-the-wordpress-admin">load them in the admin</a>, you&#8217;d use the <a
href="http://codex.wordpress.org/Plugin_API/Action_Reference/admin_enqueue_scripts">admin_enqueue_scripts()</a> function instead of wp_enqueue_scripts().</p><p>But this tutorial is just to show you how to load scripts in themes &#8211; meant for the frontend. Please start doing this. If you aren&#8217;t, you are doing yourself and your customers (whether buyers of themes or clients) a disservice and certainly causing future headaches.</p><p>Also, you&#8217;ll see I used the version of jQuery included in WordPress. <em>So should you.</em> You&#8217;re making a theme. Use the jQuery included with WordPress. It will always be up to date and compatible with core. It will always work. I&#8217;ve seen Otto argue with enough people about this (including me). He&#8217;s right. If you think Google&#8217;s jQuery is better, use this <a
href="http://wordpress.org/extend/plugins/use-google-libraries/">plugin</a>, or recommend it to your users. For themes you release, <em>just use the WordPress bundled version</em>.</p><p>I hope this has helped clear things up for some of you. I&#8217;m not the first person to write about it. But maybe I helped it click for some. And as Carl Hancock <a
href="https://twitter.com/#!/carlhancock/status/202223037066641410">said</a> (he deals with conflicts daily), &#8220;it needs to be drilled into them [me, you, all of us]. So the more articles the better.&#8221; Oh, and if I screwed something up, or you have something to add, please let me know.</p><div
class="tentblogger-rss-footer"><p>You just finished reading <a
href="http://wpcandy.com/?p=38637">Dear theme developers, this is how you add scripts in WordPress themes</a> on <a
href="http://wpcandy.com" title="WPCandy WordPress community news">WPCandy</a>. Please consider leaving a comment!</p><p></p></div>]]></content:encoded> <wfw:commentRss>http://wpcandy.com/teaches/how-to-load-scripts-in-wordpress-themes/feed</wfw:commentRss> <slash:comments>41</slash:comments> </item> <item><title>Quick Tip: Be mindful of your 404s</title><link>http://wpcandy.com/teaches/be-mindful-of-your-404s?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=be-mindful-of-your-404s</link> <comments>http://wpcandy.com/teaches/be-mindful-of-your-404s#comments</comments> <pubDate>Fri, 04 May 2012 09:14:31 +0000</pubDate> <dc:creator>Joshua Strebel</dc:creator> <category><![CDATA[Tutorials]]></category> <category><![CDATA[featured]]></category> <category><![CDATA[Themes]]></category> <category><![CDATA[WordPress]]></category><guid isPermaLink="false">http://wpcandy.com/?p=35143</guid> <description><![CDATA[The SEO overlords say &#8220;Thou shalt provide links on your 404 page&#8221;, or something to &#8230;  <a
href="http://wpcandy.com/teaches/be-mindful-of-your-404s">Continue reading <span
class="meta-nav">&#8594;</span></a><div
class="tentblogger-rss-footer"><p>You just finished reading <a
href="http://wpcandy.com/?p=35143">Quick Tip: Be mindful of your&nbsp;404s</a> on <a
href="http://wpcandy.com" title="WPCandy WordPress community news">WPCandy</a>. Please consider leaving a comment!</p><p></p></div>]]></description> <content:encoded><![CDATA[<p><a
href="http://wpcandy.com/?p=35143"><img
class="alignnone size-full wp-image-35808" title="404cache-teaser" src="http://cdn.wpcandy.com/files/2012/02/404cache-teaser.gif" alt="" width="600" height="199" /></a></p><p>The SEO overlords say &#8220;Thou shalt provide links on your 404 page&#8221;, or something to that effect. Consider this quick tip simply a word of caution for you power users.</p><p>Typically a WordPress 404 page will <strong>not</strong> be cached by your performance plugin of choice or even Varnish in most cases. And a typical 404 page template may look something like:</p><ul><li><code>wp_list_pages( 'title_li=' );</code></li><li><code>wp_list_categories( 'sort_column=name&amp;title_li=' );</code></li><li><code>wp_list_authors( 'exclude_admin=0&amp;optioncount=1' );</code></li><li><code>wp_get_archives( 'type=monthly' );</code></li><li><code>wp_get_archives( 'type=postbypost );</code></li></ul><p>All fair and good, right? 95% no harm no foul. Except in possibly these two following circumstances:</p><ol><li>Your site has 500, 1000, or even 10,000 posts/authors/categories/tags etc.</li><li>Your permalinks get botched by a plugin, and everything but your homepage is 404&#8242;ing. (We see this at Page.ly from time to time; some plugins just love to rewrite permalinks — <em>poorly.</em>)</li></ol><p><span
id="more-35143"></span></p><p>Here is the cascading effect of multiple 404 pages on a big blog under a large amount of traffic:</p><ul><li>the web server opens a connection,</li><li>pings Mysql to make these queries (grabs 242 pages, 634 categories, 25 authors, 6325 posts…),</li><li>holds open the connection while Mysql burns,</li><li>more connections to the web server stack up, waiting,</li><li><em>New Zealand falls into the ocean</em>.</li></ul><p>But wait, there must be an easy fix you say! Indeed there is: <strong>use the limit, depth, number, and other arguments that will typically add a LIMIT or more narrowly focused SELECT to the Mysql queries</strong>. This will help a 404 page render much faster.</p><p>So we would modify our list above to look like this:</p><ul><li><code>wp_list_pages( 'title_li=<strong>&amp;depth=1</strong>' );</code></li><li><code>wp_list_categories( 'sort_column=name&amp;title_li=<strong>&amp;depth=1&amp;number=10</strong>' );</code></li><li><code>wp_list_authors( 'exclude_admin=0&amp;optioncount=1<strong>&amp;number=10</strong>' );</code></li><li><code>wp_get_archives( 'type=monthly<strong>&amp;limit=10</strong>' );</code></li><li><code>wp_get_archives( 'type=postbypost<strong>&amp;limit=10</strong> );</code></li></ul><p>The W3 Total Cache plugin also has a setting to handle 404&#8242;s, basically letting the web server serve up the default (and less attractive) 404 page, with no pain of loading the WordPress stack.</p><p>And of course, always try to identify your 404&#8242;s thru your access logs and 301 redirect them to a working page.</p><p>Happy blogging.</p><h4>Additional resources:</h4><ul><li><a
href="http://codex.wordpress.org/Function_Reference/wp_list_pages">http://codex.wordpress.org/Function_Reference/wp_list_pages</a></li><li><a
href="http://codex.wordpress.org/Function_Reference/wp_list_categories">http://codex.wordpress.org/Function_Reference/wp_list_categories</a></li><li><a
href="http://codex.wordpress.org/Function_Reference/wp_list_authors">http://codex.wordpress.org/Function_Reference/wp_list_authors</a></li><li><a
href="http://codex.wordpress.org/Function_Reference/wp_get_archives">http://codex.wordpress.org/Function_Reference/wp_get_archives</a></li></ul><div
class="tentblogger-rss-footer"><p>You just finished reading <a
href="http://wpcandy.com/?p=35143">Quick Tip: Be mindful of your&nbsp;404s</a> on <a
href="http://wpcandy.com" title="WPCandy WordPress community news">WPCandy</a>. Please consider leaving a comment!</p><p></p></div>]]></content:encoded> <wfw:commentRss>http://wpcandy.com/teaches/be-mindful-of-your-404s/feed</wfw:commentRss> <slash:comments>2</slash:comments> </item> <item><title>How to manage a proper multi-author WordPress blog</title><link>http://wpcandy.com/teaches/how-to-manage-a-proper-multi-author-wordpress-blog?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=how-to-manage-a-proper-multi-author-wordpress-blog</link> <comments>http://wpcandy.com/teaches/how-to-manage-a-proper-multi-author-wordpress-blog#comments</comments> <pubDate>Fri, 13 Jan 2012 13:50:25 +0000</pubDate> <dc:creator>Ryan Imel</dc:creator> <category><![CDATA[Tutorials]]></category> <category><![CDATA[Community]]></category> <category><![CDATA[featured]]></category> <category><![CDATA[WordPress]]></category><guid isPermaLink="false">http://wpcandy.com/?p=34685</guid> <description><![CDATA[One thing I spend some amount of time thinking about each week is managing my &#8230;  <a
href="http://wpcandy.com/teaches/how-to-manage-a-proper-multi-author-wordpress-blog">Continue reading <span
class="meta-nav">&#8594;</span></a><div
class="tentblogger-rss-footer"><p>You just finished reading <a
href="http://wpcandy.com/?p=34685">How to manage a proper multi-author WordPress blog</a> on <a
href="http://wpcandy.com" title="WPCandy WordPress community news">WPCandy</a>. Please consider leaving a comment!</p><p></p></div>]]></description> <content:encoded><![CDATA[<p><a
href="http://wpcandy.com/?p=34685"><img
class="alignnone size-full wp-image-34755" title="multiauthor-teaser" src="http://cdn.wpcandy.com/files/2012/01/multiauthor-teaser.jpg" alt="" width="600" height="240" /></a></p><p>One thing I spend some amount of time thinking about each week is managing my multi-author blog at WPCandy. There are only a handful of authors that have joined WPCandy <a
title="WPCandy’s 2011 Year in Review" href="http://wpcandy.com/presents/wpcandys-2011-year-in-review">in the last year</a>, but we&#8217;ve still spent a good deal of time improving our workflow as a multi-author blog. I&#8217;ve even picked up a few (what I would call) <em>tips</em> in the process.</p><p>If you find yourself in a similar position, hopefully some of these tips will help you along. If you run a blog with a number of authors, be sure to jump down into the comments and share your experiences too.</p><p><span
id="more-34685"></span></p><h3>Establish a team blog</h3><p>If you want your team to feel like, well, a team, they need a place to come together and chat about what they&#8217;re working on. One hundred percent of my team of contributors is distributed all over the planet, so if we didn&#8217;t have a team blog of some sort we all wouldn&#8217;t have as many chances to talk.</p><p>I&#8217;ve opted to use the <a
title="P2 WordPress theme" href="http://p2theme.com/">P2 theme</a> from Automattic, because like many others I think it fits nicely between the traditional blog and a chat room. I&#8217;d recommend setting up a private P2 instance at a sub domain of your site, like at <em>team.yoursite.com</em>, and making sure that everyone on your team is always able to use it.</p><p><img
class="alignnone size-full wp-image-34749" title="multiauthor-wpcandtteamblog" src="http://cdn.wpcandy.com/files/2012/01/multiauthor-wpcandtteamblog.png" alt="" width="600" height="357" /></p><p>In addition to P2, I&#8217;ve found that using <a
title="Subscribe to Comments plugin" href="http://wordpress.org/extend/plugins/subscribe-to-comments/">Subscribe to Comments</a> and <a
title="Subscribe2 WordPress plugin" href="http://wordpress.org/extend/plugins/subscribe2/">Subscribe2</a> cover our bases when it comes to post notifications. This is also just a matter of preference, but I like to keep a list of useful links in the sidebar of the P2 blog along with a list of all the authors on the blog.</p><p>Of course you don&#8217;t <em>have</em> to use P2. The key is to have a location where your team can easily chat about what&#8217;s going on. Do whatever works best for your particular group.</p><h3>Establish proper author/editor capabilities</h3><p>This one will highly depend on your needs, but in my case I&#8217;m kind of a (<em>what&#8217;s the word?</em>) control freak. Because of this I still personally edit every word that gets published on WPCandy, so authors on WPCandy don&#8217;t have the ability to publish but can only submit posts for review.</p><p>There are a couple of ways to do it, but I opt to manage capabilities using <a
title="Members WordPress plugin" href="http://wordpress.org/extend/plugins/members/">Members</a> by Justin Tadlock. Really I haven&#8217;t done much more than remove the publish capability from authors.</p><p>Just as important as the technical side of things is making sure that roles and abilities are known by your editorial team. Make sure everyone knows what&#8217;s expected of them and what they can do on their own, either using a team blog (see above) or help text (see below).</p><h3>Use Edit Flow</h3><p>I tried the <a
title="Edit Flow WordPress plugin" href="http://wordpress.org/extend/plugins/edit-flow/">Edit Flow</a> plugin around a year ago, and just didn&#8217;t think it was quite there yet. I&#8217;m happy to say that wherever the aforementioned <em>there</em> is, Edit Flow is squarely in the middle of that location. The developers, led by Automattician Daniel Bachhuber, <a
title="Edit Flow 0.7 now available, brings modular architecture and various improvements" href="http://wpcandy.com/reports/edit-flow-0-7-now-available">released version 0.7 this week</a> and it brought some features that really got me excited to use it—features like a drag and drop editorial calendar:</p><p><img
class="alignnone size-full wp-image-34750" title="multiauthor-calendarview" src="http://cdn.wpcandy.com/files/2012/01/multiauthor-calendarview.png" alt="" width="600" height="357" /></p><p>In short, Edit Flow is a plugin that gives your WordPress Dashboard a newspaper-like editorial workflow. Along with the editorial calendar I mentioned above, Edit Flow gives more granular control over post statuses (like Pitch, Assigned, and Changes Needed in addition to Draft and Pending Review), enables author-only editorial discussion of posts as they come together, and  allows authors and editors to be notified when changes are made to posts.</p><p>Before Edit Flow the WPCandy team was using a ticketing system—on a sub blog using <a
title="FaultPress by WooThemes" href="http://www.woothemes.com/2011/05/faultpress/">WooThemes&#8217; FaultPress</a>, actually—but the changeover was worthwhile. The old system, while it worked, also required a layer of translation between the ticketing system and WPCandy itself. When a post was started in one place, a ticket in another place had to be updated. Notes for the post (sources, contacts, etc.) had to be pulled from the ticket and used to write the post. And when a post was published, the ticket elsewhere had to be updated again.</p><p><em>Kind</em> of a mess, right?</p><p>There&#8217;s nothing wrong with FaultPress, of course. Edit Flow is just perfect for multi-author blogs because it streamlined this process so that it all happens in one place.</p><h3>Author checklist for post submissions</h3><p>This is one of those tips that is useful not only for your site&#8217;s authors, but likely for yourself (at least it was for me). As you edit and publish content on your blog, pay attention to the steps you take over and over. If there&#8217;s a way to streamline those steps, such as setting a new default category to better represent the majority of your content, then definitely do that. But for other things it&#8217;s worth maintaining a checklist.</p><p>I&#8217;ve resorted to posting the checklist to the team blog or our help section (see below) but I&#8217;ve also see options like <a
title="Blogging Checklist WordPress plugin" href="http://wordpress.org/extend/plugins/blogging-checklist/">Blogging Checklist</a> before. I haven&#8217;t tried it myself, but it could be something useful if your authors need to run down a few key steps for every post they write.</p><p>In general, though, communicate best practices to your authors to make the editing process (and hopefully the writing process, in the long run) as efficient as it can be.</p><h3>Proper author attribution</h3><p>If you have other authors on your blog it&#8217;s important to give them credit where it&#8217;s due. You want them to know they are receiving proper credit for their work, but it&#8217;s also important to make sure readers know who they&#8217;re reading.</p><p>Bylines are the most important thing to get right here. As an author, seeing your name presented prominently next to your work is important. It&#8217;s important at such a basic level, really, that it&#8217;s weird to mess this one up.</p><p>And as a reader, I can&#8217;t tell you how disappointed I end up being when I find out a post I&#8217;m looking at doesn&#8217;t have proper author attribution. I want to know <em>who</em> I&#8217;m reading just as much as <em>what</em> I&#8217;m reading.</p><p><img
class="alignnone size-full wp-image-34751" title="multiauthor-bylineexample" src="http://cdn.wpcandy.com/files/2012/01/multiauthor-bylineexample.gif" alt="" width="600" height="172" /></p><p>If you wonder exactly how you should pull this one off, a good rule of thumb is to put other author&#8217;s names in the same place you&#8217;d put your own. In addition you might consider an area, perhaps beneath the post, where more information about the author is given. We have used these on WPCandy for a while and they tend to work pretty well.</p><p>One of my favorite social WordPress plugins is <a
title="WordTwit from BraveNewCode" href="http://www.bravenewcode.com/store/plugins/wordtwit-pro/">WordTwit</a> from BraveNewCode. WordTwit is a handy plugin that will tweet out messages (either automatically or manually generated) when you publish new posts. In a recent update they made it really easy to automatically mention the author&#8217;s Twitter name in the tweets, and we&#8217;ve started using that here for the bulk of our posts. For a site like ours, where a lot of our community and traffic comes from Twitter, I think it&#8217;s important to give credit to post authors there too.</p><h3>Set up author emails</h3><p>This isn&#8217;t something you can set up within WordPress itself, but believe me when I say it will make your multi-author blog all the more professional. I prefer using Google Apps to run my domain-specific emails, and I highly recommend it, but honestly use whatever you have to and get that done.</p><p>Not only will having <em><a
href="mailto:theirname@yoursite.com">theirname@yoursite.com</a></em> give your authors a sense of ownership in the site, but it will make their emails with people for your site all the better.</p><h3>Share a group RSS subscription</h3><p>I talked before about the number of RSS feeds I follow to keep up with WordPress company and project blogs. It&#8217;s quite a few. One small but helpful way to make the process of tracking new and interesting stories a bit easier is to open it up to the rest of your team and allow them to review potential story ideas too. This one will take a good deal of trust in your authors, but it can really be worth it once you have more than a few feeds/sources that are updating daily.</p><p>For the group RSS account I use one of my <a
title="Google Apps" href="http://www.google.com/apps/intl/en/business/index.html">Google Apps</a> emails set up with a <a
title="Google Reader" href="http://www.google.com/reader/view/">Google Reader</a> account. I have intended to move the various Twitter accounts I follow into one that the whole team can use, but I just haven&#8217;t gotten to it yet.</p><h3>Maintain author help texts</h3><p>You can establish this copy anywhere you like, really, but I prefer to keep as much within the bounds of the WordPress Dashboard as I can. It keeps things simpler and, to be honest, I just like it better.</p><p>So I really like <a
title="WP Help WordPress plugin" href="http://wordpress.org/extend/plugins/wp-help/">WP Help</a>, a plugin by Mark Jaquith that lets you keep help text for the authors on your blog.</p><p><img
class="alignnone size-full wp-image-34752" title="multiauthor-publishinghelp" src="http://cdn.wpcandy.com/files/2012/01/multiauthor-publishinghelp.gif" alt="" width="600" height="322" /></p><p>There are other ways to maintain this sort of information, but this one&#8217;s my favorite. In our help section we try to keep things like:</p><ul><li>what to do as a new author on the site,</li><li>tips for writing posts,</li><li>how to use our taxonomies properly,</li><li>the types of images we generally like to use,</li><li>WPCandy logos that authors can use, and</li><li>how to modify the parts of the site they can modify.</li></ul><div><span
style="color: #444444;"><span
style="line-height: 22px;">I find these documents most helpful when it comes time to bring a new author on board. As long as things are up to date, I have to do little more than direct them over to the help section to get them rolling as a contributor.</span></span></div><h3>How about you?</h3><p>There are undoubtedly more things to consider when running a blog with more than one author. I&#8217;ve based these tips only on my own experiences, which aren&#8217;t even that expansive. If you&#8217;ve run a multi-author blog (using WordPress or even something else) please jump down to the comments and share your experiences and tips.</p><div
class="tentblogger-rss-footer"><p>You just finished reading <a
href="http://wpcandy.com/?p=34685">How to manage a proper multi-author WordPress blog</a> on <a
href="http://wpcandy.com" title="WPCandy WordPress community news">WPCandy</a>. Please consider leaving a comment!</p><p></p></div>]]></content:encoded> <wfw:commentRss>http://wpcandy.com/teaches/how-to-manage-a-proper-multi-author-wordpress-blog/feed</wfw:commentRss> <slash:comments>15</slash:comments> </item> <item><title>How I built a micro-site within a WordPress theme (for The WPCandy Quarterly)</title><link>http://wpcandy.com/teaches/how-to-build-a-micro-site-within-a-theme?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=how-to-build-a-micro-site-within-a-theme</link> <comments>http://wpcandy.com/teaches/how-to-build-a-micro-site-within-a-theme#comments</comments> <pubDate>Wed, 30 Nov 2011 23:11:57 +0000</pubDate> <dc:creator>Ryan Imel</dc:creator> <category><![CDATA[Tutorials]]></category> <category><![CDATA[featured]]></category> <category><![CDATA[Plugins]]></category> <category><![CDATA[Themes]]></category><guid isPermaLink="false">http://wpcandy.com/?p=31938</guid> <description><![CDATA[I always intend to write about how I build things around WPCandy, but when the &#8230;  <a
href="http://wpcandy.com/teaches/how-to-build-a-micro-site-within-a-theme">Continue reading <span
class="meta-nav">&#8594;</span></a><div
class="tentblogger-rss-footer"><p>You just finished reading <a
href="http://wpcandy.com/?p=31938">How I built a micro-site within a WordPress theme (for The WPCandy Quarterly)</a> on <a
href="http://wpcandy.com" title="WPCandy WordPress community news">WPCandy</a>. Please consider leaving a comment!</p><p></p></div>]]></description> <content:encoded><![CDATA[<p><a
href="http://wpcandy.com/?p=31938"><img
class="alignnone size-full wp-image-31939" title="Quarterly mini-site (teaser)" src="http://cdn.wpcandy.com/files/2011/11/quarterlyminisite-teaser.jpeg" alt="" width="600" height="260" /></a></p><p>I always intend to write about how I build things around WPCandy, but when the time comes it doesn&#8217;t always happen. I fully intended to write about the creation and development of <a
title="WPCandy Pros" href="http://wpcandy.com/pros">the Pros section</a>, but then I didn&#8217;t. I started working on <a
title="WPCandy Discussions" href="http://wpcandy.com/discussions">the discussion board</a>, which in turn I never wrote about either. Around that time work began on The WPCandy Quarterly, which was only just <a
title="Introducing The WPCandy Quarterly magazine, pre-orders now available" href="http://wpcandy.com/announces/quarterly-pre-orders">announced the other day</a>. Today, I&#8217;m determined to write about the building of the Quarterly micro-site at <a
href="http://wpcandy.com/quarterly">wpcandy.com/quarterly</a> before moving on to any other projects.</p><p>When planning things out, I knew that I wanted to keep a trend going with the Quarterly that I had started with Pros and the forum: keeping everything on this domain, and simply adding new sections to the site. I&#8217;ve been avoiding subdomains and brand new sites for some time, really for the sake of simplicity and because I prefer the way it looks within the site. So I set about creating a micro-site just for The WPCandy Quarterly, which I&#8217;ll walk you through in this post.</p><p>In this post you can expect a smattering of code snippets, a good deal of me explaining my weird website preferences, and of course some bouncing between <code>functions.php</code> files and <a
title="How to create your own WordPress functionality plugin" href="http://wpcandy.com/teaches/how-to-create-a-functionality-plugin">functionality plugins</a>.</p><p><span
id="more-31938"></span></p><h3>Planning the addition to the site</h3><p>I knew the Quarterly would need its own landing page, as well as a specific page for each issue. This way discussions around specific issues and articles could easily be linked up, and it would be simple for anyone to jump back through back issues. At the same time, I knew I would need a shopping cart to manage the billing, shipping, and checkout process.</p><p>Each issue of the Quarterly would need a description and issue photos, as well as a listing of the authors and (ideally) the articles that they contributed. So I&#8217;ll want to be able to not only associate posts on the site with an issue, but eventually discussions on the forum as well.</p><p>Just to be clear, then, in this post we&#8217;ll be:</p><ol><li>setting up a new section of the site for the Quarterly and</li><li>setting up basic shopping cart functionality.</li></ol><div><span
style="color: #444444;"><span
style="line-height: 22px;">Alright then? Let&#8217;s get to it.</span></span></div><h3>Setting up the Quarterly issue pages</h3><p>The requirements for this section of the site demand &#8212; as you might expect &#8212; a custom post type. The PHP I&#8217;m using is below:</p><div
id="gist-1411401" class="gist"><div
class="gist-file"><div
class="gist-data gist-syntax"><div
class="highlight"><pre><div class='line' id='LC1'><span class="cp">&lt;?php</span></div><div class='line' id='LC2'><span class="c1">// Custom post type creation</span></div><div class='line' id='LC3'><span class="k">function</span> <span class="nf">wpcandy_cpt</span><span class="p">()</span> <span class="p">{</span></div><div class='line' id='LC4'><br/></div><div class='line' id='LC5'>	<span class="c1">//Other post types created above</span></div><div class='line' id='LC6'><br/></div><div class='line' id='LC7'>	<span class="c1">// Quarterly post type</span></div><div class='line' id='LC8'>	<span class="nx">register_post_type</span><span class="p">(</span> <span class="s1">&#39;wpcandy_issue&#39;</span><span class="p">,</span></div><div class='line' id='LC9'><br/></div><div class='line' id='LC10'>		<span class="k">array</span><span class="p">(</span></div><div class='line' id='LC11'><br/></div><div class='line' id='LC12'>			<span class="s1">&#39;labels&#39;</span> <span class="o">=&gt;</span> <span class="k">array</span><span class="p">(</span></div><div class='line' id='LC13'><br/></div><div class='line' id='LC14'>				<span class="c1">// There could be more labels here, but I was lazy I suppose.			</span></div><div class='line' id='LC15'>				<span class="s1">&#39;name&#39;</span> <span class="o">=&gt;</span> <span class="nx">__</span><span class="p">(</span> <span class="s1">&#39;Quarterly&#39;</span> <span class="p">),</span></div><div class='line' id='LC16'>				<span class="s1">&#39;singular_name&#39;</span> <span class="o">=&gt;</span> <span class="nx">__</span><span class="p">(</span> <span class="s1">&#39;Quarterly Issue&#39;</span> <span class="p">),</span></div><div class='line' id='LC17'>				<span class="s1">&#39;add_new_item&#39;</span> <span class="o">=&gt;</span> <span class="nx">__</span><span class="p">(</span> <span class="s1">&#39;Add New Issue&#39;</span> <span class="p">)</span></div><div class='line' id='LC18'><br/></div><div class='line' id='LC19'>			<span class="p">),</span></div><div class='line' id='LC20'><br/></div><div class='line' id='LC21'>		<span class="s1">&#39;exclude_from_search&#39;</span> <span class="o">=&gt;</span> <span class="k">true</span><span class="p">,</span></div><div class='line' id='LC22'>		<span class="s1">&#39;capability_type&#39;</span> <span class="o">=&gt;</span> <span class="s1">&#39;page&#39;</span><span class="p">,</span></div><div class='line' id='LC23'>		<span class="s1">&#39;has_archive&#39;</span> <span class="o">=&gt;</span> <span class="k">true</span><span class="p">,</span></div><div class='line' id='LC24'>		<span class="s1">&#39;menu_position&#39;</span> <span class="o">=&gt;</span> <span class="mi">20</span><span class="p">,</span></div><div class='line' id='LC25'>		<span class="s1">&#39;public&#39;</span> <span class="o">=&gt;</span> <span class="k">true</span><span class="p">,</span></div><div class='line' id='LC26'>		<span class="s1">&#39;publicly_queryable&#39;</span> <span class="o">=&gt;</span> <span class="k">true</span><span class="p">,</span></div><div class='line' id='LC27'>		<span class="s1">&#39;rewrite&#39;</span> <span class="o">=&gt;</span> <span class="k">array</span><span class="p">(</span> <span class="s1">&#39;slug&#39;</span> <span class="o">=&gt;</span> <span class="s1">&#39;quarterly&#39;</span><span class="p">,</span> <span class="s1">&#39;with_front&#39;</span> <span class="o">=&gt;</span> <span class="k">false</span> <span class="p">),</span></div><div class='line' id='LC28'>		<span class="s1">&#39;show_ui&#39;</span> <span class="o">=&gt;</span> <span class="k">true</span><span class="p">,</span></div><div class='line' id='LC29'>		<span class="s1">&#39;supports&#39;</span> <span class="o">=&gt;</span> <span class="k">array</span><span class="p">(</span> <span class="s1">&#39;editor&#39;</span><span class="p">,</span> <span class="s1">&#39;title&#39;</span><span class="p">,</span> <span class="s1">&#39;thumbnail&#39;</span><span class="p">,</span> <span class="s1">&#39;excerpt&#39;</span><span class="p">,</span> <span class="s1">&#39;page-attributes&#39;</span> <span class="p">),</span></div><div class='line' id='LC30'>		<span class="s1">&#39;taxonomies&#39;</span> <span class="o">=&gt;</span> <span class="k">array</span><span class="p">(</span> <span class="s1">&#39;post_tag&#39;</span> <span class="p">)</span></div><div class='line' id='LC31'><br/></div><div class='line' id='LC32'>	<span class="p">));</span></div><div class='line' id='LC33'><br/></div><div class='line' id='LC34'><span class="p">}</span></div><div class='line' id='LC35'><br/></div><div class='line' id='LC36'><span class="c1">// Add action</span></div><div class='line' id='LC37'><span class="nx">add_action</span><span class="p">(</span> <span class="s1">&#39;init&#39;</span><span class="p">,</span> <span class="s1">&#39;wpcandy_cpt&#39;</span> <span class="p">);</span></div></pre></div></div><div
class="gist-meta"> <a
href="https://gist.github.com/raw/1411401/251c1443ad74aabb94cd03e7359196a84b22d1af/gistfile1.aw" style="float:right;">view raw</a> <a
href="https://gist.github.com/1411401#file_gistfile1.aw" style="float:right;margin-right:10px;color:#666">gistfile1.aw</a> <a
href="https://gist.github.com/1411401">This Gist</a> brought to you by <a
href="http://github.com">GitHub</a>.</div></div></div><p>This PHP went into my functionality plugin, since of course I&#8217;ll want it to stick around when I switch themes.</p><p>Notice that I defined an archive for this post type so I can include a special archive template to display them. This is important, since I&#8217;ll be using this template to make the Quarterly section of the site entirely unique.</p><p>I&#8217;m also enabling the post tags taxonomy, for a reason that I&#8217;ll explain in a minute.</p><p>With the post type in place, and a quick visit to the Permalinks Settings page on the Dashboard to get the URLs working, I could visit wpcandy.com/quarterly and any specific issue at <code>/quarterly/issue-0x</code>. As you might imagine, though, at the time those pages looked just like any other page on WPCandy, which of course wouldn&#8217;t do. I created the <code>archive-wpcandy_issue.php</code> and <code>single-wpcandy_issue.php</code> templates, but of course those were still using the same styles and scripts from the rest of the site.</p><p>In order to clear the palette, so to speak, I added a few new lines to my <code>functions.php</code> file. In this case I&#8217;m dealing with the presentation layer, and not the functionality, so there&#8217;s no reason to resort to <a
title="How to create your own WordPress functionality plugin" href="http://wpcandy.com/teaches/how-to-create-a-functionality-plugin">a functionality plugin</a>.</p><p>This is what I set out to do. If viewing a Quarterly archive or single page:</p><ol><li>remove the core site styles, and any plugin styles that won&#8217;t be used,</li><li>remove the core Javascript, ana again those added by plugins that won&#8217;t be used,</li><li>add back the styles and (and maybe scripts) specific to the Quarterly.</li></ol><p>By doing this, I&#8217;m creating a sort of theme-within-a-theme. <em>Sort of</em>. I can now use a simple, smaller, and very specific stylesheet just for the Quarterly section, leaving my main site CSS file untouched.</p><p>In order to do that, here&#8217;s what I used:</p><div
id="gist-1411425" class="gist"><div
class="gist-file"><div
class="gist-data gist-syntax"><div
class="highlight"><pre><div class='line' id='LC1'><span class="cp">&lt;?php</span></div><div class='line' id='LC2'><span class="c1">// Just for the Quarterly</span></div><div class='line' id='LC3'><br/></div><div class='line' id='LC4'><span class="nx">add_action</span><span class="p">(</span> <span class="s1">&#39;wp_print_styles&#39;</span><span class="p">,</span> <span class="s1">&#39;quarterly_styles&#39;</span> <span class="p">);</span></div><div class='line' id='LC5'><span class="nx">add_action</span><span class="p">(</span> <span class="s1">&#39;wp_enqueue_scripts&#39;</span><span class="p">,</span> <span class="s1">&#39;quarterly_scripts&#39;</span> <span class="p">);</span></div><div class='line' id='LC6'><br/></div><div class='line' id='LC7'><span class="k">function</span> <span class="nf">quarterly_styles</span><span class="p">()</span> <span class="p">{</span></div><div class='line' id='LC8'><br/></div><div class='line' id='LC9'>	<span class="k">if</span> <span class="p">(</span> <span class="nx">is_post_type_archive</span><span class="p">(</span> <span class="s1">&#39;wpcandy_issue&#39;</span> <span class="p">)</span> <span class="o">||</span> <span class="nx">is_singular</span><span class="p">(</span> <span class="s1">&#39;wpcandy_issue&#39;</span> <span class="p">)</span> <span class="p">)</span> <span class="p">{</span></div><div class='line' id='LC10'>		<span class="nx">wp_dequeue_style</span><span class="p">(</span> <span class="s1">&#39;master&#39;</span> <span class="p">);</span></div><div class='line' id='LC11'>		<span class="nx">wp_enqueue_style</span><span class="p">(</span> <span class="s1">&#39;quarterly&#39;</span><span class="p">,</span> <span class="nx">THEME_CSS_URI</span> <span class="o">.</span> <span class="s1">&#39;/quarterly.css&#39;</span><span class="p">,</span> <span class="k">null</span><span class="p">,</span> <span class="s1">&#39;1.0&#39;</span> <span class="p">);</span></div><div class='line' id='LC12'>	<span class="p">}</span></div><div class='line' id='LC13'><br/></div><div class='line' id='LC14'><span class="p">}</span></div><div class='line' id='LC15'><br/></div><div class='line' id='LC16'><span class="k">function</span> <span class="nf">quarterly_scripts</span><span class="p">()</span> <span class="p">{</span></div><div class='line' id='LC17'><br/></div><div class='line' id='LC18'>	<span class="k">if</span> <span class="p">(</span> <span class="nx">is_post_type_archive</span><span class="p">(</span> <span class="s1">&#39;wpcandy_issue&#39;</span> <span class="p">)</span> <span class="o">||</span> <span class="nx">is_singular</span><span class="p">(</span> <span class="s1">&#39;wpcandy_issue&#39;</span> <span class="p">)</span> <span class="p">)</span> <span class="p">{</span></div><div class='line' id='LC19'>		<span class="nx">wp_dequeue_script</span><span class="p">(</span> <span class="s1">&#39;scripts&#39;</span> <span class="p">);</span></div><div class='line' id='LC20'>		<span class="nx">wp_dequeue_script</span><span class="p">(</span> <span class="s1">&#39;live-blogging&#39;</span> <span class="p">);</span></div><div class='line' id='LC21'>		<span class="nx">wp_dequeue_script</span><span class="p">(</span> <span class="s1">&#39;jquery-ui-accordion&#39;</span> <span class="p">);</span></div><div class='line' id='LC22'>		<span class="nx">wp_enqueue_script</span><span class="p">(</span> <span class="s1">&#39;quarterly&#39;</span><span class="p">,</span> <span class="nx">THEME_JS_URI</span> <span class="o">.</span> <span class="s1">&#39;/quarterly.js&#39;</span><span class="p">,</span> <span class="k">array</span><span class="p">(</span><span class="s1">&#39;jquery&#39;</span><span class="p">),</span> <span class="s1">&#39;1.0&#39;</span><span class="p">,</span> <span class="k">true</span> <span class="p">);</span></div><div class='line' id='LC23'>	<span class="p">}</span></div><div class='line' id='LC24'><br/></div><div class='line' id='LC25'><span class="p">}</span></div></pre></div></div><div
class="gist-meta"> <a
href="https://gist.github.com/raw/1411425/47bbde6b9a90442a33cacefa54a9f7db48f32602/gistfile1.aw" style="float:right;">view raw</a> <a
href="https://gist.github.com/1411425#file_gistfile1.aw" style="float:right;margin-right:10px;color:#666">gistfile1.aw</a> <a
href="https://gist.github.com/1411425">This Gist</a> brought to you by <a
href="http://github.com">GitHub</a>.</div></div></div><p>I added this to my theme&#8217;s functions file, since it&#8217;s specific to the theme I&#8217;m currently using.</p><p>Now I have a clean slate to work from, which is exactly what I did. I styled the navigation, the issue post type content, and the special section with the list of contributors to a specific issue.</p><p>Oh right, the contributors section. Here&#8217;s how I did that.</p><h3>Listing the contributors to an issue</h3><p>In all likelihood, at some point in the future Quarterly articles will end up on the blog. Not right away, of course, but eventually. So the first thing I did was create draft posts (standard posts, not the issue post type posts) authored by each of the Quarterly contributors. For each of them I also tagged them with a Quarterly issue-specific post tag. I made sure the issue post they belong to also included the same tag.</p><p>Then I added the query below to my templates:</p><div
id="gist-1411461" class="gist"><div
class="gist-file"><div
class="gist-data gist-syntax"><div
class="highlight"><pre><div class='line' id='LC1'><span class="nt">&lt;h3&gt;</span>In this issue<span class="nt">&lt;/h3&gt;</span></div><div class='line' id='LC2'><br/></div><div class='line' id='LC3'><span class="nt">&lt;ul&gt;</span></div><div class='line' id='LC4'><br/></div><div class='line' id='LC5'><span class="cp">&lt;?php $issue_terms = get_the_terms( $post-&gt;ID , &#39;post_tag&#39; );</span></div><div class='line' id='LC6'><br/></div><div class='line' id='LC7'><span class="cp">	if ( $issue_terms != &#39;&#39; ) {</span></div><div class='line' id='LC8'><br/></div><div class='line' id='LC9'><span class="cp">		foreach ( $issue_terms as $issue_term ) {</span></div><div class='line' id='LC10'><span class="cp">			$issue_slug = $issue_term-&gt;slug;</span></div><div class='line' id='LC11'><span class="cp">			$issue_query = new WP_Query( &#39;post_type=post&amp;showposts=-1&amp;post_status=any&amp;orderby=rand&amp;tag=&#39; . $issue_slug );</span></div><div class='line' id='LC12'><br/></div><div class='line' id='LC13'><span class="cp">		while ( $issue_query-&gt;have_posts() ) : $issue_query-&gt;the_post(); ?&gt;</span></div><div class='line' id='LC14'><br/></div><div class='line' id='LC15'>		<span class="nt">&lt;li</span> <span class="na">class=</span><span class="s">&quot;contributor&quot;</span><span class="nt">&gt;</span></div><div class='line' id='LC16'><br/></div><div class='line' id='LC17'>			<span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">&quot;avatar&quot;</span><span class="nt">&gt;</span></div><div class='line' id='LC18'>				<span class="cp">&lt;?php echo get_avatar( get_the_author_meta( &#39;user_email&#39; ), 60 ); ?&gt;</span></div><div class='line' id='LC19'>			<span class="nt">&lt;/div&gt;</span></div><div class='line' id='LC20'><br/></div><div class='line' id='LC21'>			<span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">&quot;title&quot;</span><span class="nt">&gt;</span></div><div class='line' id='LC22'>				<span class="nt">&lt;p&gt;</span><span class="cp">&lt;?php the_title(); ?&gt;</span><span class="nt">&lt;/p&gt;</span></div><div class='line' id='LC23'>				<span class="nt">&lt;p</span> <span class="na">class=</span><span class="s">&quot;author&quot;</span><span class="nt">&gt;&lt;span&gt;</span>by<span class="nt">&lt;/span&gt;</span> <span class="cp">&lt;?php the_author(); ?&gt;</span><span class="nt">&lt;/p&gt;</span></div><div class='line' id='LC24'>			<span class="nt">&lt;/div&gt;</span></div><div class='line' id='LC25'><br/></div><div class='line' id='LC26'>		<span class="nt">&lt;/li&gt;</span></div><div class='line' id='LC27'><br/></div><div class='line' id='LC28'>		<span class="cp">&lt;?php endwhile;</span></div><div class='line' id='LC29'><span class="cp">		wp_reset_postdata();</span></div><div class='line' id='LC30'><span class="cp">	}</span></div><div class='line' id='LC31'><span class="cp">} ?&gt;</span></div><div class='line' id='LC32'><br/></div><div class='line' id='LC33'><span class="nt">&lt;/ul&gt;</span></div></pre></div></div><div
class="gist-meta"> <a
href="https://gist.github.com/raw/1411461/d13540ab9f281d0905354183d1e8edc1b0d11a0d/gistfile1.html" style="float:right;">view raw</a> <a
href="https://gist.github.com/1411461#file_gistfile1.html" style="float:right;margin-right:10px;color:#666">gistfile1.html</a> <a
href="https://gist.github.com/1411461">This Gist</a> brought to you by <a
href="http://github.com">GitHub</a>.</div></div></div><p>This I added to the Quarterly-specific loop, which was called into each of my two new template files so I wouldn&#8217;t repeat myself.</p><p>And that, along with some CSS, created this:</p><p><img
class="alignnone size-large wp-image-31943" title="Quarterly contributors list" src="http://cdn.wpcandy.com/files/2011/11/Screen-Shot-2011-11-30-at-4.50.51-PM-600x544.png" alt="" width="600" height="544" /></p><p>I now have a simple, elegant way to list the contributors with each issue. It will be easy to link up these article titles to their posts, too, since they&#8217;re already querying the drafts themselves from WordPress. With a bit of CSS, I now have a method of displaying issue contributors that I can use and reuse.</p><h3>Setting up the shopping cart functionality</h3><p>If I were only in need of a simple digital purchase I likely wouldn&#8217;t bother with a full shopping cart setup. Paid <a
href="http://wpcandy.com/pros">Pros</a> accounts (which I lovingly call <em>Sweet Pros</em>) are, after all, simply a PayPal subscription created using a <a
title="Gravity Forms" href="http://www.gravityforms.com/">Gravity Forms</a> signup form. However the Quarterly is a physical product, which necessitates a more complete shopping cart experience. Having a shopping cart on the site is also helpful, since it makes the process of adding additional physical products to the site in the future a lot simpler.</p><p>I toyed around with just about every e-commerce plugin out there before ultimately deciding on <a
title="WP e-Commerce" href="http://wordpress.org/extend/plugins/wp-e-commerce/">WP e-Commerce</a>. To be honest I was thoroughly impressed by each plugin that I tried out, and my final decision was WP e-Commerce primarily because it has been around for so long.</p><p>Before now, my only extended experience with the WP e-Commerce plugin was years ago, around 2008 or so; it wasn&#8217;t a very pleasant experience at all. I&#8217;m happy to say it&#8217;s much better now, and the setup was pretty much seamless.</p><p>The Quarterly section of the site is separate from the shop for a few reasons. One, I want to have the flexibility of controlling the URLs, layout, and elements within the Quarterly micro-site. If I knew the Quarterly would be the only physical product I&#8217;d ever sell in the store, then perhaps I would have relied on that entirely. But I don&#8217;t know that, so the shopping cart (or <a
title="The WPCandy Shoppe" href="http://wpcandy.com/shoppe">WPCandy Shoppe</a>) is separate from the Quarterly site.</p><p>This separation wasn&#8217;t a big deal, since simple shortcodes are available with the WP e-Commerce plugin to add specific purchase buttons to any section of your site. I used these within the pages of the Quarterly site to create a nice transition from micro-site to cart and checkout.</p><p><img
class="alignnone size-full wp-image-31942" title="Quarterly button clicked" src="http://cdn.wpcandy.com/files/2011/11/quarterlyminisite-buttonclicked.jpeg" alt="" width="465" height="191" /></p><p>At least, I think it&#8217;s pretty slick.</p><h3>Additional thoughts on WordPress and e-commerce</h3><p>It will certainly be worthwhile to spend more time surveying e-commerce options and reviewing them more fully in the future, but in the meantime I thought I&#8217;d offer up a few thoughts. One comment I have that applies to all of the e-commerce plugins I tried out is this: the initial setup process is quite overwhelming. During my toying process I set up the basic Quarterly sales items and process for each plugin on a testing location. Without exception, each plugin presented me with options I never ended up needing, or didn&#8217;t even care about. I realize that WPCandy&#8217;s shopping cart needs aren&#8217;t as complicated as some, but that made me wish for a simplified setup process even more.</p><p>It would be great to see these plugins take more of a &#8220;decisions over options&#8221; approach. When that isn&#8217;t possible, stashing less vital options in an advanced section would lessen the initial impact of a screen full of checkboxes and dropdowns.</p><p>Easily the most delightful part of the e-commerce setup, for me, was using <a
title="BraveNewCode Piggy plugin" href="http://www.bravenewcode.com/store/plugins/piggy/">BraveNewCode&#8217;s Piggy plugin</a> to enable purchase notifications to my phone. The setup was simple, it integrates well, and I love being notified of sales. It was an easy $25 to spend, and I would recommend anyone using an e-commerce plugin (it integrates with a number of them) check it out.</p><h3>Reflecting on the development process</h3><p>I&#8217;m much happier with the development of this addition to the site than any other addition I&#8217;ve done. I approached it intelligently (for me at least) and completed the development in an efficient and future-thinking way. I wish that I had developed <a
href="http://wpcandy.com/pros">Pros</a> in as clean a fashion, and will definitely revisit the methods I used when I launch Pros 2.0.</p><p>What do you think? Have you used any of these techniques before, or do you have even better ways of pulling this off? Oh, and while I&#8217;m asking questions: <a
href="http://wpcandy.com/quarterly">have you pre-ordered your copy of the Quarterly yet?</a></p><div
class="tentblogger-rss-footer"><p>You just finished reading <a
href="http://wpcandy.com/?p=31938">How I built a micro-site within a WordPress theme (for The WPCandy Quarterly)</a> on <a
href="http://wpcandy.com" title="WPCandy WordPress community news">WPCandy</a>. Please consider leaving a comment!</p><p></p></div>]]></content:encoded> <wfw:commentRss>http://wpcandy.com/teaches/how-to-build-a-micro-site-within-a-theme/feed</wfw:commentRss> <slash:comments>18</slash:comments> </item> <item><title>Autoblog your Dribbble shots with a custom post type</title><link>http://wpcandy.com/teaches/autoblog-your-dribbble-shots-with-a-custom-post-type?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=autoblog-your-dribbble-shots-with-a-custom-post-type</link> <comments>http://wpcandy.com/teaches/autoblog-your-dribbble-shots-with-a-custom-post-type#comments</comments> <pubDate>Tue, 20 Sep 2011 12:03:20 +0000</pubDate> <dc:creator>Brian Krogsgard</dc:creator> <category><![CDATA[Tutorials]]></category> <category><![CDATA[WordPress]]></category><guid isPermaLink="false">http://wpcandy.com/?p=28125</guid> <description><![CDATA[I ran across a fun code snippet today by Tammy Hart that automatically creates posts &#8230;  <a
href="http://wpcandy.com/teaches/autoblog-your-dribbble-shots-with-a-custom-post-type">Continue reading <span
class="meta-nav">&#8594;</span></a><div
class="tentblogger-rss-footer"><p>You just finished reading <a
href="http://wpcandy.com/?p=28125">Autoblog your Dribbble shots with a custom post type</a> on <a
href="http://wpcandy.com" title="WPCandy WordPress community news">WPCandy</a>. Please consider leaving a comment!</p><p></p></div>]]></description> <content:encoded><![CDATA[<p><a
href="http://wpcandy.com/?p=28125"><img
class="aligncenter size-large wp-image-28130" title="dribbble2wp" src="http://cdn.wpcandy.com/files/2011/09/dribbble2wp-600x274.png" alt="dribbble to wp autoblog" width="600" height="274" /></a></p><p>I ran across a fun code snippet today by <a
href="http://tammyhartdesigns.com/">Tammy Hart</a> that automatically creates posts to a WordPress custom post type from your Dribbble RSS feed. The post type is called &#8220;shot&#8221; and all it requires is for you to change your Dribbble name in the fetch_feed( ) function.</p><p>In addition to Tammy&#8217;s creation of the Shot post type, I put together a simple archive template that you can use in your theme. I used markup consistent with the Twenty Eleven theme, and it simply pulls the meta data defined in the post type for the entry title and post image. It also links to the original Dribbble post.</p><p>You can get Tammy&#8217;s code from <a
href="http://forrst.com/posts/Dribbble_to_WordPress-wZv">her post on Forrst</a>, and the archive template after the jump. Thanks to Tammy for sharing her fun implementation of custom post types!</p><p><span
id="more-28125"></span></p><p>To use this archive template, you&#8217;ll want to put it in a file named archive-shot.php. This name is important so that WordPress will know to pull from the shot post type. You can read about <a
href="http://codex.wordpress.org/Template_Hierarchy">template hierarchy</a> in the codex for more information.</p><pre>&lt;?php
/**
 * The template for displaying Dribbble Shot Archives.
 *
 * Learn more: <a href="http://codex.wordpress.org/Template_Hierarchy" rel="nofollow">http://codex.wordpress.org/Template_Hierarchy</a>
 *
 * @package WordPress
 * @subpackage Twenty_Eleven
 * @since Twenty Eleven 1.2
 */

get_header(); ?&gt;

		&lt;section id="primary"&gt;
			&lt;div id="content" role="main"&gt;

			&lt;?php if ( have_posts() ) : ?&gt;

				&lt;header class="page-header"&gt;
					&lt;h1 class="page-title"&gt;Dribbble Shots&lt;/h1&gt;
				&lt;/header&gt;

				&lt;?php twentyeleven_content_nav( 'nav-above' ); ?&gt;

				&lt;?php /* Start the Loop */ ?&gt;
				&lt;?php while ( have_posts() ) : the_post(); ?&gt;

					&lt;article &lt;?php post_class(); ?&gt; id="post-&lt;?php the_ID(); ?&gt;"&gt;
					&lt;header class="entry-header"&gt;
						&lt;h1 class="entry-title"&gt;&lt;?php the_title(); ?&gt;&lt;/h1&gt;
					&lt;/header&gt;&lt;!-- .entry-header --&gt;

					&lt;!-- Let's show the image with the 'image' post meta --&gt;
					&lt;img class="thumb" src="&lt;?php echo get_post_meta($post-&gt;ID, 'image', true) ?&gt;" alt="&lt;?php the_title(); ?&gt;" /&gt;

					&lt;div class="entry-content"&gt;&lt;?php the_content(); ?&gt;&lt;/div&gt;

					&lt;!-- Let's link out to the dribbble shot with the link_url post meta --&gt;
					&lt;div class="link-out"&gt;&lt;a href="&lt;?php echo get_post_meta($post-&gt;ID, 'link_url', true); ?&gt;"&gt;View this shot on Dribbble&lt;/a&gt;&lt;/div&gt;

					&lt;/article&gt;&lt;!-- #post-ID --&gt;

				&lt;?php endwhile; ?&gt;

				&lt;?php twentyeleven_content_nav( 'nav-below' ); ?&gt;

			&lt;?php else : ?&gt;

				&lt;article id="post-0" class="post no-results not-found"&gt;
					&lt;header class="entry-header"&gt;
						&lt;h1 class="entry-title"&gt;&lt;?php _e( 'Nothing Found', 'twentyeleven' ); ?&gt;&lt;/h1&gt;
					&lt;/header&gt;&lt;!-- .entry-header --&gt;

					&lt;div class="entry-content"&gt;
						&lt;p&gt;&lt;?php _e( 'Apologies, but no results were found for the requested archive. Perhaps searching will help find a related post.', 'twentyeleven' ); ?&gt;&lt;/p&gt;
						&lt;?php get_search_form(); ?&gt;
					&lt;/div&gt;&lt;!-- .entry-content --&gt;
				&lt;/article&gt;&lt;!-- #post-0 --&gt;

			&lt;?php endif; ?&gt;

			&lt;/div&gt;&lt;!-- #content --&gt;
		&lt;/section&gt;&lt;!-- #primary --&gt;

&lt;?php get_sidebar(); ?&gt;
&lt;?php get_footer(); ?&gt;</pre><pre></pre><div
class="tentblogger-rss-footer"><p>You just finished reading <a
href="http://wpcandy.com/?p=28125">Autoblog your Dribbble shots with a custom post type</a> on <a
href="http://wpcandy.com" title="WPCandy WordPress community news">WPCandy</a>. Please consider leaving a comment!</p><p></p></div>]]></content:encoded> <wfw:commentRss>http://wpcandy.com/teaches/autoblog-your-dribbble-shots-with-a-custom-post-type/feed</wfw:commentRss> <slash:comments>2</slash:comments> </item> <item><title>How to create a custom login page template</title><link>http://wpcandy.com/teaches/how-to-create-a-custom-login-page-template?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=how-to-create-a-custom-login-page-template</link> <comments>http://wpcandy.com/teaches/how-to-create-a-custom-login-page-template#comments</comments> <pubDate>Wed, 10 Aug 2011 15:14:16 +0000</pubDate> <dc:creator>Ryan Imel</dc:creator> <category><![CDATA[Tutorials]]></category> <category><![CDATA[Themes]]></category><guid isPermaLink="false">http://wpcandy.com/?p=25669</guid> <description><![CDATA[Oli Dale has posted a tutorial showing how to create a custom login page template &#8230;  <a
href="http://wpcandy.com/teaches/how-to-create-a-custom-login-page-template">Continue reading <span
class="meta-nav">&#8594;</span></a><div
class="tentblogger-rss-footer"><p>You just finished reading <a
href="http://wpcandy.com/?p=25669">How to create a custom login page template</a> on <a
href="http://wpcandy.com" title="WPCandy WordPress community news">WPCandy</a>. Please consider leaving a comment!</p><p></p></div>]]></description> <content:encoded><![CDATA[<p>Oli Dale has <a
href="http://wplift.com/how-to-create-a-custom-login-page-for-your-wordpress-theme/">posted a tutorial</a> showing how to create a custom login page template within your WordPress theme. He opts for laying out the <abbr>HTML</abbr> himself for more control, rather than using the <code>wp_login_form()</code> template tag.</p><div
class="tentblogger-rss-footer"><p>You just finished reading <a
href="http://wpcandy.com/?p=25669">How to create a custom login page template</a> on <a
href="http://wpcandy.com" title="WPCandy WordPress community news">WPCandy</a>. Please consider leaving a comment!</p><p></p></div>]]></content:encoded> <wfw:commentRss>http://wpcandy.com/teaches/how-to-create-a-custom-login-page-template/feed</wfw:commentRss> <slash:comments>0</slash:comments> </item> <item><title>Siobhan McKeown’s notes on running a local meetup</title><link>http://wpcandy.com/teaches/notes-on-running-a-local-meetup?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=notes-on-running-a-local-meetup</link> <comments>http://wpcandy.com/teaches/notes-on-running-a-local-meetup#comments</comments> <pubDate>Thu, 28 Jul 2011 11:05:51 +0000</pubDate> <dc:creator>Ryan Imel</dc:creator> <category><![CDATA[Tutorials]]></category> <category><![CDATA[WordCamp]]></category> <category><![CDATA[WordPress]]></category><guid isPermaLink="false">http://wpcandy.com/?p=24594</guid> <description><![CDATA[I haven&#8217;t done the best job as the organizer of the WordPress meetup in my &#8230;  <a
href="http://wpcandy.com/teaches/notes-on-running-a-local-meetup">Continue reading <span
class="meta-nav">&#8594;</span></a><div
class="tentblogger-rss-footer"><p>You just finished reading <a
href="http://wpcandy.com/?p=24594">Siobhan McKeown's notes on running a local meetup</a> on <a
href="http://wpcandy.com" title="WPCandy WordPress community news">WPCandy</a>. Please consider leaving a comment!</p><p></p></div>]]></description> <content:encoded><![CDATA[<p>I haven&#8217;t done the best job as the organizer of the WordPress meetup in my city. Our last event was in March (<em>eesh</em>) and I don&#8217;t spend the time on it that I should.</p><p>Siobhan McKeown attended WordCamp Portsmouth and, as far as I can tell, did a killer job covering the event. One session McKeown covered, and <a
title="Siobhan McKeown's notes on running a local WordPress meetup" href="http://wpmu.org/tips-on-running-a-wordpress-local-meetup/">published notes on</a>, was a panel all about improving local WordPress meetups. Now I&#8217;m encouraged and have a list made to get back on top of our local event.</p><div
class="tentblogger-rss-footer"><p>You just finished reading <a
href="http://wpcandy.com/?p=24594">Siobhan McKeown's notes on running a local meetup</a> on <a
href="http://wpcandy.com" title="WPCandy WordPress community news">WPCandy</a>. Please consider leaving a comment!</p><p></p></div>]]></content:encoded> <wfw:commentRss>http://wpcandy.com/teaches/notes-on-running-a-local-meetup/feed</wfw:commentRss> <slash:comments>2</slash:comments> </item> <item><title>Introduction to Custom Hooks and Pluggable Functions</title><link>http://wpcandy.com/teaches/custom-hooks-and-pluggable-functions?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=custom-hooks-and-pluggable-functions</link> <comments>http://wpcandy.com/teaches/custom-hooks-and-pluggable-functions#comments</comments> <pubDate>Fri, 15 Jul 2011 12:23:37 +0000</pubDate> <dc:creator>Matt Cohen</dc:creator> <category><![CDATA[Tutorials]]></category> <category><![CDATA[featured]]></category> <category><![CDATA[Plugins]]></category> <category><![CDATA[Themes]]></category><guid isPermaLink="false">http://wpcandy.com/?p=23857</guid> <description><![CDATA[If you&#8217;ve read through part 1 of our introduction to WordPress Hooks, you should be &#8230;  <a
href="http://wpcandy.com/teaches/custom-hooks-and-pluggable-functions">Continue reading <span
class="meta-nav">&#8594;</span></a><div
class="tentblogger-rss-footer"><p>You just finished reading <a
href="http://wpcandy.com/?p=23857">Introduction to Custom Hooks and Pluggable Functions</a> on <a
href="http://wpcandy.com" title="WPCandy WordPress community news">WPCandy</a>. Please consider leaving a comment!</p><p></p></div>]]></description> <content:encoded><![CDATA[<p><a
href="http://wpcandy.com/?p=23857"><img
class="alignnone size-full wp-image-23861" title="WordPress hooks tutorial (teaser)" src="http://cdn.wpcandy.com/files/2011/07/wphooks2-teaser.png" alt="" width="600" height="240" /></a></p><p>If you&#8217;ve read through <a
href="http://wpcandy.com/teaches/how-to-use-wordpress-hooks">part 1 of our introduction to WordPress Hooks</a>, you should be well aware of what constitutes an &#8220;action&#8221; or &#8220;filter&#8221; hook and where they can be used. Today we&#8217;ll be exploring a little further down the rabbit hole, as we discuss pluggable functions and the concept of creating our own &#8220;action&#8221; and &#8220;filter&#8221; hook points, as well as how we can leverage these and create relationships between themes and plugins using various WordPress Hooks.</p><p>Note: This tutorial isn&#8217;t for the faint of heart (there are a few advanced bits). If you haven&#8217;t read part 1, I strongly suggest doing so before reading on.</p><p><span
id="more-23857"></span></p><h3>What are custom action and filter points?</h3><p>As we discussed previously, it&#8217;s possible to use actions to run your own code at key points during a WordPress page load, as well as using filters to modify text, settings or just about anything with a filter on it, to tailor your WordPress installation to be exactly as you&#8217;d like it. What about themes and plugins though? How do I inject my own custom goodness in there? That&#8217;s where custom action and filter points come in.</p><p>Using the same functionality built within the WordPress core itself, we can create our own action points (such as `wp_head` or `wp_footer`) within our themes and plugins. This is, at it&#8217;s core, relatively straight forward and can be used in either a standard or a more advanced way. Assuming we&#8217;re working on a plugin called, for example, &#8220;WPCandy News&#8221;, we could add the following to the top of, say, a widget that displays the latest news:</p><pre><code>&lt;?php do_action( 'wpcandy_news_widget_before' ); ?&gt;</code></pre><p>This is the core of what makes up a WordPress action point. The <a
href="http://codex.wordpress.org/Function_Reference/do_action">do_action()</a> function instructs WordPress to look for any hooks attached to whatever tag is specified (in our case, that would be &#8220;wpcandy_news_widget_before&#8221;) and run that function. Simple, right?</p><p>Hold on a moment, that&#8217;s not all. The `do_action()` function can also accept multiple arguments (parameters) which are then passed through, if desired, to the function we&#8217;re hooking on. Sounds complicated, right? Not really. Let&#8217;s use the same example above, but extend it a bit.</p><pre><code>&lt;?php do_action( 'wpcandy_news_widget_before', $limit, $id ); ?&gt;</code></pre><p>To the snippet, I&#8217;ve added 2 extra arguments; a `$limit` variable and an `$id` variable. These are example variables that would be created by the plugin, holding the number of articles to display and the ID we&#8217;re assigning to an element in the widget respectively. If we setup our `add_action()` call correctly, we should receive these values in our function, ready for us to use.</p><h3>Hold on, where does add_action() come into this?</h3><p>Without <a
href="http://codex.wordpress.org/Function_Reference/add_action">add_action()</a>, `do_action()` means nothing. The `add_action()` function allows us, and other themes or plugins, to assign functions to be run when WordPress reaches our action. At it&#8217;s core, an example of how we&#8217;d hook onto our new action point would be:</p><pre><code>&lt;?php add_action( 'wpcandy_news_widget_before', 'wpcandy_news_widget_before_content' );
function wpcandy_news_widget_before_content () {
     echo '&lt;p&gt;' . __( ' This is our custom text.', 'wpcandy' ) . &lt;/p&gt;';
} // End wpcandy_news_widget_before_content() ?&gt;</code></pre><p>Now that&#8217;s great and all, but what about `$limit` and $id`? Enter our last two parameters; the &#8220;priority&#8221; and the &#8220;accepted arguments&#8221;.</p><p>Priority allows us to optionally specify an ordering for when our action should be executed, if multiple actions are assigned to the same `do_action()` call. This can be extremely useful in controlling the flow of your theme or plugin. Additionally, the accepted arguments number allows us to optionally specify that multiple arguments will be passed through to our action. The default value is 1, so no need to specify anything if you only have 1 argument going through.</p><p>This is what our modified code would look like:</p><pre><code>&lt;?php add_action( 'wpcandy_news_widget_before', 'wpcandy_news_widget_before_content', 1, 2 );
function wpcandy_news_widget_before_content ( $limit, $id ) {
     if ( $limit &gt; 5 ) {
          echo '&lt;p&gt;' . __( ' This is our custom text.', 'wpcandy' ) . &lt;/p&gt;';
     }
} // End wpcandy_news_widget_before_content() ?&gt;</code></pre><p>We&#8217;ve made several minor changes here, which are as follows:</p><ol><li>Added the &#8220;priority&#8221; and &#8220;accepted arguments&#8221; parameter values, set at 1 and 2 respectively.</li><li>Added `$limit` and `$id` values to our function, to be passed through by `do_action()`.</li><li>Made example use of our `$limit` variable inside the function.</li></ol><p>Often, for scalability&#8217;s sake and keeping things clean and future proof, developers often encase these `do_action()` calls within functions. An example of this would be the `wp_head()` function, added to the vast majority of WordPress themes (so much so, that it is deemed a requirement). This function, in essence, runs `do_action( &#8216;wp_head&#8217; )`, which is as straight forward as explained above. Magical, right?</p><h3>Okay, but what about filters?</h3><p>The concept of custom filter points is much the same as for custom action points, except it relates to filters. As we discussed in part 1, it&#8217;s possible to place a filter on just about anything, from a snippet of content to an array of settings or options. The requirements here are much the same as with `do_action()`, except for two aspects; the first being that we&#8217;re using the `apply_filters()` function and the second being that we require two parameters instead of just the tag. The second parameter involved is the core of what makes the `apply_filters()` function necessary- <strong>the data itself</strong>.</p><p>Lets dive right into an example of how we&#8217;d put this into action. Continuing the example of our &#8220;WPCandy News&#8221; plugin, lets place a filter on our widget&#8217;s title. The code for this would look as follows:</p><pre><code>&lt;?php $title = apply_filters( 'widget_title', $title ); ?&gt;</code></pre><p>This code says; &#8220;take the value of the `$title` variable, apply any filters attached to the &#8216;widget_title&#8217; hook, and assign the filtered value back to the `$title` variable&#8221;. Simple, right?</p><p>If you&#8217;re familiar with PHP, a basic comparison I like to make when explaining how filters work is to compare them to string-related functions in PHP such as `str_replace()`. We&#8217;d use the `str_replace()` function in a much similar to way our snippet above, as follows:</p><pre><code>&lt;?php $title = str_replace( 'one', 'two', $title ); ?&gt;</code></pre><p>The concept is that we&#8217;re passing a value through to our function and getting a value back. This is the core of what a filter function does.</p><p>Much like `do_action()`, the `apply_filters()` function can also accept additional arguments. These function in exactly the same way as with `do_action()` and are made available using the &#8220;priority&#8221; and &#8220;accepted arguments&#8221; parameters on the `add_filter()` function, in the same way as they are used on `add_action()`. As can be seen, the differences between &#8220;action&#8221; and &#8220;filter&#8221; hooks and how they are created is marginal (they both function off of the same backbone code).</p><p>Even if you don&#8217;t intend to create your own action and filter points, it&#8217;s important to understand the full scope of how they work and how the `add_action()` and `add_filter()` functions fit into the grand scheme of things. If you use themes such as Canvas, for example, you&#8217;ll notice these types of custom hooks in use, which are there to allow maximum flexibility and control over the way you&#8217;d like the theme to display and function.</p><h3>Enough about hooks, what are these &#8220;pluggable function&#8221; things?</h3><p>The concept of a &#8220;pluggable function&#8221; has become popular within the WordPress community, particularly in the realm of parent themes and theme frameworks. These are functions that are overrideable by simply creating a new instance of the function within a child theme or in a part of the theme that&#8217;s triggered before the function&#8217;s original location (this is commonly the root of the `functions.php` file). This concept is option used for functions that generate commonly customised areas of themes, such as the post metadata below the title on a theme&#8217;s blog posts archives, or the area below the post content on single blog post screens. As with &#8220;action&#8221; and &#8220;filter&#8221; hooks, there are virtually infinite uses for pluggable functions.</p><h3>Okay, I get it. How do I create these?</h3><p>This part is really simple. It involves two skills; the first being knowing which functions in a theme are pluggable (and therefore, knowing the theme) and the second being knowing how to make the modification you&#8217;d like to make.</p><p>An easy way of finding out which functions in a theme are pluggable is by searching for the following code:</p><pre><code>if ( ! function_exists( 'insert_function_name_here' ) ) {</code></pre><p>This line is the beginning of a conditional statement that would commonly wrap around a function with the name &#8220;insert_function_name_here&#8221;. This just says that the function should only be created if it doesn&#8217;t already exist, which leaves room for the function to be overridden. Lets create an example of this.</p><p>This would be our original function, with the conditional statement wrapping around it:</p><pre><code>&lt;?php if ( ! function_exists( 'wpcandy_display_recent_news' ) ) { 
     function wpcandy_display_recent_news ( $limit = 5 ) {
          // This is where we'd run the meat of the function.
     } // End wpcandy_display_recent_news()
} ?&gt;</code></pre><p>Overriding this in our child theme is as simple as copying the code and removing the conditional statement (the first line and the bracket at the end), and placing this in our child theme, where we can then make any modifications to it that we desire, without needing to modify the parent theme.</p><h3>Hooks and pluggable functions are great, but when do I use which?</h3><p>A general rule of thumb that I like to stick to is: a function should only be made pluggable if not attached to an &#8220;action&#8221; or &#8220;filter&#8221; hook. The reason for this is that it&#8217;s possible to <a
href="http://codex.wordpress.org/Function_Reference/remove_filter">remove functions from hooks</a>, as well as to override them using the &#8220;priority&#8221; setting explained above, which renders the pluggable nature of the function redundant. This also makes it easier to decipher the nature of a function (if it&#8217;s pluggable, it&#8217;s not attached to a hook), which can speed up development time as well as making it easier for developers who are looking at the code for the first time to decipher what&#8217;s going on under the hood.</p><p>And that, ladies and gentlemen, is a tutorial on how to create your own action and filter points, as well as a brief introduction into the concept of pluggable functions, how to use them and when to use which techniques.</p><div
class="tentblogger-rss-footer"><p>You just finished reading <a
href="http://wpcandy.com/?p=23857">Introduction to Custom Hooks and Pluggable Functions</a> on <a
href="http://wpcandy.com" title="WPCandy WordPress community news">WPCandy</a>. Please consider leaving a comment!</p><p></p></div>]]></content:encoded> <wfw:commentRss>http://wpcandy.com/teaches/custom-hooks-and-pluggable-functions/feed</wfw:commentRss> <slash:comments>6</slash:comments> </item> <item><title>How to create your own WordPress functionality plugin</title><link>http://wpcandy.com/teaches/how-to-create-a-functionality-plugin?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=how-to-create-a-functionality-plugin</link> <comments>http://wpcandy.com/teaches/how-to-create-a-functionality-plugin#comments</comments> <pubDate>Tue, 10 May 2011 17:04:36 +0000</pubDate> <dc:creator>Ryan Imel</dc:creator> <category><![CDATA[Tutorials]]></category> <category><![CDATA[featured]]></category> <category><![CDATA[Plugins]]></category> <category><![CDATA[Themes]]></category><guid isPermaLink="false">http://wpcandy.com/?p=18260</guid> <description><![CDATA[A common, yet unfortunate practice in the WordPress community involves filling theme functions.php files with &#8230;  <a
href="http://wpcandy.com/teaches/how-to-create-a-functionality-plugin">Continue reading <span
class="meta-nav">&#8594;</span></a><div
class="tentblogger-rss-footer"><p>You just finished reading <a
href="http://wpcandy.com/?p=18260">How to create your own WordPress functionality plugin</a> on <a
href="http://wpcandy.com" title="WPCandy WordPress community news">WPCandy</a>. Please consider leaving a comment!</p><p></p></div>]]></description> <content:encoded><![CDATA[<p><a
href="http://wpcandy.com/?p=18260"><img
class="alignnone size-full wp-image-8936" title="WordPress functionality plugin" src="http://cdn.wpcandy.com/files/2010/11/functionalityplugin-teaser.png" alt="" width="600" height="250" /></a></p><p>A common, yet unfortunate practice in the WordPress community involves filling theme <code>functions.php</code> files with tweaks and functionality that is key to a site. The reason this is a bad idea, in short, is that it will tie your critical site functionality to a theme that <em>will</em> eventually change. Good news, though: there is a much better, smarter alternative. It&#8217;s called a functionality plugin.</p><p>We&#8217;re going to create a very simple, very specific functionality plugin that you can (hopefully) use to replace your theme&#8217;s <code>functions.php</code> file. After all, the poor guy deserves a break, doesn&#8217;t he?</p><p><span
id="more-18260"></span></p><h3>What (and why) is a functionality plugin?</h3><p>First of all, the thing to realize with plugins is that, for all intents and purposes, they behave no differently than your theme&#8217;s <code>functions.php</code> file. I won&#8217;t say there are no differences, of course, but a plugin file should <strong>not</strong> be treated as something foreign and strange. If you&#8217;ve edited your <code>functions.php</code> file &#8212; even if you&#8217;ve just edited it by dropping in <code>PHP</code> that you found searching online &#8212; then you are familiar enough to manage your own plugins.</p><blockquote
class="jump"><p> You can think of it as a portable functions.php file that you can take with you when you change themes.</p></blockquote><p>Having said that, when I refer to a functionality plugin, I&#8217;m talking about a certain type of plugin intended to belong to a specific website. You can think of it as a <em>portable</em> <code>functions.php</code> file that you can take with you when you change themes.</p><p>Functionality plugins should contain all of the code that is important for the <strong>necessary structure</strong> and <strong>functionality</strong> of your website. By creating a plugin specifically for your website you have the ability of taking the most important parts of your site with you from theme to theme.</p><p>Let&#8217;s look at a couple of examples. One common thing often added to <code>functions.php</code> files is a <code>register_taxonomy</code> function. This sort of function will create a custom taxonomy (like categories or tags, but defined by you) to allow you to organize your content further. This is what it would look like:</p><p><code>function people_init() {<br
/>  register_taxonomy(<br
/>     'people',<br
/>     'post',<br
/>     array(<br
/>       'label' =&gt; __('People'),<br
/>       'sort' =&gt; true,<br
/>       'args' =&gt; array('orderby' =&gt; 'term_order'),<br
/>       'rewrite' =&gt; array('slug' =&gt; 'profiles'),<br
/>     )<br
/>   );<br
/> }add_action( 'init', 'people_init' );</code></p><p>If we include this in our WordPress theme&#8217;s <code>functions.php</code> file we may run into a surprise when (<em>not if</em>) we change our theme in the future and don&#8217;t see our custom taxonomy on the Dashboard anymore. In order to maintain our taxonomy we would have to scour the <code>functions.php</code> file before the theme change to make sure we didn&#8217;t miss anything important.</p><p>Or, and this is what I recommend, we could create a plugin named after our site and put the function in there. Then we can change themes freely, knowing that our most important, core functionality is preserved safely in a plugin. I call these special types of plugins <em>functionality plugins</em>.</p><h3>What belongs in a functionality plugin?</h3><p>To decide what belongs in a <code>functions.php</code> file and what belongs in a functionality plugin, think long term. Rather than thinking about how your website will look and behave this week, think about how it will look and behave five years from now. With few exceptions, I bet all of our sites will have new and upgraded themes in five years&#8217; time.</p><p>For every item we might instinctively want to add to our <code>functions.php</code> file, we should stop and consider whether our site will depend on that functionality in five years or not. Consider the following list of functions, for example:</p><ol><li><span
style="line-height: 19px;"><code>register_post_type()</code> and <code>register_taxonomy()</code>, for creating a custom content type and related taxonomy.</span></li><li><span
style="line-height: 19px;"><code>add_shortcode()</code>, to create a shortcode for publishing certain kinds of content more easily.</span></li><li><span
style="line-height: 19px;"><code>add_theme_support( 'post-thumbnails' )</code> and <code>add_image_size()</code>, to enable post thumbnails and set a certain size.</span></li></ol><p>Let&#8217;s take the first example, <code>register_post_type()</code> and <code>register_taxonomy()</code>. In five years will you still want these types of content available to you on the Dashboard and on your site? Of course you will, that&#8217;s your site&#8217;s content! Your content and how you can access it shouldn&#8217;t be determined by the particular theme you&#8217;ve chosen. These, and others like it, should be included in a functionality plugin, not your <code>functions.php</code> file.</p><p>In the second example, <code>add_shortcode()</code>, we&#8217;re adding a way to drop in potentially complex code into our content. There&#8217;s a rule of thumb I have for determining what belongs in a plugin: if it modifies or interacts with content it belongs in a plugin. In this case we&#8217;re quite literally creating content, and if this function is missing our content will display in the raw shortcode format. In this case as well, it belongs in a functionality plugin.</p><p>For more on shortcodes and their use in WordPress themes, see <a
href="http://justintadlock.com/archives/2011/05/02/dealing-with-shortcode-madness">Justin Tadlock&#8217;s recent post</a>.</p><p>Finally, the third item <code>add_theme_support( 'post-thumbnails' )</code> and <code>add_image_size()</code> add a post thumbnail and particular size to your site. This is one case that I would say is debatable, since post thumbnails, and in particular sizes, may depend largely on the particular display of your site. In my own case I define post thumbnails in a plugin, but I could see the argument for including them in theme files instead. So, in this case: it depends.</p><h3>What belongs in functions.php?</h3><p>Your theme&#8217;s <code>functions.php</code> file is for any functions or declarations that are necessary for your theme&#8217;s appearance. As long as what you&#8217;ve added there don&#8217;t effect your content in any way, you should be just fine.</p><p>There are a number of examples of functions best kept in your theme&#8217;s functions.php file:</p><ol><li><span
style="line-height: 19px;"><code>registern_nav_menus()</code></span></li><li><span
style="line-height: 19px;"><code>register_sidebar()</code></span></li><li><span
style="line-height: 19px;"><code>wp_enqueue_script()</code> and <code>wp_enqueue_style()</code><br
/> </span></li></ol><p>The <code>register_nav_menus()</code> is appropriately placed in a theme&#8217;s <code>functions.php</code> file, since the placement of the navigation menus themselves depend on the given theme you are using. Keeping this function in a plugin would give you menu placement options on the Dashboard that wouldn&#8217;t actually display anywhere in your theme.</p><p><code>register_sidebar()</code> should also stay in your <code>functions.php</code> file, since once again registering sidebars in a plugin could mean you have active plugins on the Dashboard that don&#8217;t actually show up anywhere on your site. That would be pretty silly.</p><p><code>wp_enqueue_script()</code> and <code>wp_enqueue_style()</code> are both similar, and I would say depend on the situation. If you are creating a child theme they belong in functions.php. If you are adding them for another purpose (modifying the WordPress admin bar, for instance) then a plugin would likely be more appropriate. As in our earlier examples, this third example requires a bit of context to be sure whether it belongs in <code>functions.php</code> or a plugin.</p><h3>How to create your first functionality plugin</h3><p>Creating a functionality plugin is easy, particularly if you understand it as an extension of your <code>functions.php</code> file. You&#8217;ll want to start with a plugin file with the appropriate comment header, like this:</p><p><code>/*<br
/> Plugin Name: Your Site's Functionality Plugin<br
/> Description: All of the important functionality of your site belongs in this.<br
/> Version: 0.1<br
/> License: GPL<br
/> Author: Your Name<br
/> Author URI: yoururl<br
/> */</code></p><p>Save that as a PHP file within its own folder in your site&#8217;s plugin directory. I would also recommend maintaining a basic <code>readme.txt</code> file for your own sake. Trust me, you-in-five-years will thank you for starting it today. Document the changes you make to your functionality plugin, as well as what everything does.</p><p
class="note">If you&#8217;d like, <a
href="http://wpcandy.s3.amazonaws.com/resources/sample-functionality-plugin.zip">download our blank functionality plugin</a> to help you get started.</p><p>Now head to your WordPress plugins page and activate your plugin. Congrats, you just activated your own plugin: your own comment-only, functionally empty plugin, but your own plugin nonetheless! It won&#8217;t do anything, but the nice part now is that you have a file on your site, a plugin file, that will behave much like you&#8217;re used to <code>functions.php</code> behaving. And instead of abusing your functions.php file with code you will need later on, you can use your new functionality plugin.</p><h3>What goes in our plugin?</h3><p>Now comes the fun part, where we move over site-vital functions to our plugin. To briefly recap, we&#8217;re interested in moving functions that are vital to our site&#8217;s operation&nbsp;stuff we will want around when (not if) we change our theme in the future.</p><p>Everyone&#8217;s <code>functions.php</code> file will be slightly different, as well as what will count as &#8220;vital site functionality&#8221;. But here&#8217;s a table with a handful of functions I&#8217;ve seen floating around, and where <em>I think</em> they belong:</p><table
id="wp-table-reloaded-id-19-no-1" class="wp-table-reloaded wp-table-reloaded-id-19"><thead><tr
class="row-1 odd"><th
class="column-1">Purpose of code</th><th
class="column-2">Functionality plugin</th><th
class="column-3"><code>functions.php</code></th></tr></thead><tbody><tr
class="row-2 even"><td
class="column-1">Creating shortcodes</td><td
class="column-2">Always</td><td
class="column-3">Never</td></tr><tr
class="row-3 odd"><td
class="column-1">Adding scripts and styles</td><td
class="column-2">Depends</td><td
class="column-3">Depends</td></tr><tr
class="row-4 even"><td
class="column-1">Creating sidebars</td><td
class="column-2">Never</td><td
class="column-3">Always</td></tr><tr
class="row-5 odd"><td
class="column-1">Creating menus</td><td
class="column-2">Never</td><td
class="column-3">Always</td></tr><tr
class="row-6 even"><td
class="column-1">Add post types/taxonomies</td><td
class="column-2">Always</td><td
class="column-3">Never</td></tr><tr
class="row-7 odd"><td
class="column-1">Add post thumbnails</td><td
class="column-2">Depends</td><td
class="column-3">Depends</td></tr><tr
class="row-8 even"><td
class="column-1">Add Google Analytics to footer</td><td
class="column-2">Always</td><td
class="column-3">Never</td></tr><tr
class="row-9 odd"><td
class="column-1">Customize WordPress Dashboard</td><td
class="column-2">Always</td><td
class="column-3">Never</td></tr><tr
class="row-10 even"><td
class="column-1">Change default Gravatar</td><td
class="column-2">Always</td><td
class="column-3">Never</td></tr><tr
class="row-11 odd"><td
class="column-1">Add custom profile fields</td><td
class="column-2">Always</td><td
class="column-3">Never</td></tr></tbody></table><p>There are plenty of other examples I could use here (actually, limitless examples) but these should be enough to deliver my point.</p><h3>Your future creating plugins</h3><p>Sometimes even the functionality plugin may not provide as much universality as we want. Sometimes it may be better to create our own plugins to create unique functionality in each one. If you&#8217;re anything like me, functionality plugins like this will be your first foray into WordPress plugin development. I&#8217;m much closer to the beginner side of the spectrum than I am the expert side, but what I&#8217;ve learned the past 6 months or so has been driven in large part by working in plugins rather than <code>functions.php</code>.</p><p><img
src="http://cdn.wpcandy.com/files/2011/05/rwi-plugins-example.png" alt="" title="Ryan&#039;s recently created plugins viewed via Coda" width="264" height="109" class="alignright size-full wp-image-18547" /></p><p>Next time you are copying and pasting a function from a website, or perhaps you managed to piece together code doing just what you need for your purposes, consider abstracting it, writing yourself some solid documentation on what it does, and turning it into a plugin of its own. Likely this won&#8217;t require anything more than moving that function into a plugin file with the appropriate commented header (seen above). By doing this you will have tiny portable pieces of functionality you can enable on sites whenever you need them.</p><p>I, for instance, created a few super simple plugins just this month:</p><ul><li><span
style="line-height: 19px;"><a
href="http://wordpress.org/extend/plugins/admin-bar-hover-intent/">Admin Bar Hover Intent</a>: This one I&#8217;m proud of, because I actually released it into the wild on the plugin directory (something I&#8217;ve only done once before). It simply implements jQuery hoverIntent on the dropdowns, requiring a deliberate pause over them before they drop down. </span></li><li><span
style="line-height: 19px;">Admin Bar Cleanup: Sometimes I create plugins that tweak things to operate just the way I like them. In this case, Admin Bar Cleanup just hides the WordPress search bar from the admin bar for me. I don&#8217;t use it on every website of mine, but on a few it&#8217;s definitely active.</span></li><li><span
style="line-height: 19px;">Login Redirect Home: This plugin simply, when active, redirects all login activity back to the home page. I use this one sparingly: only on team P2 blogs, team wikis, and task tracking sites. </span></li></ul><p>Not long ago I would have just added it to my site&#8217;s functionality plugin (or worse the <code>functions.php</code> file) and moved on, only to likely re-do the same work later in another project.</p><p>But each of these plugins requires less than twenty lines of code. All I did was stop myself from adding functionality to only my own site, and stepped back to consider the usefulness of the functions outside of the current project. If there was use for it, I whipped up a quick plugin file and dropped the code in.</p><h3>What are your thoughts?</h3><p>Your turn to speak up. What are your thoughts on functionality plugins? Looking through your theme&#8217;s <code>functions.php</code> file, do you see anything which would be better off in a functionality plugin to preserve it for your next theme choice?</p><div
class="tentblogger-rss-footer"><p>You just finished reading <a
href="http://wpcandy.com/?p=18260">How to create your own WordPress functionality plugin</a> on <a
href="http://wpcandy.com" title="WPCandy WordPress community news">WPCandy</a>. Please consider leaving a comment!</p><p></p></div>]]></content:encoded> <wfw:commentRss>http://wpcandy.com/teaches/how-to-create-a-functionality-plugin/feed</wfw:commentRss> <slash:comments>98</slash:comments> </item> <item><title>Introduction to Hooks: a basic WordPress building block</title><link>http://wpcandy.com/teaches/how-to-use-wordpress-hooks?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=how-to-use-wordpress-hooks</link> <comments>http://wpcandy.com/teaches/how-to-use-wordpress-hooks#comments</comments> <pubDate>Wed, 04 May 2011 10:30:49 +0000</pubDate> <dc:creator>Matt Cohen</dc:creator> <category><![CDATA[Tutorials]]></category> <category><![CDATA[Plugins]]></category> <category><![CDATA[Themes]]></category><guid isPermaLink="false">http://wpcandy.com/?p=14182</guid> <description><![CDATA[WordPress hooks are arguably the basis of WordPress development, forming a large part of the &#8230;  <a
href="http://wpcandy.com/teaches/how-to-use-wordpress-hooks">Continue reading <span
class="meta-nav">&#8594;</span></a><div
class="tentblogger-rss-footer"><p>You just finished reading <a
href="http://wpcandy.com/?p=14182">Introduction to Hooks: a basic WordPress building block</a> on <a
href="http://wpcandy.com" title="WPCandy WordPress community news">WPCandy</a>. Please consider leaving a comment!</p><p></p></div>]]></description> <content:encoded><![CDATA[<p><a
href="http://wpcandy.com/?p=14182"><img
class="alignnone size-full wp-image-18263" src="http://cdn.wpcandy.com/files/2011/02/wphookstutorial-teaser.jpg" alt="" width="600" height="240" /></a></p><p>WordPress hooks are arguably the basis of WordPress development, forming a large part of the core functionality and used by almost every plugin and theme available to date. The concept of hooks can also be somewhat daunting for users who are starting out with developing for WordPress. Today, we&#8217;ll jump in and find out a bit more about just what exactly WordPress hooks are and how they can help you on your way to WordPress rock stardom.</p><p><span
id="more-14182"></span></p><h3>What exactly *are* WordPress hooks anyways?</h3><p>WordPress hooks are, essentially, triggers of sorts that allow users to, with short snippets of code, modify areas a WordPress theme or plugin, or add their own code to various parts of WordPress without modifying the original files. An example of this could be along the lines of either &#8220;when WordPress chooses which template file to load, run our custom code&#8221; or &#8220;when you generate the content for each post, add social bookmarking links to the end of the content&#8221;. These examples will be expanded upon once we&#8217;re a bit more familiar with what exactly the different types of hooks are.</p><p>Hooks can be divided into &#8220;Action&#8221; and &#8220;Filter&#8221; hooks, the former allowing for insertion of custom code at various points (not unlike events in JavaScript) and the latter allowing for the manipulation of various bits of content (for example, the content of a page or blog post). Lets take a closer look at each of these, shall we?</p><h3>Action Hooks</h3><p>Action hooks are designated points in the WordPress core, theme and plugin code where it is possible for outside resources (outside of the scope of where the hook is&#8230; either in the core, theme or plugin) to insert additional code and, there by, customise the code to do additional functions they may desire. An example of this is the commonly used <code>wp_head</code> action hook, used by many themes and plugins to inject additional CSS stylesheets, processing code or anything else they require to sit between the <code>&lt;head&gt;</code> and <code>&lt;/head&gt;</code> tags of their WordPress theme&#8217;s XHTML structure. This is the reason for including <code>wp_head();</code> in all WordPress themes.</p><p>To hook on to an action, create a function in your theme&#8217;s <code>functions.php</code> file (or in your plugin&#8217;s code) and hook it on using the <code>add_action()</code> function, as follows:</p><pre><code>&lt;?php
	add_action( 'wp_head', 'wpcandy_actionhook_example' );

	function wpcandy_actionhook_example () {

		echo '&lt;meta name="description" content="This is the meta description for this page." /&gt;' . "\n";

	} // End wpcandy_actionhook_example()
?&gt;</code></pre><p>The above code adds the text &#8220;Hello WPCandy Readers!&#8221; between your theme&#8217;s <code>&lt;head&gt;</code> tags. Placing &#8220;wp_head&#8221; in the call to <code>add_action()</code> with &#8220;get_header&#8221; would display this text above your theme.</p><p>The way I like to explain action hooks, in a single sentence, is: &#8220;When you get to <em>this</em> point, do <em>that</em>.&#8221;</p><h3>Filter Hooks</h3><p>Filter hooks are used to manipulate output. An example of this would be to add a line or text (or a hyperlink, or a signature sign-off—whatever you&#8217;d like) to the end of the content of each of your blog posts. Filter hooks can also be used for truncating text, changing formatting of content, or just about any other programming manipulation requirement (for example, adding to or overriding an array of values).</p><p>Custom code is added as a filter using the <code>add_filter()</code> function. The following code adds a sign-off to the end of each blog post, only when viewing the full blog post screen:</p><pre><code>&lt;?php
	add_filter( 'the_content', 'wpcandy_filterhook_signoff' );

	function wpcandy_filterhook_signoff ( $content ) {

		if ( is_single() ) {

			$content .= '&lt;div class="sign-off"&gt;Th-th-th-th-th That\'s all, folks!&lt;/div&gt;</code><code>' . "\n";

		} // End IF Statement

		return $content;

	} // End wpcandy_filterhook_signoff()
?&gt;</code></pre><p>The above code adds a new <code>div</code> tag to the end of the content of our blog post, only when on a single blog post screen.</p><p>A filter hook is like using the <code>str_replace()</code> function in <code>PHP</code>. You give it some data, manipulate, replace or reformat the data and return the new content out at the end.</p><h3>&#8230; and now, for a few commonly asked questions&#8230; answered.</h3><h4>Are custom hooks available only to the theme or plugins I&#8217;ve got activated?</h4><p>Custom hooks and filters that are added by a theme or plugin, only apply if that theme or plugin is active. There are many hooks, however, that are global (<code>get_header</code>, <code>wp_head</code> and <code>wp_footer</code> are three examples). If you&#8217;d like to switch themes regularly and maintain the functions you&#8217;ve hooked onto these, or other, global hooks or filters, I&#8217;d recommend writing them into a plugin.</p><p>Themes and plugins are able to specify custom filters and actions. We&#8217;ll get more into this in part two.</p><h4>Where can I learn more about action and filter hooks?</h4><p>My favourite resource is, without a doubt, the WordPress Codex. While there are many tutorials available online regarding filter and action hook applications, the best understanding comes, as they say, when heard from the horse&#8217;s mouth. The Codex provides useful examples, as well as up to date and informative explanations, which aid in gathering an overall understanding of the Plugin API (the API that handles action and filter hooks).</p><ul><li>Action hooks: <a
href="http://codex.wordpress.org/Plugin_API#Actions">http://codex.wordpress.org/Plugin_API#Actions</a></li><li>Filter hooks: <a
href="http://codex.wordpress.org/Plugin_API#Filters">http://codex.wordpress.org/Plugin_API#Filters</a></li><li>And for further reading on the topic, the remainder of the Plugin API page is also available: <a
href="http://codex.wordpress.org/Plugin_API#Hooks.2C_Actions_and_Filters.">http://codex.wordpress.org/Plugin_API#Hooks.2C_Actions_and_Filters</a>.</li></ul><p>Right. Now that we&#8217;ve answered a few questions, lets show some practical examples that can be used right off the bat with any WordPress theme.</p><h4>Add &#8220;time ago&#8221; time display at the end of each post.</h4><pre><code>&lt;?php
	add_filter( 'the_content', 'wpcandy_time_ago' );

	function wpcandy_time_ago ( $content ) {

		$content .= "\n" . __( 'Posted ', 'wpcandy' ) . human_time_diff( get_the_time('U'), current_time('timestamp') ) . __( ' ago', 'wpcandy' );

		return $content;

	} // End wpcandy_time_ago()
?&gt;</code></pre><h4>Use WordPress conditional tags to detect the user&#8217;s web browser and add a class with it&#8217;s name to the body tag.</h4><pre><code>&lt;?php
add_filter('body_class','browser_body_class');
function browser_body_class($classes) {
	global $is_lynx, $is_gecko, $is_IE, $is_opera, $is_NS4, $is_safari, $is_chrome, $is_iphone;

	if($is_lynx) $classes[] = 'lynx';
	elseif($is_gecko) $classes[] = 'gecko';
	elseif($is_opera) $classes[] = 'opera';
	elseif($is_NS4) $classes[] = 'ns4';
	elseif($is_safari) $classes[] = 'safari';
	elseif($is_chrome) $classes[] = 'chrome';
	elseif($is_IE) $classes[] = 'ie';
	else $classes[] = 'unknown';

	if($is_iphone) $classes[] = 'iphone';
	return $classes;
}
?&gt;</code></pre><h4>Remove the WordPress 3.1 Admin Bar.</h4><pre><code>&lt;?php add_filter( 'show_admin_bar', '__return_false' ); ?&gt;</code></pre><h3>What about Twenty Ten?</h3><p>With the introduction of Twenty Ten as the WordPress default theme, the theme received a large amount of documentation in the theme files, with several custom hooks or pluggable functions created specifically for it. Lets take a look at how we can use these hooks to enhance Twenty Ten.</p><p>The main custom hook in the TwentyTen theme serves a relatively simple purpose: adding content to the credits area in the footer. This is done by hooking on to the new &#8220;twentyten_credits&#8221; action hook. Here&#8217;s an example:</p><pre><code>&lt;?php
	add_action( 'twentyten_credits', 'wpcandy_credits' );

	function wpcandy_credits () {

		$html = '';

		$html .= 'Proudly brought to you by &lt;a href="http://wpcandy.com/"&gt;WPCandy&lt;/a&gt;.' . "\n";

		echo $html;

	} // End wpcandy_credits()
?&gt;</code></pre><p>The above function adds a simple line of credit text to the footer area in the Twenty Ten theme. In part two, we&#8217;ll discuss pluggable functions, which can be used in the Twenty Ten theme in particular to enhance and customise the output above and below the post content in the theme.</p><h3>Coming in part two:</h3><p>Creating your own hooks &amp; filters and a brief introduction to pluggable functions; the hook&#8217;s lil&#8217; sister. Please share your experiences with using WordPress action and filter hooks in the comments below.</p><div
class="tentblogger-rss-footer"><p>You just finished reading <a
href="http://wpcandy.com/?p=14182">Introduction to Hooks: a basic WordPress building block</a> on <a
href="http://wpcandy.com" title="WPCandy WordPress community news">WPCandy</a>. Please consider leaving a comment!</p><p></p></div>]]></content:encoded> <wfw:commentRss>http://wpcandy.com/teaches/how-to-use-wordpress-hooks/feed</wfw:commentRss> <slash:comments>20</slash:comments> </item> </channel> </rss><!-- Performance optimized by W3 Total Cache. Learn more: http://www.w3-edge.com/wordpress-plugins/

Minified using disk: basic
Page Caching using disk: basic
Database Caching 25/87 queries in 0.234 seconds using disk: basic
Object Caching 1853/1995 objects using disk: basic
Content Delivery Network via cdn.wpcandy.com

Served from: wpcandy.com @ 2012-05-31 18:08:26 -->

