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:
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( ']]>', ']]>', $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;
}
?>
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( ']]>', ']]>', $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!
Great little diddy. I wish I could subscribe to the comment so I could stay up to date on your post. Peace.