WebDesigner: documentazione

Documentazione per Themer, WebDesigner.

Argomenti:

Creare un sotto tema in 15 minuti.

L'esempio crea un sotto tema da Garland, ma è sufficientemente generico per qualsiasi tema (spero).

1. Decidere il nome.
Un nome a singola parola va bene, seguendo le regole per i nomi delle variabili di PHP. Ho scelto drupalitalia.

2. Creare il percorso per il tema.
Puoi metterlo in sites/all/themes o sites/default/themes. Ho scelto sites/all/themes/drupalitalia. Controlla che i permessi siano identici rispetto a quelli di themes/garland. Per riuscire ad editare i file potrebbe essere necessario cambiare il gruppo, e mettere i permessi a 775.

3. Preparare il tema.
Bisogna creare solo pochi file per il tema. Il primo, e più importante, è drupalitalia.info. Il file deve usare il nome del tema - drupalitalia, e l'estensione .info. Qui dobbiamo specificare una serie di parametri del tema (vedi http://drupal.org/node/171205).

name = Drupalitalia - modificato Garland
description = Esempio di sotto-tema per DrupalItalia.org.
base theme = garland
core = 6.x
engine = phptemplate
stylesheets[all][] = drupalitalia.css
scripts[] = drupalitalia.js
regions[left]    = Colonna sinistra
regions[right]   = Colonna destra
regions[content] = Contenuto
regions[header]  = Intestazione
regions[footer]  = Piè pagina
regions[drupalitalia]  = Speciale per questo tema

Tutto copiato dal tema originale, con qualche eccezione:

  • base theme bisogna pur dire da quale tema vogliamo ereditare la funzionalità - devi usare la nome 'macchina' cioè il nome usato per il file .info
  • stylesheets[all][] oltre ai file CSS dell'originale specifichiamo anche uno nostro.
  • scripts[] oltre ai file JavaScript dell'originale (se ci sono) specifichiamo anche uno nostro.
  • regions[drupalitalia] oltre ai famosi cinque aggiungiamo anche una regione nostra (perche no?)
    • Il secondo file sarà proprio il file CSS che abbiamo appena definito, drupalitalia.css - ovviamente possiamo darlo un nome qualsiasi, basta che corresponda con quello definito nel file .info:

      /* CSS per il nostro tema */
      body {
        font-family: monospace;
      }

      Cambiamo il font per dare un feedback visivo e per controllare che tutto funziona - poi lo elimineremo.

      Il terzo file sarà proprio il file JavaScript che abbiamo definito, drupalitalia.js - di nuovo possiamo dare un nome qualsiasi, basta che corresponda con quello definito nel file .info:

      /* JavaScript per la nostra tema */

      E' vuoto per il momento, magari più avanti avremo bisogno di mettere codice qui.

      Il prossimo file è template.php, che finirà per contenere codice di temizzazione, se necessario:

      <?php
      // Codice di temizzazione specifico per la tema
      /**
      * Override o inserire variabili per page.tpl.php.
      * Vedi http://api.drupal.org/api/function/template_preprocess_page/6
      */
      function drupalitalia_preprocess_page(&$vars) {
        // vuota per ora...
      }
      /**
      * Override o inserire variabili per node.tpl.php.
      * Vedi http://api.drupal.org/api/function/template_preprocess_node/6
      */
      function drupalitalia_preprocess_node(&$vars) {
        // vuota per ora...
      }

      Altro file 'vuoto' per il momento. Ho semplicemente aggiunto due funzioni di cui quasi sicuramente avremo bisogno in futuro.
      Si, manca un ?> finale - non è un errore, fidati.

      In fine dovremo modificare page.tpl.php aggiungendo la regione che abbiamo creato. Per fare questo, basta copiare page.tpl.php da themes/garland in sites/all/themes/drupalitalia. E' un file grosso, quindi non metto tutto il contenuto qui, solo le ultime righe dove aggiungiamo nostra regione:

          ...
          </div> <!-- /container -->
        </div>
        <!-- nostra regione aggiunto -->
        <div id="special-region" class="clear-block"><?php print $drupalitalia; ?></div>
      <!-- /layout -->
        <?php print $closure ?>
        </body>
      </html>

      4. Testare la tema.
      Fatto. Adesso andiamo in admin/build/themes, dove troviamo un nuovo tema (oooh) chiamato "Drupalitalia - modificato Garland". Clicca su attiva e predefinito, poi 'Salva configurazione' (incrociando le dita). Se tutto va bene, la maggior parte del testo sarà monospace come questo - il nostro controllo visivo che tutto va bene.

      Poi controlliamo la nostra nuova regione. Andiamo in admin/build/block/list/drupalitalia dove, nella lista di regioni, prima di 'Disattivato' troviamo 'Speciale per questo tema' mettiamo dentro 'Realizzato con Drupal (module: system)' poi 'Salva blocchi' et voilà mes amis! La goccia è in fondo alla pagina.

      Ma c'è un piccolo problema - abbiamo perso il logo nel header. Basta copiare logo.png da themes/garland in sites/all/themes/drupalitalia.

      Per i pigri tutti i file sono in allegato. Formatto zip per gli appasionati di Windows.

AllegatoDimensione
Package icon drupalitalia.zip2.43 KB

Argomenti:

I file *.tpl.php

I file *.tpl.php

Argomenti:

Il concetto di tema

Il concetto di tema

Argomenti:

Il file *.info

Il file *.info

Argomenti:

Il file template.php

Il file template.php

Argomenti:

Il funzionamento di phptemplate

Il funzionamento di phptemplate

Argomenti:

I blocchi

I blocchi

Argomenti:

I nodi

I nodi

Argomenti:

Le pagine

Le pagine

Argomenti:

Le regioni

Le regioni

Argomenti:

Integrazione con color e advanced theme

Integrazione con color e advanced theme

Argomenti:

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:

Sviluppo di un nuovo tema

Sviluppo di un nuovo tema

Argomenti: