Qui ad HCE andiamo pazzi per l’open source e quindi spesso ci troviamo ad utilizzare e personalizzare istanze di moodle, wordpress, symphony .. a volte cerchiamo anche di farli incrociare tra loro per produrre nuove razze di open source… ma in cattività sembrano poco inclini a riprodursi…
Recentemente ho dovuto modificare una installazione di WordPress per risolvere il seguente problema:
Il sito in questione deve pubblicare un calendario di eventi futuri. La questione era stata risolta settando la data di pubblicazione dell’articolo alla data dell’evento, usando quindi la funzione di schedule della pagina di pubblicazione:

Poi in una pagina separata del sito veniva fatta una query custom per estrarre solo gli articoli della categoria eventi con data nel futuro.
Il problema sorgeva però con l’RSS. Il sito infatti utilizzava dei meccanismi di propagazione per pubblicare i proprio post e specialmente gli eventi su diversi canali, tra cui facebook utilizzando l’applicazione Rss Graffiti
Gli eventi pianificati, che avevano data nel futuro comparivano nell’rss solo nel momento stesso in cui raggiungevano la data di pubblicazione. Cosi’ il concerto pianificato per domenica sera alle otto veniva postato su facebook esattamente domenica sera alle 8, rendendo inutile la segnalazione.
L’ideale sarebbe stata che gli eventi venissero pubblicati un giorno prima della loro scadenza.
La prima soluzione che mi è venuta in mente è stata di non utilizzare la data di pubblicazione di wordpress come data dell’evento, e inserire invece la data dell’evento come meta data dell’articolo. Facendo cosi’ però la query di estrazione degli eventi in ordine discendente di data (dell’ evento) risultava molto più pesante, perchè i metadata sono salvati da WP in una tabella separata.
Vincendo quindi quel misto di attrazione e repulsione che mi dava l’idea di lanciare una query di poco più breve di una canzone di Guccini, e addirittura meno intelleggibile, ho finito per utilizzare i filtri di Word Press.
Per dirla in breve, il codice di WordPress è disseminato di hooks cioè di punti prestabiliti in cui si può innestare (poi vedremo come) delle chiamate di funzione arbitrarie.
L’idea è di permettere al programmatore di personalizzare il codice senza dover metter mano e soprattutto capire tutto il flusso sottostante.
Nella maggior parte dei casi si registra una funzione che viene chiamata quando il codice arriva al punto prestabilito. La nostra funzione riceve determinati parametri (documentati nel codex di wordpress ) con cui può fare quello che vuole, e poi può restituirli eventualmente modificati.
Personalmente non vado pazzo per questo tipo di sistema, avrei preferito poter estendere una classe.. c’e’ da dire però che in questo modo anche chi non è esperto nella programmazione ad oggetti può facilmente applicare modifiche al flusso.
Torniamo al nostro esempio.
La prima cosa che ho dovuto fare è stata di dire a WordPress di includere nell’RSS anche i post con data nel futuro.
Per fare questo ho aggiunto al file functions.php (nella cartella del tema in uso)
function feedFilter($query) {
if ($query->is_feed) {
$query->set(‘post_status’,'publish,future’);
}
return $query;
}
add_filter(‘pre_get_posts’,'feedFilter’);
L’hook pre_get_posts viene attraversato da WP al momento immediatamente precedente all’esecuzione di una query che carica tutti i post da visualizzare.
Se c’e’ una funzione registrata per quell’hook, la funzione viene chiamata e le viene passato il parametro $query che è un oggetto WordPress che si occupa di interrogare il database ed estrarre i record corrispondenti agli articoli.
Come si vede la funzione verifica se effettivamente stiamo estraendo i post per inserirli in un feed, e solo in quel caso modifica lo status dei post da estrarre. Mentre per i feed lo status di default è ‘publish’ noi allarghiamo la condizione in modo da includere anche i posts futuri.
In questo modo però l’rss conterrebbe sempre TUTTI gli articoli futuri, ma noi vogliamo che includa solo quelli in scadenza il giorno successivo.
Occorre allora aggiungere delle condizioni ulteriori alla query
function feedFilterSearch($search, $query) {
if ($query->is_feed) {
$limit = date(‘Ymd’, mktime(0,0,0,date(‘m’), date(‘d’)+1,date(‘Y’)));
$search .= ‘ AND (wp_posts.post_status = \’publish\’ OR
( wp_posts.post_status = \’future\’ and wp_posts.post_date_gmt <= \”.$limit.’\')
)’;
}
return $search;
}
add_filter(‘posts_search’,'feedFilterSearch’,1,2);
L’hook posts_search permette di modificare il ramo WHERE della query che viene costruita per estrarre i post.
Il primo argomento che viene passato in automatico ( $search ) contiene eventuali condizioni già inserite nella query, il secondo è sempre l’oggetto WP query.
Come si vede in questo caso la chiamata ad add_filter contiene piu’ parametri. Questo perchè di default wordpress invia alla funzione collegata all’hook solo un parametro. L’hook posts_search invece rende disponibili 2 parametri. Occorre quindi specificare nel momento del collegamento che la funzione si aspetta di riceverli entrambi. Lo facciamo utilizzando il quarto parametro di add_filter. (Il terzo parametro specifica una priorità di esecuzione, nel caso più funzioni vengano agganciate allo stesso hook)
A questo punto nella funzione collegata a questo secondo hook non resta che aggiungere una condizione (solo nel caso di estrazione per i feed ) che dica di selezionare tutti i post già pubblicati oppure quelli futuri ma solo se hanno data di pubblicazione inferiore o uguale a quella del giorno successivo.
Si noti che il campo post_date_gmt nella tabella dei posts contiene una data che tiene conto della timezone settata nel backend di WP.
A questo punto possiamo andarcene soddisfatti canticchiando un elogio ai programmatori di WordPress che ci hanno regalato uno strumento così bello e così flessibile da risparmiare alle nostre falangi lunghe notti di programmazione.
Sergio Marchesini
HCE Web Design