Când este ștersă coloana 'post_content_filtered' din baza de date de WordPress?

8 sept. 2013, 13:08:28
Vizualizări: 13.9K
Voturi: 34

Unele pluginuri WordPress (deși foarte puține) utilizează coloana post_content_filtered din baza de date pentru a salva anumite informații legate de un articol.

De exemplu, Markdown on Save stochează versiunea Markdown a unui articol separat în coloana post_content_formatted și HTML-ul parsat în coloana post_content, astfel încât atunci când pluginul este dezactivat, articolele nu vor afișa Markdown (deoarece HTML este stocat în post_content).

Am realizat că post_content_filtered este folosită în mare parte pentru stocare temporară, adică conținutul din coloană se pierde (sau este șters) atunci când:

  • faceti modificări unui articol (titlu, taguri, categorii etc.) folosind opțiunea 'Editare Rapidă'

  • un articol programat este (automat) publicat

  • efectuați editări în masă ale articolelor

  • treceți între reviziile unui articol

  • un articol este salvat dintr-un editor extern (adică nu din editorul de articole WordPress)

Întrebări:

  1. În ce alte situații sunt șterse datele din coloana post_content_filtered?

  2. Există vreo modalitate de a preveni acest lucru? (Adică, există vreo cale de a ne asigura că datele sunt stocate permanent, așa cum este tratată coloana post_content?)

0
Toate răspunsurile la întrebare 1
0
37

Fiecare actualizare a postării în WordPress este gestionată de funcția wp_update_post.

Această funcție are câteva valori implicite, iar pentru post_content_filtered valoarea implicită este '' (șir gol).

Odată ce valorile implicite sunt combinate cu argumentele transmise funcției prin wp_parse_args, înseamnă că de fiecare dată când o postare este actualizată și post_content_filtered nu este transmis explicit, acesta este setat la un șir gol.

Acum ne putem întreba: când este transmis explicit post_content_filtered către wp_update_post? Răspunsul este: niciodată de către WordPress.

Deci, pentru prima întrebare:

În ce alte situații sunt șterse datele din coloana post_content_filtered?

Răspunsul scurt este: de fiecare dată când o postare este actualizată, indiferent de motiv.

Rețineți că schimbarea unui singur câmp este o actualizare, în special, fiecare schimbare de stare este o actualizare, de ex. din ciornă în publicat, din așteptare în publicat, din viitor în publicat, din publicat în coșul de gunoi (ștergerea unei postări), și așa mai departe...

Dacă ceva se schimbă într-o postare, atunci post_content_filtered este șters; singura excepție este atunci când post_content_filtered este transmis explicit către wp_update_post, și, după cum s-a menționat deja, acest lucru nu se întâmplă niciodată în WordPress.

Există vreo modalitate de a preveni acest lucru cu totul? (Adică, există o modalitate de a ne asigura că datele sunt stocate permanent?

Dacă ai creat acel câmp cu codul tău și dorești să-l păstrezi, trebuie să urmărești fiecare actualizare efectuată de WordPress și să preîntâmpini modificarea.

Aceasta poate părea o muncă grea, dar dacă citești prima propoziție din acest răspuns, "Fiecare actualizare a postării în WordPress este gestionată de funcția wp_update_post", înțelegi că singurul lucru necesar este să te uiți la acea funcție, care, din fericire, are diferite cârlige.

Cârligul pe care îl sugerez este wp_insert_post_data din 2 motive:

  • Rulează înainte de actualizare, așa că nu trebuie să recuperezi dar poți preveni
  • Primește 2 parametri: datele pe care funcția le va actualiza și un tablou cu parametrii transmiși, care (în cazul actualizării) conțin ID-ul postării

Deci, folosind un simplu get_post poți compara cum este postarea acum și cum va fi postarea: dacă nu-ți place ceva, poți să-l schimbi.

Să codificăm:

add_filter( 'wp_insert_post_data', 'preserve_content_filtered', 999, 2 );

function preserve_content_filtered ( $data, $postarr ) {

    /* Dacă aceasta nu este o actualizare, nu avem nimic de făcut */
    if ( ! isset($postarr['ID']) || ! $postarr['ID'] ) return $data;

    /*
     * Dorești să filtrezi pe tipul de postare?
     * Ar trebui, pentru a preveni probleme la tipuri de postare precum elementele de meniu.
     */
    if ( ! in_array( $data['post_type'], array( 'post', 'page' ) ) ) return $data;

    /* Cum este postarea acum, înainte de actualizare */
    $before = get_post( $postarr['ID'] ); 

    /* Dacă content_filtered este deja gol, nu avem nimic de păstrat */
    if ( empty( $before->post_content_filtered ) ) return $data;

    if ( empty( $data['post_content_filtered'] ) ) {
        /*
         * Hei! WordPress vrea să ne șteargă valoarea post_content_filtered...
         * Să prevenim acest lucru!
         */
        $data['post_content_filtered'] = $before->post_content_filtered;
    }

    return $data;

}

Există o posibilă problemă, unde funcția anterioară previne orice ștergere a post_content_filtered. Și dacă tu, din orice motiv, vrei să-l ștergi?

Am spus că fiecare modificare a postării în WP este gestionată de wp_update_post, dar tu nu ești WordPress.

Poți scrie o funcție precum:

function reset_post_content_filtered( $postid ) {
    global $wpdb;
    $wpdb->query( $wpdb->prepare(
        "UPDATE $wpdb->posts SET `post_content_filtered` = '' WHERE `ID` = %d", $postid
    ) );
}

Fiind o interogare $wpdb, aceasta nu declanșează filtrul nostru, astfel încât resetarea se face fără probleme, și oriunde în codul tău ai nevoie să resetezi post_content_filtered, poți apela această funcție.

Poți crea și un metabox cu un buton 'Șterge conținutul filtrat' și când acest buton este apăsat, apelează pur și simplu funcția ta reset_post_content_filtered, de exemplu prin Ajax.

11 sept. 2013 06:04:50