Comment terminer l'extrait par une phrase plutôt qu'un mot?

15

Voici l'extrait de l'article sur ma page d'accueil. Je veux terminer l'extrait par une phrase. Dans ce cas, ce sont des opportunités. ". Je sais comment modifier la longueur mais ça ne fera pas ce que je veux.

entrez la description de l'image ici

Voici un extrait d'un autre site Web. Ici, vous voyez un extrait se terminant par une phrase appropriée contrairement à ce qui précède qui se termine par le premier mot de la phrase suivante «de manière proactive».

entrez la description de l'image ici

Après avoir implémenté la solution par GM : -

entrez la description de l'image ici

Mohit
la source
Veuillez expliquer votre problème mieux que cela. D'après les réponses et les commentaires à leur sujet, il est difficile de comprendre ce que vous voulez réaliser.
kaiser
@kaiser J'ai mis à jour les détails.
Mohit
@Mohit as-tu essayé mon code?
gmazzap
Oui, l'extrait se termine par une phrase mais «Lire la suite» a disparu.
Mohit
@GM Très bien, je dois ajouter la suite dans le retour.
Mohit

Réponses:

13

Cela nécessite PHP 5.3+ (WP nécessite 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);
}

Éditer

Après le commentaire de @kaiser, j'essaie de l'exécuter lors de la sauvegarde / mise à jour pour éviter que la page ne ralentisse en affichant beaucoup de messages. Cela devrait être testé

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
la source
1
sûr de ça $end{0}:? Btw, vous pouvez simplement revenir ou breakquand quelque chose est trouvé. Remarque supplémentaire: il pourrait être préférable de le faire lors de l'enregistrement du message, il n'est donc pas régénéré pendant l'exécution, ce qui peut devenir assez lent si vous affichez beaucoup de messages.
kaiser
@kaiser cite: Les chaînes sont également accessibles à l'aide d'accolades, comme dans $ str {42}, dans le même but. php.net docs Pour trouver quelque chose, j'ai dû trouver le dernier caractère de la dernière chaîne. En utilisant $foundje romps le cycle et vérifie la dernière chaîne, donc pas besoin break.
gmazzap
Complètement raté que c'est une whilevérification false. +1
kaiser
@kaiser +1 pour la deuxième partie de votre commentaire, maintenant je modifie le code pour qu'il s'exécute lors de la sauvegarde
gmazzap
1
Bien sûr, @jessica était une mauvaise édition (dans la version originale, c'était ok). Merci, réparé.
gmazzap
2

Voici ma version, en gardant toutes les balises html et en coupant également le contenu après le dernier mot d'une phrase

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
la source
0

Juste au cas où quelqu'un utilise la réponse, un conseil: cela ruinera les champs personnalisés avancés. ACF invoque également wp_insert_post_datalors de la création ou de la mise à jour d'un champ, mais la $datavariable n'est pas la même, et le nom du champ ACF deviendra un charabia illisible, ce qui entraînera l'impossibilité d'utiliser le champ.

Eetu Purtonen
la source