5

I have an ACF-field, that gives an output like this:

<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
<p><img class="alignnone size-large wp-image-48" src="http://example.org/wp-content/uploads/2019/01/foo-bar.jpg" alt="" width="1024" height="640" /></p>
<p>Sed lacinia enim a <strong>est aliquet</strong>, et accumsan ex pellentesque. </p>
<p>Adipiscing elit, lorem ipsum dolor sit amet, consectetur.</p>

... Both images and text.

With wp_html_excerpt I can remove all tags, so I get one long text-blurp.

But with WordPress' native excerpts, then it doesn't remove line-breaks or bold text, which I find nice.

How would I go about achieving, getting an excerpt like that, from my ACF-wysiwyg-field?

So ideally, I would call my function like this: create_neat_excerpt( $html, 15 ); and get an output like this (from above-given input):

<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
<p>Sed lacinia enim a <strong>est aliquet</strong>, et accumsan...</p>

Addition: My current attempt

$project_desc = get_field( 'project_description' );

if( !empty( $project_desc ) ):
  $trimmed_text = wp_html_excerpt( $project_desc, 800 );
  $last_space = strrpos( $trimmed_text, ' ' );
  $modified_trimmed_text = substr( $trimmed_text, 0, $last_space );
  echo $modified_trimmed_text . '...';
endif; 
3
  • What kind of native excerpts do you have on mind? Commented Jan 15, 2019 at 12:45
  • Like on a regular archives-page, where it shows an excerpt, which by default returns 55 words. Source: the_excerpt ... That there removes images, but keeps line-breaks and <strong>-tags.
    – Zeth
    Commented Jan 15, 2019 at 13:55
  • @Zeth in the source the_excerpt() you provided, it actually says "An auto-generated excerpt will also have all shortcodes and tags removed." Commented Jan 17, 2019 at 5:54

3 Answers 3

6
+50

You can provide your own implementation of wp_trim_excerpt which is responsible for trimming and stripping HTML tags (it uses wp_strip_all_tags),

By copying the function source code and applying the change that you want (which is keeping the <p> and <strong> tags (or any additional tags as you wish) and it will work nicely.

I copied the function for you and applied the change of allowing <p> and <strong> to be on your final excerpt. (You should put this code in your functions.php file)

function wp_trim_excerpt_modified($text, $content_length = 55, $remove_breaks = false) {
    if ( '' != $text ) {
        $text = strip_shortcodes( $text );
        $text = excerpt_remove_blocks( $text );
        $text = apply_filters( 'the_content', $text );
        $text = str_replace(']]>', ']]&gt;', $text);
        $num_words = $content_length;
        $more = $excerpt_more ? $excerpt_more : null;
        if ( null === $more ) {
            $more = __( '&hellip;' );
        }
        $original_text = $text;
        $text = preg_replace( '@<(script|style)[^>]*?>.*?</\\1>@si', '', $text );

        // Here is our modification
        // Allow <p> and <strong>
        $text = strip_tags($text, '<p>,<strong>');

        if ( $remove_breaks )
            $text = preg_replace('/[\r\n\t ]+/', ' ', $text);
        $text = trim( $text );
        if ( strpos( _x( 'words', 'Word count type. Do not translate!' ), 'characters' ) === 0 && preg_match( '/^utf\-?8$/i', get_option( 'blog_charset' ) ) ) {
            $text = trim( preg_replace( "/[\n\r\t ]+/", ' ', $text ), ' ' );
            preg_match_all( '/./u', $text, $words_array );
            $words_array = array_slice( $words_array[0], 0, $num_words + 1 );
            $sep = '';
        } else {
            $words_array = preg_split( "/[\n\r\t ]+/", $text, $num_words + 1, PREG_SPLIT_NO_EMPTY );
            $sep = ' ';
        }
        if ( count( $words_array ) > $num_words ) {
            array_pop( $words_array );
            $text = implode( $sep, $words_array );
            $text = $text . $more;
        } else {
            $text = implode( $sep, $words_array );
        }
    }
    return $text;
}

Notice the line that is doing the stripping:

Line:22 $text = strip_tags($text, '<p>,<strong>');

And your code should be like this:

$project_desc = get_field( 'project_description' );
if( !empty( $project_desc ) ):
    $trimmed_text = wp_trim_excerpt_modified( $project_desc, 15 );
    $last_space = strrpos( $trimmed_text, ' ' );
    $modified_trimmed_text = substr( $trimmed_text, 0, $last_space );
    echo $modified_trimmed_text . '...';
endif; 

For more information, you can checkout this answer on stackoverflow it is more detailed.

2
  • Awesome. Two things, though: 1) The remove_breaks is initially defined in the if-statement. And 2) What does this line do: if ( strpos( _x( 'words', 'Word count type. Do not translate!' ), 'characters' ) === 0 && preg_match( '/^utf\-?8$/i', get_option( 'blog_charset' ) ) ) { $text = trim( preg_replace( "/[\n\r\t ]+/", ' ', $text ), ' ' );
    – Zeth
    Commented Jan 23, 2019 at 14:03
  • @Zeth Yes, this is how wordpress is doing the simple action of getting the excerpt and trimming words. the first one though I copied it and it was a parameter in the function .. but forgot to replace it (with false for example). About the second one i just copied it so we don't mess anything up. I will edit the remove_breaks option to be false by default just as wordpress did it in the source code. Commented Jan 23, 2019 at 14:15
3

using apply_filters( 'the_excerpt', get_field( 'project_description' ) ); is close, but it's missing a vital step in getting you where you want. the core excerpt builder runs another filter before it hits the_excerpt. it's get_the_excerpt and on that filter is a call to wp_trim_excerpt() which runs wp_trim_words(). if you look at that function you will see it runs wp_strip_all_tags() before trimming content to 55 words. This is the part you are missing to get your content to look like a regular excerpt without any images. I haven't tested the below but it should work without too much modification needed.

$raw_content = get_field( 'project_description' );
$trimmed_content = wp_trim_words($raw_content);
$clean_excerpt = apply_filters('the_excerpt', $trimmed_content);

echo $clean_excerpt;

Clean that up however you like, I spread it all out for readability.

EDIT: wp_trim_excerpt() only runs all the fun filters if it's pulling from post content. replaced with wp_trim_words()

6
  • Hmm... It still displays everything from the acf-wysiwyg-field.
    – Zeth
    Commented Jan 15, 2019 at 19:11
  • interesting. maybe replace wp_trim_excerpt() with a straight up call to strip_tags() of course then you'll need to trim to the word length you want after but if it's not stripping tags inside that function try doing it first?
    – mrben522
    Commented Jan 15, 2019 at 19:48
  • just reread wp_trim_excerpt() when you pass it text that function just dumps out what you gave it instead of cleaning up and filtering. try using wp_trim_words() instead. you may need to pass that through some more filters as well to get it looking right
    – mrben522
    Commented Jan 15, 2019 at 19:54
  • Hmm... Now it filters the content (using wp_trim_words). So it trims it to the 55 words and removes images. But it also remove break-lines and <strong>-tags. I don't know if it's my memory toying with me that the regular the_excerpt actually does that as well. But I'm looking for something that keeps newlines and strong-tags.
    – Zeth
    Commented Jan 15, 2019 at 23:03
  • 2
    nevermind, Ibrahim's answer is a perfectly good implementation of what I was going to do. use that
    – mrben522
    Commented Jan 16, 2019 at 14:10
0

Use the_excerpt filter (see Codex)

apply_filters( 'the_excerpt', get_field( 'my-wysiwyg-field' ) );

3
  • I tried it, and I can't get it to work. When I call it from inside the loop, in my single.php-file, then it doesn't change anything. Do I need to create a function and put that in my functions.php? Or can you elaborate on, how I'm supposed to use it?
    – Zeth
    Commented Jan 13, 2019 at 11:25
  • 1
    You should update your question to show the code that you are using (don't add it as a reply as it gets a bit messy). My answer just showed the function, as I don't know how your script handles it, but as a bare minimum, add echo to output the filter - echo apply_filters( 'the_excerpt', get_field( 'my-wysiwyg-field' ) );
    – Peter HvD
    Commented Jan 14, 2019 at 12:08
  • Thanks for your response. I've added the code now. I did try echoing the filter ( echo apply_filters( 'the_excerpt', $project_desc ), as you suggested, - but it doesn't change anything (it includes images as well, when echoing it out like that).
    – Zeth
    Commented Jan 14, 2019 at 12:16

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.