OOP in pratica con WordPress: autoloading

OOP in pratica con WordPress: autoloading

Nell' articolo precedente abbiamo discusso dell'importanza dell'OOP nel contesto di WordPress e delle convenzioni con cui scrivere il nostro codice adeguandoci alle best practices ed agli standard correnti. In questo articolo vedremo come includere le nostre classi nel flusso di WordPress.

Inclusione manuale

L'inclusione manuale delle classi in WordPress avviene in due modi diversi, a seconda del fatto se stiamo sviluppando un tema o un plugin.

In un tema le classi vanno richiamate nel file functions.php´ tramite la funzione di PHP `require_once(). In questa funzione andrebbe sempre usata la costante `TEMPLATEPATH´ di WordPress che conserva il percorso fisico sul server alla directory del tema in uso.

require_once( TEMPLATEPATH . '/framework/MyClass.php' );

Le classi possono essere sia istanziate nel file di origine che nel file `functions.php´, ovviamente secondo le necessità del design del vostro codice.

In un plugin invece l'inclusione avviene sempre nel file principale del plugin. Il metodo di inclusione è analogo a quello usato per i temi, ad eccezione del fatto che si utilizza la funzione di WordPress plugin_dir_path() con la costante "magica" di PHP __FILE__ per ottenere il percorso assoluto alla directory del plugin.

$dir = plugin_dir_path( __FILE__ );
require_once( $dir . '/framework/MyClass.php' );

Ovviamente in entrambi i casi potete anche creare un file apposito per l'inclusione manuale delle classi e quindi richiamarlo all'interno del vostro tema o plugin.

Inclusione automatica

Chi conosce il pattern MVC sa bene che in PHP è possibile eseguire l'autoloading delle classi, ossia il loro caricamento automatico.

Il caricamento automatico ha l'indubbio vantaggio di evitarci la fatica di includere manualmente nel codice una nuova classe - ed un nuovo file - specificandone nome e percorso.

PHP ha solo bisogno di un percorso iniziale da dove partire per cercare i file da includere. Tutto il resto avviene in modo automatico.

Possiamo creare un file di bootstrap (secondo la terminologia MVC) da includere nel tema o nel plugin utilizzando la funzione di PHP spl_autoload_register() (disponibile in tutte le versioni aggiornate di PHP) a cui passeremo una nostra funzione che eseguirà l'autoload a partire da un set di directory:

spl_autoload_register( 'my_autoload' );

function my_autoload( $class ) {

  if( class_exist( $class, false ) ) {

    return;
  }

  $base_path = TEMPLATEPATH; // per i temi

  $lookup_dirs = array( $base_path . '/framework/', $base_path . '/addons/' );

  foreach( $lookup_dirs as $dir ) {

     if( file_exists( $dir . $class . '.php' ) ) {

       require_once( $dir . $class . '.php' );

       break;
    }
  }
}

Quindi possiamo semplicemente includere il file di bootstrap nel file functions.php per i temi o nel file principale del nostro plugin. Ovviamente la variabile $base_path va modificata se si sta sviluppando un plugin come abbiamo visto nella sezione precedente.

Il problema della injection di classi nell'autoloading

Il maggiore problema insito nella soluzione di cui sopra è che l'inclusione delle classi avviene senza aver prima verificato che la classe corrente sia una classe legittima.

Tecnicamente parlando l'autoloading delle classi in PHP usa gli stessi principi alla base dell'inclusione di file esterni nel codice principale e come tale è soggetto alle stesse regole.

Una soluzione a questa situazione è verificare che il nome della classe passato sia valido. Possiamo per questo creare la seguente espressione regolare:

	
\\\\?(?>[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*\\
\\)*[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*
\\\\?(?>[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*\\
\\?)+

Quindi possiamo usare questa espressione regolare con la funzione PHP preg_match() all'interno della funzione di autoload:


$pattern = '(^\\\\?(?>[a-zA-Z_\x7f-\xff][a-zA- Z0-9_\x7f-\xff]*\\\\?)+$)';
$valid = (bool) preg_match($pattern, $class);

Di seguito alcuni riferimenti correlati per lo studio di questo argomento che abbiamo appena accennato.

L'ultima risorsa elencata fa riferimento alla funzione di PHP unserialize() e al fatto che l'input passato a tale funzione dovrebbe essere sempre validato prima di poter essere usato nel contesto delle classi.

Di particolare utilità l'ultimo link (PDF) contenuto nell'ultima risorsa, Shocking news in PHP exploitation.

Conclusioni

L'inclusione delle classi nei temi o nei plugin è un aspetto da non sottovalutare nello sviluppo OOP in WordPress perché solo conoscendo questa caratteristica possiamo evitare problemi futuri.

Torna su