How to end the excerpt with a sentence rather than a word?

This requires PHP 5.3+ (WP requires PHP 5.2.4+)

add_filter('get_the_excerpt', 'end_with_sentence');

function end_with_sentence($excerpt) {
  $allowed_end = array('.', '!', '?', '...');
  $exc = explode( ' ', $excerpt );
  $found = false;
  $last="";
  while ( ! $found && ! empty($exc) ) { 
    $last = array_pop($exc);
    $end = strrev( $last );
    $found = in_array( $end{0}, $allowed_end );
  }
  return (! empty($exc)) ? $excerpt : rtrim(implode(' ', $exc) . ' ' .$last);
}

Edit

After @kaiser comment I try to run this on save/update to prevent page slow down on showing a lot of posts. This should be tested

add_filter('wp_insert_post_data', 'end_with_sentence_on_save', 20, 2);

function end_with_sentence_on_save($data, $postarr) {
  if ( ! empty( $data['post_content'] ) && $data['post_status'] != 'inherit' && $data['post_status'] != 'trash' ) {
    $text = strip_shortcodes( $data['post_content'] );
    $text = apply_filters('the_content', $text );
    $text = str_replace(']]>', ']]>', $text );
    $excerpt_length = apply_filters('excerpt_length', 55);
    $data['post_excerpt'] = wp_trim_words($text, $excerpt_length, '');
  } else {
    return $data;
  }
  $allowed_end = array('.', '!', '?', '...');
  $exc = explode(' ', $data['post_excerpt']);
  $found = false;
  $last="";
  while ( ! $found && ! empty($exc) ) { 
    $last = array_pop($exc);
    $end = strrev( $last );
    $found = in_array( $end{0}, $allowed_end );
  }
  if (! empty($exc)) $data['post_excerpt'] = rtrim(implode(' ', $exc) . ' ' .$last);
  return $data; 
}

Leave a Comment