Avvio di Drupal

Quando un browser invia un URL a Drupal per richiedere una pagina , la prima azione che viene eseguita dal sistema è la lettura del codice php nel file index.php.
Nel file, riportato a fondo pagina, sono definite le quattro fasi distinte che Drupal esegue per portare a termine la visualizzazione della pagina richiesta.

Bootstrap

Il sistema chiama la funzione drupal_bootstrap() che inizializza tutte le variabili di sistema , carica i moduli attivi , si connette al database, converte l'url alias ed altro ancora, predisponendo l'ambiente alla lettura e codifica dei contenuti.

Lettura del contenuto primario (nodi)

Il sistema chiama la funzione menu_execute_active_handler() che legge e codifica il contenuto richiesto, tornando una stringa contenente il codice HTML da visualizzare. In questa fase Drupal individua, in base al path ricevuto, la page callback, che consente di estrarre il contenuto della pagina.
Ad esempio per un nodo generico la page callback è la node_page_view().

In pratica viene preparato tutto tranne le barre, l'intestazione, il piè di pagina.
Per un esempio di quello che Drupal genera in questa fase, aprire il file index.php
e aggiungere le due righe indicate sotto la funzione menu_execute_active_handler().

......
$return = menu_execute_active_handler();
print $return;
exit();
....

Richiamando ora la home page del sito si vedrà il solo contenuto della pagina senza barre laterali, intestazione e fondo pagina. Questo perchè $return contiene il codice HTML del contenuto ed è quello che viene stampato con l'istruzione print $return.
E' da notare che al risultato non sono applicati gli stili del tema corrente, poichè il tema, e quindi lo stile, non è ancora stato completamente applicato cosa che viene fatta successivamente chiamando la funzione theme('page',$return).

Lettura del contenuto secondario (blocchi, menu)

Il sistema chiama la funzione theme('page') che legge e codifica il contenuto secondario unendolo al primario. Il risultato ottenuto è inviato al browser mediante l'istruzione "print".
Anche qui è possibile isolare il risultato ottenuto sostituendo il parametro $return con una stringa vuota, come in esempio:

......
  $return=""; // annulla $return
  print theme('page', $return);
}
...

Richiamando ora la home page del sito si vedrà il solo contenuto secondario, intestazione, blocchi, menu ma senza il contenuto primario definito in $return.

Chiusura

Il sistema chiama la funzione drupal_page_footer(). Nelle fasi precedenti sono state avviate tutte le funzioni per preparare i contenuti. In questa fase Drupal chiama tutte le funzioni hook_exit() implementate nei moduli attivi, per avvisare che la pagina richiesta è stata inviata e che le operazioni da attivare sono terminate.
Queste funzioni possono essere utili per eseguire un debugging del sistema o aggiornare, in fase di chiusura, alcune tabelle associate ai moduli.

Contenuto del file index.php.

<?php
require_once './includes/bootstrap.inc';

drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);

/*
Con questa funzione viene generato
il solo contenuto dei nodi e, al ritorno, nella variabile $return
è presente il codice HTML del contenuto dei nodi.
*/

$return = menu_execute_active_handler();

// Menu status constants are integers; page content is a string.
if (is_int($return)) {
  switch (
$return) {
    case
MENU_NOT_FOUND:
     
drupal_not_found();
      break;
    case
MENU_ACCESS_DENIED:
     
drupal_access_denied();
      break;
    case
MENU_SITE_OFFLINE:
     
drupal_site_offline();
      break;
  }
}
elseif (isset(
$return)) {
 
// Print any value (including an empty string) except NULL or undefined:
/*
Con questa funzione viene generato il  contenuto dei blocchi ,
assemblato insieme al precedente contenuto dei nodi
e visualizzato sul web
*/
 
print theme('page', $return);
}
/*
* Preparazione della parte finale della pagina
*/
drupal_page_footer();
?>

Riporto di seguito la descrizione maggiormente dettagliata di quel che succede nelle quattro fasi suddette.

Decodifica URL

Drupal è un sistema in cui le pagine richieste sono quasi sempre costruite dinamicamente.
Il testo della pagina è archiviato in un database e quando viene richiesto, Drupal deve leggerlo e trasformarlo in codice HTML per essere visualizzato sul browser.
Drupal è quindi un sistema che genera pagine dinamiche.
Quando un browser invia un URL per richiedere una pagina del sito ,il sistema deve individuare dall' URL quale funzioni attivare per generare e visualizzare la pagina richiesta.
Il meccanismo che individua le funzioni da richiamare è descritto qui di seguito.

Impostazione della variabile $_GET['q']

La variabile $_GET['q'] , e il suo valore , è resa disponibile dal server web.
Il server web imposta il valore di $_GET['q'] al percorso richiesto interno al sito, in seguito indicato con il termine path. E' dal valore di questa variabile che Drupal parte per determinare quale funzione attivare per visualizzare il contenuto richiesto.

Ad esempio:
se l' URL=http://miosito.com allora $_GET['q'] = ''
se l' URL=http://miosito.com/node/345 allora $_GET['q'] = node/345
se l' URL=http://miosito.com/contabilita/elenco-fatture/attive allora $_GET['q'] = contabilita/elenco-fatture/attive

Conversione Url alias

Richiesta della home page

Se l' URL inviato contiene il solo nome del sito www.miosito.com e quindi $_GET['q'] = "", Drupal non effettua alcuna conversione riconoscendo nell' URL la richiesta della home page del sito.
In questo caso Drupal forza $_GET['q'] = "node".

Richiesta di una pagina generica

L'URL inviato al sistema, può contenere un alias dell'URL, come nell'esempio di "miosito.com/contabilita/elenco-fatture/attive". Il path contenuto nella variabile $_GET['q'] in questo caso sarà uguale a "contabilita/elenco-fatture/attive".
Il sistema per prima cosa converte il path ricevuto in un indirizzo interno e successivamente individua la funzione da attivare per estrarre dal database il contenuto richiesto.
La conversione viene eseguita nella fase di bootstrap, a cui si rimanda , ed in particolare nella fase di BOOTSTRAP_PATH.
In questa fase Drupal cerca nella tabella URL_ALIAS il path "contabilita/elenco-fatture/attive" e se esiste imposta la variabile $_GET['q'] al valore del corrispondente path di sistema.
Esempio: contabilita/elenco-fatture/attive => node/345
A conversione avvenuta avremo $_GET['q'] = node/345 e quindi il sistema saprà quale nodo deve essere visualizzato.
Evidentemente se non si trova una corrispondenza nella tabella indicata, significa che l'URL non contiene un alias e quindi la variabile $_GET['q'] non sarà alterata.

Individuazione della page_callback

Dopo l'eventuale conversione dell' URL , in $_GET['q'] si trova l'indirizzo reale della pagina da visualizzare.
Drupal deve ora individuare la page_callback, per estrarre e visualizzare il contenuto richiesto.

Abbiamo visto in Avvio di Drupal che all'interno del file index.php la lettura del contenuto viene eseguito dalla funzione menu_execute_active_handler(), il cui codice è parzialmente riportato a fondo pagina.
Questa , al suo interno, chiama la funzione menu_get_item() che individuerà la page_callback, e se specificato, caricherà anche il nodo o l'oggetto richiesto.
In che modo viene individuata la page callback?
La page_callback è individuata grazie alla tabella MENU_ROUTER. In questa tabella sono contenute le informazioni necessarie per individuare la page_callback, il cui nome è indicato nel campo <page_callback>. In particolare la colonna <path> contiene i possibili path parametrizzati che possono essere richiesti.
La tabella MENU_ROUTER è caricata da Drupal, quando si entra nel menu Amministrazione->Elenco moduli e si salva la pagina. Drupal chiamerà tutte le funzioni implementate nei moduli che hanno nome: nomemodulo_menu(). In queste funzioni sono definite le page_callback e tutte le infornazioni necessarie per eseguire le funzione richieste che saranno archiviate nella tabella MENU_ROUTER.Di tutto questo si parlerà nello parte dedicata all sviluppo dei moduli. Ad esempio, volendo modificare il nodo 12345 , potrebbe essere inviato a Drupal il path node/12345/edit.
In questo caso, il sistema cercherebbe nella colonna <path> uno dei seguenti path:

7 node/12345/edit
6 node/12345/%
5 node/%/edit
4 node/%/%
3 node/12345
2 node/%
1 node

Potrebbero non essere tutti presenti, ma tra quelli presenti, l'ordine di selezione è dato dal valore del campo <fit> della tabella.
Il path node/%/edit indica che il record della tabella contiene il nome della page_callback per tutti i path costituiti da 'node', un numero identificativo del nodo , e 'edit' come per 'node/12345/edit'
Individuato il path, il corrispondente record viene posto in un array e tornato alla funzione menu_execute_active_handler() che chiamerà la page_callback.
Oltre a tutti i campi della tabella menu_router, l'array conterrà anche:
$router_item[access] = che indica se si può accede al percorso.
$router_item[href] = equivalente al campo <path>
$router_item[localized_options] per ulteriori opzioni sul path inseribili da altre funzioni.

Gli argomenti della page callback e la lettura dell'oggetto

La funzione menu_get_item() è in grado di leggere l'oggetto richiesto (ad esempio un nodo) se nella tabella MENU_ROUTER è specificata una funzione di caricamento.

argomenti per la homepage

La page_callback chiamata è la node_page_default() a cui non vengono passati argomenti. Il valore $router_item[page_arguments] è nullo.

argomenti per un nodo generico

Abbiamo visto ad esempio che per la richiesta node/12345, il sistema trova nella tabella MENU_ROUTER il path 'node/%' e a questo corrispondono i due campi:
<page_callback> : node_page:view()
<load_function>: node_load() (serializzata in tabella)
Essendo presente il nome di una funzione di caricamento, la menu_get_item() sarà in grado di leggere l'oggetto, utilizzando la funzione indicata, e inserirlo in
$router_item[page_arguments] come argomento della funzione di page_callback.

Di seguito un frammento del codice che :

  • chiama la menu_get_item() per riempire l'array $router_item con le informazione sulla page_callback da chiamare;
  • lancia la page_callback tramite la funzione PHP call_user_func_array();
<?php

function menu_execute_active_handler($path = NULL) {
         
// altro codice ...
 
if ($router_item = menu_get_item($path)) {
    if (
$router_item['access']) {
           if (
$router_item['file']) {
              require_once(
$router_item['file']);
           }
           return 
call_user_func_array(
                                   
$router_item['page_callback'],
                                   
$router_item['page_arguments']
                                    );
    }
    else {
        
// altro codice ...
  
}
}

?>

All'avvio di Drupal, il valore di $path è NULL e la funzione menu_get_item() leggerà il path dalla variabile globale $_GET['q'].
La page_callback a questo punto leggerà il contenuto e tornerà una stringa contenente il corrispondente codice HTML.

Bootstrap

La funzione drupal_bootstrap() è contenuta nel file ./includes/bootstrap.inc che viene subito caricato. All'interno del file bootstrap.inc sono definite le otto costanti che indicano quale sotto fase attivare nel bootstrap.

  • DRUPAL_BOOTSTRAP_CONFIGURATION=0
  • DRUPAL_BOOTSTRAP_EARLY_PAGE_CACHE=1
  • DRUPAL_BOOTSTRAP_DATABASE=2
  • DRUPAL_BOOTSTRAP_ACCESS=3
  • DRUPAL_BOOTSTRAP_SESSION=4
  • DRUPAL_BOOTSTRAP_LATE_PAGE_CACHE=5
  • DRUPAL_BOOTSTRAP_PATH=6
  • DRUPAL_BOOTSTRAP_FULL=7

Alla funzione drupal_bootstrap() viene passato un parametro che indica a quale fase fermarsi del bootstrap. All'avvio, e in generale su richiesta di un nodo generico, il parametro è posto uguale a DRUPAL_BOOTSTRAP_FULL in modo tale da eseguire tutte le otto le fasi. Le funzioni attivate dalle singole fase sono definite nella funzione _drupal_bootstrap($phase).

1) DRUPAL_BOOTSTRAP_CONFIGURATION
Funzioni utilizzate:
conf_init() inizializza le variabili
conf_path() torna il percorso del file settings.php

  1. Vengono eliminate le definizioni , se esistenti (ini_get('register_globals')=1), delle variabili globali del php: _ENV, _GET, _POST, _COOKIE, _FILES, _SERVER, _REQUEST, access_check, GLOBALS .
  2. Sono inizializzate le variabili globali locali di Drupal.
    Le variabili $db_url, $db_prefix ,$db_type sono lette dal file sites/default/settings.php
    Le variabili: $base_url, $base_path, $base_root, $cookie_domain, $conf, $installed_profile sono calcolate a run-time

2) DRUPAL_BOOTSTRAP_EARLY_PAGE_CACHE

Include il file ./includes/cache.inc
Funzioni utilizzate:
_drupal_cache_init()

Inizializzazione della cache.
All'avvio non viene eseguita nessuna operazione.

3) DRUPAL_BOOTSTRAP_DATABASE

Include il file ./includes/database.inc
Funzioni utilizzate:
- db_set_active() Apre la connessione al database definito in settings.php

Apre la connessione al database.
Le funzioni per accedere al database sono definite nel file ./includes/database.$db_type.inc. (tipicamente $db_type=mysql)

Se il file non esiste, Drupal si ferma indicando che non è possibile utilizzare il tipo di database definito in $db_type. Se la connessione va a buon fine viceversa vengono impostati i valori delle seguenti variabili globali:

  • $db_url contiene la stringa di connessione definita in settings.php
  • $db_type contiene il tipo di database da utilizzare per la connessione corrente (dedotta da $db_url)
  • $active_db = Resource php al database attivo.

Se username='username' e password='password' in $db_url di settings.php, Drupal avvia l'installazione del sistema caricando il file instal.php. Il valore di ritorno della funzione db_set_active() è il nome del database precedentemente attivato, FALSE se non ce ne era nessuno.

4) DRUPAL_BOOTSTRAP_ACCESS

Funzioni utilizzate:
_drupal_is_denied()

La funzione drupal_is_denied(), verifica che ci siano i permessi per l'accesso all'host contenente Drupal.

5) DRUPAL_BOOTSTRAP_SESSION
Include il file ./includes/session.inc
Funzioni utilizzate:
session_set_save_handler() (nativa php)

Imposta le funzioni di archiviazione sessioni a livello utente, ed avvia mediante session_start() la gestione della sessione.

6) DRUPAL_BOOTSTRAP_LATE_PAGE_CACHE

Include i file ./includes/cache.inc, ./includes/module.inc
Funzioni utilizzate:
_drupal_cache_init()

Se la cache è abilitata e per la URL fornita esiste un record nella tabella cache, Drupal legge il contenuto della cache, visualizza la pagina e si ferma.
Se la cache non è abilitata o è vuota , Drupal torna dalla funzione _drupal_cache_init() e continua con il bootstrap eseguendo le funzioni e le fasi successive. In particolare in questa fase esegue le seguenti funzioni:
timer_start()
drupal_page_header()
Inizializza l'array globale $conf utilizzata dalla funzione variable_get().
Attiva , mediante drupal_page_header(), le impostazioni del protocollo HTTP per la risposta.

header("Expires: Sun,19 Nov 1978 05:00:00 GMT");
header("Last-Modified: ".gmdate("D, d M Y H:i:s")." GMT");
header("Cache-Control: store, no-cache, must-revalidate");
header("Cache-Control: post-check=0, pre-check=0", FALSE);

7) DRUPAL_BOOTSTRAP_PATH
Include il file ./includes/path.inc
Funzioni utilizzate:
drupal_init_path()

Inizializza la variabile $_GET['q'] al valore 'node'.

8) DRUPAL_BOOTSTRAP_FULL
Include il file ./includes/common.inc
Funzioni utilizzate:
_drupal_bootstrap_full()

E' l'ultima fase del bootstrap del sistema.

La funzione drupal_bootstrap_full() consente di caricare gli ultimi file include:
./includes/theme.inc
./includes/pager.inc
./includes/menu.inc
./includes/tablesort.inc
./includes/file.inc
./includes/unicode.inc
./includes/image.inc
./includes/form.inc

che conterranno le funzioni da utilizzare nelle tre successive fasi (vedi Avvio di Drupal), attivare delle funzioni di inizializzazione del sistema e caricare i moduli abilitati.
L'ultima funzione module_invoke_all('init') invoca tutte le funzioni di inizializzazione del tipo hook_init(), se esistenti, dei singoli moduli.

Visualizzazione del contenuto

Gli argomenti trattati fanno riferimento alla versione 5.x di Drupal

In questa fase Drupal visualizza la pagina richiesta utilizzando gli stili del tema impostato e il file page.tpl.php come guida per la costruzione dinamica della pagina.
Per fare questo Drupal chiama la funzione theme('page',$return) a cui passa, come argomenti, il parametro 'page' e il codice HTML del contenuto della pagina preparato nella precedente fase.

La funzione theme()
La funzione theme() individua la funzione corretta da eseguire. In questo caso, in base al parametro passato 'page' , chiamerà:

  • miotema_page() se esiste questa funzione in /miotema/template.php
  • phptemplate_page()se esiste questa funzione in phptemplate.engine >
  • theme_page() altrimenti (questa funzione è sempre presentte in includes/theme.inc )

Generalmente, e consideriamo questo caso, Drupal trova e chiama la funzione phptemplate_page()

La funzione phptemplate_page()
Al suo interno la funzione avvia le seguenti operazioni:

  • Legge e definisce la variabile $mission (missione del sito)
  • Inserisce il path di favicon.ico nel tag <HEAD>
  • Se richieste, riempie le barre laterali (sidebar-left e sidebar-right)

Le barre laterli
Per le barre laterali Drupal definisce la variabile $layout che pone uguale a:left, right, both, none a seconda che sia stata definita la barra laterale sinistra, la destra, entrambe o nessuna. In fase di definizione dello stile del tema, questa variabile può essere usata per definire le dimensioni delle regioni dei contenuti in funzione della presenza o meno delle barre laterali.

Poichè la barre laterali sono costituite da blocchi, Drupal legge tutti i blocchi da visualizzare nella pagina richiesta e genera il corrisondente codice HTML che pone nelle variabili $sidebar_left e $sidebar_right.
Il loop sui blocchi viene eseguito dalla funzione theme_blocks($region), essendo $region la regione da caricare: left o right.
Ogni singolo blocco è formattato con la funzione phptemplate_block() che a sua volta si avvale delle funzioni:

  • _phptemplate_callback() per caricare, nell'array $variables, tutte le variabili da usare nei template
  • phptemplate_default() per individuare il file di template da usare per il rendering
  • _phptemplate_render()a cui viene passato il nome del file (generalmente block.tpl.php) di template e l'array $variables per eseguire la definitiva preparazione del codice HTML del blocco.

Il processo si ripete per il blocco successivo, fino a completare il codice di tutta la barra laterale.

E' possibile generare la funzione miotema_page($return) in template.php per decidere il valore della variabile $show_blocks che consente di nascondere(=false) o mostrare (=true) le barre laterali.

function miotema_page($return) {
	$show_blocks = false
	return phptemplate_page ($return,$show_blocks)
}