Utilizzo di wp_trim_excerpt per ottenere the_excerpt() fuori dal loop
Sto sviluppando un tema che mostrerà gli excerpt nella homepage per potenzialmente decine di post. Non ho excerpt manuali su tutti i miei post, quindi $post->post_excerpt
è vuoto per molti post. Nel caso in cui non ci sia un excerpt manuale, vorrei utilizzare la funzione integrata get_the_excerpt(), ma non è disponibile al di fuori del loop.
Analizzando la funzione, sembra che utilizzi wp_trim_excerpt da wp-includes/formatting.php per creare excerpt al volo. Lo sto chiamando nel mio codice come wp_trim_excerpt( $item->post_content )
, ma sta semplicemente restituendo il contenuto completo. Sto facendo qualcosa di sbagliato?
So che posso creare la mia funzione per generare un excerpt, ma preferisco utilizzare le funzioni integrate quando possibile, mantenendo il mio codice compatibile con altri potenziali plugin / filtri.
http://adambrown.info/p/wp_hooks/hook/wp_trim_excerpt?version=3.0&file=wp-includes/formatting.php

Dalla versione 3.3.0 di WordPress, wp_trim_words()
è utile se puoi ottenere il contenuto per cui vuoi generare un riassunto. Spero che questo sia d'aiuto a qualcuno e eviti di dover creare una propria funzione per il conteggio delle parole.

La funzione wp_trim_excerpt()
ha una meccanica un po' curiosa - se le viene passato qualcosa, non fa nulla.
Ecco la logica di base dietro di essa:
get_the_excerpt()
verifica la presenza di un estratto manuale;wp_trim_excerpt()
interviene se non c'è un estratto manuale e ne crea uno dal contenuto o dall'anteprima.
Entrambe le funzioni sono strettamente legate alle variabili globali e quindi al Loop.
Al di fuori del Loop è meglio estrarre il codice da wp_trim_excerpt()
e scrivere la propria funzione di trimming.

Aggiornamento:
Ecco una derivazione di wp_trim_excerpt() che ho utilizzato. Funziona perfettamente. Derivata dalla versione di WordPress 3.0.4
function my_excerpt($text, $excerpt)
{
if ($excerpt) return $excerpt;
$text = strip_shortcodes( $text );
$text = apply_filters('the_content', $text);
$text = str_replace(']]>', ']]>', $text);
$text = strip_tags($text);
$excerpt_length = apply_filters('excerpt_length', 55);
$excerpt_more = apply_filters('excerpt_more', ' ' . '[...]');
$words = preg_split("/[\n\r\t ]+/", $text, $excerpt_length + 1, PREG_SPLIT_NO_EMPTY);
if ( count($words) > $excerpt_length ) {
array_pop($words);
$text = implode(' ', $words);
$text = $text . $excerpt_more;
} else {
$text = implode(' ', $words);
}
return apply_filters('wp_trim_excerpt', $text, $raw_excerpt);
}

Non devi pubblicare una nuova risposta, puoi sempre modificare quella vecchia per includere nuove informazioni. Potresti, ad esempio, copiare il link al codice WP dalla tua prima risposta in questa e poi eliminare la prima risposta.

Ecco la mia versione di una funzione "trim_excerpt" che accetta come parametro l'oggetto del post o un ID del post.
Ovviamente basata su ciò che è presente nel core. Non so perché questa (e get_the_author()) non abbiano equivalenti al di fuori del loop.
/**
* Genera un estratto dal contenuto, se necessario.
*
* @param int|object $post_or_id può essere l'ID del post, oppure l'oggetto $post stesso
* @param string $excerpt_more il testo aggiunto alla fine dell'estratto se viene tagliato algoritmicamente
* @return string l'estratto tagliato o l'estratto manuale se esiste
*/
function zg_trim_excerpt($post_or_id, $excerpt_more = ' [...]') {
if ( is_object( $post_or_id ) ) $postObj = $post_or_id;
else $postObj = get_post($post_or_id);
$raw_excerpt = $text = $postObj->post_excerpt;
if ( '' == $text ) {
$text = $postObj->post_content;
$text = strip_shortcodes( $text );
$text = apply_filters('the_content', $text);
$text = str_replace(']]>', ']]>', $text);
$text = strip_tags($text);
$excerpt_length = apply_filters('excerpt_length', 55);
// non assumere automaticamente che useremo il link "leggi tutto" globale fornito dal tema
// $excerpt_more = apply_filters('excerpt_more', ' ' . '[...]');
$words = preg_split("/[\n\r\t ]+/", $text, $excerpt_length + 1, PREG_SPLIT_NO_EMPTY);
if ( count($words) > $excerpt_length ) {
array_pop($words);
$text = implode(' ', $words);
$text = $text . $excerpt_more;
} else {
$text = implode(' ', $words);
}
}
return apply_filters('wp_trim_excerpt', $text, $raw_excerpt);
}

+1 per Rast. È molto strano che non esista una funzione come get_the_excerpt($post->ID), quando sarebbe abbastanza ovvio che dovrebbe esistere. Comunque, ecco wp_trim_excerpt() nella versione 3.0.4 di WordPress:
http://core.trac.wordpress.org/browser/tags/3.0.4/wp-includes/formatting.php
function wp_trim_excerpt($text) {
1824 $raw_excerpt = $text;
1825 if ( '' == $text ) {
1826 $text = get_the_content('');
1827
1828 $text = strip_shortcodes( $text );
1829
1830 $text = apply_filters('the_content', $text);
1831 $text = str_replace(']]>', ']]>', $text);
1832 $text = strip_tags($text);
1833 $excerpt_length = apply_filters('excerpt_length', 55);
1834 $excerpt_more = apply_filters('excerpt_more', ' ' . '[...]');
1835 $words = preg_split("/[\n\r\t ]+/", $text, $excerpt_length + 1, PREG_SPLIT_NO_EMPTY);
1836 if ( count($words) > $excerpt_length ) {
1837 array_pop($words);
1838 $text = implode(' ', $words);
1839 $text = $text . $excerpt_more;
1840 } else {
1841 $text = implode(' ', $words);
1842 }
1843 }
1844 return apply_filters('wp_trim_excerpt', $text, $raw_excerpt);
1845 }
Puoi vedere alla riga 1826 che è collegato alla variabile globale $post tramite get_the_contents. E sì, non ho idea di cosa stessero pensando. Ma da qui, sostituisci get_the_content con $text nella tua funzione my_excerpt, e dovrebbe comportarsi in modo simile.

La funzione get_the_content() restituirà il contenuto completo se $more != 0. È necessario impostare la variabile globale $more a 0 per assicurarsi che la funzione get_the_content() restituisca l'estratto.
Funzione wp_trim_excerpt() modificata:
function wp_trim_excerpt($text) {
$raw_excerpt = $text;
if ( '' == $text ) {
global $more;
$tmp = $more;
$more = 0;
$text = get_the_content('');
$more = $tmp;
$text = strip_shortcodes( $text );
$text = apply_filters('the_content', $text);
$text = str_replace(']]>', ']]>', $text);
$text = strip_tags($text);
$excerpt_length = apply_filters('excerpt_length', 55);
$excerpt_more = apply_filters('excerpt_more', ' ' . '[...]');
$words = preg_split("/[\n\r\t ]+/", $text, $excerpt_length + 1, PREG_SPLIT_NO_EMPTY);
if ( count($words) > $excerpt_length ) {
array_pop($words);
$text = implode(' ', $words);
$text = $text . $excerpt_more;
} else {
$text = implode(' ', $words);
}
}
return apply_filters('wp_trim_excerpt', $text, $raw_excerpt);
}

Utilizzando le risposte precedenti degli altri, ecco una soluzione più semplice che sembra funzionare bene:
global $post;
$excerpt = apply_filters('get_the_excerpt', get_post_field('post_excerpt', $post->ID));
if ( $excerpt == '' ) {
$excerpt = wp_trim_words( $post->post_content, 55 );
}
Sto utilizzando questo codice nei tag <meta>
all'interno di una funzione per definire le descrizioni OpenGraph. Quindi aggiungo semplicemente:
<meta property="og:description" content="<?php echo esc_html( $excerpt ); ?>" />
