<?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/" version="2.0">

<channel>
	<title>WordPress and Ajax</title>
	
	<link>http://wpajax.com</link>
	<description>An in-depth guide on using Ajax with WordPress</description>
	<lastBuildDate>Tue, 02 Apr 2013 17:32:18 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.5.1</generator>
		<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/wpajax" /><feedburner:info xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" uri="wpajax" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><item>
		<title>Removing All Dashboard Widgets</title>
		<link>http://wpajax.com/articles/removing-all-dashboard-widgets</link>
		<comments>http://wpajax.com/articles/removing-all-dashboard-widgets#comments</comments>
		<pubDate>Mon, 28 Nov 2011 14:38:26 +0000</pubDate>
		<dc:creator>Ronald Huereca</dc:creator>
				<category><![CDATA[Code Snippets]]></category>
		<category><![CDATA[3.3 Beta 4]]></category>

		<guid isPermaLink="false">http://wpajax.com/?p=361</guid>
		<description><![CDATA[<p>Here&#8217;s a quick snippet for removing all Dashboard widgets in the admin area. As always, I&#8217;m game for a better way &#8211; Something about four foreach loops does not strike me as efficient.</p><p>The post <a href="http://wpajax.com/articles/removing-all-dashboard-widgets">Removing All Dashboard Widgets</a> appeared first on <a href="http://wpajax.com">WordPress and Ajax</a>.</p>]]></description>
				<content:encoded><![CDATA[<p>Here&#8217;s a quick snippet for removing all Dashboard widgets in the admin area.  As always, I&#8217;m game for a better way <img src='http://wpajax.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  &#8211; Something about four foreach loops does not strike me as efficient.</p>
<pre class="brush: php; title: ; notranslate">
&lt;?php
// Create the function to use in the action hook
function remove_dashboard_widgets() {
	global $wp_meta_boxes;
	if ( !array( $wp_meta_boxes ) ) return;
	foreach ( $wp_meta_boxes as $widget_section =&gt; $widget_locations ) {
		if ( $widget_section == 'dashboard' ) {
			foreach ( $widget_locations as $widget_location =&gt; $widget_types ) {
				foreach ( $widget_types as $widget_type =&gt; $widgets ) {
					foreach ( $widgets as $widget_name =&gt; $widget ) {
						remove_meta_box( $widget_name, $widget_section, $widget_location );
					}				
				}
			}
		}
	}
} 
// Hoook into the 'wp_dashboard_setup' action to register our function
add_action('wp_dashboard_setup', 'remove_dashboard_widgets', 11 );
?&gt;
</pre>
<p>The post <a href="http://wpajax.com/articles/removing-all-dashboard-widgets">Removing All Dashboard Widgets</a> appeared first on <a href="http://wpajax.com">WordPress and Ajax</a>.</p>]]></content:encoded>
			<wfw:commentRss>http://wpajax.com/articles/removing-all-dashboard-widgets/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>A Custom the_content Filter</title>
		<link>http://wpajax.com/articles/a-custom-the_content-filter</link>
		<comments>http://wpajax.com/articles/a-custom-the_content-filter#comments</comments>
		<pubDate>Fri, 25 Nov 2011 08:03:28 +0000</pubDate>
		<dc:creator>Ronald Huereca</dc:creator>
				<category><![CDATA[Code Snippets]]></category>
		<category><![CDATA[WP 3.2]]></category>

		<guid isPermaLink="false">http://wpajax.com/?p=355</guid>
		<description><![CDATA[<p>There have been numerous times when I needed the filter capabilities of the_content, but I didn&#8217;t want other plugin and/or theme authors to be able to hook into it and add in their own stuff. Here&#8217;s a code snippet I use quite regularly (please add in your own custom prefix). Some sample use-cases: Run on [...]</p><p>The post <a href="http://wpajax.com/articles/a-custom-the_content-filter">A Custom the_content Filter</a> appeared first on <a href="http://wpajax.com">WordPress and Ajax</a>.</p>]]></description>
				<content:encoded><![CDATA[<p>There have been numerous times when I needed the filter capabilities of <a href="http://codex.wordpress.org/Function_Reference/the_content">the_content</a>, but I didn&#8217;t want other plugin and/or theme authors to be able to hook into it and add in their own stuff.</p>
<p>Here&#8217;s a code snippet I use quite regularly (please add in your own custom prefix).  </p>
<pre class="brush: php; title: ; notranslate">
&lt;?php
/* Filter for the content - Custom */
add_action( 'init', 'city_the_content', 1 );
function city_the_content() {
	//Create our own version of the_content so that others can't accidentally loop into our output - Taken from default-filters.php, shortcodes.php, and media.php
	if ( !has_filter( 'city_the_content', 'wptexturize' ) ) {
		add_filter( 'city_the_content', 'wptexturize'        );
		add_filter( 'city_the_content', 'convert_smilies'    );
		add_filter( 'city_the_content', 'convert_chars'      );
		add_filter( 'city_the_content', 'wpautop'            );
		add_filter( 'city_the_content', 'shortcode_unautop'  );
		add_filter( 'city_the_content', 'prepend_attachment' );
		$vidembed = new WP_Embed();
		add_filter( 'city_the_content', array( &amp;$vidembed, 'run_shortcode'), 8 );
		add_filter( 'city_the_content', array( &amp;$vidembed, 'autoembed'), 8 );
		add_filter( 'city_the_content', 'do_shortcode', 11);
	} //end has_filter
} //end city_the_content
?&gt;
</pre>
<p>Some sample use-cases:</p>
<ul>
<li>Run on excerpts</li>
<li>Run on Widget text output</li>
<li>Run on just about any text, really</li>
</ul>
<p>It applies the same formatting rules, and even includes the fancy <a href="http://codex.wordpress.org/Embeds">oEmbed</a> capabilities.</p>
<p>Enjoy.</p>
<p>The post <a href="http://wpajax.com/articles/a-custom-the_content-filter">A Custom the_content Filter</a> appeared first on <a href="http://wpajax.com">WordPress and Ajax</a>.</p>]]></content:encoded>
			<wfw:commentRss>http://wpajax.com/articles/a-custom-the_content-filter/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Easy Lazy Loading Via Ajax</title>
		<link>http://wpajax.com/articles/easy-lazy-loading-via-ajax</link>
		<comments>http://wpajax.com/articles/easy-lazy-loading-via-ajax#comments</comments>
		<pubDate>Mon, 07 Nov 2011 03:06:00 +0000</pubDate>
		<dc:creator>Ronald Huereca</dc:creator>
				<category><![CDATA[Code Snippets]]></category>

		<guid isPermaLink="false">http://wpajax.com/?p=347</guid>
		<description><![CDATA[<p>My friend Koop asked me over Twitter if there was an easy lazy-loading technique to load social media icons. Initially he wanted to load the icons over hover, but I talked him into doing it on a page load. The problem with social media icons is that they are loaded from external sources, and are [...]</p><p>The post <a href="http://wpajax.com/articles/easy-lazy-loading-via-ajax">Easy Lazy Loading Via Ajax</a> appeared first on <a href="http://wpajax.com">WordPress and Ajax</a>.</p>]]></description>
				<content:encoded><![CDATA[<p>My friend Koop asked me over Twitter if there was an easy lazy-loading technique to load social media icons.  Initially he wanted to load the icons over hover, but I talked him into doing it on a page load.</p>
<p>The problem with social media icons is that they are loaded from external sources, and are typically in iFrame format.  These can delay a page load (in my experience) by as much as a minute.</p>
<p>While the page load doesn&#8217;t decrease with this technique, it allows the content to render, thus giving the visitor the impression that the site is loading rather fast.</p>
<p>Here&#8217;s some bare code you are free to expand upon.  It&#8217;s basic, not necessarily secure, and not really optimized.  However, if you&#8217;re a competent enough dev, you should be able to re-factor it to suit your use-case.</p>
<p>I placed the below code in a theme&#8217;s functions.php file.  If you do decide to re-factor the code, please place a pastebin link so others can learn your technique as well.</p>
<pre class="brush: php; title: ; notranslate">
&lt;?php
//Ajax actions for lazy load
add_action( 'wp_ajax_nopriv_koop_lazy_load', 'koop_ajax_lazy_load' );
add_action( 'wp_ajax_koop_lazy_load', 'koop_ajax_lazy_load' );
function koop_ajax_lazy_load() {
	//Ajax response
	$post_id = intval( $_POST[ 'pid' ] );
	$permalink = get_permalink( $post_id );
	ob_start();
	?&gt;
    &lt;a href=&quot;https://twitter.com/share&quot; class=&quot;twitter-share-button&quot; data-count=&quot;horizontal&quot;&gt;Tweet&lt;/a&gt;&lt;script type=&quot;text/javascript&quot; src=&quot;http://platform.twitter.com/widgets.js&quot;&gt;&lt;/script&gt;
    &lt;?php
	$twitter = ob_get_clean();
	die( $twitter );
} //end koop_ajax_lazy_load

//Add the DIV to the content
add_filter( 'the_content', 'koop_the_content' );
function koop_the_content( $content ) {
	global $post;
	ob_start();
?&gt;
	&lt;div id='koop_lazy_load' rel='&lt;?php echo absint( $post-&gt;ID ); ?&gt;'&gt;
    &lt;input type='hidden' value='&lt;?php echo esc_url( admin_url( 'admin-ajax.php' ) ); ?&gt;' name='koop_ajax_url' id='koop_ajax_url' /&gt;
    &lt;/div&gt;
&lt;?php
	$return = $content . ob_get_clean();
	return $return;
} //end koop_the_content
add_action( 'wp_print_scripts', 'koop_print_scripts' );
//Load jQuery
function koop_print_scripts() {
	wp_enqueue_script( 'jquery' );
}
//Load our lazy loader script
add_action( 'wp_footer', 'koop_head', 100 );
function koop_head() {
	?&gt;
    &lt;script type=&quot;text/javascript&quot;&gt;
    	jQuery( document ).ready( function( $ ) {
			var post_id = $( '#koop_lazy_load' ).attr( 'rel' );
			var koop_ajax_url = $( '#koop_ajax_url' ).val();
			//Do ajax
		$.post( koop_ajax_url, { action: 'koop_lazy_load', pid: post_id },
			function( response ){
				$( &quot;#koop_lazy_load&quot; ).html( response );
			} //end ajax response
		 ); //end ajax
		} );
    &lt;/script&gt;
    
    &lt;?php
} //end koop_head
?&gt;
</pre>
<p>The code creates an empty container DIV below the post content.  jQuery captures the post ID, sends an Ajax request, and the response contains the HTML for all the social media icons necessary.  A sample Twitter button is included in the code.</p>
<p>The post <a href="http://wpajax.com/articles/easy-lazy-loading-via-ajax">Easy Lazy Loading Via Ajax</a> appeared first on <a href="http://wpajax.com">WordPress and Ajax</a>.</p>]]></content:encoded>
			<wfw:commentRss>http://wpajax.com/articles/easy-lazy-loading-via-ajax/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Delete Cron Jobs from WordPress</title>
		<link>http://wpajax.com/articles/delete-cron-jobs-from-wordpress</link>
		<comments>http://wpajax.com/articles/delete-cron-jobs-from-wordpress#comments</comments>
		<pubDate>Tue, 27 Sep 2011 20:24:44 +0000</pubDate>
		<dc:creator>Ronald Huereca</dc:creator>
				<category><![CDATA[Code Snippets]]></category>

		<guid isPermaLink="false">http://wpajax.com/?p=342</guid>
		<description><![CDATA[<p>I recently had the struggle of deleting cron jobs from a site within a Multisite network. None of the delete cron functions seemed to work for me, so I wrote a function to brute-force it. I&#8217;m all ears for a better way</p><p>The post <a href="http://wpajax.com/articles/delete-cron-jobs-from-wordpress">Delete Cron Jobs from WordPress</a> appeared first on <a href="http://wpajax.com">WordPress and Ajax</a>.</p>]]></description>
				<content:encoded><![CDATA[<p>I recently had the struggle of deleting cron jobs from a site within a Multisite network.  None of the delete cron functions seemed to work for me, so I wrote a function to brute-force it.</p>
<p>I&#8217;m all ears for a better way <img src='http://wpajax.com/wp-includes/images/smilies/icon_biggrin.gif' alt=':D' class='wp-smiley' /> </p>
<pre class="brush: php; title: ; notranslate">
//Removes a cron based on a hook name
function delete_cron_hooks( $hooks = array(), $blog_id = 0 ) {
	if ( is_multisite() &amp;&amp; $blog_id != 0 ) {				
		switch_to_blog( $blog_id );
	}
	$crons = get_option( 'cron' );
	if ( !$crons ) return false;
	foreach ( $crons as $timestamp =&gt; $cron ) {
		foreach ( $hooks as $hook ) {
			if ( isset( $cron[ $hook ] ) ) {
				unset( $crons[ $timestamp ] );
			}
		}
	}

	update_option( 'cron', $crons );
	
	
} //end delete_cron
</pre>
<p>The post <a href="http://wpajax.com/articles/delete-cron-jobs-from-wordpress">Delete Cron Jobs from WordPress</a> appeared first on <a href="http://wpajax.com">WordPress and Ajax</a>.</p>]]></content:encoded>
			<wfw:commentRss>http://wpajax.com/articles/delete-cron-jobs-from-wordpress/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>WordPress Multisite Explained</title>
		<link>http://wpajax.com/articles/wordpress-multisite-explained</link>
		<comments>http://wpajax.com/articles/wordpress-multisite-explained#comments</comments>
		<pubDate>Fri, 23 Sep 2011 19:27:36 +0000</pubDate>
		<dc:creator>Ronald Huereca</dc:creator>
				<category><![CDATA[Resources]]></category>

		<guid isPermaLink="false">http://wpajax.com/?p=337</guid>
		<description><![CDATA[<p>Over the past few weeks, my friend Bes Zain and I created a few videos that demonstrate how to install WordPress Multisite. Both videos also demonstrate how to utilize the WordPress commercial plugin BackupBuddy to help transferring sites into and outside of a network a breeze. How to set up WordPress Multisite Domain Mapping How [...]</p><p>The post <a href="http://wpajax.com/articles/wordpress-multisite-explained">WordPress Multisite Explained</a> appeared first on <a href="http://wpajax.com">WordPress and Ajax</a>.</p>]]></description>
				<content:encoded><![CDATA[<p>Over the past few weeks, my friend Bes Zain and I created a few videos that demonstrate how to install WordPress Multisite.</p>
<p>Both videos also demonstrate how to utilize the <a href="http://pluginbuddy.com/purchase/backupbuddy/">WordPress commercial plugin BackupBuddy</a> to help transferring sites into and outside of a network a breeze.</p>
<h3>How to set up WordPress Multisite Domain Mapping</h3>
<p><span class='embed-youtube' style='text-align:center; display: block;'><iframe class='youtube-player' type='text/html' width='640' height='390' src='http://www.youtube.com/embed/oDM5v2Ymk1M?version=3&#038;rel=1&#038;fs=1&#038;showsearch=0&#038;showinfo=1&#038;iv_load_policy=1&#038;wmode=transparent' frameborder='0'></iframe></span></p>
<h3>How to set up and use BackupBuddy with WordPress Multisite</h3>
<p><iframe src="http://player.vimeo.com/video/29432403" width="500" height="281" frameborder="0" webkitAllowFullScreen mozallowfullscreen allowFullScreen></iframe></p>
<p>The post <a href="http://wpajax.com/articles/wordpress-multisite-explained">WordPress Multisite Explained</a> appeared first on <a href="http://wpajax.com">WordPress and Ajax</a>.</p>]]></content:encoded>
			<wfw:commentRss>http://wpajax.com/articles/wordpress-multisite-explained/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>wp_print_r – My favorite debugging function that isn’t included in core</title>
		<link>http://wpajax.com/articles/wp_print_r-my-favorite-debugging-function-that-isnt-included-in-core</link>
		<comments>http://wpajax.com/articles/wp_print_r-my-favorite-debugging-function-that-isnt-included-in-core#comments</comments>
		<pubDate>Thu, 07 Jul 2011 16:09:50 +0000</pubDate>
		<dc:creator>Ronald Huereca</dc:creator>
				<category><![CDATA[Code Snippets]]></category>

		<guid isPermaLink="false">/?p=332</guid>
		<description><![CDATA[<p></p><p>The post <a href="http://wpajax.com/articles/wp_print_r-my-favorite-debugging-function-that-isnt-included-in-core">wp_print_r &#8211; My favorite debugging function that isn&#8217;t included in core</a> appeared first on <a href="http://wpajax.com">WordPress and Ajax</a>.</p>]]></description>
				<content:encoded><![CDATA[<pre class="brush: php; title: ; notranslate">
if ( !function_exists( 'wp_print_r' ) ) {
	function wp_print_r( $args, $die = true ) {
		$echo = '&lt;pre&gt;' . print_r( $args, true ) . '&lt;/pre&gt;';
		if ( $die ) die( $echo );
		else echo $echo;
	}
}
</pre>
<p>The post <a href="http://wpajax.com/articles/wp_print_r-my-favorite-debugging-function-that-isnt-included-in-core">wp_print_r &#8211; My favorite debugging function that isn&#8217;t included in core</a> appeared first on <a href="http://wpajax.com">WordPress and Ajax</a>.</p>]]></content:encoded>
			<wfw:commentRss>http://wpajax.com/articles/wp_print_r-my-favorite-debugging-function-that-isnt-included-in-core/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>jQuery Fundamentals</title>
		<link>http://wpajax.com/articles/jquery-fundamentals</link>
		<comments>http://wpajax.com/articles/jquery-fundamentals#comments</comments>
		<pubDate>Fri, 22 Apr 2011 14:37:31 +0000</pubDate>
		<dc:creator>Ronald Huereca</dc:creator>
				<category><![CDATA[Resources]]></category>

		<guid isPermaLink="false">/?p=327</guid>
		<description><![CDATA[<p>For those who have read my WordPress and Ajax book, you&#8217;ll know that I get pretty involved with jQuery throughout. I have a basic chapter on jQuery, but for those who want to know more, I recommend jQuery Fundamentals (a free resource). From their site: jQuery is fast becoming a must-have skill for front-end developers. [...]</p><p>The post <a href="http://wpajax.com/articles/jquery-fundamentals">jQuery Fundamentals</a> appeared first on <a href="http://wpajax.com">WordPress and Ajax</a>.</p>]]></description>
				<content:encoded><![CDATA[<p>For those who have read my WordPress and Ajax book, you&#8217;ll know that I get pretty involved with jQuery throughout.  I have a basic chapter on jQuery, but for those who want to know more, I recommend <a href="http://jqfundamentals.com/book/index.html">jQuery Fundamentals</a> (a free resource).</p>
<p>From their site:</p>
<blockquote><p>jQuery is fast becoming a must-have skill for front-end developers. The purpose of this book is to provide an overview of the jQuery JavaScript library; when you&#8217;re done with the book, you should be able to complete basic tasks using jQuery, and have a solid basis from which to continue your learning. This book was designed as material to be used in a classroom setting, but you may find it useful for individual study.</p></blockquote>
<p>Source:  <a href="http://jqfundamentals.com/book/index.html">jQuery Fundamentals</a></p>
<p>The post <a href="http://wpajax.com/articles/jquery-fundamentals">jQuery Fundamentals</a> appeared first on <a href="http://wpajax.com">WordPress and Ajax</a>.</p>]]></content:encoded>
			<wfw:commentRss>http://wpajax.com/articles/jquery-fundamentals/feed</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Quick Tip:  Disallow File Editing on Client Dev Sites</title>
		<link>http://wpajax.com/articles/quick-tip-disallow-file-editing-on-client-dev-sites</link>
		<comments>http://wpajax.com/articles/quick-tip-disallow-file-editing-on-client-dev-sites#comments</comments>
		<pubDate>Fri, 18 Mar 2011 19:09:38 +0000</pubDate>
		<dc:creator>Ronald Huereca</dc:creator>
				<category><![CDATA[Code Snippets]]></category>

		<guid isPermaLink="false">/?p=322</guid>
		<description><![CDATA[<p>If you&#8217;ve ever dealt with clients, you&#8217;ve probably also set up development sites to demonstrate plugins and/or themes. One danger before receiving final payment is the person ripping off your code through the plugin/theme editor. While this is tedious to do, it is still a real and scary possibility. To deactivate the plugin/theme editor, just [...]</p><p>The post <a href="http://wpajax.com/articles/quick-tip-disallow-file-editing-on-client-dev-sites">Quick Tip:  Disallow File Editing on Client Dev Sites</a> appeared first on <a href="http://wpajax.com">WordPress and Ajax</a>.</p>]]></description>
				<content:encoded><![CDATA[<p>If you&#8217;ve ever dealt with clients, you&#8217;ve probably also set up development sites to demonstrate plugins and/or themes.</p>
<p>One danger before receiving final payment is the person ripping off your code through the plugin/theme editor.  While this is tedious to do, it is still a real and scary possibility.</p>
<p>To deactivate the plugin/theme editor, just add the following line into your dev site&#8217;s wp-config file:</p>
<pre class="brush: php; title: ; notranslate">define( 'DISALLOW_FILE_EDIT' , true );</pre>
<p>That&#8217;s it.  Simple and sweet.  Hat tip to <a href="http://strangework.com/">Brad Williams</a> for the suggestion (here&#8217;s also <a href="http://core.trac.wordpress.org/ticket/11306">the Trac discussion</a>).</p>
<p>The post <a href="http://wpajax.com/articles/quick-tip-disallow-file-editing-on-client-dev-sites">Quick Tip:  Disallow File Editing on Client Dev Sites</a> appeared first on <a href="http://wpajax.com">WordPress and Ajax</a>.</p>]]></content:encoded>
			<wfw:commentRss>http://wpajax.com/articles/quick-tip-disallow-file-editing-on-client-dev-sites/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>WordPress Upgrade Class for Commercial or Client Plugins</title>
		<link>http://wpajax.com/articles/wordpress-upgrade-class-for-commercial-or-client-plugins</link>
		<comments>http://wpajax.com/articles/wordpress-upgrade-class-for-commercial-or-client-plugins#comments</comments>
		<pubDate>Tue, 08 Mar 2011 16:04:13 +0000</pubDate>
		<dc:creator>Ronald Huereca</dc:creator>
				<category><![CDATA[Code Snippets]]></category>

		<guid isPermaLink="false">/?p=315</guid>
		<description><![CDATA[<p>If you have a plugin hosted outside of the official WordPress repo (whether commercial or for clients), one issue you&#8217;ll inevitably run into is how to utilize automatic upgrades. For my upcoming release of Ajax Edit Comments, I coded an upgrade class that immensely simplified the process for me. First, I&#8217;ll share the code to [...]</p><p>The post <a href="http://wpajax.com/articles/wordpress-upgrade-class-for-commercial-or-client-plugins">WordPress Upgrade Class for Commercial or Client Plugins</a> appeared first on <a href="http://wpajax.com">WordPress and Ajax</a>.</p>]]></description>
				<content:encoded><![CDATA[<p>If you have a plugin hosted outside of the official WordPress repo (whether commercial or for clients), one issue you&#8217;ll inevitably run into is how to utilize automatic upgrades.</p>
<p>For my upcoming release of <a href="http://www.ajaxeditcomments.com">Ajax Edit Comments</a>, I coded an upgrade class that immensely simplified the process for me.</p>
<p>First, I&#8217;ll share the code to the upgrade class and then go over implementation.  Please note that this class is still a work in progress, and it being GPL, you&#8217;re welcome to expand on it.  I do ask that if you do this, please share the changes with me so I can better improve the class.</p>
<p>Here are the current features of the class:</p>
<ol>
<li>Automatic updates work automagically upon successful instantiation.</li>
<li>Filters to overwrite common parameters.</li>
<li>Two public methods to check upgrades manually and perform remote requests.</li>
</ol>
<h3>The Upgrade Class</h3>
<pre class="brush: php; title: ; notranslate">
&lt;?php
//Plugin Upgrade Class
if ( !class_exists( &quot;PluginUpgrade&quot; ) ) :
class PluginUpgrade {
			private $plugin_url = false;
			private $remote_url = false;
			private $version = false;
			private $plugin_slug = false;
			private $plugin_path = false;
			private $time_upgrade_check = false;
			private $plugins = '';
			
			function __construct( $args = array() ) {
				//Load defaults
				extract( wp_parse_args( $args, array( 
					'remote_url' =&gt; false,
					'version' =&gt; false,
					'plugin_slug' =&gt; false,
					'plugin_path' =&gt; false,
					'plugin_url' =&gt; false,
					'time' =&gt; 43200
				) ) );
				$this-&gt;plugin_url = $plugin_url;
				$this-&gt;remote_url = $remote_url;
				$this-&gt;version = $version;
				$this-&gt;plugin_slug = $plugin_slug;
				$this-&gt;plugin_path = $plugin_path;
				$this-&gt;time_upgrade_check = apply_filters( &quot;pu_time_{$plugin_slug}&quot;, $time );
				
				//Get plugins for upgrading
				$this-&gt;plugins = $this-&gt;get_plugin_options();
				
				add_action( 'admin_init', array( &amp;$this, 'init' ), 1 );
				add_action( &quot;after_plugin_row_{$plugin_path}&quot;, array( &amp;$this, 'plugin_row' ) );
				
				
			} //end constructor
			public function init() {
				//Set up update checking and hook in the filter for automatic updates
				//Do upgrade stuff
				//todo check is_admin() ?
				if (current_user_can(&quot;administrator&quot;)) {
					$this-&gt;check_periodic_updates();
					if ( isset( $this-&gt;plugins[ $this-&gt;plugin_slug ]-&gt;new_version ) ) {
						if( !version_compare( $this-&gt;version, $this-&gt;plugins[ $this-&gt;plugin_slug ]-&gt;new_version, '&gt;=' ) ) {
							add_filter( 'site_transient_update_plugins', array( &amp;$this, 'update_plugins_filter' ),1000 );
						}
					}
				}
			}
			//Performs a periodic upgrade check to see if the plugin needs to be upgraded or not
			private function check_periodic_updates() {	
				$last_update = isset( $this-&gt;plugins[ $this-&gt;plugin_slug ]-&gt;last_update ) ? $this-&gt;plugins[ $this-&gt;plugin_slug ]-&gt;last_update : false;
				if ( !$last_update ) { $last_update = $this-&gt;check_for_updates(); }
				if( ( time() - $last_update ) &gt; $this-&gt;time_upgrade_check ){
						$this-&gt;check_for_updates();
				}
			} //end check_periodic_updates
			public function get_remote_version() {
				if ( isset( $this-&gt;plugins[ $this-&gt;plugin_slug ]-&gt;new_version ) ) {
					return $this-&gt;plugins[ $this-&gt;plugin_slug ]-&gt;new_version;
				}
				return false;
			}
			private function get_plugin_options() {
				//Get plugin options
				if ( is_multisite() ) {
					$options = get_site_option( 'pu_plugins' );
				} else {
					$options = get_option( 'pu_plugins' );
				}
				if ( !$options ) {
					$options = array();
				}
				return $options;
			}
			private function save_plugin_options() {
				//Get plugin options
				if ( is_multisite() ) {
					update_site_option( 'pu_plugins', $this-&gt;plugins );
				} else {
					$options = update_option( 'pu_plugins', $this-&gt;plugins );
				}
			}
			public function check_for_updates( $manual = false ) {
				if ( !is_array( $this-&gt;plugins ) ) return false;
				//Check to see that plugin options exist
				if ( !isset( $this-&gt;plugins[ $this-&gt;plugin_slug ] ) ) {

					$plugin_options = new stdClass;
					$plugin_options-&gt;url = $this-&gt;plugin_url;
					$plugin_options-&gt;slug = $this-&gt;plugin_slug;
					$plugin_options-&gt;package = '';
					$plugin_options-&gt;new_version = $this-&gt;version;
					$plugin_options-&gt;last_update = time();
					$plugin_options-&gt;id = &quot;0&quot;;
					
					$this-&gt;plugins[ $this-&gt;plugin_slug ] = $plugin_options;
					$this-&gt;save_plugin_options();
				}
												

				$current_plugin = $this-&gt;plugins[ $this-&gt;plugin_slug ];
				if( ( time() - $current_plugin-&gt;last_update ) &gt; $this-&gt;time_upgrade_check || $manual ) {
					//Check for updates
					$version_info = $this-&gt;perform_remote_request( 'get_version' );
					if ( is_wp_error( $version_info ) ) return false;
					//$version_info should be an array with keys ['version'] and ['download_url'] 
					if ( isset( $version_info-&gt;version ) &amp;&amp; isset( $version_info-&gt;download_url ) ) {
						$current_plugin-&gt;new_version = $version_info-&gt;version;
						$current_plugin-&gt;package = $version_info-&gt;download_url;
						$this-&gt;plugins[ $this-&gt;plugin_slug ] = $current_plugin;
						$this-&gt;save_plugin_options();
					}
				}
				return $this-&gt;plugins[ $this-&gt;plugin_slug ];
			} //end check_for_updates
			
			public function plugin_row( $plugin_name ) {
				do_action( &quot;pu_plugin_row_{$this-&gt;plugin_slug}&quot;, $plugin_name );
			}
			public function perform_remote_request( $action, $body = array(), $headers = array(), $return_format = 'json' ) {
			
				$body = wp_parse_args( $body, array( 
					'action' =&gt; $action,
					'wp-version' =&gt; get_bloginfo( 'version' ),
					'referer' =&gt; site_url()
				) ) ;
				$body = http_build_query( apply_filters( &quot;pu_remote_body_{$this-&gt;plugin_slug}&quot;, $body ) );
				
				$headers = wp_parse_args( $headers, array( 
					'Content-Type' =&gt; 'application/x-www-form-urlencoded',
					'Content-Length' =&gt; strlen( $body )
				) );
				$headers = apply_filters( &quot;pu_remote_headers_{$this-&gt;plugin_slug}&quot;, $headers );
				
				$post = array( 'headers' =&gt; $headers, 'body' =&gt; $body );
				//Retrieve response
				$response = wp_remote_post( esc_url( $this-&gt;remote_url ), $post );
				$response_code = wp_remote_retrieve_response_code( $response );
				$response_body = wp_remote_retrieve_body( $response );
				
				if ( $response_code != 200 || is_wp_error( $response_body ) ) {
					return false;
				}
				
				if ( $return_format != 'json' ) {
					return $response_body;
				} else {
					return json_decode( $response_body );
				}
				return false;
			} //end perform_remote_request
		
		//Return an updated version to WordPress when it runs its update checker
		public function update_plugins_filter( $value ) {
			if ( isset( $this-&gt;plugins[ $this-&gt;plugin_slug ] ) &amp;&amp; $this-&gt;plugin_path ) {
				$value-&gt;response[ $this-&gt;plugin_path ] = $this-&gt;plugins[ $this-&gt;plugin_slug ];
			}
			return $value;
		}
		
} //end class
endif;
?&gt;
</pre>
<h3>Instantiating the Class</h3>
<p>Somewhere in your plugin, you would instantiate the class (assuming you&#8217;ve included the class in with your plugin):</p>
<pre class="brush: php; title: ; notranslate">
&lt;?php
$args = array(
	'remote_url' =&gt; 'http://domain.com/remoteupgrade.php',
	'version' =&gt; '4.2.0.0',
	'plugin_slug' =&gt; 'wp-ajax-edit-comments',
	'plugin_path' =&gt; 'wp-ajax-edit-comments/wp-ajax-edit-comments.php',
	'plugin_url' =&gt; 'http://www.ajaxeditcomments.com',
	'time' =&gt; 43200
);
				
$upgrade = new PluginUpgrade( $args );
?&gt;
</pre>
<p>The class accepts six parameters upon instantiation.</p>
<ol>
<li><strong>remote_url:</strong> A URL that the upgrader will ping to retrieve update information.  I&#8217;ll get into this in a bit.</li>
<li><strong>version:</strong>  A string version number of the current plugin installed.</li>
<li><strong>plugin_slug:</strong>  A unique slug that identified your plugin.</li>
<li><strong>plugin_path:</strong>  The path to your plugin from the /plugins/ directory.</li>
<li><strong>plugin_url:</strong>  The URL to your plugin.</li>
<li><strong>time:</strong> An integer in seconds that dictates how long to wait between upgrade checks.  Default is 12 hours (or 43200 seconds).</li>
</ol>
<p>On the remote side of it, assuming a URL with the <strong>http://domain.com/remoteupgrade.php</strong> path, you&#8217;ll need to return a JSON string of the new plugin&#8217;s version and a download URL.</p>
<p>When sending an update request, the class automatically passes an <strong>action</strong> POST variable to the <strong>remote_url</strong>.  The default action for checking for upgrades is <strong>get_version</strong>.</p>
<p>At the <strong>remote_url</strong> location, you would do a check for an <strong>action</strong> variable and do something based on the action.</p>
<p>Here&#8217;s an example:</p>
<pre class="brush: php; title: ; notranslate">
&lt;?php
$action = $_POST['action'];
switch ( $action ) {
	case 'get_version': 
		echo json_encode( array( 
			'version' =&gt; '4.3.0.0',
			'download_url' =&gt; 'http://domain.com/downloads/wp-ajax-edit-comments.zip'
			) );
		break;
	case 'some_other_action':
		//...//
		break
} //end switch
?&gt;
</pre>
<p>The upgrade class assumes two JSON variables being returned:  <strong>version</strong> and <strong>download_url</strong>.   How you get those values in your remote_url is up to you.</p>
<h3>Public Methods</h3>
<p>The class has two public methods to assist in performing other requests besides checking for plugin updates.</p>
<h4>perform_remote_request</h4>
<p>The <strong>perform_remote_request</strong> method allows you to perform an arbitrary remote request on the <strong>remote_url</strong> you specified.  Again, this is action based.</p>
<p>Here&#8217;s an example:  </p>
<pre class="brush: php; title: ; notranslate">
$result = $upgrade-&gt;perform_remote_request( 'authkey_check', array( 'key' =&gt; $key ) );
</pre>
<p>The first argument is an action name.  The second and third arguments are optional, and allow you to set header/body arguments respectively.  A fourth argument is also optional, and allows you to specify the return format (e.g., json).</p>
<p>Here&#8217;s an example I have of retrieving a remote changelog:</p>
<pre class="brush: php; title: ; notranslate">
$result = $upgrade-&gt;perform_remote_request( 'changelog', array(), array(), 'html' );
</pre>
<h4>check_for_updates</h4>
<p>If your plugin has an option to check for updates manually (without having to wait until the magic 12 hour mark), you can call the <strong>check_for_updates</strong> method.  Just pass a <strong>true</strong> to the method to skip the time check.</p>
<pre class="brush: php; title: ; notranslate">
$plugin_info = $upgrade-&gt;check_for_updates( true );
</pre>
<h3>Class Hooks</h3>
<ul>
<li>pu_remote_body_{$plugin_slug} &#8211; Filter &#8211; Allows you to add default body arguments for the remote request</li>
<li>pu_remote_headers_{$plugin_slug} &#8211; Filter &#8211; Allows you to add default header arguments for the remote request</li>
<li>pu_time_{$plugin_slug} &#8211; Filter &#8211; Allows you to overwrite the default time between upgrade checks</li>
</ul>
<h3>Conclusion</h3>
<p>In summary, the class allows you to:</p>
<ol>
<li>Automagically set up automatic upgrades upon instantiation.   This requires you to pass some parameters back based on your remote_url.</li>
<li>Perform manual upgrade checks.</li>
<li>Perform arbitrary remote requests to your remote_url.</li>
<li>Set default headers/body arguments per filters.</li>
</ol>
<p>I hope this can help get the ball rolling for other plugin authors.  </p>
<p>The post <a href="http://wpajax.com/articles/wordpress-upgrade-class-for-commercial-or-client-plugins">WordPress Upgrade Class for Commercial or Client Plugins</a> appeared first on <a href="http://wpajax.com">WordPress and Ajax</a>.</p>]]></content:encoded>
			<wfw:commentRss>http://wpajax.com/articles/wordpress-upgrade-class-for-commercial-or-client-plugins/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>WordPress Professional Plugin Development Book Review</title>
		<link>http://wpajax.com/articles/wordpress-professional-plugin-development-book-review</link>
		<comments>http://wpajax.com/articles/wordpress-professional-plugin-development-book-review#comments</comments>
		<pubDate>Wed, 02 Mar 2011 23:40:59 +0000</pubDate>
		<dc:creator>Ronald Huereca</dc:creator>
				<category><![CDATA[Reviews]]></category>

		<guid isPermaLink="false">/?p=300</guid>
		<description><![CDATA[<p>A formula for success: Put together an idea and outline for a book that hasn&#8217;t been covered in-depth before. Gather three of the most talented WordPress developers/writers and have them write the book. Release the book and watch the Elves return back to Middle Earth to rejoice with men. Professional Plugin Development, written by Ozh [...]</p><p>The post <a href="http://wpajax.com/articles/wordpress-professional-plugin-development-book-review">WordPress Professional Plugin Development Book Review</a> appeared first on <a href="http://wpajax.com">WordPress and Ajax</a>.</p>]]></description>
				<content:encoded><![CDATA[<p><img src="http://wpajax.com/files//2011/03/51j90CzibLL._SL160_.jpg" alt="WordPress Professional Plugin Development" title="WordPress Professional Plugin Development" width="127" height="160" class="alignright size-full wp-image-301" /></p>
<p>A formula for success:</p>
<ol>
<li>Put together an idea and outline for a book that hasn&#8217;t been covered in-depth before.</li>
<li>Gather three of the most talented WordPress developers/writers and have them write the book.</li>
<li>Release the book and watch the Elves return back to Middle Earth to rejoice with men.</li>
</ol>
<p>Professional Plugin Development, written by <a href="http://planetozh.com/">Ozh Richard</a>, <a href="http://justintadlock.com/">Justin Tadlock</a>, and <a href="http://strangework.com/">Brad Williams</a>, is a much-needed and very timely book.</p>
<p>Even after releasing my own book (ahem), there were several that have approached me saying they needed a start-from-the-basics WordPress plugin development book.  And while Professional Plugin Development does teach the basics of plugin development, it quickly moves on to much more complex topics.</p>
<p>The book covers the topics I care most about, such as:</p>
<ul>
<li>WordPress Plugin Foundation and Best Practices</li>
<li>WordPress Security</li>
<li>WordPress Actions and Filters (aka, hooks)</li>
<li>And&#8230; (ahem) Ajax</li>
</ul>
<p>But the book goes beyond basic plugin development.  It teaches you about plugin options, CRON for scheduling common tasks, storing data (whether it is via post types, transients, or options), the HTTP API (for retrieving remote data), users (how to set up roles and capabilities), localization (err, internationalization), and how to test plugin performance.</p>
<p>For a novice PHP and WordPress developer, this is a good starting point.  But don&#8217;t think of this book as your way to learn PHP, jQuery, or even basic WordPress (there&#8217;s WordPress for Dummies for that).</p>
<p>This is a book written by developers for developers.  And I must say that I learned a lot from this book, and I&#8217;ve been developing WordPress plugins and themes for almost six years.</p>
<p>Here are the things I learned most from this book:</p>
<ul>
<li><strong>The Why</strong>.  I&#8217;ve used a lot of the techniques from the book before, but now I have a better understanding of why the techniques should be implemented.  An example is security and WordPress coding best practices.</li>
<li><strong>Rewrites and Cron</strong>.  These two topics escape me (no pun intended) for some reason, but I have a much better understanding of how everything works behind the scenes.</li>
<li><strong>Security</strong>.  Security can not be stressed enough, and very solid security tips are sprinkled throughout the book (and the topic even receives treatment via its own dedicated chapter).</li>
<li><strong>Multisite</strong>.  I&#8217;ve been working with multisite for almost a year now, and it&#8217;s a topic I&#8217;m still learning in-depth.  The chapter gives a great explanation of terms and common pitfalls.</li>
</ul>
<p>Last, but certainly not least, the book goes into great detail for what you should do after you&#8217;ve released a plugin, whether you want to release it for free in the official WordPress repo, or have it available exclusively on your own site (whether commercial or free).  The book explains marketing, how to set up automatic updates (albeit a bit glossed over), and how to get the plugin on the official repo.</p>
<p><a href="http://www.amazon.com/Professional-WordPress-Plugin-Development-Williams/dp/0470916222/">Professional Plugin Development</a> (Amazon.com, non-affiliate) is a highly recommended purchase.  It&#8217;s currently available for pre-order, but will be out soon.  You can also <a href="http://p2p.wrox.com/content/blogs/jminatel/wrox-drm-free-ebooks-now-lower-priced-print">pick up the ebook</a> (Wrox.com, non-affiliate) at Wrox.  Make sure you use the coupon code <strong>FROST</strong> to get a nice discount.</p>
<p>The post <a href="http://wpajax.com/articles/wordpress-professional-plugin-development-book-review">WordPress Professional Plugin Development Book Review</a> appeared first on <a href="http://wpajax.com">WordPress and Ajax</a>.</p>]]></content:encoded>
			<wfw:commentRss>http://wpajax.com/articles/wordpress-professional-plugin-development-book-review/feed</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
	</channel>
</rss>
