La temizzazione della pagina: vista a raggi X

Stato documento: Alfa

Spesso la sequenza di temizzazione (rendering) della pagina in Drupal crea confusione. Dopo qualche ore tentando di seguire il codice, ho deciso di tagliare corto, ed installare un pò di codice per creare un X-Ray del processo. Questo dà un pò più informazione di quello disponibile usando Devel e Theme Developer.

Il codice della macchina a raggi X
Ho aggiunto qualche riga di codice in includes/theme.inc, e giusto che puoi sperimentare per conto proprio, ti spiego le modifiche. Bisogna 'catturare' informazione durante le chiamate a theme() ed a template_preprocess()
Iniziamo subito, alla riga 577, inserisci:

<?php
 
function theme() {
 
$args = func_get_args();
 
$hook = array_shift($args);
?>
<?php
global $drupal_calls;
if (!isset(
$drupal_calls)) { $drupal_calls = array(); }
$drupal_calls[] = "theme(start): ". $hook ."\n";
?>
<?php
 
static $hooks = NULL;
?>

Poi alla riga 694, inserisci:
<?php
 
// Add final markup to the full page.
 
if ($hook == 'page' || $hook == 'book_export_html') {
   
$output = drupal_final_markup($output);
  }
?>
<?php
global $drupal_calls;
if (!isset($drupal_calls)) { $drupal_calls = array(); }
$drupal_calls[] = "theme(end): ". $hook .' = '. $output ."\n";
if ($hook == 'page') { foreach ($drupal_calls as $call) { print($call); } }
  return $output;
}?>
Ed infine, alla riga 1720, inserisci:
<?php
function template_preprocess(&$variables, $hook) {
  global
$user;
  static
$count = array();
?>
<strong><?php
global $drupal_calls;
if (!isset($drupal_calls)) { $drupal_calls = array(); }
$drupal_calls[] = "template_preprocess(): ". $hook ."\n";
  // Track run count for each hook to provide zebra striping.
?>
<strong>Avviso:</strong> con tutto questo informazione addizionale, compreso elementi di form, <em>meglio stare lontano dalle pagine di amministrazione.
</em>
&#160;
&#160;
<strong>Risultati della visualizzazione di un nodo</strong>
Prima, viene chiamata la temizzazione del node 'nudo e crudo' preso dalla tabella <code>node_revisions

theme(start): markup
theme(end): markup = <p>This is the fourth page...</p>

Poi viene temizzato il nodo vero e proprio, caricando il nodo completo tramite template_preprocess_node() (nota che theme() viene chiamato ricursivamente):

theme(start): node
  template_preprocess(): node
  theme(start): username
  theme(end): username = <a href="/users/syger" title="Mostra il profilo utente.">syger</a>
  theme(start): links
  theme(end): links =
theme(end): node = <div class="node"><span class="submitted"></span><div class="taxonomy"></div><div class="content"><p>This is the fourth page...</p></div></div>

In fine, viene temizzato la pagina, chiamando template_preprocess_page():

theme(start): page
  template_preprocess(): page

Inizia con i blocchi:
  theme(start): blocks
    theme(start): system_powered_by
      theme(start): image
      theme(end): image = <img src="/misc/powered-blue-80x15.png" alt="Realizzato con Drupal...
    theme(end): system_powered_by = <a href="http://drupal.org"><img src="/misc/powered-blue-80x15.png" alt="Realizzato con Drupal...
    theme(start): block
     template_preprocess(): block
    theme(end): block = <div class="block block-system" id="block-system-0"><div class="title"><h3></h3></div><div class="content"><a href="http://drupal.org"><img src="/misc/powered-blue-80x15.png" alt="Realizzato con Drupal...
  theme(end): blocks = <div class="block block-system" id="block-system-0"><div class="title"><h3></h3></div><div class="content"><a href="http://drupal.org"><img src="/misc/powered-blue-80x15.png" alt="Realizzato con Drupal...

Seguito dai briccole di pane, messaggi di status, tab di editing (ero loggato come editore), ed i menu primario e secondario:
  theme(start): breadcrumb
  theme(end): breadcrumb = <div class="breadcrumb"><a href="/">Home</a></div>
  theme(start): help
    theme(start): menu_item_link
    theme(end): menu_item_link = <a href="/content/fourth-page" class="active">Mostra</a>
    theme(start): menu_local_task
    theme(end): menu_local_task = <li class="active" ><a href="/content/fourth-page" class="active">Mostra</a></li>
    theme(start): menu_item_link
    theme(end): menu_item_link = <a href="/node/61/edit">Modifica</a>
    theme(start): menu_local_task
    theme(end): menu_local_task = <li ><a href="/node/61/edit">Modifica</a></li>
  theme(end): help =
  theme(start): status_messages
  theme(end): status_messages = <div class="messages error">Warning - you're logged in as the super user.</div>
  theme(start): menu_local_tasks
  theme(end): menu_local_tasks = <ul class="tabs primary"><li class="active" ><a href="/content/fourth-page" class="active">Mostra</a></li><li ><a href="/node/61/edit">Modifica</a></li></ul>
  theme(start): links
  theme(end): links = <ul class="links" id="navlist"><li class="menu-5541 first"><a href="/content/test1" title="Test 1">Test 1</a></li><li class="menu-5551 last"><a href="/content/test2" title="Test 2">Test 2</a></li></ul>
  theme(start): links
t  heme(end): links = <ul class="links" id="subnavlist"><li class="menu-16751 first"><a href="/content/faclets" title="Faclets">Java Faclets</a></li><li class="menu-16761 last"><a href="/content/pro-drupal-development" title="Pro Drupal Development">Pro Drupal Development</a></li></ul>

Infine vediamo la chiusura (closure) ed il risultato finale - una pagina HTML:
  theme(start): closure
  theme(end): closure =
theme(end): page = <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">...[/codefilter...
 
 
Risultati della visualizzazione di una lista (front page classico)
Come per un singolo nodo, ogni nodo nella lista viene temizzato:
theme(start): markup
theme(end): markup = <p>This is the ninth page...</p>
theme(start): node
  template_preprocess(): node
  theme(start): username
  theme(end): username = <a href="/users/syger" title="Mostra il profilo utente.">syger</a>
  theme(start): links
  theme(end): links =
theme(end): node = <div class="node"><h1 class="title"><a href="/content/ninth-page">Ninth page</a></h1><span class="submitted"></span><div class="taxonomy"></div><div class="content"><p>This is the ninth page...</p></div></div>
theme(start): markup
theme(end): markup = <p>This is the eighth page...</p>
theme(start): node
  template_preprocess(): node
  theme(start): username
  theme(end): username = <a href="/users/syger" title="Mostra il profilo utente.">syger</a>
  theme(start): links
  theme(end): links =
theme(end): node = <div class="node"><h1 class="title"><a href="/content/eighth-page">Eighth page</a></h1><span class="submitted"></span><div class="taxonomy"></div><div class="content"><p>This is the eighth page...</p></div></div>

Per non morire dalla noia, saltiamo al ultimo nodo nella lista:
theme(start): markup
theme(end): markup = <p>This is the first page.</p>
theme(start): node
  template_preprocess(): node
  theme(start): links
  theme(end): links = <ul class="links inline"><li class="node_read_more first last"><a href="/content/development-page" title="Leggi il resto di Development Page.">Leggi tutto</a></li></ul>
  theme(start): username
  theme(end): username = <a href="/users/syger" title="Mostra il profilo utente.">syger</a>
  theme(start): links
  theme(end): links =
theme(end): node = <div class="node"><h1 class="title"><a href="/content/development-page">Development Page</a></h1><span class="submitted"></span><div class="taxonomy"></div><div class="content"><p>This is the first page.</p></div><div class="links">&raquo; <ul class="links inline"><li class="node_read_more first last"><a href="/content/development-page" title="Leggi il resto di Development Page.">Leggi tutto</a></li>
</ul></div></div>

Nota l'aggiunto della 'read more' per questo nodo che ha più contenuto di quanto visualizzabile nel sommario (teaser).
 
Altri elementi nuovi sono il feed RSS e l'impaginatore (paginator) che non verrà usato dato che il numero di nodi non superava la lunghezza della lista.
theme(start): feed_icon
  theme(start): image
  theme(end): image = <img src="/misc/feed.png" alt="Condividi contenuti" title="Sandbox RSS" width="16" height="16" />
theme(end): feed_icon = <a href="http://dev.autonomous-sandbox/rss.xml" class="feed-icon"><img src="/misc/feed.png" alt="Condividi contenuti" title="Sandbox RSS" width="16" height="16" /></a>
theme(start): pager
  theme(start): pager_first
  theme(end): pager_first =
  theme(start): pager_previous
  theme(end): pager_previous =
  theme(start): pager_next
  theme(end): pager_next =
  theme(start): pager_last
  theme(end): pager_last =
theme(end): pager =

A questo punto segue la temizzazione della pagina, esattamente uguale come per un singolo nodo - quindi evitiamo di ripetere la stessa informazione.
 
 
Risultati della visualizzazione di una pagina non nodo - l'utente amministratore user/1

theme(start): user_picture
  template_preprocess(): user_picture
  theme(start): image
  theme(end): image = <img src="http://dev.autonomous-sandbox/sites/default/files/pictures/picture-1.jpg" alt="Ritratto di syger" title="Ritratto di syger"  />
theme(end): user_picture = <div class="picture"><a href="/users/syger" title="Mostra il profilo utente." class="active"><img src="http://dev.autonomous-sandbox/sites/default/files/pictures/picture-1.jpg" alt="Ritratto di syger" title="Ritratto di syger"  /></a></div>
theme(start): user_profile
  template_preprocess(): user_profile
  theme(start): markup
  theme(end): markup = <div class="picture"><a href="/users/syger" title="Mostra il profilo utente." class="active"><img src="http://dev.autonomous-sandbox/sites/default/files/pictures/picture-1.jpg" alt="Ritratto di syger" title="Ritratto di syger"  /></a></div>
  theme(start): user_profile_item
    template_preprocess(): user_profile_item
  theme(end): user_profile_item = <dt>Membro da</dt><dd>17 settimane 4 giorni</dd>
  theme(start): user_profile_category
    template_preprocess(): user_profile_category
  theme(end): user_profile_category = <h3>Cronologia</h3><dl class="user-member"><dt>Membro da</dt><dd>17 settimane 4 giorni</dd></dl>
theme(end): user_profile = <div class="profile"><div class="picture"><a href="/users/syger" title="Mostra il profilo utente." class="active"><img src="http://dev.autonomous-sandbox/sites/default/files/pictures/picture-1.jpg" alt="Ritratto di syger" title="Ritratto di syger"  /></a></div><h3>Cronologia</h3><dl class="user-member"><dt>Membro da</dt><dd>17 settimane 4 giorni</dd></dl>

A questo punto segue la temizzazione della pagina, esattamente uguale come per un singolo nodo.
 
 
Conclusioni
Questo piccolo esercizio dimostra il metodo usato da Drupal per visualizzare le pagine. Ci sono due osservazioni importante; la prima è che Drupal non crea il modello dei dati prima di iniziare il prcesso di temizzazione, ma richiede i dati man mano che procede nella lista di oggetti da temizzare. Per questo motivo Drupal è un pò difficile da gestire se c'è bisogno della condivisione di questi dati fra zone temizzati (fra il nodo ed un blocco, per esempio). La seconda, che mi ha un pò sorpreso, è che non sono apparsi chiamate a theme() per la costruzione dei componenti dei menù, ma solo per i menù stessi.

Argomenti: