Countdown Timer v3.0.6

Sometime in June of 2012 I released version 3.0 of Countdown Timer. Before that, the last major release was version 2.4 in April of 2010.

I’ve just been busy with other things1. The other reason was that the program had grown from it’s modest roots as a single 321 sloc2 program to a multiple files (80% PHP / 20% JS) with 1,450 sloc. Managing all the files, testing, and integration is — well — hard and not fun. And no one pays me to do it.

It’s taken some time, but I’ve more or less completely redesigned how I develop PHP. I’ve switched to using Aptana, Git Hub, and FirePHP — a PHP integration into FireBug. This was a multimonth project to slowly learn a new way of developing, but it’s been fun! I just spent most of May 2012 essentially rewriting how Countdown Timer works. All the logic is ultimately the same, much of it was converting function and variables into appropriate classes. I’m somewhat particularly happy about being able to extend the DateTime class and use that, although the lastest bug fix release (v3.0.6) was released because of my new found hatred for the DateTime class.

Another big change from 2.4 was taking advantage of some of WordPress’ core i18n3 updates which make handling date and time information a bit easier. Version 3 (and the subsequent dot fix updates) haven’t been a big flashy update, things are more or less where you left them, but you should hopefully see some little things that make you smile and make your life easier. It’s always a challenge to keep making something truly better, but I still have a couple of things I want to implement. However, Countdown Timer is on GitHub and WordPress TRAC, I don’t want this to be code that’s hidden in a cave, so please fork, patch, push and pull away.

Anyway, version 3.0.6 is now out. It fixes some crazy bug with that developed sometime after PHP 5.2 was released that caused the “white screen of death.” There were three issues that I found:

  • WordPress is calling the sanitize callback twice…not sure if this is new behavior or not, but it was breaking things because the second time it was being called it was trying to sanitize a different type of input. I’ll probably need to rewrite the sanitize function in the future.
  • The DateTime class has been expanded and some of the new functions clashed with stuff I had written. PHP can’t overload functions, so instead it just barfs.
  • For some reason, if certain, presumably optional, methods of the new PHP DateTime class are missing, PHP will also barf. In particular, date4, timezone_type5, and timezone.

Anyway, several hours were spent backtracing the errors and providing suitable fixes. So, enjoy!

As per tradition:

Read more or download version 3.0.6!

Also, please consider that I spend several dozens hours making updates for each release…have you donated recently?


  1. which is to say that Countdown Timer has been pushed lower down my priority list 

  2. source lines of code 

  3. internationalization 

  4. which was never supposed to be exposed 

  5. also maybe a bug? 

Milestone for WordPress self-hosted v0.9

The website I made for Rachel and myself is, of course, run on WordPress. After looking through some themes, I eventually settled on the Forever theme. Forever is a WordPress.com theme, but can be downloaded via SVN from
https://wpcom-themes.svn.automattic.com/forever/1 so someone can use it on a self-hosted WordPress installation. Everything was going great, but I couldn’t find the plugin for this really neat widget they have that counts down to The Big Day:

The Milestone Widget in Forever (http://en.blog.wordpress.com/2012/01/12/wedding-theme/)

It’s called Milestone and as of January 2012 it was supposed to be included in a future release of Jetpack, the official WordPress plugin for things of that nature.

But here we are in August and there’s no plugin.

And I don’t know what the timeline is for actually releasing it.

So I did what any engineer would do when they don’t want to wait, I made my own version. There’s decent enough documentation on the backend and the front end is just stylized with CSS. It’s a pretty simple implementation and only took a few hours to crank out. There are some more things I want to add and tweak, like adding a drop down calendar select and better input checking, but it will work for now.

Here’s how it looks:

Milestone clone

It’s a quick solution that I hope others will enjoy too. I also got a chance to try out using a deploy script to help automate the push from GitHub to SVN. This could help a lot of things go smother.

Read more or download v0.9!


  1. svn co http://wordpress.org/extend/plugins/milestone/ 

Using Shortcodes in the_excerpt

I was working on a project for a client that requested using shortcodes in the_excerpt:

From codex.wordpress.org:

Displays the excerpt of the current post with […] at the end, which is not a “read more” link. If you do not provide an explicit excerpt to a post (in the post editor’s optional excerpt field), it will display an automatic excerpt which refers to the first 55 words of the post’s content. Also in the latter case, HTML tags and graphics are stripped from the excerpt’s content. This tag must be within The Loop.

You’ve probably encountered this functionality when you’ve done a search on a WordPress site or viewed an archive, the post will often end in “…”

From a programming standpoint, there was a point in time where if you wanted to have shortcodes used in an excerpt for WordPress, all you had to do what include this in your code1

add_filter( 'the_excerpt', 'do_shortcode');

However, I found out that at some point in the last few years since I tested the above system, the way in which WordPress process shortcodes has changed. I poked around a little bit in the WordPress TRAC, but didn’t see anything that would explain it. I suspect it might be a filter order, but I’m not sure and I decided that investigating the root cause at this point wouldn’t make a difference (although I would like to find out eventually).

Here’s what I learned and how I solved the problem.

When you have not provided an explicit excerpt, WordPress creates one via wp_trim_excerpt2:

function wp_trim_excerpt($text = '') {
	$raw_excerpt = $text;
	if ( '' == $text ) {
	$text = get_the_content('');
  
	$text = strip_shortcodes( $text );
  
          $text = apply_filters('the_content', $text);
          $text = str_replace(']]>', ']]>', $text);
          $excerpt_length = apply_filters('excerpt_length', 55);
          $excerpt_more = apply_filters('excerpt_more', ' ' . '[...]');
          $text = wp_trim_words( $text, $excerpt_length, $excerpt_more );
      }
      return apply_filters('wp_trim_excerpt', $text, $raw_excerpt);
  }
 

The way wp_trim_excerpt gets called is not super intuitive, but looks like this:

the_excerpt3 calls get_the_excerpt4 via filter hook

wp_trim_excerpt is hooked into get_the_excerpt via a filter hook defined in /wp-includes/default-filters.php5

A quick glance at the code for wp_trim_excerpt reveals that strip_shortcodes is run immediately after getting the content of the post. Also, there is really no way to filter this out easily unless you rewrite the entire function, which is what I did:


remove_filter( 'get_the_excerpt', 'wp_trim_excerpt'  ); //Remove the filter we don't want
add_filter( 'get_the_excerpt', 'fergcorp_wp_trim_excerpt' ) ); //Add the modified filter
add_filter( 'the_excerpt', 'do_shortcode' ); //Make sure shortcodes get processed

//Copy and paste from /wp-includes/formatting.php:2096
function fergcorp_wp_trim_excerpt($text = '') {
	$raw_excerpt = $text;
	if ( '' == $text ) {
		$text = get_the_content('');
		//$text = strip_shortcodes( $text ); //Comment out the part we don't want
		$text = apply_filters('the_content', $text);
		$text = str_replace(']]>', ']]>', $text);
		$excerpt_length = apply_filters('excerpt_length', 55);
		$excerpt_more = apply_filters('excerpt_more', ' ' . '[...]');
		$text = wp_trim_words( $text, $excerpt_length, $excerpt_more );
	}
	return apply_filters('wp_trim_excerpt', $text, $raw_excerpt);
}

So there’s the solution. It’s definitely a bit longer than the way it used to work, but it should do just fine.


  1. functions.php or elsewhere 

  2. WordPress 3.4.1: /wp-includes/formatting.php -> line 2096 

  3. WordPress 3.4.1: /wp-includes/post-template.php -> line 240 

  4. WordPress 3.4.1: /wp-includes/post-template.php -> line 258 

  5. WordPress 3.4.1, line 147: add_filter( ‘get_the_excerpt’, ‘wp_trim_excerpt’ );  

Calculating Downloads

I recently hit 70,000 downloads on Countdown Plugin, a small plugin I wrote for WordPress about five years ago. Actually, the timer is older than that. I’ve only been using WordPress since my freshman year of college (spring semester circa 2005), before that I had this crazy home brew content management system. Part of that system included the original source of Countdown Timer. When I made the move to WordPress, I forked the code and made it into a WordPress plugin. The basic and display of the timer has remained relatively similar, although the code has pretty much been rewritten.

Download stats with 10- and 40-day moving averages

I digress. Having 70,000 is a great accomplishment. However, it’s not a very telling metric. What I really want to know is how many people are using the plugin currently?

In order to get an idea of how many active users there are, I looked at two pieces of data:

  • Temporal downloads prior to my last release
  • Temporal downloads subsequent to my last release

The theory is that when a new update is released, an upgrade notice goes out to all users of the plugin. This is the cause of the massive spike in downloads. By eliminating the background noise downloads (i.e. people just trying it out), I can calculate the area under the curve and get a rough estimate of the number of users.

I fit a power regression line to the subsequent downloads with an R2 value of 0.83, which is a little lower than I would have liked, but still usable, described by the equation:615.16x^{-0.481}

The average downloads for the 24 days prior to the release were 81.375 downloads/day. Using WolframAlpha, I solved for the intersection of the two lines:
x = \frac{308915776 \cdot 26^{114/481}}{5405625 \cdot 5^{76/481} \cdot 93^{38/481}}\approx 67.0498

The bounds of my function are now 0 (the day that the plugin was released) and 67 (the day the plugin will again be at ~81 downloads). It’s just a mater of integrating the function and subtracting out the base downloads:

\left (\int_{0}^{67}615.16x^{-0.481}  \right ) - \left (81.375\cdot67  \right ) = 5056.675

5,000 seems to be about the base number of users at this point. It will be interesting to see how this number changes over time. Especially since I have the historical data and could analyze how long it takes downloads to return to normal.

5/11/2010: Here’s the data I used: downloads.csv

Countdown Timer v2.4

Just over a year ago I released Countdown Timer v2.3.5. I’ve had the fortunate opportunity to participate many great things over the last year, which is probably why there hasn’t been an release since.

Anyway, I’ve been slaving away at this release for the last three weeks:

Weeks of 2010 - Blue = Internet Applications (i.e. Chrome, Firefox, IE); Red = Development Applications (i.e. Dreamweaver); Tan = Utilities (i.e. PuTTY, FileZilla, etc)
Weeks of 2010 - Blue = Internet Applications (i.e. Chrome, Firefox, IE); Red = Development Applications (i.e. Dreamweaver); Tan = Utilities (i.e. PuTTY, FileZilla, etc)

I probably spent close to twenty hours, committed over 50 revisions, and had 865 lines changes in the core code1. For all this change behind the scenes, you expect to see some changes in the actual interface. Amazingly not.

Most of the work had to do with bringing the code up to WordPress 2.9/3.0 standards. This will ensure that this plugin continues to work well in to the future. As well as trying to keep up with best practices for WordPress Plugin coding.

The other major update dealt with adding CSS hooks to the html elements so that they can be customized better/more fully. In doing this, I also rewrote part of fergcorp_countdownTimer_format to make it less repetitive. This, unfortunately, caused a minor issue with using the [fergcorp_cdt_single date="ENTER_DATE_HERE"] shortcode that has the li-element included; I’ll fix that in a dot-dot release (i.e. 2.4.1).

The settings for Countdown Timer moved the WordPress Tools to Settings in the Admin Menu and you only need to be an Options Manager instead of Administrator to update the options. I think the only other change worth mentioning is that there is now an option to parse shortcodes in the_excerpt. Note that enabling this functionality will parse all shortcodes, not just ones related to Countdown Timer.

As per tradition:

Read more or download version 2.4!


  1. There’s only 1000 source lines of code [SLOC] to begin with, so this is sort of substantial 

Countdown Timer Update is in the Works

It’s been over a year since I’ve had the chance to update Countdown Timer. However, a couple of weeks ago the stars aligned just so and I started working on a slew of updates. Nothing huge, mostly just updating code in the back end to do things properly and rewriting some sections of code to take advantage of new methods WordPress has implemented in the last few releases.

So far I have almost 100 diffs involving a shit ton of source code1

It’s not quite ready yet, but I am working on it; as is hopefully evident by this freakishly late night/early morning post.

Please consider yourselves informed that a new version is on its way.


  1. yes, that’s a technical unit of measurement, similar to the Hella- prefix [See: The Official Petition to Establish ‘Hella-‘ as the SI Prefix for 10^27] 

wc: Word Count

The goal for this Programming Praxis was to implement the Unix wc function. This one took me a couple days (I haven’t had a lot of time recently) to complete, but I finally finished it and this it works pretty good. It’s not a drop in replacement for wc, but it works – a programmers solution: by programmers, for programmers.

use Switch;

#print "arg num ". $#ARGV;
if ($#ARGV == -1) {
	usage();
}

@option;
@input;

#check first char of each argument
foreach $arg (@ARGV){
	if($arg =~ m/-.*/){
		@option = split //, $arg;
		#print "!".$arg."\n";
	}
	else{
		push(@input, $arg);
	}
}
#remove the "-" from the array
shift(@option);

foreach $input (@input){
	
	if(-e $input){
	#file exists, continue
		local( *FH ) ;
		open( FH, $input ) or die "sudden flaming death\n";
		$file = do { local( $/ ) ; <FH> };
		$fileSize = (-s $input);
		close(FH);
	}else{
		die("No such file or directory");
	}
	print "$input ";
	foreach $flag (@option){
		switch ($flag){
			
			case "c" {print "$fileSize "}
			case "m" {print length($file) . " "}
			case "l" {print $file =~ s/((^|\s)\S)/$1/g ." "}
			case "L" {print maxLineLength($input)." "}
			case "w" {print $file =~ s/(\n)/$1/g . " "}
			else {die ("invalid option -- $flag")}
		}
	}
	print "\n";
}

sub maxLineLength($input){
	my($thisInput) = @_;
	open(FH, $thisInput);
	$maxLine = 0;
	foreach $line (<FH>){
		if(length($line) > $maxLine){
			$maxLine = length($line);
		}
	}
	return $maxLine;
}

sub usage{

	print "Usage: wc [OPTION]... [FILE]...\n";
	print "  or:  wc [OPTION]... --files0-from=F\n";
	print "Print newline, word, and byte counts for each FILE, and a total line if\n";
	print "more than one FILE is specified.  With no FILE, or when FILE is -,\n";
	print "read standard input.\n";
	print "  -c            print the byte counts\n";
	print "  -m            print the character counts\n";
	print "  -l            print the newline counts\n";
	print "  -L, --max-line-length  print the length of the longest line\n";
	print "  -w, --words            print the word counts\n";
}

Autokey

On the recommendation of my friend Dan, I’m going to try to do some of these programming puzzles from time to time. I’m also going to try work these problems using Perl. Today’s assignment is to make a simple Autokey Cipher, which I accomplished over my lunch break.

use List::Util qw/sum/;

if ($#ARGV != 1 ) {
	print "usage: autokey.pl plainText key\n";
	exit;
}

$plainText = uc $ARGV[0];
$keyBase = uc $ARGV[1];

$key = $keyBase.$plainText;

print $key;

#$plainText	= "ACOLLECTIONOFETUDES";
#$key		= "PRAXISACOLLECTIONOF";
$cipherText	= "";

sub encipher{
	my($thisPlainText, $thisKey) = @_;

	#Clear Cipher'd text
	$thisCipherText = "";

	#Clear i
	$i=0;

	@arrayPlainText = split //, $thisPlainText;
	@arrayKey = split //, $thisKey;

	for($i = 0;  $i < scalar @arrayPlainText; $i++){
		if(@h{@arrayPlainText[$i]} + @h{@arrayKey[$i]} > 27){
			$thisCipherText .= @k[@h{@arrayPlainText[$i]} + @h{@arrayKey[$i]} - 27];
			#print @h{@arrayPlainText[$i]} + @h{@arrayKey[$i]} - 26 . "\n";
			#print @k[@h{@arrayPlainText[$i]} + @h{@arrayKey[$i]} - 26] . "\n";
		}
		else{
			$thisCipherText .= @k[@h{@arrayPlainText[$i]} + @h{@arrayKey[$i]} - 1];
			#print @h{@arrayPlainText[$i]} + @h{@arrayKey[$i]} . "\n";
			#print @k[@h{@arrayPlainText[$i]} + @h{@arrayKey[$i]}] . "\n";
		}

	}

	return $thisCipherText;

}

sub decipher{
	my($thisCipherText, $thisKey) = @_;

	@arrayCipherText = split //, $thisCipherText;
	@arrayKey = split //, $thisKey;

	for($i = 0;  $i < scalar @arrayCipherText; $i++){
		if(@h{@arrayCipherText[$i]} - @h{@arrayKey[$i]} < 0){
			$thisPlainText .= @k[@h{@arrayCipherText[$i]} - @h{@arrayKey[$i]} + 27];
		}
		else{
			$thisPlainText .= @k[@h{@arrayCipherText[$i]} - @h{@arrayKey[$i]} + 1];
		}
	}
	return $thisPlainText;
}

@h{'A' .. 'Z'} = (1 .. 26);
@k[1 .. 26] = ('A' .. 'Z');

$cipherText = &encipher($plainText, $key);

$decipherText = &decipher($cipherText, $key);

print " Plain text is: " . $plainText . "\n";
print "Cipher text is: " . $cipherText . "\n";
print "Decipher text is: " . $decipherText . "\n";