Bachi di inizio anno: WordPress update e WPML get_page_by_path()

Il 2012 è iniziato con qualche ora di deep-debugging a causa di due (noti) bachi abbastanza fastidiosi. Il primo, tra l’altro abbastanza datato, presente nel core di WordPress che riguarda il metodo update() della classe wpdb, con la globale (e famosa) omonima istanza $wpdb. Il difetto appare quando si tenta di aggiornare un campo a NULL. Nonostante le numerose lamentele, il team di sviluppo WordPress sembra non trovare soluzione al fastidioso problema. Infatti, ad oggi, l’unica soluzione è quella di scriversi l’SQL per proprio conto.

C’è stato un momento in cui credevo di aver aggirato il problema, passando al metodo anche l’array con l’elenco dei tipi campo, sul tipo:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$values = array(
  'name'       => 'prova',
  'date_start' => null
);

$formats = array(
  '%s',
  'NULL'
);

$where = array(
  'id' => 5
);

$wpdb->update('tablename', $values, $where, $formats);

In questo modo, la SQL che ne esce è:

1
UPDATE `tablename` SET `name` = 'prova', `date_start` = NULL WHERE `id` = ''

Tutto perfetto tranne che si è perso la condizione di where! In pratica “incasinando” la formattazione con 'NULL', scoppia tutto il resto. Passando anche i formati per la condizione di where:

1
2
3
4
...
$where_formats = array('%d');

$wpdb->update('tablename', $values, $where, $formats, $where_formats);

Si ottiene (direi quasi peggio):

1
UPDATE `tablename` SET `name` = 'prova', `date_start` = NULL WHERE `id` = 0

Ovviamente è chiaro che chi comanda in questo giochino è la formattazione e non il 'date_start' => null. Così l’unica soluzione possibile è un brute-force attack, ovvero:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
$values = array(
  'name'       => 'prova',
  'date_start' => null
);

$formats = array(
  '%s',
  '%NNULL'
);

$where = array(
  'id' => 5
);

$where_formats = array('%d');

$wpdb->update('tablename', $values, $where, $formats, $where_formats);

Che finalmente costruirà la SQL come si deve:

1
UPDATE `tablename` SET `name` = 'prova', `date_start` = NULL WHERE `id` = 5

Tuttavia, sono io il primo a dirlo, '%NNULL' non è proprio passabile, risolve l’impasse ma è meglio scriversi l’update per conto proprio.

WPML

Rimanendo sempre in tema WordPress, ci spostiamo adesso lato Plugin. WPML (WordPress Multi Language) è un plugin dedicato alla localizzazione di WordPress, cioè la gestione di un sito multi-lingua. Una sua caratteristica, dovuta all’architettura della soluzione che gli sviluppatori hanno adottato per permettere la scrittura e gestione di post in diverse lingue, è quella di “insinuarsi” tramite l’uso massivo azioni e filtri, nelle funzioni più a basso livello di WordPress. Questo gli permette di manipolare tutte le chiamate del core di WordPress, in particolare tutte quelle che hanno a che fare con il database (e non sono poche).
Il problema è che se sbagliano qualcosa, salta tutto il giochino in quanto si vanno a rompere funzioni che, di solito, non hanno assolutamente bachi. Una di queste è get_page_by_path(), storica e comodissima funzione WordPress.
Alterata malamente da WPML, non funziona più quando il tipo di pagina richiesta non è stata “fagocitata” da WPML stesso.

Le pagine, compresi i Custom Post Type (CPT), indicati come “da tradurre” nel backend di amministrazione di WPML, funzionano perfettamente con get_page_by_path(). Il difetto si riscontra solo con le pagine che non sono inserite – in pratica – nella tabella  icl_translations di WPML.

Per questa non c’è soluzione immediata, in quanto bisognerebbe modificare il core stesso di WPML, cosa che sconsiglio ovviamente. Tuttavia, essendo io utente registrato, ho segnalato la cosa nel forum dove è in atto una discussione per trovare la soluzione migliore (correggere l’errore nella select SQL secondo me). Confidiamo nel prossimo aggiornamento.

Comunque sia, se non potete attende la fix, c’è un artifizio abbastanza rapido ed indolore per superare ‘temporaneamente’ il problema e consiste – come accennato sopra – nell’impostare il tipo pagina incriminato come “da tradurre” nel backend di WPML. Aggiornate le impostazioni. Aggiornate la pagina. E rimettere – eventualmente – tutto com’era prima. Una volta che la pagina è “stivata” nella tabella di WPML, get_page_by_path() riprenderà a funzionare come sempre.

Attendiamo comunque patch…

Non ci sono commenti per questo Post

Lascia un commento

TAG XHTML PERMESSI: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> INSERIMENTO CODICE:
<pre></pre> // blocco generico
                   <code></code> // blocco generico
                   [cc_actionscript][/cc_actionscript] // Actionscript
                   [cc_actionscript3][/cc_actionscript3] // Actionscript 3
                   [cc_css][/cc_css] // CSS Style Sheet
                   [cc_html][/cc_html] // HTML
                   [cc_js][/cc_js] // Javascript
                   [cc_objc][/cc_objc] // Objective-C
                   [cc_php][/cc_objc] // PHP
                   [cc_sql][/cc_sql] // SQL