From 43f347bc7c3edd2d39936e6a8f3983842146baa9 Mon Sep 17 00:00:00 2001 From: Greg Date: Fri, 6 Jan 2023 20:04:05 -0500 Subject: [PATCH] Make the excerpt code actually crop the excerpt at 400 characters. The existing implementation crops at words and may return very short strings based upon filters, or very long strings based upon user inputted excerpts. Make sure we never return a excerpt longer than we expect. --- includes/model/class-post.php | 58 ++++++++++++++++++++++++++++++++--- 1 file changed, 54 insertions(+), 4 deletions(-) diff --git a/includes/model/class-post.php b/includes/model/class-post.php index e885199..84ed4fd 100644 --- a/includes/model/class-post.php +++ b/includes/model/class-post.php @@ -286,12 +286,62 @@ class Post { $excerpt = \apply_filters( 'the_content', $excerpt ); $excerpt = \str_replace( ']]>', ']]>', $excerpt ); - $excerpt_length = \apply_filters( 'excerpt_length', $excerpt_length ); + } + } - /** This filter is documented in wp-includes/formatting.php */ - $excerpt_more = \apply_filters( 'excerpt_more', ' [...]' ); + // Strip out any remaining tags. + $excerpt = \wp_strip_all_tags( $excerpt ); - $excerpt = \wp_trim_words( $excerpt, $excerpt_length, $excerpt_more ); + /** This filter is documented in wp-includes/formatting.php */ + $excerpt_more = \apply_filters( 'excerpt_more', ' [...]' ); + $excerpt_more_len = strlen( $excerpt_more ); + + // We now have a excerpt, but we need to check it's length, it may be longer than we want for two reasons: + // + // * The user has entered a manual excerpt which is longer that what we want. + // * No manual excerpt exists so we've used the content which might be longer than we want. + // + // Either way, let's trim it up if we need too. Also, don't forget to take into account the more indicator + // as part of the total length. + // + + // Setup a variable to hold the current excerpts length. + $current_excerpt_length = strlen( $excerpt ); + + // Setup a variable to keep track of our target length. + $target_excerpt_length = $current_excerpt_length - $excerpt_more_len; + + // Setup a variable to keep track of the current max length. + $current_expcerpt_max = $target_excerpt_length; + + // This is a loop since we can't calculate word break the string after 'the_excpert' filter has run (we would break + // all kinds of html tags), so we have to cut the excerpt down a bit at a time until we hit our target length. + while( $current_excerpt_length > $target_excerpt_length && $current_expcerpt_max > 0 ) { + // Trim the excerpt based on wordwrap() positioning. + // Note: we're using
as the linebreak just in case there are any newlines existing in the excerpt from the user. + // There won't be any
left after we've run wp_strip_all_tags() in the code above, so they're + // safe to use here. It won't be included in the final excerpt as the substr() will trim it off. + $excerpt = substr( $excerpt, 0, strpos( wordwrap( $excerpt, $current_expcerpt_max, '
' ), '
' ) ); + + // If something went wrong, or we're in a language that wordwrap() doesn't understand, + // just chop it off and don't worry about breaking in the middle of a word. + if( strlen( $excerpt ) > $excerpt_length - $excerpt_more_len ) { + $excerpt = substr( $excerpt, 0, $current_expcerpt_max ); + } + + // Add in the more indicator. + $excerpt = $excerpt . $excerpt_more; + + // Run it through the excerpt filter which will add some html tags back in. + $excerpt_filtered = apply_filters( 'the_excerpt', $excerpt ); + + // Now set the current excerpt length to this new filtered length. + $current_excerpt_length = strlen( $excerpt_filtered ); + + // Check to see if we're over the target length. + if( $current_excerpt_length > $target_excerpt_length ) { + // If so, remove 20 characters from the current max and run the loop again. + $current_expcerpt_max = $current_expcerpt_max - 20; } }