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’ );  

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 

New Plugin: WP Plugin Data

For better or worse, I’ve released a brand new plugin. It was one of those things I did spur of the moment because I wanted to implement something and the way I wanted to do it wasn’t available (insert some comment about necessity being the mother of invention here).

The new plugin is WP Plugin Data. It’s designed to use the WordPress.org Plugin API to get data about a specific plugin. John Blackbourn already wrote a plugin, Plugin Info, that does something similar. However, it requires that you set a Custom Field to the plugin name. I didn’t like this approach because I could only grab data for one plugin per a page.

So, using John’s plugin as a template, I wrote my own plugin that used shortcodes to add the data. And then I released it. This is why I love the GNU GPL. As for naming, I really hate it when plugins use the “WP” moniker in their titles. Typically, the plugin has absolutely no affiliation to WordPress and I feel the only reason they put “WP” in their name is to gain some form of (undeserved) recognition. For this reason, I really didn’t want to put “WP” in the title. However, I did end up using because this plugin actually does integrate itself into the WP.org backend using the API…so I feel the use is justified.

Anyway, enough about that.

Read more, or download version 0.5!