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 code ((functions.php or elsewhere))

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_excerpt ((WordPress 3.4.1: /wp-includes/formatting.php -> line 2096)):

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_excerpt ((WordPress 3.4.1: /wp-includes/post-template.php -> line 240)) calls get_the_excerpt ((WordPress 3.4.1: /wp-includes/post-template.php -> line 258)) via filter hook

wp_trim_excerpt is hooked into get_the_excerpt via a filter hook defined in /wp-includes/default-filters.php ((WordPress 3.4.1, line 147: add_filter( ‘get_the_excerpt’, ‘wp_trim_excerpt’ ); ))

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.

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 code ((There’s only 1000 source lines of code [SLOC] to begin with, so this is sort of substantial)). 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!