Quando viene cancellata la colonna 'post_content_filtered' nel database da WordPress?
Alcuni plugin WordPress (anche se pochi) utilizzano la colonna post_content_filtered
nel database per salvare alcuni dati relativi a un articolo.
Ad esempio, Markdown on Save memorizza la versione markdown di un articolo separatamente nella colonna post_content_formatted
e l'HTML parsato nella colonna post_content
, in modo che quando il plugin viene disattivato gli articoli non visualizzino il markdown (perché l'HTML è memorizzato in post_content
).
Ora, ho capito che post_content_filtered
viene utilizzata praticamente per lo storage temporaneo, cioè il contenuto nella colonna viene perso (o cancellato) quando:
apporti modifiche a un articolo (titolo, tag, categorie, ecc.) utilizzando l'opzione 'Modifica rapida'
un articolo programmato viene (automaticamente) pubblicato
effettui modifiche in blocco agli articoli
passi da una revisione all'altra di un articolo
un articolo viene salvato da un editor esterno (cioè non dall'editor di articoli di WordPress)
Domande:
In quali altre situazioni vengono cancellati i dati dalla colonna
post_content_filtered
?Esiste un modo per evitare che questo accada del tutto? (Voglio dire, c'è un modo per assicurarsi che i dati vengano memorizzati in modo permanente, come viene trattata la colonna
post_content
?)

Ogni aggiornamento di un post in WordPress viene gestito dalla funzione wp_update_post
.
Questa funzione ha alcuni valori predefiniti, e per post_content_filtered
il valore predefinito è '' (stringa vuota).
Una volta che i valori predefiniti vengono uniti agli argomenti passati alla funzione tramite wp_parse_args
, significa che ogni volta che un post viene aggiornato e post_content_filtered
non viene passato esplicitamente, viene impostato su una stringa vuota.
Ora possiamo chiederci: quando viene passato esplicitamente post_content_filtered
a wp_update_post
? La risposta è: mai da parte di WordPress.
Quindi per la tua prima domanda:
In quali altre situazioni i dati nella colonna post_content_filtered vengono cancellati?
La risposta breve è: ogni volta che un post viene aggiornato, per qualsiasi motivo.
Nota che modificare solo un campo è un aggiornamento, in particolare, ogni cambio di stato è un aggiornamento, ad esempio da bozza a pubblicato, da in attesa a pubblicato, da programmato a pubblicato, da pubblicato a cestino (un'eliminazione del post), e così via...
Se qualcosa cambia in un post, allora post_content_filtered
viene cancellato; l'unica eccezione è quando post_content_filtered
viene passato esplicitamente a wp_update_post
, e come già detto, questo non viene mai fatto da WordPress.
C'è un modo per evitare che questo accada del tutto? (Voglio dire, c'è un modo per assicurarsi che i dati vengano memorizzati permanentemente?)
Se crei quel campo con il tuo codice e vuoi preservarlo, devi controllare ogni aggiornamento eseguito da WordPress e prevenire la modifica.
Questo potrebbe sembrare un lavoro difficile, ma se leggi la prima frase di questa risposta, "Ogni aggiornamento di un post in WordPress viene gestito dalla funzione wp_update_post
", capisci che l'unica cosa necessaria è controllare quella funzione, che fortunatamente ha diversi hook.
L'hook che suggerisco è wp_insert_post_data
per 2 motivi:
- Viene eseguito prima dell'aggiornamento, quindi non devi recuperare ma puoi prevenire
- Passa 2 parametri: i dati che la funzione sta per aggiornare e un array dei parametri passati, che (in caso di aggiornamento) contengono l'ID del post
Quindi, usando un semplice get_post
puoi confrontare come è il post ora e come sarà: se qualcosa non ti piace, puoi cambiarlo.
Vediamo il codice:
add_filter( 'wp_insert_post_data', 'preserve_content_filtered', 999, 2 );
function preserve_content_filtered ( $data, $postarr ) {
/* Se non è un aggiornamento, non abbiamo nulla da fare */
if ( ! isset($postarr['ID']) || ! $postarr['ID'] ) return $data;
/*
* Vuoi filtrare per post_type?
* Dovresti, per evitare problemi su tipi di post come le voci di menu.
*/
if ( ! in_array( $data['post_type'], array( 'post', 'page' ) ) ) return $data;
/* Come è il post ora, prima dell'aggiornamento */
$before = get_post( $postarr['ID'] );
/* Se content_filtered è già vuoto, non abbiamo nulla da preservare */
if ( empty( $before->post_content_filtered ) ) return $data;
if ( empty( $data['post_content_filtered'] ) ) {
/*
* Ehi! WordPress vuole cancellare il nostro prezioso post_content_filtered...
* Preveniamolo!
*/
$data['post_content_filtered'] = $before->post_content_filtered;
}
return $data;
}
C'è un possibile problema, dove la funzione precedente previene ogni pulizia di post_content_filtered
. E se tu, per qualsiasi motivo, volessi cancellarlo?
Ho detto che ogni modifica di un post in WP viene gestita da wp_update_post
, ma tu non sei WordPress.
Puoi scrivere una funzione come:
function reset_post_content_filtered( $postid ) {
global $wpdb;
$wpdb->query( $wpdb->prepare(
"UPDATE $wpdb->posts SET `post_content_filtered` = '' WHERE `ID` = %d", $postid
) );
}
Essendo una query $wpdb
, non attiva il nostro filtro, quindi il reset viene eseguito senza problemi, e ovunque nel tuo codice hai bisogno di resettare post_content_filtered
, puoi chiamare questa funzione.
Puoi anche creare un metabox con un pulsante 'Pulisci content filtered' e quando questo pulsante viene cliccato chiamare semplicemente la tua funzione reset_post_content_filtered
, ad esempio via Ajax.
