Con il codice descritto nel capitolo precedente, è già possibile creare eventi e visualizzarli nel frontend. Tuttavia questi ancora non si differenziano sostanzialmente dai comuni post.
Un evento dovrà distinguersi quanto meno per una data di inizio, una data conclusiva e una location. In mancanza di questi elementi non sarebbe necessario creare un tipo di post specifico per gli eventi.
L'utente può aggiungere manualmente i custom field necessari a trasformare un post in un evento, ma questa soluzione non da qualità al tema. Si dovrebbe dotare invece la pagina di creazione/modifica degli eventi di un metabox che contenga i custom field necessari.
Si apra il file functions.php
e si aggiunga il seguente codice:
function seventyone_add_meta_box(){
add_meta_box('seventyone_event_meta_box', __( 'Event details', 'seventyone' ), 'seventyone_build_meta_box', 'event', 'side' );
}
function seventyone_build_meta_box( $post ){
wp_nonce_field( 'seventyone_save_meta_box_data', 'seventyone_meta_box_nonce' );
$start_date = get_post_meta( $post->ID, '_seventyone_event_start_date', true );
$end_date = get_post_meta( $post->ID, '_seventyone_event_end_date', true );
$location = get_post_meta( $post->ID, '_seventyone_event_location', true );
?>
<div class="inside">
<p><strong>Start</strong></p>
<p><input type="date" id="seventyone_event_start_date" name="seventyone_event_start_date" value="<?php echo esc_attr( $start_date ); ?>" /></p>
<p><strong>End</strong></p>
<p><input type="date" id="seventyone_event_end_date" name="seventyone_event_end_date" value="<?php echo esc_attr( $end_date ); ?>" /></p>
<p><strong>Location</strong></p>
<p><input type="text" id="seventyone_event_location" name="seventyone_event_location" value="<?php echo esc_attr( $location ); ?>" /></p>
</div>
<?php
}
add_action( 'add_meta_boxes', 'seventyone_add_meta_box' );
Quando WordPress aggiunge i metabox alla pagina di modifica dei post (add_meta_box
) viene invocata la funzione di callback seventyone_add_meta_box
con argomento $post
.
La funzione recupera il Nonce Field del form per il salvataggio in sicurezza dei dati, subito dopo recupera i valori dei custom field già presenti in archivio. Per generare un custom field nascosto, si è premesso un underscore al suo nome. Una volta recuperati i dati vengono generati i campi form.
Nell'esempio sono stati utilizzati due input di tipo date
, che purtroppo al momento sono gestiti correttamente solo da Chrome e Opera. Gli altri browser degradano verso gli input text
e non generano incompatibilità.
Salvataggio dei dati
L'ultimo passaggio è il salvataggio dei dati. Sempre nel file functions.php
si aggiunga:
function seventyone_save_meta_box_data( $post_id ) {
if ( ! isset( $_POST['seventyone_meta_box_nonce'] ) )
return;
if ( ! wp_verify_nonce( $_POST['seventyone_meta_box_nonce'], 'seventyone_save_meta_box_data' ) )
return;
if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE )
return;
if ( isset( $_POST['post_type'] ) && 'event' == $_POST['post_type'] ) {
if ( ! current_user_can( 'edit_post', $post_id ) )
return;
}
if ( ! isset( $_POST['seventyone_event_start_date'] ) )
return;
if ( ! isset( $_POST['seventyone_event_end_date'] ) )
return;
if ( ! isset( $_POST['seventyone_event_location'] ) )
return;
$start_date = sanitize_text_field( $_POST['seventyone_event_start_date'] );
$end_date = sanitize_text_field( $_POST['seventyone_event_end_date'] );
$location = sanitize_text_field( $_POST['seventyone_event_location'] );
update_post_meta( $post_id, '_seventyone_event_start_date', $start_date );
update_post_meta( $post_id, '_seventyone_event_end_date', $end_date );
update_post_meta( $post_id, '_seventyone_event_location', $location );
}
add_action( 'save_post', 'seventyone_save_meta_box_data' );
Dopo la verifica del Nonce si controlla se si tratta di un salvataggio automatico (nel qual caso la funzione viene interrotta), se l'utente ha i privilegi necessari e se esistono i custom field start_date
, end_date
e location
. I valori vengono filtrati tramite sanitize_text_field
e archiviati nel database.
Formato dati e controllo dell'input
sanitize_text_field
filtra i dati prima che questi vengano memorizzati ma essa non permette di evitare errori di digitazione e formati di dati non compatibili.
È opportuno, soprattutto quando l'input utente deve rispettare uno specifico formato, prevedere dei controlli sul valore dei campi. Nell'esempio si è ricorso ad un campo date
, ma questo è ancora poco supportato. Un'alternativa potrebbero essere librerie come jQuery per generare un datepicker.
Lo stesso vale per la località geografica. In questo esempio si è inserito il nome della città, ma potrebbe essere utile una coppia di coordinate per la visualizzazione su mappa. A tal fine si potrebbe sviluppare un sistema di geolocalizzazione basato sulle API di Google o Yahoo!
Visualizzare i dati
Il template predefinito per la visualizzazione degli archivi è archive.php
, mentre quello che genera l'output dei singoli eventi è single.php
. La gerarchia prevede template più specifici sia per gli archivi di custom post type che per i file singoli. Ciò è utile per differenziare la struttura delle pagine degli eventi dalle pagine di post o tipi personalizzati. Basterà creare i file archive-event.php
e single-event.php
e apportare le modifiche necessarie.
Non è sempre necessario creare un template per ogni tipo di post. Nel caso in cui le modifiche non siano strutturalmente rilevanti si può filtrare il contenuto prima che questo venga inviato al client. Nel file functions.php
si aggiunga quindi il seguente codice:
function seventyone_customize_content( $content ) {
if ( !is_singular( 'event' ) )
return $content;
$start_date = get_post_meta( get_the_ID(), '_seventyone_event_start_date', true );
$end_date = get_post_meta( get_the_ID(), '_seventyone_event_end_date', true );
$location = get_post_meta( get_the_ID(), '_seventyone_event_location', true );
$list = "<ul>";
if ( !empty( $start_date ) )
$list .= "<li>" . __( 'From', 'seventyone' ) . ': ' . $start_date . "</li>";
if ( !empty( $end_date ) )
$list .= "<li>" . __( 'To', 'seventyone' ) . ': ' . $end_date . "</li>";
if ( !empty( $location ) )
$list .= "<li>" . __( 'Location', 'seventyone' ) . ': ' . $location . "</li>";
$list .= "</ul>";
return $content . $list;
}
add_filter( 'the_content', 'seventyone_customize_content' );
La lista generata sarà associata ad ogni evento pubblicato, ma solo nelle pagine singole.