Utente: Anonymous

Il theme registry

Abbiamo visto come l'applicazione di un tema agli elementi del sito , venga eseguito da Drupal mediante funzioni come theme_breadcrumb($breadcrumb), theme_links($links, $attributes) o mediante file template come page.tpl.php, node.tpl.php, block.tpl.php. Per tenere traccia di queste e delle altre informazioni necessarie per applicare correttamente un tema agli elementi del sito, Drupal genera il cosiddetto theme registry. Fisicamente il tema registry è costituito da un'array associativa , indicata in seguito come $hooks, contenente tutti i nomi dei possibili hooks (breadcrumb,links,block,node,page) e, per ciascuno di essi, le corrette informazioni per gestire quella tipologia di elemento.L'array generato è salvato nel database. L'individuazione della funzione o del file template da utilizzare avviene passando sempre attraverso la funzione che è alla base della tematizzazione di Drupal: theme($hook,$args). Il parametro $hook indica a quale elemento applicare il tema. Ad esempio theme('breadcrumb',$args) per il breadcrumb, theme('links',$args) per i links del nodo, theme('node',$args) per un nodo, theme('page', $args) per la pagina finale.
Il valore $args indica qui semplicemente il passaggio di uno o più argomenti alla funzione theme().
Infatti come si vede dal frammento di codice della funzione theme

<?php
 
function theme() {
 
$args = func_get_args();
 
$hook = array_shift($args);

  static

$hooks = NULL;
  if (!isset(
$hooks)) {
   
init_theme();
   
$hooks = theme_get_registry();
  } 
.....
 
$info = $hooks[$hook];
  .....

?>

i parametri non sono passati esplicitamente , ma sono letti mediante la funzione func_get_args().
In questo modo possono essere passati un numero di argomenti indefinito che la funzione theme() passerà alla funzione o al file template che effettivamente si occuperà di tematizzare l'elemento.
Il primo parametro è sempre il valore hook che viene estratto dall'array $args.
Dopo aver letto gli argomenti e individuato l'hook, Drupal carica l'array $hooks dal database. La lettura dell'array è eseguita la prima volta che viene chiamata la funzione theme() mediante la funzione theme_get_registry(). Successive chiamate di theme() troveranno l'array $hooks carico in quanto definito come variabile 'static'.

Da dove è letto il theme registry?
Il theme registry è generato ogni volta che si entra nella pagina contenente la lista dei moduli. Dopo averlo generato Drupal salva l'array nel database e precisamente nella tabella CACHE.
In questa tabella, ogni tema ha un suo theme registry salvato nel campo DATA , e individuato dal record con il campo CID uguale a "theme_registry:NomeTema", dove NomeTema è ovviamente il nome del tema. Volendo quindi forzare la rigenerazione del theme registry basterà semplicemente cancellare il record associato al tema.

L'array $hooks
L'array $hooks è un array associativo nella forma $hooks['hook'][propietàX] = valore , dove valore può essere anche un array o un oggetto. Poco più avanti nel frammento di codice, Drupal per comodità, carica in $info le sole informazioni relative all'hook corrente:$hooks[$hook].

Costruzione del theme registry

Come viene costruita l'array $hooks? Da dove Drupal prende le informazioni in essa contenute?
Vediamo in dettaglio la costruzione dell'array, supponendo di voler generare il theme registry per il tema Minnelli derivato dal tema Garland e gestito dal motore phptemplate.
Entrando in theme(), Drupal verifica l'esistenza della variabile statica $hooks e se non ancora impostata,
avvia l'inizializzazione del tema corrente tramite la init_theme().
Il tema corrente è definito o in $user->theme o , se nullo, con il tema di default letto con la funzione variable_get('theme_default', 'garland').
Tra le operazione attivate durante l'inizializzazione del tema, quella che a noi qui interessa è la creazione del theme registry. Per leggere gli hooks, Drupal usa la funzione _theme_load_registry() definita in theme.inc, che verifica l'esistenza del theme registry nella tabella CACHE e in caso affermativo riporta l'array contenuto nel campo DATA, altrimenti avvia la sua costruzione.
Nel secondo caso, Drupal dovrà quindi individuare tutti gli hooks e le loro proprietà definiti all'interno del sistema.
La costruzione del theme registry avviene in due fasi:
a) Individuazione di tutti gli hooks definiti nel sistema;
b) Modifica dei parametri degli hooks letti mediante ricerca di funzioni e/o file template personalizzate.

Ricerca degli hook definiti nel sistema

La funzione che avvia la costruzione del theme registry è la funzione _theme_build_registry($theme, $base_theme, $theme_engine) in cui i parametri indicano il nome del tema, il tema base di riferimento (nullo se il tema è già un tema base) , il nome del motore di gestione del tema, nel nostro caso phptemplate.
Gli hooks appartenenti al theme registry sono definiti all'interno dei moduli.
Ogni modulo che vuole esporre i propri hooks deve implementare la funzione nomemodulo_theme() che deve fornire un'array contenente nomi e proprietà degli hooks da esporre.
Ad esempio il modulo di gestione dei blocchi, implementa la funzione block_theme():

<?php
 
function block_theme() {
  return array(
   
'block_admin_display_form' => array(
     
'template' => 'block-admin-display-form',
     
'file' => 'block.admin.inc',
     
'arguments' => array('form' => NULL),
    ),
  );
}
?>

che espone il solo hook "block_admin_display_form" e indicando che deve essere gestito tramite file template. Dove starà il file template? Se non altrimenti definito Drupal si aspetta di trovarlo nel percorso del modulo. Altri esempi è possibile vederli in node_theme() nel modulo node.module, in comment_theme() nel modulo comment.module etc. Per individuare tutti gli hooks dei moduli Drupal esegue un ciclo su tutti i moduli attivi chiamando per ogni modulo la funzione: _theme_process_registry(&$cache, $name, $type, $theme, $path)
dove:

  • $cache è l'array degli hooks che si sta generando a cui accodare eventuali altri hooks
  • $name è il nome del modulo in cui cercare gli hooks
  • $type ='module' indica a Drupal che è in corso una ricerca in un modulo
  • $theme nonostante il nome fuorviante, in questo caso ripete il nome del modulo
  • $path indica la directory del modulo

La funzione _theme_process_registry legge l'array restituito dalla funzione nomemodulo_theme() e aggiunge al theme registry gli hook in essa definiti.
Di seguito indichiamo con $info[] l'array restituito dalla funzione nomemodulo_theme() per un singolo hook.
Per l'esempio precedente si avrebbe:
$info[template]= 'block-admin-display-form'
$info[file]= 'block.admin.inc
$info[arguments]=array('form' => NULL)
e con $hook[] le proprietà generate nel theme registry per l'hook letto, ad esempio per block_admin_display_form .
Ad ogni hooks Drupal assegna le seguenti proprietà:

$hook[type]
Valore sempre presente, definito da codice.
Indica dove l'hook è stato definito. Per i moduli è uguale a 'module'

$hook[theme path]
Indica il percorso del modulo. $hook[theme path]=$path (passato come argomento)

$hook[arguments]
Array.Indica il nome e il valore di default degli argomenti da fornire alla funzione o al file template.
E' il valore $info[arguments]

$hook[function]
Indica il nome della funzione di gestione dell'hook.
Se un modulo non definisce ne la proprietà "template" ne la proprietà "function" Drupal imposta
$hook[function]=theme_hook() come nome della funzione che dovrà gestire l'hook. Naturalmente la funzione theme_hook() deve essere implementata nel modulo.

$hook[file]
Se è impostata la proprietà $info[file] , significa che le funzioni di tematizzazione dell'hook sono definite nel file indicato, ad esempio nomemodulo.inc. La corrispondente proprietà dell'hook sarà:
$hook[file]=$path .'/'. $info['file'] con $path percorso del modulo.
E' possibile mettere le funzioni di gestione anche in file esterni alle directory del modulo , impostando la proprietà $info[path]. In questo caso il valore $hook[file] non viene impostato, ma è caricato immediatamente il file
$info['path'] .'/'. $info['file'] per individuare nelle successive fasi eventuali funzioni di tematizzazione.

$hook[template]
Solo se non definita la proprietà $info[function]
Indica il nome e percorso del file template.
Per default il file template viene definito nel percorso del modulo:
$hook[template] = $path ."\" . $info[template];

$hook[theme paths]
Array.Indica un array di directory in cui cercare eventuali implementazioni per il tema.
Per i moduli è aggiunto o la directory del modulo o la proprietà $info[path] se definita.

$hook[preprocess functions]
Array.Indica un array di funzioni di preprocessing da usare in caso di gestione con file template.
Se è definita l'array $info[preprocess functions] allora sarà $hook[preprocess functions]=$info[preprocess] altrimenti Drupal genera l'array $info[preprocess] avviando la ricerca in tutti i moduli delle seguenti funzioni:

  • nomenodulo_preprocess
  • nomenodulo_preprocess_hook

e aggiungendo sempre la funzione template_preprocess definita in theme.inc e, se esistente, la funzione template_preprocess_hook
Al termine della ricerca sarà: $hook[preprocess functions]=$info[preprocess].
Terminato di impostare le proprietà di tutti gli hooks appartenenti al modulo, la funzione _theme_preprocess_registry aggiiungerà gli hooks inidividuati nel modulo corrente all'array generale degli hooks $cache.

Ricerca di funzioni e template personalizzati

Nella fase precedente, Drupal ha individuato tutti gli hook definiti nei moduli tramite le funzioni nomemodulo_theme(). Chi sviluppa un modulo deve fornire anche le funzioni o i file template associati agli hooks esposti in nomemodulo_theme(). Drupal consente però di eseguire un "override" delle funzioni e file template fornite mediante la ricerca di funzioni e template alternativi.
Per ogni hook definito Drupal cerca l'esistenza delle seguenti funzioni in ordine di priorità

- nometema_hook()
- nometemabase_hook()
- engine_hook()

e quindi continuando a suppore minnelli come tema corrente, garland come tema base e phptemplate come motore per i temi , Drupal cercherà le seguenti funzioni:

- minnelli_hook()
- garland_hook()
- phptemplate_hook()

Per i file template chercherà i seguenti file:

- hook.tpl.php nella directory del tema corrente (minnelli)
- hook.tpl.php nella directory del tema base (garland)

Per ogni funzione trovata Drupal imposta:
$hook['function]=<nuovo_nome_funzione>

Per ogni template trovato Drupal imposta:
$hook['template]=<file template>
$hook['path]=<directory del tema>

Infine Drupal modifica anche le seguenti proprietà:

$hook[type]
Il valore è posto uguale a 'base_theme_engine' se la ricerca avviene all'interno della directory
del tema base. E' posto uguale a 'theme_engine' se la ricerca avviene all'interno della directory
del tema corrente.

$hook[theme path]
Indica il percorso del tema.

$hook[theme paths]
Oltre ai paths già individuati, aggiunge il path del tema:
$hook[theme paths][]=$path

$hook[preprocess functions]
Drupal aggiorna la proprietà cercando le seguenti funzioni di preprocessing:

- phptemplate_engine_preprocess
- phptemplate_engine_preprocess_hook
- phptemplate_preprocess
- phptemplate_preprocess_hook
- nometemabase_preprocess
- nometemabase_preprocess_hook
- nometema_preprocess
- nometema_preprocess_hook

Ulteriore modifica mediante drupal_alter()

L'ultima possibilità di modificare il theme registry è data da Drupal mediante la funzione drupal_alter('theme_registry', $cache).
Questa funzione ricerca e chiama tutte le funzioni nomemodulo_themaregistry_alter($hooks) che possono quindi modificare ulteriormente le informazioni fornite precedentemente. Ad esempio un modulo che implementa funzioni tipo theme_hook() potrebbe utilizzare funzioni differenti in base al contesto in cui si trova.

Le funzioni usate

Riepiloghiamo di seguito le principali funzioni utillizzate per la generazione del theme registry.

_theme_build_registry($theme, $base_theme, $theme_engine)
dove:
$theme è il nome del tema
$base_theme è il tema base di riferimento (nullo se il tema è già un tema base)
$theme_engine è il nome del motore di gestione del tema, nel nostro caso phptemplate.
Contenuta in includes/theme.inc
Questa funzione avvia il processo di costruzione del theme registry.

_theme_process_registry(&$cache, $name, $type, $theme, $path)
dove:
$cache è l'array degli hooks che si sta generando a cui accodare eventuali altri hooks
$name è il nome del modulo o del tema in cui cercare gli hooks
$type = indica il tipo di ricerca che si sta eseguendo. Assume i valori: module, base_theme_engine, base_theme, theme_engine, theme.
$theme nome del modulo o del tema
$path indica la directory del modulo
Definita in includes/theme.inc
E' chiamata cinque volte all'interno della funzione _theme_build_registry(), una per ogni tipologia di ricerca.

1) $type= module
$name e $theme corrispondono al nome del modulo
Ricerca delle definizioni degli hooks nei moduli.
Per eseguire la ricerca chiama le funzioni nomemodulo_theme()

2) $type= base_theme_engine
$name=motore del tema , nel nostro caso: phptemplate
$theme=nome del tema base su cui eseguire la ricerca (garland ad esempio)
$path=percorso del tema
Ricerca le funzioni personalizzate con nome phptemplate_hook() e nometemabase_hook()
Ricerca i template personalizzati nella directory del tema base (garland)
Per eseguire la ricerca chiama la funzione phptemplate_theme() definita in themes/engines/phptemplate

3) $type= base_theme
$name e $theme corrispondono al nome del tema base
$path=percorso del tema base
Per eseguire la ricerca chiama, se esiste, la funzione nometemabase_theme().
Questa funzione non è implementata in Drupal..

4) $type=theme_engine
$name=motore del tema , nel nostro caso: phptemplate
$theme=mode le tema su cui eseguire la ricerca (minnelli ad esempio)
$path=percorso del tema
Ricerca le funzioni personalizzate con nome phptemplate_hook() e nometema_hook()
Ricerca i template personalizzati nella directory del tema (minnelli)
Per eseguire la ricerca chiama la funzione phptemplate_theme() definita in themes/engines/phptemplate

5) $type=theme
$name e $theme corrispondono al nome del tema base
$path=percorso del tema
Per eseguire la ricerca chiama, se esiste, la funzione nometema_theme().
Questa funzione non è implementata in Drupal.

phptemplate_theme($existing, $type, $theme, $path)
dove:
$existing è l'array degli hooks definiti nel sistema
$type uguale a 'base_theme_engine' (ricerca per tema base ) o 'theme_engine' (ricerca per tema derivato)'
$theme è il nome del tema per cui cercare funzioni o template personalizzati
$path è il percorso del tema
Definita in themes/engines/phptemplate/pgptemplate.engine
Praticamente è la funzione che ricerca tutte le funzioni e i file template personalizzati, consentendo allo sviluppatore di eseguire l'override delle funzioni e template di default..