apply_filters() and the_excerpt are giving unexpected results

I feel like I must be missing something pretty obvious, here, but I can’t seem to get WordPress to cooperate.

I’m generating Facebook OG tags with a function. Everything works fine, except for the excerpt.

Read More

Since the deprecation of get_the_excerpt($post->ID), is there another way to create an excerpt without having to create a whole new loop? It seems excessive to me.

My first instinct was to use apply_filters():

$description = apply_filters('the_excerpt', get_post($post->ID)->post_content);

That gives me the full post, complete with HTML-formatted content. Okay, must be wrong. So I tried the next logical idea:

$description = apply_filters('get_the_excerpt', get_post($post->ID)->post_content);

No dice. Now there’s no HTML, but it’s still the full post (which is really confusing).

Okay, no problem. Let’s skip all the fancy stuff and just go for the trimmed entry:

$description = wp_trim_excerpt(get_post($post->ID)->post_content);

No change.

So, my question is this: what the heck is going on? Is there something I’m missing, here?

I got into the WP core to find how the_excerpt() works, and it appears to be identical to my call:

/**
 * Display the post excerpt.
 *
 * @since 0.71
 * @uses apply_filters() Calls 'the_excerpt' hook on post excerpt.
 */
function the_excerpt() {
    echo apply_filters('the_excerpt', get_the_excerpt());
}

I have a few questions based on my findings:

  1. Why isn’t the filter applying as expected?
  2. Is there a way to get the excerpt outside of the loop without creating a new loop?
  3. Am I crazy?

Thanks in advance for having a look. I’m fairly stumped, here.

Related posts

Leave a Reply

3 comments

  1. Turns out the answer was in wp_trim_excerpt().

    It’s defined in wp-includes/functions.php:1879:

    /**
     * Generates an excerpt from the content, if needed.
     *
     * The excerpt word amount will be 55 words and if the amount is greater than
     * that, then the string ' [...]' will be appended to the excerpt. If the string
     * is less than 55 words, then the content will be returned as is.
     *
     * The 55 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
     *
     * @since 1.5.0
     *
     * @param string $text Optional. The excerpt. If set to empty, an excerpt is generated.
     * @return string The excerpt.
     */
    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);
    }
    

    So any text passed in doesn’t get processed; it only works if it’s called with an empty parameter.

    To solve this, I added a quick filter to my theme that solves the problem:

    /**
     * Allows for excerpt generation outside the loop.
     * 
     * @param string $text  The text to be trimmed
     * @return string       The trimmed text
     */
    function rw_trim_excerpt( $text='' )
    {
        $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', ' ' . '[...]');
        return wp_trim_words( $text, $excerpt_length, $excerpt_more );
    }
    add_filter('wp_trim_excerpt', 'rw_trim_excerpt');
    

    It’s somewhat redundant, but I like it better than opening new loops every time I want to generate an excerpt.

  2. You can use my custom function to filte the content (it’s from NARGA Framework)

    • If the post has custom excerpt, display it instead the content
    • Auto generate excerpt from the conten if the post hasn’t custom cerpt
    • Auto trim shortcode, HTML code, remove […], add “Read More” text (translatable)

          /**
          * Auto generate excerpt from content if the post hasn't custom excerpt
          * @from NARGA Framework - http://www.narga.net/narga-core
          * @param $excerpt_lenght  The maximium words of excerpt generating from content
          * @coder: Nguyễn Đình Quân a.k.a Narga - http://www.narga.net
          **/  
          function narga_excerpts($content = false) {
          # If is the home page, an archive, or search results
          if(is_front_page() || is_archive() || is_search()) :
              global $post;
          $content = $post->post_excerpt;
          $content = strip_shortcodes($content);
          $content = str_replace(']]>', ']]>', $content);
          $content = strip_tags($content);
          # If an excerpt is set in the Optional Excerpt box
          if($content) :
              $content = apply_filters('the_excerpt', $content);
          # If no excerpt is set
          else :
              $content = $post->post_content;
              $excerpt_length = 50;
              $words = explode(' ', $content, $excerpt_length + 1);
          if(count($words) > $excerpt_length) :
              array_pop($words);
              array_push($words, '...<p><a class="more-link" href="' . get_permalink() . '" title="' . the_title_attribute('echo=0') . '">  ' . __( 'Read more »', 'narga' ) . ' </a></p>');
              $content = implode(' ', $words);
          endif;
          $content = '<p>' . $content . '</p>';
          endif;
          endif;
          # Make sure to return the content
          return $content;
          }
          // Add filter to the_content
          add_filter('the_content', 'narga_excerpts');