Gli articoli di WordPress di consueto vengono mostrati per data di pubblicazione, possiamo decidere se in modo crescente o decrescente, ma cosa succede se per esempio dobbiamo sviluppare un sito di eventi o viaggi organizzati, e ci viene chiesto di ordinare gli articoli sempre per date, ma non di pubblicazione ma di effettiva partenza dell’evento?

Prendiamo come esempio un ipotetico sito che si occupa di cinema e delle prossime uscite dei film. E’ necessario per un sito del genere che i film siano tutti ordinati per data di uscita dei singoli film.

Si potrebbe giocare con la data di pubblicazione per poter ordinare i post in maniera giusta, ma sarebbe comunque un prova e riprova infinito. Non sarebbe quindi meglio che i post si ordinassero da soli?

Per poter arrivare a questo risultato dobbiamo innanzitutto creare dei custom post meta, ovvero dei campi aggiuntivi ai normali post dove andremmo a salvare la data di uscita del film. Successivamente creiamo un template di pagina con una custom query che andrà ad ordinare i nostri post come meglio ci aggrada.

I requisiti per questo tutorial sono la conoscenza base della creazione/modifica di un tema WP, e di conseguenza l’utilizzo di hook e filters. Do per scontato che si conoscano almeno i fondamenti di PHP, HTML, CSS e Javascript, sopratutto le librerie jQuery.

N.B: Sarebbe meglio che tutte le stringhe che creano un output visibile (come il testo di bottoni, titoli ecc) del vostro tema siano traducibili, utilizzando quindi le funzioni _e( $string, $domain ) (per fare l’output diretto, al posto di echo;) oppure __( $string, $domain ) (per l’output indiretto, al posto di return;, usato sopratutto in parametri di altre funzioni). In questo modo una volta terminato le modifiche/creazione del tema si possono tradurre le stringhe tramite PoEdit. Per ulteriori informazioni consultare la guida ufficiale

Custom Post Meta

Meta Box

Per inserire dei campi aggiuntivi ai nostri post, prima di tutto dobbiamo inserire un nuovo Meta Box all’interno della pagina di modifica/creazione dei post (sono i riquadri bianchi che contengono i campi con le informazioni degli articoli). Apriamo quindi functions.php

function my_custom_meta_box() {

add_meta_box( ‘my_meta_box_id’,

__( ‘My custom meta box’, ‘theme-domain’ ),

‘my_custom_meta_box_cb’,

‘post’,

‘side’,

‘high’

);

}

add_action( ‘add_meta_boxes’, ‘my_custom_meta_box’ );

inseriamo una nuova funziona my_custom_meta_box(), e andiamo ad “hookarla” ad ‘add_meta_boxes’, con add_action( 'add_meta_boxes', 'my_custom_meta_box');. Ora dentro la funzione andremmo a chiamare add_meta_box() che accetta i seguenti parametri:

$id (stringa) (obbligatorio): id univoco per questo meta box

$title (stringa) (obbligatorio): una stringa che porta il titolo della meta box. (come specificato nell’introduzione per questo tipo di stringa sarebbe meglio usare la funzione per l’output traducibile)

$callback (stringa) (obbligatorio): stringa con il nome della funzione callback che andrà a gestire il contenuto della meta box.

$screen (stringa, array): stringa con la tipologia di post nella quale mostrare la meta box

$context (stringa): posizione della meta box

$priority (stringa): la priorità di visualizzazione del meta box

$callback_args (array): array con valori da passare alla funzione di callback in caso di necessità

Come potete vedere nell’esempio utilizziamo tutti i campi a parte gli argomenti da inviare alla callback in quanto non ci serve. Vediamo cosa abbiamo passato alla funzione add_meta_box(). Abbiamo il nostro ID che è ‘my_custom_meta_box’, il titolo della meta box per il quale usiamo la funzione per le traduzioni __( ‘My custom meta box’, ‘theme-domain’), e il nome della funzione che andrà a gestire l’output del meta box ‘my_custom_meta_box_cb’. Questi argomenti sono obbligatori, se non ne inserite uno la funzione restituirà errore. Ora quelle facoltative, per screen abbiamo ‘post’ perche ci interessa che solamente nella pagina di modifica degli articoli esca la meta box, nel context abbiamo ‘side’ questo valore indica che vogliamo che la nostra metà box sia nella parte laterale della pagina (dove per esempio ce la gestione della data del post), come priority abbiamo ‘high’ cercando di tenere la meta box il piu alto possibile (questo potrebbe variare se avete altri plugin attivi che inseriscono dei meta box all’interno della pagina, come per esempio Woocommerce).

Meta Field

Ora all’interno del box dobbiamo creare i nostri campi personalizzati. Ma dobbiamo stare attenti perché il valore della data che dovremmo inserire deve essere in formato americano, MM-DD-YYYY. Per evitare che chi utilizza il sito vada a inserire erroneamente DD-MM-YY, oppure MM/DD/YYYY inseriremo un campo con jQuery e il plugin Datepicker, cosi da dover semplicemente selezionare una data, e poi ci pensa jQuery a formattare la data nel modo giusto.

Iniziamo quindi prima con l’inserire i campi nel meta box

function my_custom_meta_box_cb( $post ) {

// campo nonce per sicurezza

wp_nonce_field( ‘my_custom_meta_box_save’, ‘my_custom_meta_box_nonce’ );

// prendiamo il valore del campo dal DB

$realease_date = get_post_meta( $post->ID, ‘realease_date’, true );

// output html

?>

<p>

<label for=”realease_date”><?php _e( ‘Release Date’, ‘theme-domain’ ); ?>:</label>

<input type=”text” name=”realease_date” id=”realease_date” value=”<?php echo ( !empty( $realease_date ) ) ? esc_attr( date( ‘m/d/y’, $realease_date ) ) : ” ; ?>”>

</p>

<?php

}

qui dichiariamo la funzione di callback che abbiamo inserito in add_meta_box(), questa parte è abbastanza semplice, perche basta che chiudiamo i tag PHP e inseriamo l’HTML per i campi di input.

L’unica funzione particolare che utilizziamo qui è wp_nonce_field(), che è una funzione di sicurezza, in quanto ci successivamente ci garantisce che il form sia stato inviato dalla pagina giusta. Seguendo le linee guida di WP, su ogni form che creiamo ne dovremmo inserire 1 di nonce field. La funzione accetta 2 parametri, il prima chiamato $action non è altro che un’id, e deve essere univoco. Poi abbiamo $name che è il nome che assegniamo al campo. Nessuno dei due campi sono obbligatori, ma fortemente consigliati.

La funzione subito successiva è get_post_meta() che è la funzione che ci permette di prendere i valori inseriti nel DB.

Tutto il resto è puro HTML, quindi di facile comprensione. Vi invito solamente a porre attenzione al campo <input name=”realease_date”>, in quanto il nome utilizzato qui è lo stesso che poi ci servirà per ritrovare il valore inserito dall’utente quando andremo a salvare il meta field.

.

jQuery UI Datepicker

Inseriamo jQuery Ui Datepicker all’interno del tema, in piu un nostro file JavaScript che chiameremo datepicker-initializer.js e che salviamo nella directory principale del tema. Questo file servirà piu tardi per avviare il Datepicker.

function my_custom_meta_box_enqueue_scripts() {

$screen = get_current_screen();

if ( in_array( $screen->base, array( ‘post’ ) ) ) {

wp_enqueue_script(‘my-custom-js’, get_stylesheet_directory_uri().’/datepicker-initializer.js’, array( ‘jquery’ ), ‘1’, true);

wp_enqueue_script( ‘jquery-ui-datepicker’ );

}

}

add_action( ‘admin_enqueue_scripts’, ‘my_custom_meta_box_enqueue_scripts’ );

Non è mai una buona cosa inserire nel header dei temi i link ai script hardcoded, è sempre il caso di usare le funzione che ci mette a disposizione wordpress. per gli stili (CSS) usiamo wp_enqueue_style(), mentre per gli script Javascript utilizziamo wp_enqueue_script(). Utilizziamo le stesse funzioni anche per il backend, con la differenza che la nostra funzione va hookata a admin_enqueue_scripts(); cosi che i file vengano inseriti solamente nel backend. Inoltre come potete vedere abbiamo una variabile $screen che chiama la funzione get_current_screen();, cio ci serve per verificare che siamo solamente sulla pagina di modificar/inserimento del post, senza dover caricare JS inutile in altre parti di WP,

Ora nel file datepicker-initializer.js

jQuery(document).ready(function($) {

$(‘#realease_date’).datepicker({});

});

E questo è tutto quello che serve in questo file JS. Ci sono altri modi per poter modificare il vostro Datepicker con parametri aggiuntivi, per questo vi invito a visitare la guida ufficiale

Ora il meta box dovrebbe essere perfettamente funzionante… o quasi.

Salvare i meta-dati

Se avete provato a salvare/aggiornare il vostro post vi sarete accorti che i campi non si salvano!

Per questo dobbiamo dare istruzioni a wordpress, prima di sanificare e successivamente di salvare i dati in DB. E’ sempre buona cosa sanificare gli input degli utenti prima di salvarli nel DB, questo per evitare attacchi di hacking del nostro sito. Anche se bisogna menzionare che grazie al Datepicker siamo quasi certi di cosa aspettarci, pero è comunque buona cosa sanificare gli input prima.

function my_custom_meta_box_save( $post_id ) {

// Facciamo alcune verifiche prima di inserire il contenuto nel DB

// Verifichiamo innanzitutto che il nonce sia stato inviato

if( ! isset( $_POST[‘my_custom_meta_box_nonce’] ) ) {

return;

}

// Ora verifichiamo la effettiva validità del campo nonce

if( ! wp_verify_nonce( $_POST[‘my_custom_meta_box_nonce’], ‘my_custom_meta_box_save’ ) ) {

return;

}

// Verifichiamo che non stiamo faccendo autosave, se è cosi, usciamo

if( defined( ‘DOING_AUTOSAVE’ ) && DOING_AUTOSAVE ) {

return;

}

// Ultima verifica, verificare che l’utente a tutti gli effetti ha i permessi di potre modificare questo post

if ( ! current_user_can( ‘edit_post’, $post_id ) ) {

return;

}

// ora recuperare il campo dei metadati, e lo sanifichiamo allo stesso momento

$realease_date = esc_html( $_POST[‘realease_date’] );

//ora verifichiamo che effettivamente la nostra variabile non sia vuota

if( ! empty ( $realease_date) ) {

// ora MOLTO IMPORTANTE, perche il tutto funzioni dobbiamo prima convertire la nostra data, in una stringa di tempo standard UNIX

$realease_timestamp = strtotime( $realease_date );

// ora andiamo ad aggiornare il campo nel DB

update_post_meta( $post_id, ‘realease_date’, $realease_timestamp );

}

}

// hookiamo la nostra funzione al save del post

add_action( ‘save_post’, ‘my_custom_meta_box_save’ );

Ora analizziamo l’ultimo pezzo di codice, per prima cosa voglio attirare la vostra attenzione sull’ultima linea add_action( ‘save_post’, ‘your_function’ );. Questa chiamata è assolutamente obbligatoria in quanto altrimenti non verrebbe chiamato la funzione di salvataggio, e quindi tutto il lavoro fatto fin’ora risulta inutile. Sono onesto, quando lavoro con i meta box, mi dimentico di questa chiamata 95% delle volte.

Per tornare indietro vediamo brevemente cosa fa la funzione (in realtà molto basica), prima verifichiamo se è stato settato il campo nonce, poi verifichiamo che questo sia valido, successivamente verifichiamo che non siamo in autosave e per ultimo verifichiamo che l’utente ha a tutti gli effetti permessi di scrittura per questo post. Possono sembrare troppe verifiche, ma queste garantiscono che non creiamo buchi di sicurezza all’interno di WordPress.

Come ultima cosa recuperiamo il valore inserito nel form precedentemente, e lo sanifichiamo, verifichiamo che non sia vuoto, e MOLTO IMPORTANTE lo convertiamo da semplice data in una UNIX STANDARD TIMESTAMP. Questo passaggio è obbligatorio, in quanto la custom wp_query(); che andremo ad utilizzare per ordinare i post utilizza proprio questi TIMESTAMP. Potete trovare ulteriori informazioni su cosa sono nella guida ufficiale PHP. Ora per ultima cosa usiamo update_post_meta(), questa funzione verifica se nel DB esiste un campo meta con la chiave da noi fornita, se la trova verifica se il valore è uguale o cambiato ed aggiorna il valore solamente se è cambiato. Se non esiste la chiave, la aggiunge. update_post_meta(), accetta 3 parametri $post_id, che è l’id del post a cui inserire/modificare il campo meta, $key che è la chiave sotto la quale viene salvato il valore e $value che è il valore da salvare.

E con questo abbiamo terminato la parte backend del nostro piccolo tutorial. Se ora proverete a salvare/modificare un post inserendo un valore nel meta campo, questo verrà salvato.

Prima di procedere il file functions.php al completo come dovreste averlo:

function my_custom_meta_box() {

add_meta_box( ‘my_meta_box_id’,

__( ‘My custom meta box’, ‘theme-domain’ ),

‘my_custom_meta_box_cb’,

‘post’,

‘side’,

‘high’

);

}

add_action( ‘add_meta_boxes’, ‘my_custom_meta_box’ );

 

 

function my_custom_meta_box_cb( $post ) {

// campo nonce per sicurezza

wp_nonce_field( ‘my_custom_meta_box_save’, ‘my_custom_meta_box_nonce’ );

// prendiamo il valore del campo dal DB

$realease_date = get_post_meta( $post->ID, ‘realease_date’, true );

// output html

?>

<p>

<label for=”realease_date”><?php _e( ‘Release Date’, ‘theme-domain’ ); ?>:</label>

<input type=”text” name=”realease_date” id=”realease_date” value=”<?php echo ( !empty( $realease_date ) ) ? esc_attr( date( ‘m/d/y’, $realease_date ) ) : ” ; ?>”>

</p>

<?php

}

 

 

function my_custom_meta_box_enqueue_scripts() {

$screen = get_current_screen();

if ( in_array( $screen->base, array( ‘post’ ) ) ) {

wp_enqueue_script(‘my-custom-js’, get_stylesheet_directory_uri().’/datepicker-initializer.js’, array( ‘jquery’ ), ‘1’, true);

wp_enqueue_script( ‘jquery-ui-datepicker’ );

}

}

add_action( ‘admin_enqueue_scripts’, ‘my_custom_meta_box_enqueue_scripts’ );

 

 

function my_custom_meta_box_save( $post_id ) {

// Facciamo alcune verifiche prima di inserire il contenuto nel DB

// Verifichiamo innanzitutto che il nonce sia stato inviato

if( ! isset( $_POST[‘my_custom_meta_box_nonce’] ) ) {

return;

}

// Ora verifichiamo la effettiva validità del campo nonce

if( ! wp_verify_nonce( $_POST[‘my_custom_meta_box_nonce’], ‘my_custom_meta_box_save’ ) ) {

return;

}

// Verifichiamo che non stiamo faccendo autosave, se è cosi, usciamo

if( defined( ‘DOING_AUTOSAVE’ ) && DOING_AUTOSAVE ) {

return;

}

// Ultima verifica, verificare che l’utente a tutti gli effetti ha i permessi di potre modificare questo post

if ( ! current_user_can( ‘edit_post’, $post_id ) ) {

return;

}

// ora recuperare il campo dei metadati, e lo sanifichiamo allo stesso momento

$realease_date = esc_html( $_POST[‘realease_date’] );

//ora verifichiamo che effettivamente la nostra variabile non sia vuota

if( ! empty ( $realease_date) ) {

// ora MOLTO IMPORTANTE, perche il tutto funzioni dobbiamo prima convertire la nostra data, in una stringa di tempo standard UNIX

$realease_timestamp = strtotime( $realease_date );

// ora andiamo ad aggiornare il campo nel DB

update_post_meta( $post_id, ‘realease_date’, $realease_timestamp );

}

}

// hookiamo la nostra funzione al save del post

add_action( ‘save_post’, ‘my_custom_meta_box_save’ );

Custom Query

Ora questa è la parte facile, prima di tutto creiamo un nuovo file template-date-ordering.php, per prima cosa apriamo un tag php <?php e inseriamo il seguente commento:

<?php

/**

* Template Name: Date Ordering

**/

?>

Se creerete una nuova pagina, sulla vostra destra potrete scegliere un Template Pagina, qui ora vedrete Date Ordering. I template di pagina sono un’arma molto potente in WordPress in quanto ci permettono di creare delle pagine particolare, diverse da quelle standard previste dal tema.

Per convenienza conviene copiare e incollare, sotto al nostro commento, il contenuto di index.php (che di consueto contiene la lista dei post di base di ogni tema).

Dovreste trovare una riga con la seguente dicitura:

if( have_posts() ) :

while( have_posts() ) : the_post();

Che è il ciclo standard di WordPress per la visualizzazione degli articoli. Ora noi lo andremo a modificare, posizioniamoci sopra alla riga con if() e inseriamo la seguente custom query

$query = new WP_Query(array(

‘post_type’ => ‘post’,

‘meta_key’ => ‘realease_date’,

‘meta_type’ => ‘DATETIME’,

‘order’ => ‘DESC’,

‘orderby’ => ‘meta_value_num’,

‘posts_per_page’ => -1,

‘ignore_sticky_posts’ => 1

));

Ora dobbiamo sostituire nel ciclo have_posts() e the_post() con $query->have_posts() e $query->the_post(). In questo modo siamo sicuri che la pagina sta usando la nostra custom Query.

Ricordatevi che perchè funzioni dovrete entrare nei singoli post e assegnare il campo meta che abbiamo inserito. Fatto questo se andrete a vedere la pagina che avete creato con il template di pagina vedrete che tutti i post ora sono ordinati seguenti le date che sono state inserite nel custom meta field.

Non esistate a scrivermi nei commenti le vostre riflessioni/domande su questo tutorial.

Spero di esservi stato utile. Alla prossima! Saluti.

Marco Comerci