How to trim the_content()

My latest work was a customization of Rooster theme for one of my clients who didn’t like the idea of using <!–more–> separator. He wanted to have a split content at certain number of words and the idea of using the_excerpt() didn’t work hence the fact that this function strips out all the HTML code. So I was faced with the problem and major issue was how to trim HTML formatted text? Why? Because HTML formatted text may contain tags which MUST BE CLOSED and in the same time HTML tags are counted as characters!
As you guess, the task may look like this:

  • Temporary remove all eventual HTML tags
  • Trim stripped content at desired words length
  • Get all HTML tags back on their initial positions
  • Watch for unclosed tags

OK, I guess the task is quite clear. Now we gonna create a function, paste it at the bottom of ‘functions.php’ so it can be (re)used whenever is needed. I didn’t want to bother with making widget or plugin coz it takes more time and does the same job. Maybe one day I will. Here is our function:


<?php
function trim_the_content( $the_contents, $read_more_tag = ' READ MORE...', $perma_link_to = '', $all_words = 45 ) {
	// make the list of allowed tags
	$allowed_tags = array( 'a', 'abbr', 'b', 'blockquote', 'b', 'cite', 'code', 'div', 'em', 'fon', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'hr', 'i', 'img', 'label', 'i', 'p', 'pre', 'span', 'strong', 'title', 'ul', 'ol', 'li', 'object', 'embed' );
	if( $the_contents != '' ) {
		// process allowed tags
		$allowed_tags = '<' . implode( '><', $allowed_tags ) . '>';
		$the_contents = str_replace( ']]>', ']]&gt;', $the_contents );
		$the_contents = strip_tags( $the_contents, $allowed_tags );
		// exclude HTML from counting words
		if( $all_words > count( preg_split( '/[\s]+/', strip_tags( $the_contents ), -1 ) ) ) return $the_contents;
		// count all
		$all_chunks = preg_split( '/([\s]+)/', $the_contents, -1, PREG_SPLIT_DELIM_CAPTURE );
		$the_contents = '';
		$count_words = 0;
		$enclosed_by_tag = false;
		foreach( $all_chunks as $chunk ) {
			// is tag opened?
			if( 0 < preg_match( '/<[^>]*$/s', $chunk ) ) $enclosed_by_tag = true;
			elseif( 0 < preg_match( '/>[^<]*$/s', $chunk ) ) $enclosed_by_tag = false;
			// get entire word
			if( !$enclosed_by_tag && '' != trim( $chunk ) && substr( $chunk, -1, 1 ) != '>' ) $count_words ++;
			$the_contents .= $chunk;
			if( $count_words >= $all_words && !$enclosed_by_tag ) break;
		}
                // note the class named 'more-link'. style it on your own
		$the_contents = $the_contents . '<a class="more-link" href="' . $perma_link_to . '">' . $read_more_tag . '</a>';
		// native WordPress check for unclosed tags
		$the_contents = force_balance_tags( $the_contents );
	}
	return $the_contents;
}
?>

How to use this code with your own theme templates?

That’s easy, the only thing you need to do is to call our function (pasted in functions.php, remember?) and pass required arguments or parameters. For example…instead of using either the_excerpt() or the_content() WP’s functions you would write something like this:


<?php
	// find out your post permalink
	$perma_link = get_permalink( $post->ID );
	// save original post content to variable
	$content = get_the_content();
	// prevent tags strip | it's a bug in WordPress!
	$content = apply_filters( 'the_content', $content );
	$content = str_replace( ']]>', ']]&gt;', $content );
	// throw out trimmed: content to process, read more tag, post permalink, words length
	echo trim_the_content( $content, 'READ MORE...', $perma_link, 45 );
?>

Hopefully you find this function useful so share it with others PLEASE! Thanks!

Share with others...

deliciousdiggreddittechnoratifacebooktwittergoogleyahoowikioblinklistsimpyspurl
Comments (10)

Track comments via RSS 2.0 feed. Feel free to post the comment, or trackback from your web site.

  • easy3gger on Sep 28, 2009

    That’s just awsome mate!!! I’ve been looking for this for a long time, a big THANK YOU for sharing it.
    PS
    Keep up good work! It’s great to see unique content and fresh ideas.

  • topofbusiness on Oct 10, 2009

    Thanks for shared the nice info.

  • jukswebguy on Oct 16, 2009

    Thanks for this info, I have been looking for this. thanks man.

  • hanif on May 19, 2010

    it’s work…
    great man…

  • Karen Ho on May 26, 2010

    I love you!!

  • Matt on Jun 8, 2010

    Thanks a lot… just saved me the 30 min to write a similar function!

  • baseer on Jun 8, 2010

    nice but i saw another mathod just u hav to change 2 line n u r fixed

  • RobinH on Jun 12, 2010

    The ‘wordpress bug fix!’ was a real big help!

    Thanks

  • odys on Jun 23, 2010

    THANK YOU!!! awesome code..

    you can also avoid wordpress bug
    by getting formatted content using:

    ob_start();
    the_content();
    $content = ob_get_clean();

  • Jason Gegere on Jul 22, 2010

    Great little diddy. I wish I could subscribe to the comment so I could stay up to date on your post. Peace.

Leave a Comment

Search

Latest comment by Jason Gegere

Great little diddy. I wish I could subscribe to the comment so I could stay up to date on your post. Peace.

Advertisement

GraphicRiver ThemeForest