¿Cómo terminar el extracto con una oración en lugar de una palabra?

15

Aquí está el extracto de la publicación en mi página de inicio. Quiero terminar el extracto con una oración. En este caso es 'oportunidades. '. Sé cómo modificar la longitud, pero no hará lo que quiero.

ingrese la descripción de la imagen aquí

Aquí hay un extracto de otro sitio web. Aquí puede ver un extracto que termina con una oración adecuada, a diferencia de lo anterior, que termina con la primera palabra de la siguiente oración 'Proactivamente'.

ingrese la descripción de la imagen aquí

Después de implementar la solución por GM : -

ingrese la descripción de la imagen aquí

Mohit
fuente
Por favor, explique su problema mejor que eso. Por las respuestas y comentarios sobre ellos, es difícil entender lo que quieres lograr.
Kaiser
@kaiser He actualizado los detalles.
Mohit
@Mohit, ¿has probado mi código?
gmazzap
Sí, el extracto termina con una oración, pero 'Leer más' se ha ido.
Mohit
@ GM Muy bien, tengo que agregar la lectura más en la devolución.
Mohit

Respuestas:

13

Esto requiere PHP 5.3+ (WP requiere 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);
}

Editar

Después del comentario de @kaiser, trato de ejecutar esto en guardar / actualizar para evitar que la página se ralentice al mostrar muchas publicaciones. Esto debe ser probado

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; 
}
gmazzap
fuente
1
seguro de eso $end{0}:? Por cierto, podrías regresar o breakcuando se encuentre algo. Nota adicional: puede ser mejor para eso al guardar la publicación, por lo que no se regenera durante el tiempo de ejecución, lo que puede ser bastante lento si está mostrando muchas publicaciones.
Kaiser
@kaiser cite: a las cadenas también se puede acceder usando llaves, como en $ str {42}, con el mismo propósito. php.net docs Para encontrar algo, tuve que encontrar el último carácter de la última cadena. Usando $foundrompo el ciclo y verifico la última cadena, así que no es necesario break.
gmazzap
Completamente perdido que es una whilecomprobación false. +1
kaiser
@kaiser +1 para la segunda parte de tu comentario, ahora edito el código para que se ejecute en guardar
gmazzap
1
Claro que @jessica fue una mala edición (en la versión original estaba bien). Gracias, arreglado.
gmazzap
2

Aquí está mi versión, manteniendo todas las etiquetas html y también recortando el contenido después de la última palabra de una oración

if ( ! function_exists( 'pietergoosen_custom_wp_trim_excerpt' ) ) : 

    function pietergoosen_custom_wp_trim_excerpt($pietergoosen_excerpt) {
    global $post;
    $raw_excerpt = $pietergoosen_excerpt;
        if ( '' == $pietergoosen_excerpt ) {

            $pietergoosen_excerpt = get_the_content('');
            $pietergoosen_excerpt = strip_shortcodes( $pietergoosen_excerpt );
            $pietergoosen_excerpt = apply_filters('the_content', $pietergoosen_excerpt);
            $pietergoosen_excerpt = str_replace(']]>', ']]>', $pietergoosen_excerpt);

            //Set the excerpt word count and only break after sentence is complete.
                $excerpt_word_count = 75;
                $excerpt_length = apply_filters('excerpt_length', $excerpt_word_count); 
                $tokens = array();
                $excerptOutput = '';
                $count = 0;

                // Divide the string into tokens; HTML tags, or words, followed by any whitespace
                preg_match_all('/(<[^>]+>|[^<>\s]+)\s*/u', $pietergoosen_excerpt, $tokens);

                foreach ($tokens[0] as $token) { 

                    if ($count >= $excerpt_word_count && preg_match('/[\?\.\!]\s*$/uS', $token)) { 
                    // Limit reached, continue until  ? . or ! occur at the end
                        $excerptOutput .= trim($token);
                        break;
                    }

                    // Add words to complete sentence
                    $count++;

                    // Append what's left of the token
                    $excerptOutput .= $token;
                }

            $pietergoosen_excerpt = trim(force_balance_tags($excerptOutput));

                $excerpt_end = ' <a href="'. esc_url( get_permalink() ) . '">' . '&nbsp;&raquo;&nbsp;' . sprintf(__( 'Read more about: %s &nbsp;&raquo;', 'pietergoosen' ), get_the_title()) . '</a>'; 
                $excerpt_more = apply_filters('excerpt_more', ' ' . $excerpt_end); 

                //$pos = strrpos($pietergoosen_excerpt, '</');
                //if ($pos !== false)
                // Inside last HTML tag
                //$pietergoosen_excerpt = substr_replace($pietergoosen_excerpt, $excerpt_end, $pos, 0);
                //else
                // After the content
                $pietergoosen_excerpt .= $excerpt_end;

            return $pietergoosen_excerpt;   

        }
        return apply_filters('pietergoosen_custom_wp_trim_excerpt', $pietergoosen_excerpt, $raw_excerpt);
    }

endif; 

remove_filter('get_the_excerpt', 'wp_trim_excerpt');
add_filter('get_the_excerpt', 'pietergoosen_custom_wp_trim_excerpt'); 
Pieter Goosen
fuente
0

En caso de que alguien esté usando la respuesta, un consejo: esto arruinará los campos personalizados avanzados. ACF también se invoca wp_insert_post_dataal crear o actualizar un campo, pero la $datavariable no es la misma, y ​​dará como resultado que el nombre del campo ACF se convierta en una jerga ilegible, lo que resulta en no poder usar el campo.

Eetu Purtonen
fuente