Skip to content
Advertisement

End excerpts with a full sentence for specific post types

I am trying to make excerpts end with a sentence, for a specific post type on my website, but for some reason, it is also effecting page excerpts and I cannot understand why.

function vhr_variable_length_excerpt($text, $w_length, $finish_sentence){
    global $post;
    if ( $post->post_type == 'poi' ) {
        //Word length of the excerpt. This is exact or NOT depending on your '$finish_sentence' variable.
        $w_length = 20; /* Change the Length of the excerpt. The Length is in words. */
     
        //1 if you want to finish the sentence of the excerpt (No weird cuts).
        $finish_sentence = 1; // Put 0 if you do NOT want to finish the sentence.
            
        $tokens = array();
        $out = '';
        $word = 0;

        //Divide the string into tokens; HTML tags, or words, followed by any whitespace.
        $regex = '/(<[^>]+>|[^<>s]+)s*/u';
        preg_match_all($regex, $text, $tokens);
        foreach ($tokens[0] as $t){ 
            //Parse each token
            if ($word >= $w_length && !$finish_sentence){ 
                //Limit reached
                break;
            }
            if ($t[0] != '<'){ 
                //Token is not a tag. 
                //Regular expression that checks for the end of the sentence: '.', '?' or '!'
                $regex1 = '/[?.!]s*$/uS';
                if ($word >= $w_length && $finish_sentence && preg_match($regex1, $t) == 1){ 
                    //Limit reached, continue until ? . or ! occur to reach the end of the sentence.
                    $out .= trim($t);
                    break;
                }   
                $word++;
            }
         //Append what's left of the token.
         $out .= $t;     
        }
        return trim(force_balance_tags($out)); 
    }
}

function vhr_excerpt_filter($text){
    global $post;
    if ( $post->post_type == 'poi' ) {
        //Get the full content and filter it.
        $text = get_the_content('');
        $text = strip_shortcodes( $text );
        $text = apply_filters('the_content', $text);
    
        $text = str_replace(']]>', ']]&gt;', $text);
    
        //If you want to Allow SOME tags: 
        $allowed_tags = '<p>,<a>,<strong>,<b>'; /* Here I am allowing p, a, strong tags. Separate tags by comma. */
            
        $text = strip_tags($text, $allowed_tags);
    
        //Create the excerpt.
        $text = vhr_variable_length_excerpt($text, $w_length, $finish_sentence); 
  
        return $text;
    }
}
//Hooks the 'vhr_excerpt_filter' function to a specific (get_the_excerpt) filter action.
add_filter('get_the_excerpt', 'vhr_excerpt_filter', 5);

It doesn’t effect any of my other custom post types, just the one I specify in the function, and then all pages on the website. It still effects my pages, even if I change the logic to something like = poi && != page as well. Any ideas why this would also be effecting pages? Is there an easier way to make this happen?

Thanks!

Advertisement

Answer

There is a multitudes of ways we can approach it. Taking the time to write a custom excerpt instead on relying on WordPress is one of them…

We can count sentences by targeting end-of-sentence period.

function get_sentence_tally_excerpt( $content = '', $tally = 2, $stitches = '' ) {

    $buffer = array_slice( explode( '.', sanitize_text_field( $content ) ), 0, $tally );

    $filter = array_filter( array_map( 'trim', $buffer ), 'strlen' );

    $excerpt = join( '. ', $filter ) . '.';

    return esc_attr( $excerpt . $stitches );

};

You can specify what type of content should be ‘truncated’ and by how many sentences. On the front-end we can call our function get_tally_excerpt() like so:

<?= get_sentence_tally_excerpt( get_the_content() ); ?> //... 2 sentences by DEFAULT 
<?= get_sentence_tally_excerpt( get_the_content(), 1 ); ?> //... 1 sentences ONLY
<?= get_sentence_tally_excerpt( get_the_content(), 5, '[...]' ); ?> //... 5 sentences ONLY with stitches at the end. 
User contributions licensed under: CC BY-SA
9 People found this is helpful
Advertisement