Fixing The Excerpt In WordPress
WordPress theme designers, as well as “hobbyist” designers will most likely be familiar with WordPress’ the_excerpt() Template Tag; a post excerpt is displayed as a summary of the post wherever the_excerpt() is used. However it does have some limitations, such as stripping HTML tags, and not stripping JavaScript.
The best solution we have found to these limitations was provided by Aaron Russell, but this also had just a couple of stumbling blocks, as evidenced by reading through the comments section of Aaron’s post.
We here at Palehorse have come up with solutions to two of the weak points brought to light by Aaron’s readers, and have updated the function for WordPress 2.9 and above.
The two upgrades to the function deal with un-closed HTML tags, and adding a “read more” link (or some sort of anchor tag) to the ‘[...]‘ string at the end of the excerpt.
Here is Aaron’s original solution:
function improved_trim_excerpt($text) {
global $post;
if ( '' == $text ) {
$text = get_the_content('');
$text = apply_filters('the_content', $text);
$text = str_replace(']]>', ']]>', $text);
$text = preg_replace('@<script[^>]*?>.*?</script>@si', '', $text);
$text = strip_tags($text, '<p>');
$excerpt_length = 80;
$words = explode(' ', $text, $excerpt_length + 1);
if (count($words)> $excerpt_length) {
array_pop($words);
array_push($words, '[...]');
$text = implode(' ', $words);
}
}
return $text;
}
remove_filter('get_the_excerpt', 'wp_trim_excerpt');
add_filter('get_the_excerpt', 'improved_trim_excerpt');
Our upgrades include the new (in WordPress 2.9) excerpt_more filter hook, to which we have added a permalink in order to get a “read more” link. Of course we had come up with an elegant solution for this, only to discover that the designers were once again one step ahead of us. So the function has been updated with the new hook. I hate love it when that happens.
Next, in order to prevent any “snipped” HTML tags, we added this line:
$text = force_balance_tags( $text );
That will balance any open tags automatically.
Putting it all together is a bit involved, but is achieved by just “plugging in” a few lines of code. Instead of explaining the whole thing line-by-line, I will just post the final code in toto, with comments where we have added the fixes. If anyone has any questions, just leave a comment and I’ll explain further, if required.
The completed, augmented improved_trim_excerpt() function:
/**
* Generates an improved excerpt from the content, if needed
*
* The excerpt word amount will be 80 words and if the amount is greater than
* that, then the string '[...]' will be appended to the excerpt. If the string
* is less than 80 words, then the content will be returned as is.
*
* The 80 word limit can be modified by plugins/themes using the excerpt_length filter
* The '[...]' string can be modified by plugins/themes using the excerpt_more filter
*
* @link http://www.aaronrussell.co.uk/blog/improving-wordpress-the_excerpt/
* @link http://palehorseinformation.com/2009/12/23/fixing-the-wordpress-excerpt/
*
* @param string $text The excerpt. If set to empty an excerpt is generated.
* @return string The excerpt.
*/
function improved_trim_excerpt( $text ) {
if ( '' == $text ) {
$permalink = get_permalink(); // my addition
$text = get_the_content( '' );
$text = strip_shortcodes( $text );
$text = apply_filters( 'the_content', $text );
$text = preg_replace( '@<script[^>]*?> . *?</script>@si', '', $text );
$text = str_replace( ']]>', ']]>', $text );
$text = strip_tags( $text, '<b><em><i><p><strong><sub><sup>' ); // allowed tags (change as needed)
$excerpt_length = apply_filters( 'excerpt_length', 80 );
$excerpt_more = apply_filters('excerpt_more', ' ' . '<em><a href="' . $permalink . '">[...]</a></em>'); // my addition
$words = explode( ' ', $text, $excerpt_length + 1 );
if ( count( $words ) > $excerpt_length ) {
array_pop( $words );
$text = implode( ' ', $words );
$text = $text . $excerpt_more;
$text = force_balance_tags( $text ); // my addition
}
}
return $text;
}
remove_filter( 'get_the_excerpt', 'wp_trim_excerpt' );
add_filter( 'get_the_excerpt', 'improved_trim_excerpt' );
If you would like, you can change the ‘[...]‘ string and/or the HTML <em> tags in this line to your liking:
$excerpt_more = apply_filters('excerpt_more', ' ' . '<em><a href="' . $permalink . '">[...]</a></em>');
That’s all for now. Let us know what you think, if you have any problems with our revisions, or if you have any improvements of your own by leaving a comment. Thanks for reading, and thanks especially to Aaron for his original solution!
