Nella prima parte di questo capitolo vedremo come implementare un framework di base per operare sui plugin di WordPress partendo dai concetti fondamentali esposti nel corso della guida. Il nostro framework includerà delle classi base che verranno estese dalle classi che le utilizzeranno. Le classi base avranno sostanzialmente il compito di automatizzare il più possibile dei task che in WordPress richiedono sempre le medesime routine.
Implementazione della componente AJAX
In WordPress AJAX viene implementato tramite una procedura che prevede i seguenti passaggi:
- Viene registrata una action tramite i prefissi
wp_ajax
(per gli utenti loggati) ewp_ajax_nopriv
(per tutti i visitatori). - Viene associata alla action una funzione o un metodo di una classe; nel secondo caso la parola chiave
$this
farà riferimento alla classe che definisce il metodo.
WordPress imposta il Content Type della risposta su text/html
, quindi sarà necessario modificare questa impostazione prima che venga restituito l'output al client.
class My_Ajax_Wrapper {
protected $_actions = array();
protected $_types;
public function __construct( $contentTypes ) {
$this->_types = $contentTypes; // es. application/json, text/xml ecc.
}
public function addAction( $name, $visibility, $method ) {
$this->_actions[] = array(
'name' => $name, // Nome action
'visibility' => $visibility, // all, public, private
'method' => $method // Metodo della classe discendente
);
}
// $reference è l'istanza della classe discendente
public function registerActions( $reference ) {
$actions = $this->_actions;
if( count( $actions ) == 0 ) {
return;
}
foreach( $actions as $action ) {
$visibility = $action['visibility'];
if( $visibility == 'all' ) {
add_action( 'wp_ajax_' . $action['name'], array( $reference, $action['method'] ) );
add_action( 'wp_ajax_nopriv_' . $action['name'], array( $reference, $action['method'] ) );
} else if( $visibility == 'public' ) {
add_action( 'wp_ajax_nopriv_' . $action['name'], array( $reference, $action['method'] ) );
} else {
add_action( 'wp_ajax_' . $action['name'], array( $reference, $action['method'] ) );
}
}
}
public function setContentType( $type = 'application/json' ) {
$allowed = $this->_types;
if( !in_array( $type, $allowed ) ) {
return;
}
header( 'Content-Type: ' . $type );
}
}
Di seguito verrà proposto un semplice esempio d'utilizzo pratico della classe wrapper precedentemente definita:
require_once( 'My_Ajax_Wrapper.php' );
class My_Ajax {
protected $_ajax;
public function __construct() {
$this->_ajax = new My_Ajax_Wrapper( array( 'application/json', 'text/xml' ) );
$this->actions();
$this->_ajax->registerActions( $this );
}
public function actions() {
$this->_ajax->addAction( 'test', 'all', 'foo' );
$this->_ajax->addAction( 'bar', 'all', 'bar' );
}
public function foo() {
$this->_ajax->setContentType( 'text/xml' );
echo '<foo>ok</foo>';
exit();
}
public function bar() {
$this->_ajax->setContentType( 'application/json' );
echo json_encode( array( 'ok' => 'bar' ) );
exit();
}
}
$myA = new My_Ajax();
Come è possibile notare l'action test
restituisce il suo output in formato XML, mentre la seconda action lo restituisce in JSON. $this
nel metodo registerActions()
punta alla classe corrente, ossia My_Ajax
.
In conclusione è possibile affermare che un framework ha sempre il compito di semplificare ed automatizzare il più possibile i compiti necessari al funzionamento di un plugin secondo il principio DRY, ossia Don't Repeat Yourself. Analizzando il codice creato in precedenza è possibile osservare come esso possa essere impiegato con successo anche nei temi. In un approccio del genere, il segreto è in pratica cercare di puntare al massimo livello di astrazione possibile.