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

<channel>
	<title>scompt.com &#187; Uncategorized</title>
	<atom:link href="http://scompt.com/blog/archives/category/uncategorized/feed/" rel="self" type="application/rss+xml" />
	<link>http://scompt.com</link>
	<description>The website of Edward Dale</description>
	<lastBuildDate>Sun, 04 Sep 2011 15:54:07 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
<xhtml:meta xmlns:xhtml="http://www.w3.org/1999/xhtml" name="robots" content="noindex" />
		<item>
		<title>Book Review: Play Framework Cookbook</title>
		<link>http://scompt.com/blog/archives/2011/09/04/book-review-play-framework-cookbook</link>
		<comments>http://scompt.com/blog/archives/2011/09/04/book-review-play-framework-cookbook#comments</comments>
		<pubDate>Sun, 04 Sep 2011 15:54:07 +0000</pubDate>
		<dc:creator>Edward Dale</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[book]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[play]]></category>
		<category><![CDATA[web]]></category>

		<guid isPermaLink="false">http://scompt.com/?p=367</guid>
		<description><![CDATA[The Play Framework is a Java web framework that disposes of much of the traditional Java dogma and strives to create a developer experience similar to that of more established frameworks in other languages such as Rails and Django. Gone are the routine getters and setters, replaced by public static fields. Similarly, controller methods are [...]]]></description>
			<content:encoded><![CDATA[<p>The <a href="http://www.playframework.org/" rel="nofollow" >Play Framework</a> is a Java web framework that disposes of much of the traditional Java dogma and strives to create a developer experience similar to that of more established frameworks in other languages such as Rails and Django. Gone are the routine getters and setters, replaced by public static fields. Similarly, controller methods are implemented as public static methods. Once a seasoned Java developer has gotten over these shocking design decisions and actually written an application or two with Play, the <a href="http://www.packtpub.com/play-framework-cookbook/book" rel="nofollow" >Play  Framework Cookbook</a> by <a href="http://twitter.com/spinscale" rel="nofollow" >Alexander Reelsen</a> is a good next step to learning the full depth of the framework.</p>
<p><span id="more-367"></span></p>
<p>It took me about 50 pages to get into the Play Framework Cookbook. The stated goal of the book is to pick up where the beginner&#8217;s documentation leaves off. Having already written a couple applications using Play, I was hoping the book would jump right into some nice advanced topics that I wasn&#8217;t familiar with. Instead, the first chapter (Basics of the Play Framework) dealt with exactly the beginner issues that are better handled with a <a href="http://www.playframework.org/documentation/1.2.3/home#started" rel="nofollow" >Getting Started</a> guide. If you&#8217;ve spent much time with the Play framework, you&#8217;ll probably be best served by jumping ahead to Chapter 2 (Using Controllers). Here, the author makes an emphasis on keeping your controllers lean by generous use of helper classes and methods. The <code>renderPDF</code> and <code>renderRSS</code> methods presented are good examples of this.</p>
<p>The similar concept that your application should remain lean and functionality should be extracted into modules is introduced in Chapter 3 (Leveraging Modules). The author shows a nice selection of built-in and downloadable modules that can be used to clean up your code (dependency injection), lock down your application (security), and interact with other databases (MongoDB). This would have been a nice place to jump right into writing your own modules, but first there&#8217;s the small interlude that is Chapter 4 (Creating and Using APIs). This chapter included a nice example for creating a custom tag to display charts from the Google Chart API, but it still seemed out of place.</p>
<p>Chapters 5 (Introduction to Writing Modules) and 6 (Practical Module Examples) provide a solid overview of the module system and how it can be used. Even more important, it discusses the limitations of Play modules and how they can be avoided. The author also gets his hands dirty with topic of bytecode enhancement, a technique that Play uses to provide the optimum developer experience. Writing the code to provide that experience (non-type-checked code in quotes, eek!) is something I&#8217;d like to avoid, but at least I know now how Play does it. Other examples include relevant topics such as indexing with Solr and interacting with ActiveMQ.</p>
<p>The final chapter (Running in Production) addresses some issues that pop up when moving from developer machine to the data center. A number of recipes demonstrate deployment with popular web servers (Apache, Nginx, Lighttpd) if you don&#8217;t want to use the built-in Play server in production. Integration with the Jenkens and Calimoucho continuous integration systems is also discussed in this chapter, although I think these topics would have been better suited to a separate chapter focusing on testing. Rounding out the production chapter are a number of topics related to monitoring and logging.</p>
<p>Overall, I think the Play Framework Cookbook would be a reasonable purchase for someone who&#8217;s written a couple smaller applications using Play and is looking towards something larger and more complex. The suggestions for keeping your classes and application lean will surely be useful. The <a href="http://www.packtpub.com/sites/default/files/5528OS-Chapter-2-Using-Controllers.pdf" rel="nofollow" >second chapter</a> is available as a sample from the publisher&#8217;s website.</p>
<p><em>Disclosure</em>: I was provided with an eBook copy of the Play Framework Cookbook by <a href="http://www.packtpub.com/" rel="nofollow" >Packt Publishing</a> for the purposes of this review.</p>
]]></content:encoded>
			<wfw:commentRss>http://scompt.com/blog/archives/2011/09/04/book-review-play-framework-cookbook/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Creating a maintenance window in GridEngine using JSVs</title>
		<link>http://scompt.com/blog/archives/2010/01/23/creating-a-maintenance-window-in-gridengine-using-jsvs</link>
		<comments>http://scompt.com/blog/archives/2010/01/23/creating-a-maintenance-window-in-gridengine-using-jsvs#comments</comments>
		<pubDate>Sat, 23 Jan 2010 15:15:16 +0000</pubDate>
		<dc:creator>Edward Dale</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[gridengine]]></category>
		<category><![CDATA[jsv]]></category>
		<category><![CDATA[sge]]></category>

		<guid isPermaLink="false">http://scompt.com/?p=351</guid>
		<description><![CDATA[One thing that&#8217;s always been a pain on the BASS is getting the cluster clear when we have a maintenance window, which usually happens monthly. Our initial solution was to send out an email notifying users of the upcoming outage and then simply killing all of the jobs at the appointed time. This obviously has [...]]]></description>
			<content:encoded><![CDATA[<p>One thing that&#8217;s always been a pain on the <a href="http://www.cs.unc.edu/bass" rel="nofollow" ><acronym title="Biomedical Analysis and Simulation Supercomputer">BASS</acronym></a> is getting the cluster clear when we have a maintenance window, which usually happens monthly.  Our initial solution was to send out an email notifying users of the upcoming outage and then simply killing all of the jobs at the appointed time.  This obviously has its downsides.  The solution that is currently implemented uses a <acronym title="Job Submission Verifier">JSV</acronym> to modify the hard runtime limit on the job and notify the user of the change.<br />
<span id="more-351"></span><br />
On the BASS, the default runtime for a job is 2 days (set in the cluster-wide sge_request file).  Therefore, to be most effective, the maintenance must be scheduled at least two days in advance to make sure all incoming jobs have their runtime limited.  A couple users require longer runtime limits, so we have to make sure they&#8217;re covered too.</p>
<p>The JSV below calculates the time at which the incoming job will reach the hard runtime limit and if it is after the configured maintenance window begin, modifies the hard runtime limit and notifies the user.  This ensures that all jobs running on the cluster will end before the maintenance window begins and that the users know that.</p>
<p>Without further ado, here&#8217;s the code.  It looks for a file named <code>maintenance</code> in the <code>$SGE_ROOT/$SGE_CELL/common</code> directory that contains the unix timestamp that the maintenance window begins.  It&#8217;s executed client-side from the cluster-wide <code>sge_request</code> file in the same directory.  The script requires the <code>Date</code> and <code>Time</code> libraries for some date math that it does.  I&#8217;m not a perl programmer, so bear with me.</p>
<pre class="brush: perl; title: ; notranslate">
#!/usr/bin/perl

use strict;
use warnings;
no warnings qw/uninitialized/;

use Env qw(SGE_ROOT SGE_CELL);
use lib &quot;$SGE_ROOT/$SGE_CELL/common/perl/lib/perl5/site_perl/5.8.8/&quot;;
use Date::Format;
use Time::Duration;
use lib &quot;$SGE_ROOT/util/resources/jsv&quot;;
use JSV qw( :DEFAULT jsv_sub_is_param jsv_sub_add_param jsv_sub_get_param jsv_send_env jsv_log_info jsv_is_param jsv_get_param );

sub hms2s {
	my $input = shift;
	if( $input =~ m/(\d*):(\d*):(\d*)/ ) {
		my $h = $1 || 0;
		my $m = $2 || 0;
		my $s = $3 || 0;
		return $h*3600+$m*60+$s
	} elsif( $input =~ m/(\d+)/) {
		return $1;
	} else {
		return 0;
	}
}

jsv_on_start(sub {
	jsv_send_env();
});

jsv_on_verify(sub {

	my $data_file=&quot;$SGE_ROOT/$SGE_CELL/common/maintenance&quot;;
	my $success = open(DAT, $data_file); 

	if( !$success ) {
		jsv_accept(&quot;No maintenance window scheduled.&quot;);
		return;
	}

	my $maintenance_begin = &lt;DAT&gt;;
	close(DAT);
	if( !$maintenance_begin ) {
		jsv_accept(&quot;No maintenance window scheduled.&quot;);
		return;
	}

	# Allow a 5 minute window for jobs to die before the maintenance officially starts.
	my $delta = 300;
	my $now = time();

	if( $maintenance_begin-$delta &lt; $now ) {
		jsv_log_info('*'x81);
		jsv_log_info('* Maintenance is currently in progress');
		jsv_log_info('* For more information, see http://blahblah');
		jsv_log_info('*'x81);
		jsv_reject();
		return;
	}

	my $requested_rt = hms2s(jsv_sub_get_param('l_hard', 'h_rt'));
	if( $now + $requested_rt &gt; $maintenance_begin - $delta ) {
		my $time_to_run = $maintenance_begin - $delta - $now;
		jsv_sub_add_param('l_hard','h_rt',$time_to_run);
		jsv_log_info('*'x81);
		jsv_log_info('* A maintenance window is scheduled for '.time2str('%m/%d/%Y %H:%M:%S', $maintenance_begin, 'EST'));
		jsv_log_info('* Your job will be allowed to run for '.duration($time_to_run));
		jsv_log_info('* For more information, see http://blahblah');
		jsv_log_info('*'x81);
	}
	jsv_correct('Job is accepted');
	return;
}); 

jsv_main();
</pre>
]]></content:encoded>
			<wfw:commentRss>http://scompt.com/blog/archives/2010/01/23/creating-a-maintenance-window-in-gridengine-using-jsvs/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Keeping Grid Engine configuration information in Subversion</title>
		<link>http://scompt.com/blog/archives/2009/10/13/versioned-grid-engine-configuration</link>
		<comments>http://scompt.com/blog/archives/2009/10/13/versioned-grid-engine-configuration#comments</comments>
		<pubDate>Tue, 13 Oct 2009 11:46:17 +0000</pubDate>
		<dc:creator>Edward Dale</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[bash]]></category>
		<category><![CDATA[gridengine]]></category>
		<category><![CDATA[sge]]></category>
		<category><![CDATA[subversion]]></category>

		<guid isPermaLink="false">http://scompt.com/?p=305</guid>
		<description><![CDATA[Something I&#8217;ve been doing for the past couple weeks on the BASS is storing the Grid Engine configuration in Subversion. This allows me to do cool stuff like diff&#8217;ing and rolling back to previous configurations. The Script Run this regularly from cron to enable the real power that I&#8217;ll discuss below. Explanation Lines 4-8 define [...]]]></description>
			<content:encoded><![CDATA[<p>Something I&#8217;ve been doing for the past couple weeks on the <a href="http://www.cs.unc.edu/bass" rel="nofollow"  title="Biomedical Analysis and Simulation Supercomputer">BASS</a> is storing the <a href="http://gridengine.sunsource.net/" rel="nofollow" >Grid Engine</a> configuration in Subversion.  This allows me to do cool stuff like diff&#8217;ing and rolling back to previous configurations.</p>
<p><span id="more-305"></span></p>
<h2>The Script</h2>
<pre class="brush: bash; title: ; notranslate">
#!/bin/bash

# Configuration values
SGE_ROOT=/usr/share/gridengine
SGE_CELL=default
SVN_URL=file:///home/user/subversion
SVN_IMPORT_DIR=gridconfig
SVN_LOAD=/usr/share/doc/subversion-1.4.2/svn_load_dirs.pl

# The real work
TMPD=`mktemp -d`
source $SGE_ROOT/$SGE_CELL/common/settings.sh
$SGE_ROOT/util/upgrade_modules/save_sge_config.sh $TMPD
find $TMPD -name accounting -exec rm -v {} \;
sed -i &quot;/^load_values/d&quot; $TMPD/execution/*

$SVN_LOAD -no_user_input $SVN_URL $SVN_IMPORT_DIR $TMPD

rm -fr $TMPD
</pre>
<p>Run this regularly from cron to enable the real power that I&#8217;ll discuss below.</p>
<h2>Explanation</h2>
<p>Lines 4-8 define configuration variables used later on.  The <code>SGE_*</code> variables might already be defined for your shell.  If not, you know what they should be.  <code>SVN_URL</code> is the URL of the Subversion repository you&#8217;d like to store the configuration in.  It should have already been created using <code>svnadmin create &lt;dir&gt;</code>.  <code>SVN_IMPORT_DIR</code> is the name of the directory in your repository that will store the configuration information.  The real magic of this script comes from <code>svn_load_dirs.pl</code>, which comes with Subversion.  Provide the path to it in the <code>SVN_LOAD</code> variable.</p>
<p>Lines 11-13 setup the SGE environment and dump the current configuration to a temporary directory.  The <code>save_sge_config.sh</code> script comes with Grid Engine and is a gem.  It writes the grid configuration to a directory structure.  It&#8217;s worthwhile to run it on your own and browse the output.</p>
<p>Lines 14 and 15 do some post-processing on the dumped configuration.  In particular, the <code>accounting</code> file is deleted because in our case, it&#8217;s huge and dynamic, so I don&#8217;t want to store multiple copies of it in the repository.  Another piece of dynamic information is the <code>load_values</code> for each execution host.  These will change each time you run the script and don&#8217;t provide any useful historical information that you can&#8217;t get in better form from <a href="http://ganglia.sourceforge.net/" rel="nofollow" >Ganglia</a>, so I get rid of them.  One last piece of dynamic information is the <code>backup_date</code> file which contains the date and time that <code>save_sge_config.sh</code>.  I like to keep this around because it provides some context, but you could also delete that file here.</p>
<p>With the configuration gathered, line 17 simply calls <code>svn_load_dirs.pl</code> to load it into Subversion.  A commit message in the form of &#8216;Load /tmp/sakfjaskfj into gridconfig.&#8217; is attached to the import.</p>
<h2>Cool stuff</h2>
<p>Now that all the configuration information is stored in Subversion, the world is our oyster.  We can use any of the normal Subversion tools to learn more about the configuration.</p>
<h3>Finding out what&#8217;s changed</h3>
<p>By using <code>svn diff</code>, you can find out what&#8217;s changed between different dates.  For example, here are the changes that I made between October 2nd and 3rd:</p>
<pre class="brush: bash; title: ; notranslate">
user@host ~$ svn diff file:///home/user/subversion/gridconfig -r {2009-10-02}:{2009-10-03}
Index: backup_date
============================================
--- backup_date (revision 177)
+++ backup_date (revision 181)
@@ -1 +1 @@
-2009-10-01_00:10:01
+2009-10-02_00:10:01
Index: usersets/superusers
============================================
--- usersets/superusers  (revision 177)
+++ usersets/superusers  (revision 181)
@@ -2,4 +2,4 @@
 type    ACL
 fshare  0
 oticket 0
-entries johnny
+entries johnny,billy
</pre>
<p>You&#8217;ll notice the <code>backup_date</code> is there, as I mentioned previously.  Additionally, you&#8217;ll notice I added billy to the superusers userset.  Good to know.</p>
<p><a href="http://scompt.com/wordpress/wp-content/uploads/2009/10/websvn.png"><img src="http://scompt.com/wordpress/wp-content/uploads/2009/10/websvn-150x150.png" alt="WebSVN Example" title="WebSVN Example" width="150" height="150" class="alignright size-thumbnail wp-image-312" /></a></p>
<h3>WebSVN</h3>
<p><a href="http://www.websvn.info/" rel="nofollow" >WebSVN</a> is an online Subversion repository browser.  Set it up correctly to point at your new <code>gridconfig</code> repository and you can get the same diff information as before through your browser.</p>
<h3 style="clear:both">Rollback your grid configuration</h3>
<p>Did something go horribly wrong with your configuration?  Rollback to a previous version using the <code>load_sge_config.sh</code> that also comes with Grid Engine and is located in <code>$SGE_ROOT/util/upgrade_modules</code>.  Simply checkout the version of the repository you want to load and pass it to <code>load_sge_config.sh</code>.  If you do this successfully, let me know.  So far we haven&#8217;t had any catestrophic configuration changes.</p>
<h2>Something else?</h2>
<p>If you manage to do something else interesting with your versioned configuration information, leave a comment below or send me a <a href="/contact/" rel="nofollow" >message</a>.</p>
<p><strong>Update: </strong>Fixed a typo in the code with the <code>$TMPD</code> variable.</p>
]]></content:encoded>
			<wfw:commentRss>http://scompt.com/blog/archives/2009/10/13/versioned-grid-engine-configuration/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>WordPress GSoC 2009 Idea: Workflow</title>
		<link>http://scompt.com/blog/archives/2009/03/29/wordpress-gsoc-2009-idea-workflow</link>
		<comments>http://scompt.com/blog/archives/2009/03/29/wordpress-gsoc-2009-idea-workflow#comments</comments>
		<pubDate>Mon, 30 Mar 2009 02:38:18 +0000</pubDate>
		<dc:creator>Edward Dale</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[gsoc]]></category>
		<category><![CDATA[wordpress]]></category>

		<guid isPermaLink="false">http://scompt.com/?p=273</guid>
		<description><![CDATA[Birds are chirping, trees are blooming, and each day is a little longer. This can mean only one thing: Google Summer of Code is upon us. This year, I&#8217;m proposing to add a publishing workflow to WordPress. Introduction Some of these ideas are taken from a page I started on the WordPress Codex to mull [...]]]></description>
			<content:encoded><![CDATA[<p>Birds are chirping, trees are blooming, and each day is a little longer.  This can mean only one thing: <a href="http://code.google.com/soc/" rel="nofollow" >Google Summer of Code</a> is upon us.  This year, I&#8217;m proposing to add a publishing workflow to <a href="http://wordpress.org/" rel="nofollow" >WordPress</a>.</p>
<p><span id="more-273"></span></p>
<h2>Introduction</h2>
<p>Some of these ideas are taken from a <a href="http://codex.wordpress.org/User:Scompt/Workflow_With_WordPress" rel="nofollow" >page</a> I started on the WordPress Codex to mull over workflow ideas.</p>
<p>WordPress is built to cater to the single user running a personal blog up to the global company running an entire website. In the big cases such as the latter, some controls and processes need to be in place to restrict what users can do and to assure that certain events take place in the correct order. Collectively, I&#8217;ll call these controls and processes a workflow and they&#8217;re the heart of the project I&#8217;d like to do for Google Summer of Code.</p>
<p>Wikipedia defines a workflow as:</p>
<blockquote><p>A workflow is a reliably repeatable pattern of activity enabled by a systematic organization of resources, defined roles and mass, energy and information flows, into a work process that can be documented and learned. </p></blockquote>
<p>This definition can be trimmed and refined a bit to better suit its application to WordPress, yielding:</p>
<blockquote><p>A workflow is a reliably repeatable pattern of activity enabled by a systematic organization of resources, defined roles, and information flows, into a work process that can be documented and learned. </p></blockquote>
<h2>Use Cases</h2>
<ul>
<li><strong>category editors</strong> &#8211; to be published in a category, a post/page must be approved by an editor for that category</li>
<li> <strong>writer->editor->designer</strong> &#8211; the writer writes text, which is edited by the editor, and then made pretty by the designer</li>
<li><strong>the big boss</strong> &#8211; everything that gets published must get the ok of the boss</li>
</ul>
<h2>System Design</h2>
<p>I envision the workflow system being implemented as a plugin.  I don&#8217;t think the number of people needing workflow controls justify putting it in the core.  I do, however, think there is a critical mass of sites that would benefit from the plugin.</p>
<p>My initial thinking about the plugin leads to three main components: design, notification, and moderation.</p>
<h3>Design</h3>
<p>Under &#8216;design&#8217;, I categorize the definition of the workflow.  This would be a &#8216;Settings&#8217; page and would utilize some kind of GUI to create a funnel-like representation of the workflow.  Posts/pages enter the system at the wide end of the funnel, go through a number of workflow stages, and emerge <em>published</em> at the other end.    Designing the workflow would consist of creating vertices and edges in this tree.  Vertices are moderation checkpoints that must be passed in order to move towards the root (publication).  Edges are the path that documents travel along.</p>
<p>Another facet of the workflow design is assigning users to the vertices.  A user at a vertex is the gatekeeper (moderator) of that stage, allowing documents to pass unscathed, modifying them, and/or sending them back to the previous stage.  Here, I picture a drag/drop interface to assign users to vertices.  Multiple users can occupy a vertex, as can one user occupy multiple vertices.</p>
<h3>Notification</h3>
<p>Notification is simply the idea that a user be notified when a document reaches his/her stage.  This would naturally occur when a document has passed from the previous stage, but also when a document has been turned back from the next stage.  Some options would be useful here to prevent a user from getting swamped with notification emails.  For example, only notify a user once between logins or at most once per day.</p>
<h3>Moderation</h3>
<p>This is really the heart of the plugin.  In order to pass through a stage, a moderator for that stage has to approve a document.  The moderator can optionally modify the document before approving it.  Once approved, a document either moves to the next stage or is published.  A rejected document is sent back to the previous stage.  Comments can be attached to the document to provide a justification for the decision.</p>
<h2>Implementation</h2>
<p>The design component will be implemented as a settings page that allows the user to graphically design the workflow.  When saved, the workflow will be captured as a tree structure and written to the options table.</p>
<p>Each stage of the workflow will have a shortname (think post slug).  This short name will be used to call an action when a post {enters, exits, &#8230;} that stage.  For example, the action &#8216;workflow_editor_entered&#8217; would be called with the post/page id when an author submits a document to the editor stage.  Default action handlers would be included that would email the users in that stage.  This is the notification component.  These default action handlers could be disabled if a user wanted to just notice the waiting posts, or a different action handler that twittered or SMSed a user.</p>
<p>Forcing posts to go through the workflow would be largely accomplished with the current capabilities system.  Many of the capabilities are meta-capabilities and are also sent through a <em>user_has_cap</em> filter before being processed.  The plugin would add a handler to this filter that looked up in the workflow to see if that action was allowed.  For example, in the case of an author X working on post 100 in the editing stage, the filter would receive the values (X, 100, editing).  The plugin would determine if the user is able to pass posts through that stage.</p>
<p>There are a couple open questions about the implementation.  If a published document is edited, where does it enter the workflow pipeline?  Is the published version un-published?  How does the revision control introduced in WP 2.6 play factor in?</p>
<h2>Existing Functionality</h2>
<p>WordPress introduced the concept of a &#8216;pending review&#8217; state in version 2.3.  This was a big step towards providing a workflow system, but it doesn&#8217;t go far enough.  Indeed, it only covers the last use case above.  In that case, the &#8216;big boss&#8217; would need to be the only user with permission to publish.  All other users would be able to create posts/pages and submit them for review.  This only provides the <strong>moderation</strong> component of the design.  There&#8217;s no built-in mechanism to <strong>notify</strong> the boss that a post is waiting for review.  The only way to <strong>design</strong> the workflow is to designate the boss as having the publishing capability.  There&#8217;s no further way to design such a trivial workflow.</p>
<p>The pending state doesn&#8217;t provide a workflow, but it makes it much easier to implement a full workflow system.  Basically, the entire workflow exists inside of the pending state.  When the original author thinks that a document is ready to be published, it is submitted for review, at which point it enters the workflow system and is given the pending state.  The editors at that first level of the workflow are notified that a document is waiting for them.  An editor makes any necessary changes and passes the document through to the next stage in the workflow.  It is still in the pending state at this point.  Until the document reaches the root of the workflow and is green-lighted to be published, it&#8217;s in the pending state.</p>
<p>When Mark Jaquith posted about the <a href="http://markjaquith.wordpress.com/2007/06/16/new-wordpress-feature-pending-review/" rel="nofollow" >new pending state</a> in June 2006, he wrote that &#8220;There are obviously a lot more &#8216;editorial process&#8217; types of features that we could implement&#8221;.  In addition, the comments on that post requested many of the features that this GSoC project would provide.</p>
<h2>Previous Work</h2>
<p>I&#8217;ve previously implemented a much simpler 1-stage workflow in a plugin called <a href="http://wordpress.org/extend/plugins/zensor" rel="nofollow" >Zensor</a>.  It hasn&#8217;t been updated in quite a while due to external time constraints.  This work was done for a high school in Germany where all changes to the website needed to be approved by the headmaster.</p>
<h2>Public Comment</h2>
<p>I <a href="http://comox.textdrive.com/pipermail/wp-hackers/2009-March/025470.html" rel="nofollow" >solicited comments</a> for this idea on the wp-hackers mailing list, but didn&#8217;t receive too much feedback.  Maybe more comments will appear below.</p>
<h2>Updates</h2>
<p><strong>4/10/2009</strong>: I added the Existing Functionality section and expanded on the Implementation details in response to comments from Jane Wells on the <a href="http://socghop.appspot.com/student_proposal/show/google/gsoc2009/scompt/t123838296093" rel="nofollow" >GSoC site</a>.</p>
<blockquote><p>
I don&#8217;t think this has enough information. There is a review process built into WP core already&#8230; what actual functions are you proposing to built, how will they differ from current functions, and how will you approach it technically? Those are the questions that the application needs to answer.
</p></blockquote>
]]></content:encoded>
			<wfw:commentRss>http://scompt.com/blog/archives/2009/03/29/wordpress-gsoc-2009-idea-workflow/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>The most popular WordPress actions and filters</title>
		<link>http://scompt.com/blog/archives/2009/01/18/the-most-popular-wordpress-actions-and-filters</link>
		<comments>http://scompt.com/blog/archives/2009/01/18/the-most-popular-wordpress-actions-and-filters#comments</comments>
		<pubDate>Sun, 18 Jan 2009 21:32:59 +0000</pubDate>
		<dc:creator>Edward Dale</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[graphs]]></category>
		<category><![CDATA[wordpress]]></category>

		<guid isPermaLink="false">http://scompt.com/?p=250</guid>
		<description><![CDATA[WordPress has an amazing plugin system that has allowed thousands of plugins to be created. At the heart of the plugin system are actions and filters that allow developers to hook into the WordPress internals and tweak things. There are hundreds of actions and filters, many of which are described on the codex, and developers [...]]]></description>
			<content:encoded><![CDATA[<p>WordPress has an amazing plugin system that has allowed <a href="http://wordpress.org/extend/plugins/" rel="nofollow" >thousands of plugins</a> to be created.  At the heart of the plugin system are actions and filters that allow developers to hook into the WordPress internals and tweak things.  There are hundreds of <a href="http://codex.wordpress.org/Plugin_API/Action_Reference" rel="nofollow" >actions</a> and <a href="http://codex.wordpress.org/Plugin_API/Filter_Reference" rel="nofollow" >filters</a>, many of which are described on the codex, and developers can create their own as well.  I was curious which ones were most used by plugin developers so I parsed the WordPress <a href="http://svn.wp-plugins.org" rel="nofollow" >plugin database</a> and ended up with the graphs and analysis below.</p>
<p><span id="more-250"></span></p>
<h2>Top 20 WordPress actions</h2>
<a href="http://scompt.com/wordpress/wp-content/uploads/2009/01/top_actions.png"><img src="http://scompt.com/wordpress/wp-content/uploads/2009/01/top_actions-300x200.png" alt="" title="Most popular WordPress actions" width="300" height="200" class="aligncenter size-medium wp-image-251" /></a>
<p style="clear:both">
As is clear from the graph, the most popular WordPress action is <code>admin_menu</code>.  This makes sense, as one of the first things a plugin developer might want to do is have their plugin show up in the WordPress backend.  Not surprisingly, many of the other top 20 actions are used just to get the plugin up and running: <code>init</code>, <code>plugins_loaded</code>, <code>activate_</code>, <code>deactivate_</code>, etc.  The other well-represented group of actions are those dealing with the post life-cycle: <code>save_post</code>,<code>publish_post</code>,  <code>edit_post</code>, <code>delete_post</code>.</p>
<p>In total, there were 659 unique actions used 12373 times.  The graph above represents about 72% of the actions.</p>
<h2>Top 20 WordPress filters</h2>
<p><a href="http://scompt.com/wordpress/wp-content/uploads/2009/01/top_filters.png"><img src="http://scompt.com/wordpress/wp-content/uploads/2009/01/top_filters-300x200.png" alt="" title="Most popular WordPress filters" width="300" height="200" class="alignnone size-medium wp-image-252" /></a></p>
<p style="clear:both">
The shape of the top 20 filters graph is a bit different.  <code>the_content</code> is the clear favorite of plugin developers, along with a couple other content filters: <code>the_excerpt</code>, <code>the_content_rss</code>, <code>the_excerpt_rss</code>.  The query filters are also well-represented: <code>posts_where</code>, <code>query_vars</code>, <code>wp</code>, <code>posts_join</code>.  The filter graph drops off pretty quickly so that most of the filters are used a maximum of 20 times.</p>
<p>In total, there were 512 unique filters used 5071 times.  The above graph represents about 55% of the filters.</p>
<h2>Method</h2>
<p>I&#8217;ll post more about my method in the future.  The numbers and graphs should be current as of SVN revision #85627 on 1/10/2009.  A number of errors were encountered along the way and some corners were cut, so the numbers aren&#8217;t perfect.</p>
]]></content:encoded>
			<wfw:commentRss>http://scompt.com/blog/archives/2009/01/18/the-most-popular-wordpress-actions-and-filters/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Walking around at Occoneechee Mountain</title>
		<link>http://scompt.com/blog/archives/2008/12/06/walking-around-at-occoneechee-mountain</link>
		<comments>http://scompt.com/blog/archives/2008/12/06/walking-around-at-occoneechee-mountain#comments</comments>
		<pubDate>Sat, 06 Dec 2008 22:05:44 +0000</pubDate>
		<dc:creator>Edward Dale</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[northcarolina]]></category>
		<category><![CDATA[Occoneechee]]></category>
		<category><![CDATA[statepark]]></category>

		<guid isPermaLink="false">http://scompt.com/?p=232</guid>
		<description><![CDATA[With the semester winding down, I took a couple hours this morning to go outside and see the world for a change. My goal was Occoneechee Mountain State Natural Area, a state park about 10 miles away. The drive there along Old Highway 86 was pleasant enough. Until, that is, I got closer and passed [...]]]></description>
			<content:encoded><![CDATA[<p>With the semester winding down, I took a couple hours this morning to go outside and see the world for a change.  My goal was Occoneechee Mountain State Natural Area, a state park about 10 miles away.  The drive there along Old Highway 86 was pleasant enough.  Until, that is, I got closer and passed under I-40 and I-85.  You see, from the park itself, you can hear these interstates because it borders on one of them and the other is only a couple miles away.  The interstates largely tainted the pleasantness of being out in the woods.</p>
<p><span id="more-232"></span></p>
<div id="attachment_236" class="wp-caption alignright" style="width: 160px"><a href='http://scompt.com/wordpress/wp-content/uploads/2008/12/pinebark.jpg'><img src="http://scompt.com/wordpress/wp-content/uploads/2008/12/pinebark-150x150.jpg" alt="Pine bark" title="Pine bark" width="150" height="150" class="alignright size-thumbnail wp-image-236" /></a><p class="wp-caption-text">Pine bark</p></div>
<p>I drove along I-85 to get to the parking area, which had only a couple cars in it at 11am on a Saturday.  Indeed, I only saw a few other people on the 2.2 mile trail.  The first half a mile or so, there&#8217;s still a direct line-of-sound to the highway, but after curving around the back of the mountain, it dropped away and I was left with just the quiet of the woods.  There&#8217;s much more pine around here than in Roanoke, so I snapped a couple pictures of the interesting bark texture.  At this point, it was overcast, but bright.  As I progressed on the path, it got darker and more overcast.</p>
<div id="attachment_233" class="wp-caption alignleft" style="width: 160px"><a href='http://scompt.com/wordpress/wp-content/uploads/2008/12/fungus.jpg'><img src="http://scompt.com/wordpress/wp-content/uploads/2008/12/fungus-150x150.jpg" alt="Interesting fungus" title="Interesting fungus" width="150" height="150" class="alignleft size-thumbnail wp-image-233" /></a><p class="wp-caption-text">Interesting fungus</p></div>
<p>The thing that most caught my eye on the first half of the trail was this bit of fungus growing on a stump.  There weren&#8217;t too many mushrooms around.  It&#8217;s too cold for them at this point, I suppose.  While walking around a different park in the area a couple months ago, there were lots of types of mushrooms popping up all over the place.  In general, there wasn&#8217;t too much green around.  On the back side of the mountain, there was a certain leafy tree/bush that was doing well for itself, but that was it.  This is visible in the <a href="http://maps.google.com/maps?f=q&#038;hl=en&#038;geocode=&#038;q=36.060835,-79.116900+(Occoneechee+Mountain+State+Natural+Area)&#038;sll=36.062196,-79.119716&#038;sspn=0.009124,0.013669&#038;dirflg=w&#038;ie=UTF8&#038;ll=36.06178,-79.118557&#038;spn=0.009124,0.013669&#038;t=h&#038;z=16&#038;g=36.060835,-79.116900&#038;iwloc=addr" rel="nofollow" >Google Map</a>.</p>
<div id="attachment_235" class="wp-caption alignright" style="width: 160px"><a href='http://scompt.com/wordpress/wp-content/uploads/2008/12/fridge.jpg'><img src="http://scompt.com/wordpress/wp-content/uploads/2008/12/fridge-150x150.jpg" alt="Busted fridge" title="Busted fridge" width="150" height="150" class="alignright size-thumbnail wp-image-235" /></a><p class="wp-caption-text">Busted fridge</p></div>
<p>Also around back, the park butts up against a powerline right-of-way.  I walked under and around the structures.  A long time ago (months, years, decades?) someone decided to use one of the towers as his personal dumb.  On that day, he had two tires, a refrigerator, and random metal bits with him.  It&#8217;s all slowly becoming part of the landscape, but I think the fridge will be around for a while.  From the right-of-way, there was a view of a quarry a mile away and a smaller road.  It was quieter, but they weren&#8217;t the most peaceful or natural surroundings.  Luckily, the trail quickly led back into the woods.</p>
<div id="attachment_234" class="wp-caption alignleft" style="width: 160px"><a href='http://scompt.com/wordpress/wp-content/uploads/2008/12/warning.jpg'><img src="http://scompt.com/wordpress/wp-content/uploads/2008/12/warning-150x150.jpg" alt="Warning sign" title="Warning sign" width="150" height="150" class="alignleft size-thumbnail wp-image-234" /></a><p class="wp-caption-text">Warning sign</p></div>
<p>The next adventure on the path was this warning sign which, while intimidating, didn&#8217;t keep me from walking the forbidden 20 feet to take a peek from the overlook.  It was indeed a steep drop and it wasn&#8217;t until I went around to the bottom that I saw how undercut the overlook itself was.  It does look like it&#8217;ll disappear to the bottom of <em>Panther&#8217;s Den</em> some day.  However, today wasn&#8217;t that day and I live to disobey warning signs yet another day.  Further along the bottom of the cliff was a fire circle and a pile of tent stakes giving the appearance that someone had braved the risk of an overlook falling on them and spent the night there.</p>
<div id="attachment_237" class="wp-caption alignright" style="width: 160px"><a href='http://scompt.com/wordpress/wp-content/uploads/2008/12/bumpy.jpg'><img src="http://scompt.com/wordpress/wp-content/uploads/2008/12/bumpy-150x150.jpg" alt="Bumpy tree" title="Bumpy tree" width="150" height="150" class="alignright size-thumbnail wp-image-237" /></a><p class="wp-caption-text">Bumpy tree</p></div>
<p>At this point, the trail goes along the Eno River for a short stretch.  At its widest, the Eno was about 20 feet across and if I squinted, I could see it flowing.  A women walked by me impatiently calling her dog, who had managed to get on the other bank.  Further upstream and downstream, the park ends and private land begins, giving one the sense that they really had to shoehorn the park into this space.  Reading the <a href="http://www.enoriver.org/eno/parks/Occoneechee.htm" rel="nofollow" >history</a> of the (somewhat new) park seems to confirm this.  I don&#8217;t know whether they&#8217;ve added the additional 250 acres yet, but it doesn&#8217;t seem like there&#8217;s too much room to grow from it&#8217;s current size.</p>
<div id="attachment_238" class="wp-caption alignleft" style="width: 160px"><a href='http://scompt.com/wordpress/wp-content/uploads/2008/12/interstate.jpg'><img src="http://scompt.com/wordpress/wp-content/uploads/2008/12/interstate-150x150.jpg" alt="Ever-present interstate" title="Ever-present interstate" width="150" height="150" class="alignleft size-thumbnail wp-image-238" /></a><p class="wp-caption-text">Ever-present interstate</p></div>
<p>From the Eno River, I came back around to the front of the mountain and was confronted with the sound of I-85 again.  Perhaps in the Summer when all of the trees have grown in, the aural assault isn&#8217;t as brutal.  On this stretch, I found a couple interesting trees and started passing more people coming from the other direction.  A couple steps later, I was back at the parking area and on my way home.</p>
<p>In general, Occoneechee Mountain was a nice, quick getaway.  It&#8217;s closeness almost makes up for the intrusiveness of the interstate while at the park.  Maybe I&#8217;ll try back in the Spring when there&#8217;s a bit more foliage on the trees.  As for Winter, I think I&#8217;ve seen all the park has to offer.</p>
]]></content:encoded>
			<wfw:commentRss>http://scompt.com/blog/archives/2008/12/06/walking-around-at-occoneechee-mountain/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Consider the lobster</title>
		<link>http://scompt.com/blog/archives/2008/09/13/consider-the-lobster</link>
		<comments>http://scompt.com/blog/archives/2008/09/13/consider-the-lobster#comments</comments>
		<pubDate>Sun, 14 Sep 2008 04:43:21 +0000</pubDate>
		<dc:creator>Edward Dale</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[writing]]></category>

		<guid isPermaLink="false">http://scompt.com/?p=231</guid>
		<description><![CDATA[As my time in Würzburg teaching English was winding to an end, I was seeking a longer text that could challenge my advanced class of juniors. We had spent almost a year (two for some of them) reading political articles and random current events, but I wanted to find something literary, something that had some [...]]]></description>
			<content:encoded><![CDATA[<p>As my time in Würzburg teaching English was winding to an end, I was seeking a longer text that could challenge my advanced class of juniors.  We had spent almost a year (two for some of them) reading political articles and random current events, but I wanted to find something literary, something that had some level of merit.  I also wanted something that would be interesting and hopefully draw them in.</p>
<p><span id="more-231"></span><br />
My first thought went to <a href="http://www.nytimes.com/2007/04/12/books/12vonnegut.html" rel="nofollow" >Kurt Vonnegut</a>.  Not only was his writing amazing and funny and poignant, but having died recently, the media was full of articles singing his praises, which I thought I could use to pique my students&#8217; interest.  Unfortunately, in the end, I wasn&#8217;t able to find a piece of suitable length with a suitable vocabulary.</p>
<p>After further consideration, my mind went to David Foster Wallace.  Of course, his <a href="http://en.wikipedia.org/wiki/Infinite_Jest" rel="nofollow" >>1000 page tome</a> wouldn&#8217;t do, but his much shorter essay on the ethics of eating/cooking/celebrating <a href="http://www.lobsterlib.com/feat/davidwallace/page/lobsterarticle.pdf" rel="nofollow" >lobster</a> fit the bill for length and humor well.</p>
<p>We started reading it and soon enough we were immersed in a world of lobster fests, melted butter, &#8230; and footnotes.  DFW is famous for his footnotes and although I tried to stress the importance of the footnotes and the suggestion that they should be read with the text, I never quite convinced the students to give them the respect they deserved.</p>
<p>On my last day of class at <a href="http://siebold-gymnasium.de/" rel="nofollow" >Siebold Gymnasium</a>, we only had another page or two to read.  It was definitely a length that we could have tackled in the hour that we had.  However, the students had other plans and we ended up celebrating my departure with two cakes, one in the shape of&#8230; a lobster.  Little did I know, but in the weeks that we had read the essay, the students had started to wonder if I had some kind of lobster fetish.</p>
<p>This is why it&#8217;s especially sad to read today that <a href="http://www.nytimes.com/aponline/books/AP-Obit-Wallace.html" rel="nofollow" >DFW</a> hanged himself last night.</p>
]]></content:encoded>
			<wfw:commentRss>http://scompt.com/blog/archives/2008/09/13/consider-the-lobster/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Use WP-Crontrol to keep track of Akismet</title>
		<link>http://scompt.com/blog/archives/2008/06/18/use-wp-crontrol-to-keep-track-of-akismet</link>
		<comments>http://scompt.com/blog/archives/2008/06/18/use-wp-crontrol-to-keep-track-of-akismet#comments</comments>
		<pubDate>Wed, 18 Jun 2008 10:20:41 +0000</pubDate>
		<dc:creator>scompt</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[cron]]></category>
		<category><![CDATA[wordpress]]></category>

		<guid isPermaLink="false">http://scompt.com/?p=228</guid>
		<description><![CDATA[If you&#8217;re using Akismet to tackle spam on WordPress, there are a number of statistics available to you about your current spam situation. These are all available in the Comments page of your blog, but who wants to go there every day to check up on things. By taking control of WordPress Cron with WP-Crontrol [...]]]></description>
			<content:encoded><![CDATA[<p>If you&#8217;re using <a href="http://akismet.com/" rel="nofollow" >Akismet</a> to tackle spam on WordPress, there are a number of statistics available to you about your current spam situation.  These are all available in the Comments page of your blog, but who wants to go there every day to check up on things.  By taking control of <a href="http://scompt.com/projects/wp-crontrol" rel="nofollow" >WordPress Cron</a> with WP-Crontrol and a couple lines of code, you can receive this information sent by mail every day.</p>
<p><span id="more-228"></span></p>
<p>As discussed <a href="http://scompt.com/archives/2008/06/16/using-wordpress-cron-and-wp-crontrol-to-make-you-post-more" rel="nofollow" >previously</a> in this <a href="http://scompt.com/archives/series/taking-control-of-wp-cron-using-wp-crontrol" rel="nofollow" >series</a>, you&#8217;ll need to have <a href="http://scompt.com/projects/wp-crontrol" rel="nofollow" >WP-Crontrol</a> installed and go to the Add PHP Cron Entry screen under Manage->Crontrol.  For Hook Code, enter the following snippet:</p>
<p><code>
<pre name="code" class="php">    $email  = 'There are currently ';
    $email .= akismet_spam_count();
    $email .= ' spams identified by Akismet, of which ';
    $email .= akismet_spam_count('comment');
    $email .= ' are comment spams and ';
    $email .= akismet_spam_count('trackback');
    $email .= ' are trackback spams.  Akismet has caught ';
    $email .= number_format_i18n(get_option('akismet_spam_count'));
    $email .= ' spams since you first installed it.';
    wp_mail('scompt@scompt.com', 'Spam statistics', $email);</pre>
<p></code></p>
<p>Notice that all we&#8217;re doing is tossing a string together and sending it off to the <code>wp_mail</code> function to be emailed.  You&#8217;ll of course want to change the email address.  I personally don&#8217;t need to know how much spam you&#8217;re getting&#8230; I&#8217;ve got problems of my own.</p>
]]></content:encoded>
			<wfw:commentRss>http://scompt.com/blog/archives/2008/06/18/use-wp-crontrol-to-keep-track-of-akismet/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
	
		<series:name><![CDATA[Taking control of WP-Cron using WP-Crontrol]]></series:name>
	</item>
		<item>
		<title>Plugin Stats 1.1 Released</title>
		<link>http://scompt.com/blog/archives/2008/06/17/plugin-stats-11-released</link>
		<comments>http://scompt.com/blog/archives/2008/06/17/plugin-stats-11-released#comments</comments>
		<pubDate>Tue, 17 Jun 2008 10:41:56 +0000</pubDate>
		<dc:creator>scompt</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[releases]]></category>
		<category><![CDATA[wordpress]]></category>

		<guid isPermaLink="false">http://scompt.com/?p=227</guid>
		<description><![CDATA[Last week, I released Version 1.0 (and quickly thereafter, Version 1.1) of a WordPress plugin called Plugin Stats! The plugin is designed for WordPress plugin developers to keep track of downloads of their plugins. The plugin graphs the number of downloads in three different ways: A Shortcode for use in posts and pages A template [...]]]></description>
			<content:encoded><![CDATA[<p>Last week, I released Version 1.0 (and quickly thereafter, Version 1.1) of a WordPress plugin called <a href="http://scompt.com/projects/plugin-stats" rel="nofollow" >Plugin Stats</a>!  The plugin is designed for WordPress plugin developers to keep track of downloads of their plugins.  The plugin graphs the number of downloads in three different ways:</p>
<p><span id="more-227"></span></p>
<ul>
<li>A <a href="http://codex.wordpress.org/Shortcode_API" rel="nofollow" >Shortcode</a> for use in posts and pages</li>
<li>A template function for use in templates</li>
<li>A dashboard widget</li>
</ul>
<p>An example download graph looks like this:</p>
<a href='http://wordpress.org/extend/plugins/wp-crontrol/stats/'><img src='http://chart.apis.google.com/chart?chxr=1,0,11&chxp=0,13.33,30,47.22,63.89,81.11,98.33&chxt=x,y&chxl=0:|September|October|November|December|January|February&chs=360x100&cht=lc&chd=s:nWhy99cWnLWLLWRLLLLWcLGnWRARWRsLWLGAWcLWLLRGnWRGRRLWRhRcLWLnLGLAGcGLGRRLGAWGRGALnRGLGWGLLWWARLLGGLLGGLRWGLcLLLRWLcLccGLRWLGLLRLLRAGGnLhcRsGGGLWhWRGRRWcLGRcccLRRLLRRhLGWLcARWRRnRGRW&chtt=wp-crontrol&chm=h,FF0000,0,0.36,0.5|r,99FF99,0,0.09,0.45' /></a>
<p><a href="http://downloads.wordpress.org/plugin/plugin-stats.1.1.zip" rel="nofollow" >Download Plugin-Stats Version 1.1</a></p>
]]></content:encoded>
			<wfw:commentRss>http://scompt.com/blog/archives/2008/06/17/plugin-stats-11-released/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Using WordPress Cron and WP-Crontrol to make you post more</title>
		<link>http://scompt.com/blog/archives/2008/06/16/using-wordpress-cron-and-wp-crontrol-to-make-you-post-more</link>
		<comments>http://scompt.com/blog/archives/2008/06/16/using-wordpress-cron-and-wp-crontrol-to-make-you-post-more#comments</comments>
		<pubDate>Mon, 16 Jun 2008 10:32:18 +0000</pubDate>
		<dc:creator>scompt</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[cron]]></category>
		<category><![CDATA[wordpress]]></category>

		<guid isPermaLink="false">http://scompt.com/?p=225</guid>
		<description><![CDATA[The new version of WP-Crontrol allows you to add new cron entries with code. This allows you to write code that will repeatedly be executed without actually touching any .PHP files. Below, I present a way to utilize this functionality to remind you to post something if you haven&#8217;t done so in the past two [...]]]></description>
			<content:encoded><![CDATA[<p>The new version of <a href="http://scompt.com/projects/wp-crontrol" rel="nofollow" >WP-Crontrol</a> allows you to add new cron entries with code.  This allows you to write code that will repeatedly be executed without actually touching any .PHP files.  Below, I present a way to utilize this functionality to remind you to post something if you haven&#8217;t done so in the past two days.</p>
<p><span id="more-225"></span></p>
<div class="imageright">
<a href="http://scompt.com/wordpress/wp-content/uploads/2008/06/php_cron_entry_screen.jpg"title="PHP Cron Entry Screen" ><img alt="PHP Cron Entry Screen" src="http://scompt.com/wordpress/wp-content/uploads/2008/06/php_cron_entry_screen-150x150.jpg"/></a></p>
<p>PHP Cron Entry Screen</p>
</div>
<p>The first requirement is to install <a href="http://scompt.com/projects/wp-crontrol" rel="nofollow" >WP-Crontrol</a>.  This will add the Manage->Crontrol admin screen.  Head there and you&#8217;ll get a quick insight into what&#8217;s going on behind the scenes in the WP-Cron system.  We want to add a new PHP cron entry, so click on the small link next to &#8216;Add Cron Entry&#8217;.  Now you should have something like the screen to the right.</p>
<p>The code that we&#8217;re going to use for the hook is below.  I won&#8217;t go deep into it.  Suffice to say, it looks at the date of the most recent post.  If it&#8217;s more than 2 days old, it sends out an email reminder.</p>
<p><code>
<pre name="code" class="php">    global $post;
    $recent = new WP_Query("showposts=1");
    if( $recent->have_posts() ) {
        $recent->the_post();
        if(time()-strtotime($post->post_date)>60*60*24*2)
            mail('scompt@scompt.com', 'Post reminder',
                 "Hey!  You haven't posted in a while.");
    }</pre>
<p></code></p>
<p>The only other options to set are when to run the hook and how often.  After saving the hook, it should run immediately.  Depending on how good you&#8217;ve been, you&#8217;ll get an email.</p>
]]></content:encoded>
			<wfw:commentRss>http://scompt.com/blog/archives/2008/06/16/using-wordpress-cron-and-wp-crontrol-to-make-you-post-more/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
	
		<series:name><![CDATA[Taking control of WP-Cron using WP-Crontrol]]></series:name>
	</item>
	</channel>
</rss>

