Guida DRUPAL

Più che una guida completa, riporto in queste pagine alcuni appunti su ciò che ho potuto capire leggendo la Guida in linea in drupal.org e lavorando a questo e ad altri siti.

Non nascondo che quando ho iniziato a lavorare con Drupal, ho avuto forti perplessità e difficoltà a comprendere questo CMS. Ne esistevano altri più intuitivi, meno tecnici. Però ne sentivo parlare molto bene e quindi sono andato avanti.

L'approccio iniziale a Drupal è quello di provare gli svariati temi disponibili, attivare modulli, leggere la documentazione ufficiale inglese (per me molto dispersiva) e quel poco che si trova in rete, in italiano, in siti e forum. Inizialmente ho girato dentro al codice cercando di capire come funzionasse, cercando di modificare i temi, arrabbiandomi quando le cose non funzionavano. Ma alla fine mi rendevo sempre conto di non sapere ancora bene dove mettere le mani. Mano a mano che capivo come risolvere qualcosa , me l' appuntavo e alla fine è nata la sezione Come fare per.

Dopo lungo girovagare per il codice , alla fine mi si sono schiarite un po' le idee, quando mi sono chiesto: Ma cosa fa Drupal quando parte? Logico, legge il file index.php. Allora ho cominciato a seguire il codice dall'inizio e finalmente mi si sono schiarite le idee (credo). Ho cominciato a capire cosa veramente è un nodo e come è salvato, cosa sono i file templete e quando sono utilizzati, cosa è un tema etc.

Ecco perchè in questi miei appunti ho messo tra i primi argomenti proprio l' Avvio di Drupal, cercando di spiegare, e mentre scrivevo di fermare le idee, cosa succede da quando viene letto il file index.php a quando termina la presentazione della home page. Ho cercato di approfondire l'argomento in modo tale da poter controllare la situazione e capire meglio gli argomenti successivi. Ci sono ancora delle lacune, ma credo sia un buon punto di partenza per avvicinarsi a Drupal.

Ovviamente per approfondire gli argomenti trattati è d'obbligo la guida ufficiale di drupal.org, e i forum di drupalitalia.org e di drupal.it

Però , andate anche, in questo sito, alla pagina Drupal e al paragrafo "Ma si parla di Drupal anche in ..." dove riporto alcuni link verso siti che ritengo veramente ben fatti e da cui è possibile "attingere sapere" e imparare molte cose su Drupal. Buona lettura

Come fare per

Questa sezione della guida è dedicata a quei piccoli problemi che ho incontrato durante lo sviluppo con Drupal a cui però non avevo trovato , nei vari forum su Drupal , risposta immediata.

Installare Drupal 7

  • scaricare drupal ultima versione da http://drupal.org/project/drupal
  • decomprimere la versione di Drupal e scaricarla nella root del sito
  • copiare da sites/default/default.settings.php in sites/default/settings.php
  • dare i permessi di scrittura (chmod 777) al file setting.php
  • creare un database MuSql
  • lanciare da browser miosito.com/install.php
  • Database: inserire nome/username/password richiesti del db creato
    inserire amche tra le opzioni avanzate il nome del server ad esempio "mysql1065.servage.net"
    Tra le altre cose domandate inserire l'utente amministratore: admin/password
  • Traduzione italiana

  • scaricare la traduzione italiana da http://localize.drupal.org/translate/languages/it e chiamarla it.po
  • mettere il file it.po in drupal/profiles/standard/translations
  • Quando viene installato, drupal chiedere se si vuole installare in inglese (default) o italiano.
  • La prima volta lasciare la lingia inglese
    - dopo l'installazione andare nel menu "modules" e attivare il modulo "locale"
    - da configurazione->language aggiungere la lingua italiana, partirà la traduzione che richiederà diverso tempo.

    Modificare il titolo del sito

    Come amministratore del sito, andando sulla voce di menu amministra->impostazioni compare la pagina con tutte le impostazioni del sito. Su impostazioni generali è possibile definire il titolo del sito, la email e l'icona.

    Icone del linguaggio, installare http://drupal.org/project/languageicons

    Ripristinare la pagina di login scomparsa

    Se è stata disabilitata la visualizzazione del Login , collegarsi con
    www.miosito.it/user oppure www.miosito.it/?q=user,
    per far comparire la pagina di login.

    Sito off-line:non riesco più ad entrare

    Provare in uno di questi modi:

    • Provare a collegarsi con www.miosito.com/user, per far comparire la pagina di login. Se si visualizza entrare come amministratore e riportare il sito on-line.

    • Controllare se nella tabella variable c'è un record con name= 'site_offline': se c'è cancellarlo insieme al record della tabella cache con cid='variables'

    • Se ancora non funziona il controllo del sito offline è fatto in includes/menu.inc funzione _menu_site_is_offline() chiamata dalla funzione menu_execute_active_handler()

    • Verificare 'impostazione della variabile $db_url nel file /sites/defaultl/settings.php

    • Se ancora non funziona il controllo del sito offline è fatto in includes/menu.inc funzione _menu_site_is_offline() chiamata dalla funzione menu_execute_active_handler()

    Eseguire il Logout

    Per eseguire un Log-out non da menu chiamare la pagina http://miosito.com/logout

    Aprire una nuova finestra da menu (target="_blank")

    L'apertura di una nuova finestra viene eseguita impostando l'attributo "target" nel tag href.
    La funzione di default che prepara il tag href e' la funzione theme_menu_item_link() (contenuta in includes/menu.c).
    Dobbiamo quindi creare una delle due seguenti funzioni in modo tale che Drupal le possa chiamare in sostituzione della funzione di default.
    Le due funzioni, da inserire nel file template.php, sono:
    - miotema_menu_item_link($link)
    - phptemplate_menu_item_link($link)
    Se esistono entrambe , Drupal darà la precedenza a miotema_menu_item_link($link).
    Considerando ad esempio la seconda, possiamo fare in modo che l'attributo Target sia presente se il riferimento al link inizia con "http" indicando un percorso esterno al sito. Ecco il codice.
    Per versione 6.x

    <?php
     
    function phptemplate_menu_item_link($link) {

      if (empty(

    $link['localized_options'])) {
       
    $link['localized_options'] = array();
      }
    if(
    strtolower(substr($link['href'],0,4))=="http") {
        
    $link['localized_options']['attributes'] = array('target' => '_blank');
    }

      return

    l($link['title'], $link['href'], $link['localized_options']);
    }
    ?>

    In alternativa possiamo sfruttare l'attributo $link[external]=1 che Drupal fornisce nel caso il link sia esterno. Ecco il codice.

    <?php
     
    function phptemplate_menu_item_link($link) {

      if (empty(

    $link['localized_options'])) {
       
    $link['localized_options'] = array();
      }
    if (
    $link['external']==1) {{
        
    $link['localized_options']['attributes'] = array('target' => '_blank');
    }
      return
    l($link['title'], $link['href'], $link['localized_options']);
    }
    ?>

    Per versione 5.x

    <?php
     
    function theme_menu_item_link($item, $link_item) {
    $attributes = array();
    if (!empty(
    $item['description'])) $attributes['title'] = $item['description'];
    if(
    strtolower(substr($link_item['path'],0,4))=="http") {
        
    $attributes['target'] = "_blank";
    }
    return
    l($item['title'], $link_item['path'], $attributes, isset($item['query']) ? $item['query'] : NULL);
    }
    ?>

    Attenzione , se il tema che si sta utilizzando implementa la funzione miotema_menu_item_link() nel file template.php, inserire la patch anche in questa funzione.

    Il test per abilitare URL semplificati fallisce

    Per sistemi Windows e server Apache fare le seguenti modifiche:
    in httpd.conf

    1. scommentare LoadModule rewrite_module modules/mod_rewrite.so
    2. impostare AllowOverride All in ..
    <Directory "C:/drupal">
        AllowOverride All
        Options None
        Order allow,deny
        Allow from all
    </Directory>

    essendo C:/drupal la documentRoot di Apache

    Ordinare i contenuti nella prima pagina

    Come sono ordinati i contenuti nella rima pagina?
    All'avvio di Drupal viene eseguita la funzione node_page_default() , contenuta in includes/node.module. In questa funzione viene eseguita la seguente query per vedere quali contenuti devono essere inseriti in prima pagina.

    SELECT n.nid, n.sticky, n.created FROM node n
     WHERE n.promote = 1 AND n.status = 1 ORDER BY n.sticky DESC, n.created DESC

    Quindi affinché un contenuto compaia in prima pagina nella tabella NODE si deve avere:
    promote = 1 ; cioè promosso in prima pagina.
    status = 1; cioè pubblicato.
    L'ordinamento è fatto sui due campi: sticky(opzione fisso in cima alla lista ) e created (data creazione) e su entrambi in modo discendente.
    Per il campo sticky più è alto il valore più il commento sarà in cima alla lista.
    Per il campo created , i commenti più recenti saranno visualizzati per primi.

    Quindi, al di là della data di creazione, per portare un commento al primo posto nella pagina, basta assegnarli (direttamente nella tabella NODE) il valore di sticky più alto in assoluto e via via decrescente per i contenuti che devono seguire.
    Per tutti i contenuti che si vogliono visualizzare in base alla loro data di creazione, basta mantenere sticky=0.
    Attenzione:se ad un contenuto si assegna l'opzioe "fisso in cima alla lista" il valore di sticky sarà posto=1 sovrascrivendo eventuali valori da noi impostati direttamente nella tabella NODE.

    Cambiare il proprietario di un contenuto

    Ci sono due modi per modificare il proprietario del nodo.
    1. Il primo consiste nell'entrare nel nodo del contenuto come amministratore e nelle informazioni sull'autore inserire il nome dell'utente a cui dare la proprietà del nodo.

    Attenzione: il nuovo utente potrà ora modificare il contenuto solo se in Controllo accessi ha il permesso amministra filtri nel modulo filter oppure se il formato del contenuto è Filtered HTML. Nel caso non fosse così, permessi non assegnati o formato uguale a PHP code o Full HTML, è necessario o cambiare il permesso o impostare il formato a Filtered HTML.

    2. Il secondo metodo consiste nel modificare il campo uid nella tabella node inserendo il valore uid assegnato all'utente (vedere tabella users). Vale la stessa considerazione fatta precedentemente per il formato. Il valore del formato selezionato è comunque indicato nella tabella node_revisions nel campo format per il/i record con campo nid uguale al valore nid del nodo nella tabella node.
    La tabella node_revisions ha anche il campo uid che per correttezza dovrebbe essere posto uguale al valore in tabella node, ma anche se mantiene il precedente valore non inficia il cambiamento del proprietario.

    Format = 1 Filtered HTML valore di default per tutti gli utenti
    Format = 2 PHP code
    Format = 3 Full HTML

    I fogli di stile non sono caricati

    Compare solamente il contenuto senza sidebar intestazione etc.

    • Controllare che il nome del tema assegnato all'utente sia presente nella tabella system per type="theme"
    • Controllare che file di stile indicato nella tabella system nel campo filename, esista per quel tema e che non sia corrotto

    Usare una vista nel codice PHP

    Drupal 6.x
    Views 2.0
    Supponiamo di avere un modulo che chiama la funzione miomodulo_output () generando un output per il contenuto principale.

    <?php
     
    function   miomodulo_output () {
      
    $output = "Messaggio di prova";
       return
    $output;
    }
    ?>

    Voglio ora inserire dopo il messaggio il risultato di una vista creata mediante l' interfaccia delle viste.
    Il nome della vista è "vista_di_prova" e accetta in ingresso un argomento numerico passato alla funzione miomodulo_output().
    Al codice precedente dobbiamo aggiungere una sola riga:

    <?php
     
    function   miomodulo_output ($arg1) {
      
    $output = "Messaggio di prova<br>";
       
    $output  .= views_embed_view('vista_di_prova', 'page_1',$arg1);
       return
    $output;
    }
    ?>

    Dove page_1 è il nome del display_id da visualizzare definito nell'interfaccia della vista.
    Per approfondimenti
    http://drupal.org/node/48816

    Eliminare la data ed il nome utente da una pagina

    Come amministratore andare alla pagina delle "impostazioni globali" dei temi. (/admin/build/themes/settings/global)
    Per ogni tipo di contenuto presente nella sezione "Mostra le informazioni del contenuto su",
    eliminare il segno di spunta sul tipo di contenuto su cui non si vuole mostrare nome e data.

    Ripristinare la password di amministratore

    Eseguire la query:
    UPDATE users SET pass = MD5( 'NUOVAPASSWORD' ) WHERE uid =1;
    Per saper il nome associato all'amministratore:
    SELECT name FROM users WHERE uid =1;
    Ulteriori informazioni possono essere lette direttamente dalla tabella users degli utenti.

    Conoscere la directory di ...

    global $theme_path

    Cosa come
    directorydel sito global $base_url
    directory di un modulo $path = drupal_get_path('module', 'nomemodulo');
    directory di un tema $path = drupal_get_path(theme', 'nometema');
    directory di un engine $path = drupal_get_path(theme_engine', 'nomeengine');
    directory tema corrente global $theme_path

    Utenti: Sapere se un utente appartiene a un ruolo

    Per verificare se l'utente corrente appartiene ad uno dei ruoli definiti nella tabella ROLE
    definire la seguente funzione:

    <?php
    /**
    * @param $role   Il nome del ruolo da verificare
    * @param $user  Oggetto utente
    * @return  TRUE se l'utente appartiene al ruolo richiesto , FALSE altrimenti
    */
    function user_has_role($role, $user = NULL) {
      if (
    $user == NULL) {
        global
    $user;
      }
      if (
    is_array($user->roles) && in_array($role, array_values($user->roles))) {
        return
    TRUE;
      }
      return
    FALSE;
    }
    ?>

  • I contenuti

    Contenuti

    In questa documentazione sarà indicato con il termine di contenuto l'informazione archiviata in un sistema CMS come Drupal.

    L'informazione pubblicata è orientata alla diffusione di conoscenza , idee, proposte e altro che gli ideatori del sito hanno come loro missione. L'informazione è resa disponibile nel sito web sotto forma di articoli, libri, forum e ancora con il supporto di immagini , video e suoni.
    Tutto questo è quello che chiameremo contenuto primario del sito.

    Ma oltre al contenuto primario, nel sito sono presenti altri contenuti come i menu per la navigazione, maschere per l'interazione con l'utente, commenti agli argomenti lasciati dai visitatori o utenti del sito, pubblicità e tutto ciò che può essere necessario per raggiungere lo scopo finale per cui il sito è stato pensato.
    Tutto questo è quello che chiameremo contenuto secondario del sito

    Il contenuto primario viene gestito dal Drupal attraverso i NODI.
    Possiamo pensare al nodo come il contenitore della nostra informazione che viene poi visualizzato sul web sotto forma di pagina singola o di pagina di un libro o ancora come contenuto di un singolo intervento in un forum.
    Drupal mette a disposizione dei nodi di base come appunto la creazione di una singola pagina o di un pagina appartenente ad un libro come questa che state leggendo. Ma Drupal consente anche di creare nuove tipologie di nodi. Si potrebbe creare quindi una rubrica telefonica dove ogni nodo è costituito da un singolo nominativo , uno scadenzario, un reportage fotografico e così via.

    Il contenuto secondario viene gestito da Drupal attraverso i BLOCCHI.
    I menu di navigazione sono dei blocchi, l'elenco degli ultimi commenti alle pagine o delle ultime discussioni aperte in un forum sono dei blocchi, la maschera di login è un blocco così come i tag di ricerca delle pagine. In pratica, come detto, tutto ciò che è utile per una buona navigazione e fruibilità del sito va a finire in un blocco.

    Come descritto in Avvio di Drupal il contenuto primario e secondario è letto rispettivamente dalle due funzioni:

    Queste due funzioni sono contenute nel file index.php che è il primo ad essere eseguito ad ogni caricamento di pagina.

    Event, Hook, Action

    Per utilizzare Drupal, è fondamentale capire i concetti di event , hook, action e operazione
    Drupal è un sistema software che lavora essenzialmente su tre fasi:

    Se non ci fosse un modo per interaggire dall'esterno, Drupal sarebbe un sistema completo, non espandibile.
    Potremmo pensarlo come un frigorifero:

    Sicuramente a un frigorifero non si potrà mai chiedere di fare il caffè!
    Fortunatamente , come per la maggior parte dei sistemi software, non è così.

    Eventi

    Drupal interagisce con il mondo esterno tramite eventi.
    Gli eventi (in inglese events) indicano al mondo esterno cosa sta succedendo all'interno della macchina Drupal.
    Eventi possibili sono ad esempio :

    Ma l'evento è un concetto astratto. Ad esso deve corrispondere qualcosa di concreto che consenta di agganciarsi al flusso di elaborazione di Drupal per modificarlo.

    In pratica ad ogni elaborazione Drupal dice:

    Hook
    A questo punto è chiaro che un Hook o Gancio è qualcosa che ci permette di dare un nome predefinito ad una funzione in modo tale che possa essere riconosciuta ed eseguita da Drupal quando si verifica l'evento,

    Facciamo l'esempio in cui un utente esegue il login al sistema.
    Vogliamo creare un' azione che su questo evento visualizzi il messaggio "Benvenuto nel sito"
    Il modulo che contiene le funzioni supponiamo si chiami miomodulo.

    La funzione che sarà necessario scrivere è la seguente:

    <?php
     
    function  miomodulo_user($op,&$edit,&$account,$category=NULL) {
      if(
    $op== 'login')  return  "Benvenuto nel sito";
    }
    ?>

    Infatti:

    Dove Operazione =' login' è l'operazione particolare della coppia Evento/Hook
    Ad esempio lo stesso evento e lo stesso hook sono utilizzabili anche per una operazione di cancellazione (delete) di un utente. In tal caso la funzione sarebbe stata scritta nel seguente modo:

    <?php
     
    function  miomodulo_user($op,&$edit,&$account,$category=NULL) {
    if(
    $op== 'login')      return  "Benvenuto nel sito";
    if(
    $op== 'delete')    return  "Grazie di essere stato con noi!";
    }
    ?>

    Quindi per eseguire un'azione sul verificarsi di un evento , basta generare la funzione:

    nomemodulo_hook($op);

    Verificando all'interno il tipo di operazione avviata su quell'evento.

    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)
    }
    

    Nodi

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

    I nodi contengono il contenuto primario del sito.
    L'elenco di tutti i nodi inseriti nel sistema è contenuto nella tabella NODE.
    Le informazioni sono lette e codificate dal sistema, mediante la funzione menu_execute_active_handler(), descritta in Decodifica URL. La funzione individua la page callback e, tramite essa, torna la stringa del contenuto codificato.
    Per i nodi sono disponibili due page callback:

    La home page - node_page_default()

    La prima pagina del sito mostra generalmente più di un nodo. Questi sono i nodi a cui è stato assegnato l'attributo di pubblicazione "promosso in prima pagina". Per selezionare tali nodi, la funzione node_page_default() esegue la seguente query sulla tabella NODE:

    SELECT n.nid, n.sticky, n.created 
    FROM node n 
    WHERE n.promote = 1 AND n.status = 1 
    ORDER BY n.sticky DESC, n.created DESC

    Dalla query si vede che le condizioni affinché un nodo venga selezionato sono:

    L'ordine di visualizzazione dei nodi è fornito invece dal valore sticky:più è alto, più il nodo salirà nell'elenco. A parità di valore l'ordine è dato dalla data di creazione. I nodi più recenti , sono visti per prima.
    Il valore di sticky normalmente vale zero. Volendo quindi mostrare un nodo sempre per primo, indipendentemente dalla data di creazione, basterà assegnare un valore >0 al nodo, ad esempio 100.
    Individuati i nodi da visualizzare , la funzione node_page_default(), inizia un ciclo di lettura e visualizzazione di tutti i nodi. Questo viene eseguito all'interno del ciclo contenuto nella funzione node_page_default().

    <?php
    function node_page_default() { 
    ......
     
    $output = '';
     
    $num_rows = FALSE;
      while (
    $node = db_fetch_object($result)) {
       
    $output .= node_view(node_load($node->nid),  1);
       
    $num_rows = TRUE;
      }
    // Il valore 1 in node_view indica che si tratta del contenuto teaser
    .....
    ?>

    All'interno del ciclo sono visibili le due funzioni di Drupal per il caricamento del nodo node_load() e per la visualizzazione del nodo node_view(). Al termine la stringa $output conterrà tutti i contenuti dei nodi da visualizzare in prima pagina.

    Contenuto singolo - node_page_view()

    Se la pagina richiesta non è la home page, ma un singolo contenuto, Drupal seleziona la page callback node_page_view(). Poichè la richiesta di visualizzazione è di un particolare nodo (ad esempio http://miosito.com/node/100), Drupal carica prima il nodo richiesto mediante la funzione node_load() e successivamente chiama la node_page_view() passando le informazioni sul nodo ($node) lette e un identificativo ($cid) che, se non nullo, indica che la pagina del nodo è già presente nella cache.
    La funzione node_page_view() imposta il titolo della pagina (drupal_set_title(check_plain($node->title))) e chiama la funzione node_view($node, FALSE, TRUE). Il terzo parametro a TRUE indica che Drupal deve visualizzare l'intero contenuto del nodo.

    Caricamento e visualizzazione del contenuto

    In definitiva abbiamo visto che le due funzioni di base utilizzate da Drupal sia per la visualizzazione della home page sia per la visualizzazione di un singolo contenuto sono sempre node_load() e node_view().
    Il funzionamento di queste due funzioni e quindi la logica del caricamento e della visualizzazione dei nodi è descritto nei successivi paragrafi: Caricamento, Visualizzazione.

    Le funzioni principali

    node_page_default()
    node_page_view()
    node_load()
    node_view()
    node_invoke()
    node_invoke_api()

    Caricamento

    Lettura del contenuto di un nodo - node_load()

    La lettura del contenuto del nodo, è eseguita mediante la funzione node_load($nid) a cui è passato il valore dell'identificativo univoco del nodo <nid> da caricare. Al suo interno viene generata la query indicata, che usa tre tabelle:

    • NODE da cui sono estratte informazioni sulla pubblicazione e tipo del nodo
    • NODE_REVISIONS da cui sono estratte informazioni sul contenuto del nodo (Il titolo del nodo è letto da questa tabella e non da NODE come si potrebbe pensare)
    • USERS da cui sono estratte informazioni sul proprietario del nodo

    Query di selezione

    SELECT n.nid, n.type, n.language, n.uid, n.status, n.created, n.changed, n.comment, n.promote, 
    n.moderate,  n.sticky, n.tnid, n.translate, r.vid, r.uid AS revision_uid, r.title, r.body, r.teaser, r.log,
     r.timestamp AS revision_timestamp, r.format, u.name, u.picture, u.data 
    FROM node n 
    INNER JOIN users u ON u.uid = n.uid 
    INNER JOIN node_revisions r ON r.nid = n.nid AND r.vid = <n.nid>
    WHERE n.nid = <n.nid>

    Dala funzione node_load() torna un oggetto ($node) contenente le informazioni lette mediante la query.
    In particolare i valori $node->body e $node->teaser conterranno rispettivamente contenuto e sommario del nodo.

    Oggetto $node generato dalla funzione.
    (ND=da tabella NODE; NR da tabella NODE_REVISIONS; US da tabella USERS)

    $node->nid ND identificativo univoco del nodo
    $node->language ND lingua del contenuto:'it' , 'en', 'fr', …
    $node->type ND tipo del nodo. Tabella di codifica NODE_TYPE
    $node->uid ND identificativo utente del proprietario del nodo
    $node->status ND =0 non visibile; =1 visibile
    $node->created ND timestamp della data di creazione del nodo
    $node->changed ND timestamp della data di modifica del nodo
    $node->comment ND identificativo utente dell'ultimo commento
    $node->promote ND =1 il nodo è visualizzato in prima pagina
    $node->moderate ND =1 il nodo deve essere controllato prima della pubblicazione
    $node->sticky ND numero d'ordine del nodo nella prima pagina
    $node->tnid ND set ID traduzione (da capire meglio)
    $node->translate ND Booleano.Indica se la traduzione deve essere aggiornata
    $node->sticky ND numero d'ordine del nodo nella prima pagina
    $node->vid NR identificativo del numero di revisione
    $node->uid NR identificativo utente del proprietario del nodo
    $node->title NR titolo del nodo per la revisione corrente
    $node->body NR contenuto del nodo per la revisione corrente
    $node->teaser NR sommario del nodo per la revisione corrente
    $node->log NR Messaggio di log contenente le modifiche eseguite
    $node->revision_timestamp NR data di modifica del nodo
    $node->format NR formato del nodo da tabella FILTERS_FORMAT
    $node->name US nome utente
    $node->picture US percorso all'immagine utente
    $node->data US serializzazione di un array che rappresenta i campi dela form utente

    Lettura extra-contenuto di un nodo

    Oltre alla lettura delle informazioni contenute specificatamente nelle tabelle NODE e NODE_REVISIONS, Drupal consente di aggiungere ulteriori informazioni ai nodi e quindi all'oggetto $node.
    Potremmo decidere di definire un nuovo tipo di nodo con informazioni aggiuntive salvate in una tabella separata.
    Pensiamo ad esempio ad una rubrica telefonica. Il nominativo e l'identificativo univoco potrebbero essere rispettivamente il campo <title> e il campo <nid> della tabella NODE, mentre tutte le informazioni aggiuntive come l'indirizzo, il telefono, l'email etc, potrebbero essere memorizzate in una tabella separata.
    Si pone quindi il problema di leggere queste ulteriori informazioni associate ai nodi.
    Drupal consente di leggere queste extra informazioni implementando funzioni particolari che gestiscano queste situazioni.
    Dobbiamo distinguere due casi:

    Implementazione della funzione legata alla tipologia del nodo

    Nella tabella NODE_TYPES sono elencati il tipo di nodi definiti nel sistema. Tra questi sono presenti i nodi principali, forniti con il sistema, quali: page, book, story etc.
    Dalla stessa tabella vediamo che il campo <module> ci dice da quale modulo sono gestiti i nodi.
    Ora supponiamo di aggiungere il nuovo tipo di nodo "rubrica" e che questo tipo di nodo sia gestito dall'omonimo modulo con tutte le sue funzioni implementate in rubrica.module. Ora quando Drupal leggerà un nominativo dal nodo rubrica, nominativo e identificativo saranno letti come indicato nel precedente paragrafo, mentre l'ulteriore contenuto sarà letto chiamando la funzione rubrica_load($node). La funzione deve tornare un array associativo costituito dalle coppie chiave=valore. Un esempio di semplice codice è il seguente:

    <?php
    function rubrica_load($node) {

          

    // rid = identificativo nominativo ;
          
    $r = db_fetch_object(db_query('SELECT  telefono, indirizzo,citta  FROM {rubrica} WHERE rid = %d ', $node->nid));
          
    info = array();
          
    info['telefono'] = $r->telefono;
          
    info['indirizzo'] = $r->indirizzo;
          
    info['citta']        = $r->citta;
           return
    $info;
    }
    ?>

    All'oggetto $node originale, Drupal aggiungerà le informazioni:

    $node->telefono
    $node->indirizzo
    $node->citta

    La funzione è chimata all'interno di node_load() mediante node_invoke($node,'load');
    Attenzione:Nel caso il modulo di gestione sia quello di default node, il nome della funzione deve essere node_content_load() e non node_load() come dovrebbe.

    Implementazione della funzione legata ad un modulo

    In questo caso viene chiamata una funzione per avvisare altri moduli che si sta caricando un nodo.
    Infatti la funzione non appartiene al modulo che gestisce il tipo di nodo come nel caso precedente , ma ad altri moduli attivi.
    A questo punto la funzione chiamata potrebbe compiere due diverse operazioni:

    • aggiungere informazione al nodo. Si ricade nel caso precedente e quindi anche la funzione potrebbe essere implementata in modo analogo.
    • Utilizzare l'informazione di lettura del nodo contenute in $node per altre attività ad esempio per eseguire statistiche sulla frequenza di lettura di quel nodo.

    In entrambi i casi possono dunque essere aggiunte o meno extra informazioni all'oggetto $node.
    La funzione da implementare deve chiamarsi nomemodulo_nodeapi($node,$opz).
    A questa funzione è passato l'oggetto $node e il valore $opz='load. che indica l'operazione che si sta eseguendo sul nodo .
    Un esempio di semplice codice, nel caso in cui venga aggiunta informazione a $node, è il seguente:

    <?php
    function rubrica_nodeapi($node,$opz) {

        switch (

    $opz)     {
            case
    'load':
                              
    info = array();
                              
    info['telefono'] = $r->telefono;
                             
    info['indirizzo'] = $r->indirizzo;
                             
    info['citta']        = $r->citta;
                              return
    $info;
                break;
            default:
                break;
    }
    ?>

    La funzione è chiamata all'interno di node_load() mediante node_invoke_nodeapi($node,'load');
    La funzione node_load() per ogni nodo letto chiama tutte le funzioni implametate in questo modo.

    Visualizzazione

    Abbiamo visto che la funzione node_load() insieme ad altre funzioni di integrazione, genera l'oggetto $node con tutte le informazioni sul nodo e, tra queste, quelle sul corpo ($node->body) e sul sommario ($node->teaser). Drupal deve ora leggere queste informazioni,e prepararle alla visualizzazione finale. La fase di preparazione del contenuto usa quindi la funzione node_view($node, $teaser = FALSE, $page = FALSE, $links = TRUE). Il parametro $node è l'oggetto nodo; $teaser indica se visualizzare o meno il sommario; $page indica se visualizzare o meno l'intero contenuto del nodo; $links indica se visualizzare o meno i links associati al nodo.
    Ma perchè è necessaria la fase di preparazione dei contenuti? Ci sono diversi motivi, ad esempio:

    • Necessità di codificare le informazioni in codice HTML
    • Eseguire codice PHP contenuto nei campi del nodo
    • Verificare che non ci sia codice malevolo
    • Consentire di tematizzare le informazioni del nodo
    • Tradurre le informazioni
    • Avviare eventi che avvisino la visualizzazione di quel nodo
    • Applicare il tema corrente al nodo

    In questa fase Drupal genera l'array $node->content[<campo>] che contiene tutti i contenuti del nodo, sia del campo body sia di tutti i campi aggiunti dai moduli esterni a quella tipologia di nodo.
    Vediamo quindi quali sono i passi che portano alla definizione del contenuto da visualizzare.
    Per fare questo di seguito è riportato integralmente il codice della funzione node_view()

    <?php
    function node_view($node, $teaser = FALSE, $page = FALSE, $links = TRUE) {
     
    $node = (object)$node;
     
    // ############## FASE 1
     
    $node = node_build_content($node, $teaser, $page);
     
    // ############## FASE 2
     
    if ($links) {
       
    $node->links = module_invoke_all('link', 'node', $node, $teaser);
       
    drupal_alter('link', $node->links, $node);
      }
     
    // Set the proper node part, then unset unused $node part so that a bad
      // theme can not open a security hole.
      // ############## FASE 3
     
    $content = drupal_render($node->content);
      if (
    $teaser) {
       
    $node->teaser = $content;
        unset(
    $node->body);
      }
      else {
       
    $node->body = $content;
        unset(
    $node->teaser);
      }
     
    // ############## FASE 4
      // Allow modules to modify the fully-built node.
     
    node_invoke_nodeapi($node, 'alter', $teaser, $page);
     
    // ############## FASE 5
     
    return theme('node', $node, $teaser, $page);
    }
    ?>

    La funzione comprende cinque fasi:
    1.Costruzione del contenuto
    Per prima cosa la funzione node_build_content (costruzione del contenuto) genera l'array $node[content].
    2. Costruzione dei links del contenuto
    Se richiesti i links nel contenuto, Drupal chiama tutte le funzioni dei moduli esterni che implementano la funzione nomemodulo_link($node,$teaser) e successivamente consente di modificare i links costruiti chiamando la funzione, se esistente, nomemodulo_tiponodo_alter(). Ad esempio avendo un tipo nodo rubrica e gestito dal modulo node, la funzione si chiamerà node_rubrica_alter().
    3. Rendering del contenuto
    Drupal esegue il rendering dei campi definiti in $node->content. Il risultato è una stringa che viene copiata in $node->body o $node_teaser in funzione dei valori passati in $page e $teaser.
    4. Modifica globale del contenuto
    Qui Drupal dà l'ultima possibilità di modificare le informazioni del nodo, contenuto e links inclusi, prima di applicare il tema corrente e di visualizzare il nodo.i
    5. Tematizzazione del contenuto
    Al termine il contenuto costruito viene tematizzato per la definitiva visualizzazione. Per un nodo generalmente è usato il template node.tpl.php.

    Fase 1: costruzione del contenuto nell'array $node[content]

    Avvia la costruzione del contenuto del nodo mediante la node_build_content($node, $teaser, $page);
    Qui, la preparazione dell'array $node[content] può avvenire mediante due funzioni:
    1. Una funzione personalizzata
    2. La funzione standard node_prepare()

    Funzione personalizzata

    Drupal legge il tipo di nodo corrente ($node->type) e dalla tabella NODE_TYPE ricava il modulo che gestisce il tipo di nodo, che supponiamo abbia il nome nomemodulo.
    Cerca quindi la funzione nomemodulo_view($node, $teaser, $page) e se esiste la chiama.
    Nel caso il nodo sia gestito dal modulo "node" la funzione si dovrebbe chiamare node_view, ma poichè questa funzione è quella che stiamo descrivendo, solo per questo caso la costruzione del nome della funzione non segue la regola generale, ma si dovrà chiamare node_content_view() (che comunque non esiste).
    La costruzione dell' array $node->content[] per tutti i campi del nodo è quindi totalmente affidata alla funzione personalizzata.

    Funzione standard node_prepare($node, $teaser)

    Se non è fornita la funzione personalizzata , Drupal chiama la sua funzione node_prepare()
    Qui viene elaborato il contenuto del corpo (body) o del sommario (teaser) del nodo applicando i fitri impostati tramite la funzione check_markup(), di cui parleremo in altra parte. Inoltre imposta il flag $node->readmore= True/False in funzione del valore di $teaser/$page. Al termine è generato il primo pezzo dell'array node->content e precisamente:
    node->content['body']['#value'] che contiene il valore del corpo o del sommario del nodo,
    node->content['body']['#weight']=0 posizione del corpo del nodo in fase di visualizzazione.
    Si pone ora il problema di generare il contenuto di tutti quei campi non standard del nodo, aggiunti eventualmente da altri moduli. Ad esempio se è stato generato un nuovo tipo di nodo usando il modulo CCK, il nodo conterrà campi aggiuntivi che devono essere gestiti dal modulo CCK. Per fare questo Drupal esegue tutte le funzione nomemodulo_nodeapi($node,'view', $teaser, $page).
    Gli array node->content['nome campo'] che vengono creati possono avere strutture complesse e non omogenee.
    Ad esempio per un campo CCK immagine la struttura che si ottiene è la seguente

    $node[content][field_immagine]	Array [6]	
    	field	Array [11]	
    		#type		content_field	
    		#title		immagine	
    		#field_name	field_immagine	
    		#access		true	
    		#label_display	above	
    		#node		stdClass	
    		#teaser		1	
    		#page		false	
    		#context	teaser	
    		#single		true	
    		items	Array [1]	
    			0	Array [7]	
    				#item	Array [12]	
    					fid	20	
    					list	0	
    					data	Array [0]	
    					uid	3	
    					filename	foto.jpg	
    					filepath	sites/files/foto.jpg	
    					filemime	image/jpeg	
    					filesize	123453	
    					status	1	
    					timestamp	1265803634	
    					nid	7	
    					#delta	0	
    				#weight	0	
    				#theme		filefield_formatter_default	
    				#field_name	field_immagine	
    				#type_name	nuovotipo	
    				#formatter	default	
    				#node		stdClass	
    	#weight	1	
    	#post_render	Array [1]	
    			0	content_field_wrapper_post_render	
    	#field_name	field_immagine	
    	#type_name	nuovotipo	
    	#context	teaser

    All'oggetto $node sono associati i Links di navigazione del nodo che , generalmente, compaiono al termine del sommario di un nodo in prima pagina. Se presenti sono inseriti nell' array $node->links. Drupal consente di generare l'array $node->links chiamando due funzioni personalizzate:
    - nomemodulo_link($type, $node, $teaser = FALSE)
    Dove:
    $type è il tipo di nodo (ad esempio 'node'),
    $node l'oggetto in cui inserire l'array del link,
    $teaser indica se il nodo è in prima pagina o meno.
    La funzione è chiamata per tutti i moduli che la implementano. Ad esempio node_link(), comment_link() taxonomy_link() etc.
    La funzione deve tornare un array contenente le componenti caratteristiche della funzione di costruzione del link: l().
    Come esempio di implementazione riporto integralmente la funzione node_link().

    <?php
    function node_link($type, $node = NULL, $teaser = FALSE) {
     
    $links = array();
      if (
    $type == 'node') {
        if (
    $teaser == 1 && $node->teaser && !empty($node->readmore)) {
         
    $links['node_read_more'] = array(
           
    'title' => t('Read more'),
           
    'href' => "node/$node->nid",
           
    // The title attribute gets escaped when the links are processed, so
            // there is no need to escape here.
           
    'attributes' => array('title' => t('Read the rest of !title.', array('!title' => $node->title)))
          );
        }
      }
      return
    $links;
    }

    ?>

    Come si vede , Il valore di ritorno è l'array $links che sarà aggiunta agli array già definiti. L'oggetto nodo non deve quindi essere modificato all'interno della funzione.
    - nomemodulo_link_alter(&$data)
    Dopo che l'intero array dei link è stato costruito, Drupal da una ultima opportunità di modificarlo chiamando ancora per tutti i moduli le funzioni nomemodulo_link_alter() passando in &$data il riferimento il valore $node->links.

    Fase 3:rendering del contenuto

    Il rendering del contenuto (generazione del codice HTML definitivo) avviene mediante la funzione drupal_render(&$elements) chiamata ricorsivamente su tutti i campi del nodo. Il parametro $elements corrisponde all'array precedentemente generata $node->content[]. La funzione torna la stringa $content contenente tutto il contenuto del nodo pronto per essere visualizzato. Il contenuto è copiato in $node->body o in $node->teaser a seconda dei valori $teaser e $page passati alla funzione node_view(). In $node , la variabile in cui non è copiato il contenuto è eliminata da Drupal.
    Al''interno della funzione drupal_render(), Drupal ci consente di modificare il contenuto sia prima di eseguire il rendering sia dopo averlo eseguito. Vediamo come.
    - Personalizzazione mediante $node->content['#pre_render']
    Prima di eseguire il rendering del contenuto, Drupal chiama tutte le funzioni eventualmente definite nell'array $node->content['#pre_render']. Le funzioni possono avere un qualsiasi nome e ad esse Drupal passa tutta l'array $node->content precedentemente generata.
    - Personalizzazione mediante $node->content[<campo>]['#pre_render']
    Il valore [#pre_render] può essere assegnato ad ogni campo (Es.: $content[body][#pre_render]) per chiamare una o più funzioni da eseguire per il particolare elemento. In questo caso è passato alla funzione il solo elemento $content[<campo>].
    - Personalizzazione mediante $node->content['#post_render']
    Dopo aver eseguito il rendering del contenuto, Drupal chiama tutte le funzioni eventualmente definite nell'array $node->content['#post_render']. Le funzioni possono avere un qualsiasi nome e ad esse Drupal passa la stringa $content contenente il rendering del contenuto e l'array $node->content.
    - Personalizzazione mediante $node->content[<campo>]['#post_render']
    Il valore [#post_render] può essere assegnato ad ogni campo (Es.: $content[body][#post_render]) per chiamare una o più funzioni da eseguire per il particolare elemento. Le funzioni possono avere un qualsiasi nome e ad esse Drupal passa la stringa $content contenente il rendering del contenuto e l'array $node->content[<campo>].
    - Personalizzazione mediante ['#prefix'] e ['suffix']
    Il rendering finale di ogni singolo elemento del contenuto viene sempre racchiuso tra i valori #prefix e #suffix forniti per quell'elemento come vediamo dal codice stesso della funzione drupal_render(&$elements)

    <?php

    function drupal_render(&$elements) {
    ......
     
    $prefix = isset($elements['#prefix']) ? $elements['#prefix'] : '';
     
    $suffix = isset($elements['#suffix']) ? $elements['#suffix'] : '';
        return
    $prefix . $content . $suffix;
    ...
    }
    ?>

    Fase 4:modifica globale del contenuto

    In questa fase, l'oggetto $node contiene il rendering del contenut , l'array dei links se presenti e quanto modificato o aggiunto dai moduli che implementano la funzione nomemodulo_nodeapi($node,'view', $teaser, $page).
    Qui il nodo può essere ulteriormente modificato prima che sia applicato il tema corrente, implementando nei moduli la funzione nomemodulo_nodeapi($node,'alter', $teaser, $page).

    Fase 5:tematizzazione del contenuto

    Al nodo è applicata la tematizzazione mediante la funzionetheme('node', $node, $teaser, $page) . Generalmente per tematizzare un nodo viene usato il file template node.tpl.php. Di questo ne parleremo in altra parte.

    Eventi

    Drupal durante le operazioni di caricamento, inserimento, aggiornamento, cancellazione e visualizzazione dei nodi , consente allo sviluppatore di eseguire funzioni personalizzate per alterare la modalità operativa standard.
    Indichiamo con:

    • nomemodulo il nome di un modulo personallizzato che implementa le funzioni richieste.
    • nomemodulotipo il nome del modulo che gestisce il tipo di nodo, letto dalla tabella NODE_TYPE nel campo module. Nel caso che il tipo sia node, nomemodulotipo sarà uguale a node_content, e i nomi di funzione dovranno essere quindi node_content_load, node_content_view, node_content_save, questo perchè le funzioni node_load, node_view, node_save etc. sono funzioni standard di Drupal.
    • nometipo il nome del tipo di nodo.

    Per ogni tipo di operazione, la sequenza con cui sono descritte le funzioni coincide con quella di esecuzione.
    Di seguito riportiamo le funzioni che , se esistenti, sono chiamate da Drupal nei diversi contesti.

    Caricamento

    nomemodulotipo_load(&$node,$page,$teaser)

    Implementata nel modulo che gestisce il tipo di nodo, consente di caricare dei campi aggiuntivi all'oggetto nodo.

    nomemodulo _nodeapi($node,$op='load')

    Consente a ogni modulo che la implementa di aggiungere ulteriori campi all'oggetto nodo non definiti nella tabella NODE.

    Visualizzazione

    nomemodulotipo_view($node,$page,$teaser)

    Implementata nel modulo che gestisce il tipo di nodo, se presente sosituisce la funzione node_prepare() che è responsabile della generazione dell'array $node->[content].

    nomemodulo _nodeapi(&$node,$op='view')

    Consente a ogni modulo che la implementa di preparare alla visualizzazione i campi aggiunti al nodo.

    nomemodulo_link($type, $node, $teaser = FALSE)

    $type è il tipo di nodo (ad esempio 'node'),
    Consente a ogni modulo che la implementa di aggiungere links da visualizzare nel nodo corrente.

    nomemodulo_link_alter(&$node->links)

    Consente a ogni modulo che la implementa di modificare l'intero array dei links da visualizzare nel nodo corrente.

    nomemodulo_nodeapi($node,'alter', $teaser, $page)

    Consente a ogni modulo che la implementa di modificare l'intero oggetto $node prima che il nodo sia passato alla funzione theme('node', $node).

    Blocchi

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

    Fanno parte dei blocchi, oltre ai blocchi stessi, anche i menu, i commenti, gli utenti, le categorie etc.
    Tutti i blocchi condividono la tabella BLOCKS su cui il sistema salva informazioni di carattere generale. I contenuti sono invece salvati in tabella specifiche per ciascun tipologia di blocco.

    Le funzioni principali

    Riporto, per comodità, le principali funzioni che sono implicate nel processo di lettura e visualizzazione del contenuto dei blocchi.

    - template_preprocess_page(&$variables)
    La funzione template_preprocess_page(), contenuta in includes/theme.inc, viene chiamata da theme('page') ed è la funzione che avvia il processo di lettura dei blocchi utilizzando le successive funzioni.

    - theme_blocks($region)
    La funzione theme_blocks($region) legge tuttii blocchi da visualizzare e contenuti nella regione identificata da $region.
    Torna una stringa stampabile su web contenente tutto il codice HTML della regione richiesta.
    Il contenuto della regione è inserito in $variables[$region] per essere utilizzato da page.tpl.php.
    Le regioni generalmente sono:$left,$right,$header,$footer,$content.

    - theme_block('view',$block)
    La funzione theme_block('view',$block) formatta il contenuto $block->content chiamando il file template block.tpl.php. Può essere creata una funzione utente definendo la miotema_block() o phptemplate_block().
    Torna una stringa stampabile su web contenente il codice HTML del contenuto $block->content.

    - block_list($region)
    La funzione block_list($region) legge le informazioni ed il contenuto dei blocchi da visualizzare nella pagina richiesta e nella regione identificata da $region.
    Torna un oggetto $block per ogni blocco letto. Questo oggetto è utilizzato dal file template block.tpl.php.

    La selezione dei blocchi

    Quando viene richiesta la visualizzazione di una qualsiasi pagina, Drupal carica per prima cosa il file index.php. All'interno di questo file viene chiamata la funzione theme() a cui è passato il paramentro 'page' . Con questo parametro la funzione theme() chiamerà la funzione template_preprocess_page.
    All'interno di essa è contenuto il seguente codice:

    <?php
     
      
    ............................................

      global

    $theme;
     
    // Populate all block regions.
     
    $regions = system_region_list($theme);
     
    // Load all region content assigned via blocks.
     
    foreach (array_keys($regions) as $region) {
         
    // Prevent left and right regions from rendering blocks
           
    when 'show_blocks' == FALSE.
          if (!(!
    $variables['show_blocks'
                                   && (
    $region == 'left' || $region == 'right'))) {
         
    $blocks = theme('blocks', $region);
        }
        else {
          
    $blocks = '';
        }
       
    // Assign region to a region variable.
       
    isset($variables[$region])
                          ?
    $variables[$region] .= $blocks
                         
    : $variables[$region] = $blocks;
      }
    .........................
    ?>

    La system_region_list legge le regioni del tema corrente e, nel successivo cilclo, per ciascuna di esse, la funzione theme('blocks', $region) legge il contenuto dei blocchi appartenenti alla regione indicata e lo pone nella variabile $variables[$region] che sarà successivamente utilizzata dal file template del tema: page.tpl.php.

    Sappiamo che chiamare la funzione theme('blocks', $region) equivale a chiamare la funzione theme_blocks($region) implementata nel modulo includes/theme.inc e di seguito riportata.

    <?php
    function theme_blocks($region) {
     
    $output = '';

      if (

    $list = block_list($region)) {

        foreach (

    $list as $key => $block) {
         
    // $key == <i>module</i>_<i>delta</i>
         
    $output .= theme('block', $block);
        }
      }
    ?>

    In theme_blocks() sono presenti le due funzioni responsabili della lettura e visualizzazione dei blocchi:

    La prima estrae dal database i contenuti da visualizzare insieme ad altre informazioni relative ai blocchi.
    La seconda incapsula il contenuto ($block->content) in codice HTML secondo quanto definito nei file di template del tema corrente block.tpl.php o in altri definiti dall'utente.

    Query di selezione dei blocchi

    Il contenuto dei blocchi da visualizzare sulla pagina è individuato all'interno della funzione block_list() mediante l'esecuzione della seguente query di selezione:

    SELECT DISTINCT b.* FROM blocks b
             LEFT JOIN blocks_roles r ON b.module = r.module AND b.delta = r.delta
             WHERE b.theme = '<nome tema corrente>'
                          AND b.status = 1
                         AND (r.rid IN ( <elenco dei ruoli dell'utente corrente>  ) OR r.rid IS NULL)
              ORDER BY b.region, b.weight, b.module

    Da questa query vediamo che un blocco per essere selezionato deve:

    Da quanto detto si capisce perchè, cambiando tema o utente certe volte non vengono visualizzati alcuni blocchi.

    Il contenuto dei blocchi

    Abbiamo visto che la funzione block_list() è chiamata nel seguente modo: $list = block_list($region)
    Il valore di ritorno $list è un array associativa i cui elementi sono così formati:

    $block= $list["modulo_delta"] = oggetto

    dove:

    $block->bid da tabella BLOCKS
    $block->module da tabella BLOCKS
    $block->delta da tabella BLOCKS
    $block->theme da tabella BLOCKS
    $block->status da tabella BLOCKS
    $block->weight da tabella BLOCKS
    $block->region da tabella BLOCKS
    $block->custom da tabella BLOCKS
    $block->throttle da tabella BLOCKS
    $block->visibility da tabella BLOCKS
    $block->pages da tabella BLOCKS
    $block->title da tabella BLOCKS
    $block->cache da tabella BLOCKS
    $block->content contenuto del blocco (per un blocco , il contenuto di body)
    $block->subject titolo da visualizzare nella pagina
    $block->enabled VERO/FALSO (indica se il blocco è abilitato ad essere visualizzato)
    $block->page_match VERO/FALSO (indica se il blocco può essere visualizzato)

    Queste informazioni sono disponibili in fase di lettura del file template block.tpl.php.

    Le tabelle dei contenuti
    L'oggetto precedente contiene il valore $block->content che rappresenta il vero contenuto del blocco, ciò che è stato effettivamente inserito come informazione del blocco.
    Questa informazione non è contenuta nella tabella BLOCKS ma nelle tabelle relative alla tipologia del blocco.
    Ad esempio, per i principali moduli:

    Per moduli non di sistema, potranno esserci altre tabelle di contenuto.

    Le funzioni di lettura dei contenuti
    Il contenuto del blocco è letto dalla funzione di gestione del modulo: nomemodulo_block().
    La funzione di lettura dei contenuti del blocco è chiamata all'interno di block_list() mediante la funzione:
    module_invoke($block->module, 'block', 'view', $block->delta).
    Per i blocchi precedentemente indicati, il contenuto sarà letto da:

    In generale , per moduli non di sistema , Drupal chiamerà la funzione nomemodulo_block('view', $blocks).

    Menu

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

    I menu sono un particolare tipo di blocco.
    La loro gestione è fornita dal modulo modules/menu.module e dalle funzioni contenute nel file includes/menu.inc.

    Le funzioni principali

    menu_block($op = 'list', $delta = 0)
    La funzione menu_block() legge il contenuto del menu individuato dal valore $delta. E' chiamata in fase di generazione dei blocchi dalla funzione block_list() con $op='view'.
    Torna la seguente array:
    $block['subject'] = titolo del bloccco
    $block['content'] = stringa del contenuto del menu in formato HTML. [vedi menu_tree()]
    L'array è usata in block.tpl.php.

    menu_tree($delta)
    La funzione menu_tree() ,chiamata da menu_block(), genera il codice HTML del menu individuato dal valore $delta.
    Il valore di ritorno è una stringa.
    Questa funzione chiama la menu_tree_page_data() per la lettura del contenuto del menu e la menu_tree_output() per la generazione del contenuto in codice HTML.

    menu_tree_page_data($menu_name)
    La funzione menu_tree_page_data() legge i contenuti dalle tabelle MENU_LINKS e MENU_ROUTER.
    Ttornando un array associativa.
    Vedere Il contenuto dei menu per una descrizione più dettagliata.

    menu_tree_output($tree)
    La funzione menu_tree_output() prende in ingresso l'array $tree prodotto da menu_tree_page_data() contenente tutte le informazioni sul menu da visualizzare e la converte in codice HTML .
    Torna una stringa.
    Questa funzione chiama le funzioni personalizzabili:

    menu_primary_links()
    La funziome menu_primary_links() torna un array $tree contenente titolo e riferimenti del menu di navigazione Primary links.

    menu_secondary_links()
    La funziome menu_secondary_links() torna un array $tree contenente titolo e riferimenti del menu di navigazione Secondary links.

    theme_links($links,$attributes)
    La funzione theme_links() genera il codice HTML dei menu di navigazione Primary links e Secondary links.
    E' chiamata in page.tpl.php

    menu_list_system_menus()
    La funzione menu_list_system_menus() torna un array con i nomi dei menu di sistema:''navigation', 'primary-links', 'secondary-links';

    menu_get_menus()
    La funzione menu_get_menus() legge i nomi dei menu utente e di sistema dalla tabella MENU_CUSTOM.
    Torna un array associativo con i nomi dei menu.
    Esempio:
    $menu[menu-mio] = "Menu mio"
    $menu[navigation] = "Navigation"
    $menu[primary-links] = "Primary links"
    $menu[secondary-links] = "Secondary links"

    menu_get_item($path=NULL, $router_item = NULL)
    La funzione menu_get_item() legge i record dalla tabella MENU_ROUTER filtrando suii valori del campo "path" compatibili al percorso della pagina richiesta.
    Ad esempio se il percorso della pagina richiesta è node/12345/edit, i possibili valori su cui sarà eseguito il filtro saranno:

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

    La funzione torna il primo record di MENU_ROUTER in cui il campo "path" è uguale ad uno dei valori suddetti.
    La ricerca del valore di "path" che soddisfa ad uno dei valori suddetti è eseguita secondo il numero d'ordine discendente definito nel campo "FIT".

    La selezione dei menu

    Abbiamo detto che un menu è un particolare tipo di blocco. Questo significa che le informazioni di selezione sono contenute nella tabella BLOCKS e seguono gli stessi criteri descritti per i blocchi. Quindi i menu selezionati saranno quelli che nella query di selezione dei blocchi hanno il nome modulo uguale a "menu".
    Questo è vero per i menu generici.Per i menu primary-links e secondary-links la selezione avviene mediante le due funzion menu_primary_links() e menu_secondary_links() chiamate in template_preprocess_page() durante la generazione della pagina.
    Rispetto ai blocchi, nei menu ciò che cambia è come leggere e visualizzare il contenuto e questo verrà descritto qui di seguito.

    Il contenuto dei menu

    Il conenuto di un menu è letto dalla funzione menu_block(). All'interno di essa, la lettura e codifica del contenuto del menu viene eseguita, attraverso la funzione menu_tree($menu_name) , dalle due funzioni: menu_tree_page_data() e menu_tree_output().
    - La prima , prende in input un nome di menu e in output fornisce un array ($tree) contenente tutte le informazioni lette dalle tabelle MENU_LINKS e MENU_ROUTER per il menu richiesto.
    - La seconda, prende in input l'array $tree e genera in output il codice HTML del menu richiesto passandolo alla funzione menu_block().

    <?php
    function menu_tree($menu_name = 'navigation') {
      static
    $menu_output = array();

      if (!isset(

    $menu_output[$menu_name])) {
       
    $tree = menu_tree_page_data($menu_name);
       
    $menu_output[$menu_name] = menu_tree_output($tree);
      }
      return
    $menu_output[$menu_name];
    }
    ?>

    L'array $tree, contiene quindi tutte le informazioni delle singole voci appartenenti all'albero del menu corrente.
    La singola voce del menu è individuata da una stringa costruita nel seguente modo:
    $tree[<50000 + campo_weight> spazio <campo_title> spazio <campo_mlid>]
    dove:
    50000 è un valore fisso;
    <campo_weight> è il peso (ordine) della voce nel menu;
    <campo_title> è il titolo della voce corrente;
    <campo_mlid> è l'identificativo univoco della voce in MENU_LINKS

    Ad esempio per weight=-10 , title=Drupal mlid=96 la stringa che individua la voce è: $tree["49990 Drupal 96"]
    Tutti i valori estratti per la singola voce del menu sono posti in $tree["49990 Drupal 96"][link].

    Qui di seguito sono riportati i valori contenuti in $tree per ogni voce del menu:

     (MR = da tabella MENU_ROUTER; ML= da tabella MENU_LINKS; AL=da altre fonti  )
    
    MR $tree[ 49990 Drupal 96][link][load_functions]
    MR $tree[ 49990 Drupal 96][link][to_arg_functions] 
    MR $tree[ 49990 Drupal 96][link][access_callback] 
    MR $tree[ 49990 Drupal 96][link][access_arguments]
    MR $tree[ 49990 Drupal 96][link][page_callback] 
    MR $tree[ 49990 Drupal 96][link][page_arguments]
    MR $tree[ 49990 Drupal 96][link][title] = Drupal
    MR $tree[ 49990 Drupal 96][link][title_callback] 
    MR $tree[ 49990 Drupal 96][link][type] 
    MR $tree[ 49990 Drupal 96][link][description] 
    ML $tree[ 49990 Drupal 96][link][menu_name] 
    ML $tree[ 49990 Drupal 96][link][mlid]  = 96
    ML $tree[ 49990 Drupal 96][link][plid] 
    ML $tree[ 49990 Drupal 96][link][link_path] =  node/67
    ML $tree[ 49990 Drupal 96][link][options]  => array()
    ML $tree[ 49990 Drupal 96][link][module] 
    ML $tree[ 49990 Drupal 96][link][hidden] 
    ML $tree[ 49990 Drupal 96][link][has_children] 
    ML $tree[ 49990 Drupal 96][link][expanded ] 
    ML $tree[ 49990 Drupal 96][link][weight ]  = -10 
    ML $tree[ 49990 Drupal 96][link][depth] 
    ML $tree[ 49990 Drupal 96][link][customized] 
    ML $tree[ 49990 Drupal 96][link][p1]  = 96
    ML $tree[ 49990 Drupal 96][link][p2]
    ML $tree[ 49990 Drupal 96][link][p3]
    ML $tree[ 49990 Drupal 96][link][p4]
    ML $tree[ 49990 Drupal 96][link][p5]
    ML $tree[ 49990 Drupal 96][link][p6]
    ML $tree[ 49990 Drupal 96][link][p7]
    ML $tree[ 49990 Drupal 96][link][p8]
    ML $tree[ 49990 Drupal 96][link][p9]
    ML $tree[ 49990 Drupal 96][link][updated ]
    AL $tree[ 49990 Drupal 96][link][in_active_trail] = FALSO/VERO
    AL $tree[ 49990 Drupal 96][link][access ] = VERO/FALSO
    AL $tree[ 49990 Drupal 96][link][href ]  =  node/67
    AL $tree[ 49990 Drupal 96][link][localized_options] = array()
    AL $tree[ 49990 Drupal 96][link][below] = FALSO/VERO

    Le prime componenti riguardano le funzioni e gli argomenti richiesti per visualizzare la voce del menu.
    Poi ci sono alcune voci interessanti: il nome del menu [menu_name], se la voce è espansa o no [expanded], se ha figli [has_children], la pagina a cui punta [href ], il livello di profondità a cui appartiene la voce [depth], se la voce è quella selezionata [in_active_trail]. La componente [localized_options] può contenere un array caricato da funzioni di tematizzazione. Ad esempio la funzione theme_menu_item_link() la usa per inserite gli attributi per il tag HTML <a>.
    Avendo il menu una struttura ad albero , l' eventuale identificativo della voce padre è posto in [plid], ed inoltre, per ogni ramo, sono indicati i nodi di diramazione <mlid> fino al nodo radice , attraverso i valori da [p1] (radice) a [p9].
    Infine il valore [below] può contenere un array. Questa array è ancora di tipo $tree e rappresenta tutto il sotto albero che si sviluppa a partire dalla voce corrente.

    Il contenuto dei menu Primary links e Secondary links

    Le due funzioni preposte alla lettura dei menu di navigazione sono la menu_primary_links() e menu_secondary_links(), chiamate all'interno della funzione template_preprocess_page(). Il codice HTML dei menu generato viene posto in $variables['primary_links'] e $variables['secondary_links'], per essere infine reso disponibile nel template page.tpl.php mediante le variabili $primary_links e $secondary_links.

    Il contenuto di Primary links

    Dalla funzione menu_primary_links() torna un array $links[] ad esempio formato nel seguente modo:

    $links[menu-45 active-trail][] = array() eventuali attibuti
    $links[menu-45 active-trail][href] => node/18
    $links[menu-45 active-trail][title] => LINK_1
    
    $links[menu-48][] = array() eventuali attibuti
    $links[menu-48][href] => node/19
    $links[menu-48][title] => LINK_2
    
    $links[menu-46l][] = array() eventuali attibuti
    $links[menu-46][href] => node/17
    $links[menu-46][title] => LINK_3
    
    

    Nell'esempio il menu è formato da:

    Questa array viene successivamente elaborata dalla funzione theme_links($primary_links,array('class' => 'links primary-links') ), chiamata nel file template page.tpl.php (tema garland), e che produce il codice HTML definitivo:.

    <ul class="links primary-links">
    		<li class="first menu-45 active-trail">
    			<a href="/node/18" class="active">LINK1</a>
    		</li>
    		<li class="menu-48">
    			<a href="/node/19">LINK_2</a>
    		</li>
    		<li class="menu-46">
    			<a href="/node/17">LINK_3</a>
    		</li>
    </ul>
    

    Per la precisione in page.tpl.php viene chiamata la funzione theme('links',$primary_links,array('class' => 'links primary-links')) ma che sappiamo corrispondere alla theme_links(). Questa funzione peraltro può essere personalizzata generando in template.php la funzione miotema_links() o phptemplate_links().

    Il codice generato , è infine incapsulato in page.tpl.php all'interno di un blocco <DIV> nel seguente modo:

    <div class="links primary-links" > 
       
         codice HTML prodotto
    
    </div> 

    Di seguito è riportato il codice della funzione theme_links() fornita con Drupal .
    All'interno dell codice sono riportati alcuni commenti esplicativi.

    <?php
    // Parametri in ingresso
    // $links contiene l'array prodotto da menu_primary_links()
    // $attibutes è un array che conterrà il valore passato in page.tpl.php, in paticolare per il tema garland viene passata il // valore array('class' => 'links primary-links')
    function theme_links($links, $attributes = array('class' => 'links')) {
     
    $output = '';

    // Qui vengono contati il numero di link del menu per definire la class 'first' e 'last'
     
    if (count($links) > 0) {

    // Inizio della lista con TAG <ul>  l'attributo ID del tag corrisponde al valore 'class' passato in input
       
    $output = '<ul'. drupal_attributes($attributes) .'>';
       
    $num_links = count($links);
       
    $i = 1;

    // Inizio lettura LINK
       
    foreach ($links as $key => $link) {
    // Definizione dell' attributo 'class' per il tag   <li>
    // Il nome minimo sarà menu-xx. nel nostro esempio menu-45 menu-46 menu-48
         
    $class = $key;

    // Aggiunge 'first', 'last' e 'active'  alla stringa della classe per meglio specificare l'elemento che si sta visualizzando.
         
    if ($i == 1) {
           
    $class .= ' first';
          }
          if (
    $i == $num_links) {
           
    $class .= ' last';
          }
          if (isset(
    $link['href']) && ($link['href'] == $_GET['q'] || ($link['href'] == '<front>' && drupal_is_front_page()))) {
           
    $class .= ' active';
          }
    // Scittura del tag <li>
         
    $output .= '<li'. drupal_attributes(array('class' => $class)) .'>';

    // preparazione del tag anchor <a>
         
    if (isset($link['href'])) {
           
    // Pass in $link as $options, they share the same keys.
           
    $output .= l($link['title'], $link['href'], $link);
          }
          else if (!empty(
    $link['title'])) {
           
    // Some links are actually not links, but we wrap these in <span> for adding title and class attributes
           
    if (empty($link['html'])) {
             
    $link['title'] = check_plain($link['title']);
            }
           
    $span_attributes = '';
            if (isset(
    $link['attributes'])) {
             
    $span_attributes = drupal_attributes($link['attributes']);
            }
           
    $output .= '<span'. $span_attributes .'>'. $link['title'] .'</span>';
          }
    // fine primo link
         
    $i++;
         
    $output .= "</li>\n";
        }
    // fine lista
       
    $output .= '</ul>';
      }

    // torna il codice prodotto

     

    return $output;
    }
    ?>

    Il contenuto di Secondary links

    Quanto detto per il menu Primary links vale per Il menu Secondary links.
    E' utilizzata per la lettura dei contenuti la funzione: menu_secondary_links().
    In page.tpl.php la variabile usata è la $secondary_links.
    Il blocco <div> che coniene il codice HTML è il seguente:

    <div class="links secondary-links" > 
       
         codice HTML prodotto
    
    </div> 

    Temi

    Un tema identifica tutto ciò che consente di visualizzare i contenuti del sito secondo una rappresentazione grafica definita dal tema stesso. I contenuti del sito sono quindi sempre gli stessi ma posizionati e visualizzati in modo diverso in funzione del tema scelto.

    In generale un tema è costituito dai seguenti elementi:

    Le regioni
    Le regioni indicano come i diversi conenuti da visualizzare sulla pagina devono essere posizionati.
    In pratica rappresentano lo scheletro della pagina, una serie di buchi da riempire con contenuti.
    La struttura maggiormente usata per le regioni è la seguente:
    Una intestazione (header), una o due barre laterali a sinistra e a destra (sidebar) per blocchi, menu, pubblicità, una regione centrale (content) contenente il contenuto principale della pagina e una regione a fondo pagina (footer) per informazioni secondarie del sito. Nulla vieta naturalmente di complicare la pagina definendo più regioni.

    I fogli di stile CSS
    Uno o più file contenenti le definizioni degli stili da applicare ai tag HTML del tema.
    Il file principale per definizione è il file style.css

    I file template
    Sono i file che applicano il codice HTML ai contenuti da visualizzare. Questi file hanno sempre
    estensione .tpl.php
    I temi di Drupal hanno quattro file template fondamentali che si trovano sempre nella directory del tema.

    Il file template.tpl.php
    In questo file possono essere implementate funzioni che consentono di eseguire un override delle funzioni di base della tematizzazione.
    Ad esempio il codice HTML per i link che compaiono sotto un nodo quando è mostrato in modalità sommario (teaser) come leggi tutto, aggiungi un commento etc, è definito nella funzione di base theme_links(). Volendo visualizzare in modo diverso questi link si potrà definire la funzione miotema_links() nel file template.tpl.php. Drupal trovando questa nuova funzione, la eseguirà al posto della theme_link().

    Immagini e icone
    Immagini e icone di corredo al tema.

    Theme System

    QUESTA SEZIONE E' IN LAVORAZIONE
    ----------------------------------------------

    Quando Drupal deve generare il codice HTML per elementi come nodi, blocchi , menu, breadcrumb, links e altro, cerca, per il tema corrente, le funzioni e file teplate che consentono di codificare gli elementi richiesti.
    La ricerca avviene applicando regole sulla priorità di ricerca, sui nomi e sulla posizione delle funzioni e dei file all'interno delle directory e dei moduli che consentono a Drupal di ottenere una elevata personalizzazione del sistema.
    Conoscendo e seguendo le regole di ricerca è possibile personalizzare un sito generando nuove funzioni e file template in base alle proprie esigenze.

    Convenzioni su nomi e file

    Nome del tema

    Il nome del tema deve essere diverso dal nome di qualsiasi modulo

    Directory del tema

    Tutti i file appartenenti alla definizione di un tema , devono stare all’interno di una propria subdirectory che prende il nome del tema. La subdirecotory può essere contenuta all'interno di una delle seguente directory:

    • miosito/themes/miotema
    • miosito/sites/all/....../miotema

    Il motore di elaborazione del tema controllerà , per il tema selezionato, la presenza di file template con estensione .tpl.php.


    Il file screenshot del tema

    Il file deve essere in formato .png di dimensioni 150x90.
    Se presente viene mostrato nella pagina di amministrazione dei temi.

    I file di stile CSS

    Il file di stile del tema

    Il tema utilizza come dichiaratore di stile il file style.css per default.
    Altri file possono essere caricati utilizzando l'istruzione @import dei file css.

    Temi multipli con più file di stile

    E’ possibile creare temi che differiscono per il solo file di definizione degli stili css:style.css.
    Per fare questo bisogna creare nella directory di base del tema, delle subdirectory contenenti i file style.css. Ogni subdirectory costituirà un nuovo tema. Ad Esempio:

    miosito/sites/all/themes/miotema_A/ (directory principale del tema)

    • template.tpl.php file di template comuni
    • page.tpl.php file di template comuni
    • ...
    • style.css
    • miotema_B/style.css
    • miotema_C/style.css

    Il motore riconoscerà tre temi: miotema_A, miotema_B, miotema_C.
    Ciascun tema utilizzerà i file di base con estensione .tpl.php, e ciascuno avrà nella propria subdirectory il file di stile style.css.

    La suddivisione in Regioni

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

    Funzioni principali:
    phptemplate_regions()
    drupal_set_content($region=NULL,$data=NULL)

    I temi possono definire ed implementare un numero generico di regioni.
    Le regioni sono essenzialmente contenitori di... contenuti.
    Le regioni suddividono la pagina del browser in aree che costituiranno i limiti in cui visualizzare i contenuti stessi. Così, generalmente, tutti i temi hanno una regione per:

    • i contenuti dell’intestazione, header
    • due regioni per i contenuti dei menu laterali, sidebar-left e sidebar-right
    • una regione per i contenuti del fondo pagina, footer
    • una regione centrale, content

    ed altre regioni che possono complicare notevolmente il layout del sito.

    Definizione delle regioni

    Le regioni sono definite mediante una funzione php che torna un array associativo contenente la codifica delle regioni e la loro descrizione utilizzata nella pagina di amministrazione dei blocchi.
    La funzione è la seguente:

    function phptemplate_regions() {
      return array(
           'left' => t('left sidebar'),
           'right' => t('right sidebar'),
           'content' => t('content'),
           'header' => t('header'),
           'footer' => t('footer')
      );
    }

    Il primo nome della regione diventa la regione di default per il posizionamento di blocchi nel caso in cui non sia dichiarata espressamente una regione.

    Nel caso di PhpTemplate Engine la funzione phptemplate_regions() è contenuta nel file: miosito/themes/engines/phptemplate/phptemplate.engine.
    Drupal prima di chiamare questa funzione , verifica se esiste una funzione analoga fornita nei file template del tema corrente e che si chiami miotema_regions().
    Per cui, per personalizzare le regioni di un tema, bisogna definire la funzione miotema_regions() nel file template.php nella directory del tema.

    function miotema_regions() {
      return array(
           'regione1' => t('regione1'),
           'regione2' => t('regione2'),
           'regione3' => t('regione3'),
           'header' => t('header'),
           'footer' => t('footer')
      );

    Nel caso di .theme Engine la funzione è contenuta nel file del tema miotema.theme

    Per riempire una regione è possibile utilizzare la funzione

    function drupal_set_content($region = NULL, $data = NULL) {
      static $content = array();
      if (!is_null($region) && !is_null($data)) {
        $content[$region][] = $data;
      }
      return $content;
    }

    Es.: drupal_set_content('left', 'Hello there.')

    phptemplate engine

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

    Il motore phptemplate è contenuto nella direcotory themes/engines/phptemplate ed è costituito dai seguenti file:

    1) phptemplate.engine contenente le funzioni di default per la gestione di blocchi, box. commenti, nodi
    2) default.tpl.php non è ancora chiaro l'uso
    3) node.tpl.php per la stampa dell’oggetto nodo
    4) block.tpl.php per la stampa dell’oggetto blocco
    5) box.tpl.php per la stampa dell’oggetto box
    6) comment.tpl.php per la stampa dell’oggetto commento

    Questi sono alcuni dei file necessari per la gestione di un tema di default. Ma per la realizzazione del tema sono necessari altri due file,fondamentali, contenuti obbligatoriamente nella subdirectory del tema selezionato:

    page.tpl.php è il file principale del tema che definisce il layout del tema.
    style.css contiene la definizione degli stili del tema.

    Ogni tema può quindi utilizzare, i due file page.tpl.php e style.css pi ù i cinque file di default .tpl.php contenuti in themes/engines/phptemplate oppure una loro implementazione personalizzata. In questo caso i file si dovranno chiamare allo stesso modo , ma dovranno trovarsi nella subdirectory del tema.

    Aggiungere un tema

    Per aggiungere un nuovo tema, si deve quindi:

    creare una nuova directory con il nome del tema in /sites/all/themes/miotema oppure /themes/miotema

    • copiare nella directory i file *.tpl.php
    • scrivere un nuovo file page.tpl.php per la definizione del layout del tema
    • scrivere un nuovo file style.css per la definizione degli stili del tema

    La cosa più semplice, comunque, è prendere i file di un tema esistente, magari di quelli di default (bluemarine), copiarli nella nuova directory e cominciare a modificarli secondo le proprie esigenze.

    block.tpl.php

    I blocchi sono costituiti da codice HTML , eventualmente costruito dinamicamente da script PHP, posizionato all’interno di una regione del tema corrente. Esempi di un blocco sono i campi utente/password per il login al sistema, il menu di navigazione e in generale i menu utente, il calendario etc.

    Un blocco può anche essere costituito da una singola stringa, immagine o altro da posizionare in una determinata regione del tema.

    Per definire un blocco si hanno due possibilità:

    Aggiunta da interfaccia di un nuovo blocco utente

    In questa modalità un utente con permessi di amministrazione dei blocchi, può creare un nuovo blocco. Basta andare nella pagina di amministrazione dei blocchi ed eseguire Aggiungi blocco.
    Impostare un titolo e nell’area Corpo del blocco definire il codice HTML o PHP del nuovo blocco.

    Esempio.:

    <p>questo è un blocco </p>
     oppure
    <?php  print “questo è un blocco”; ?>
    

    Attenzione, selezionare l’opzione appropriata per il formato di input.

    Blocco che contiene un altro blocco

    Un blocco può anche contenere, a sua volta, un altro blocco.

    Per richiamare un blocco utente scrivere:

     
    <?php 
     $block = module_invoke('block', 'block', 'view', 1); 
     print $block['content'];
     ?> 
    

    Dove il valore 1 indica il delta , ma per i blocchi utenti rappresenta il primo blocco creato, 2 il secondo blocco creato etc. etc. Questo valore può essere letto nella tabella blocks di MySQL nel campo delta.
    Il codice scritto dall’utente &erave; invece contenuto nella tabella boxes nel campo body mettendo in join i campi boxes.bid = blocks.delta.

    Definizione di un modulo

    Per definire un blocco all’interno di un modulo Drupal, è necessario implementare la funzione nomemodulo_block() all’interno del modulo. Questo esula dalla presente documentazione e si rimanda l’argomento alla trattazione dei moduli.

    Posizionamento di un blocco

    Tutti i blocchi definiti sono visibili nella pagina di amministrazione dei blocchi, da cui è possibile indicare in quale regione visualizzare il blocco.

    node.tpl.php

    Template del tema corrente per la visualizzazione del contenuto di un nodo.
    E' usato nella fase di preparazione del codice HTML per il contenuto della pagina richiesta, preparazione avviata dalla funzione menu_execute_active_handler()

    La funzione theme()

    E' sconsigliato inserire direttamente codice HTML in Drupal, sebbene sia permesso dai formati di input (FilteredHTML,FullHTML). Drupal mette a disposizione delle funzioni proprio per produrre codice HTML personalizzabili all'interno di ciascun tema.

    Le funzioni che producono codice HTML, devono però poter funzionare per qualunque tema selezionato. Ad esempio volendo stampare una tabella si può usare la funzione theme_table() o volendo stampare un blocco si può usare la funzione theme_block(). Tutte le funzioni tematizzate di sistema si trovano nel file includes/theme.inc. Ma se, ad esempio, un tema deve visualizzare l’oggetto ‘blocco’ in un modo particolare può essere implementata la funzione theme_block(), chiamandola miotema_block(), ed inserendola nel file template.tpl.php.

    A questo punto è necessario che Drupal sia in grado di sapere che esiste una funzione personalizzata ed usare quella invece della funzione di default. Prendondo come esempio la funzione theme_table(), Drupal, nel momento in cui deve chiamare la funzione, verifica, con le priorità indicate, se:

    Il tema implementa la funzione

    Verifica se la funzione theme_table() è implementata nel tema corrente.
    La funzione implementata:

    • si deve chiamare: miotema_table()
    • può stare nel file template.php o in un file .tpl.php del tema

    Il motore di template implementa la funzione

    Se il tema non implementa la funziona, Drupal verifica se la funzione theme_table() &egrave implementata dal motore di template del tema corrente.
    La funzione implementata:

    • si deve chiamare phptemplate_table()
    • può stare:
      • nel file che implementa il motore (es.: phptemplate.engine)
      • nei file .php o .tpl.php del tema (es.: template.php, block.tpl.php)

    Il sistema implementa la funzione

    Se il motore non implementa la funziona, Drupal chiama la funzione theme_table() implementata da sistema.

    La funzione implementata:

    • starà nel file includes/theme.inc

    Un help delle funzioni di sistema tematizzate può essere trovato in http://api.drupal.org/api/group/themeable/5?sort=asc&order=Name

    La funzione theme()

    Quando abbiamo bisogno di chiamare una funzione tematizzata, è bene non chiamare la funzione direttamente, ma lasciare che sia Drupal a fare questo per noi tramite la funzione theme('block',args). Infatti supponiamo di voler visualizzare una tabella all'interno di codice php scritto da noi, la chiamata alla funzione giusta potrebbe essere del tipo:

      function miafunzione() {
      ......
         // stampa tabella
         if (isset('miotema_table') miotema_table(.....);
         elseif (isset('phptemplate_table') phptemplate_table(.....);
         else theme_table();
         ......
      }

    Tutto questo può essere semplificato utilizzando la funzione theme() e delegare a Drupal la scelta della funzione corretta:

      function miafunzione() {
      ......
         // stampa tabella
         theme('table',$args);
         ......
      }

    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..

    Svilluppare un Modulo

    Drupal cerca i moduli da installare nelle directory e sottodirectory:

    /modules contiene i moduli di sistema (core)
    /sites/all contiene altro tra cui moduli propri.

    E’ consigliato creare una sottodirectory per i moduli aggiuntivi.

    /sites/all/modules

    I file principali del modulo , che devono essere contenuti in /sites/all/modules/miomodulo si devono chiamare :

    Tipologia dei moduli

    Un modulo può essere di tipo:

    Block module

    Sono moduli che generalmente vengono posizionati sulle barre laterali. Drupal chiama la funzione miomodulo_block($op=='view') con opzione uguale a view per ottenere il contenuto del blocco. In particolare Drupal si aspetta un array $block di ritorno con i seguenti valori impostati:

    $block['subject'] = t('MioModulo');
    $block['content'] = contenuto del blocco;

    Node module

    Sono moduli che generalmente generano pagine di contenuto come blog, forum, book pages.

    Le funzioni minime che è bene definire per un modulo sono:

    • miomodulo_block()
    • miomodulo_help()
    • miomodulo_perm()

    Hook principali

    IN FASE DI REALIZZAZIONE

    Elenco degli hook principali

    hook_exit

    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.

    L' hook exit può essere utile per eseguire un debugging del sistema o aggiornare, in fase di chiusura della pagina, alcune tabelle associate ai moduli.
    Due moduli di sistema che usano questo hook sono:

    • Modulo statistics che esegue le statistiche di accesso al sito.
      Funzione statistics_exit();
    • Modulo throttle che esegue il controllo della congestione del sito.
      Funzione throttle_exit();

    hook_load

    Drupal chiama tutte le funzioni hook_load() implementate nei moduli attivi, per aggiungere campi non predefiniti nell'oggetto nodo.
    Ad esempio una rubrica telefonica può avere campi come indirizzo, telefono etc. con un modulo rubrica che implementa la funzione rubrica_load (&$nodo)

    Accesso ai moduli:permessi

    Premesso che , l’accesso ad un modulo viene impostato tramite la pagina Gestione utenti->Controlli accessi.

    In questa pagina compaiono per ogni modulo i permessi associati ad esso e per ogni permesso a quale ruolo è assegnato il permesso.
    I ruoli per default sono due: anonymous user e authenticated user.
    E’ possibile aggiungere altri ruoli utilizzando la pagina Gestione utenti->Ruoli.
    Detto questo, le descrizione dei permessi che compaiono nella pagina Gestione utenti->Controlli accessi sono definite mediante la funzione:

    <?php
    function miomodulo_perm()
    {
       return array(
                   
    "amministra contenuti miomodulo",
                   
    "crea contenuti miomodulo");,
    }
    ?>

    Qui sopra sono riportati solo due permessi, ma ovviamente ne potrebbero essere definiti altri. E' bene inserire sempre il nome nel modulo per ogni permesso. In caso contrario Drupal potrebbe assegnare la stringa di permesso a più moduli, creando seri problemi all'impianto di sicurezza.

    Per verificare se l’utente corrente ha determinati permessi usare la funzione user_access()

    <?php
    if (!user_access("amministra contenuti miomodulo")) {
     
    $form['error'] = array('#type' => 'item',
        
    '#title' => t("Non sei autorizzato ad accedere a miomodulo."));
      return
    $form;
    }

    ?>

    Versioni precedenti alla 5.0 di Drupal usavano la funzione message_access() ora deprecata.

    Messaggi di configurazione del modulo

    Pagina dei moduli
    Nella pagina dei moduli le descrizioni associate al modulo provengono dal file miomodulo.info contenuto nella directory del modulo. All’interno del file sono contenute almeno le prime due variabili:

    $Id$
    name = miomodulo
    description = "Descrizione MioModulo"
    dependencies = modulo1 modulo2 modulo3
    package = MieModuli
    

    con i seguenti significati

    • name Nome del modulo
    • description Descrizione del modulo
    • dependencies Indica i moduli da cui il modulo stesso dipende. Drupal non attiverà il modulo finchè non saranno attivi i moduli da cui dipende
    • package Pakage di appartenenza del modulo.Tutti i moduli appartenenti allo stesso package sono mostrati raggruppati nella pagina dei moduli

    Pagina dei blocchi
    Nome del blocco nella lista blocchi

    Funzione miomodulo_block($op=’list’)

    Esempio:

    <?php
    function miomodulo_block($op = 'list', $delta = 0)
    {
        if (
    $op == "list")
        {
           
    $block[0]["info"] = t('MioBlocco');
            return
    $block;
        }
    }
    ?>

    * Descrizione dell'help all’interno della configurazione del blocco

    Funzione miomodulo_help($section = "")

    Come definito al paragrafo Accesso ai moduli:permessi, i permessi di accesso ai moduli sono definiti mediante la funzione miomodulo_perm()

    <?php
    function miomodulo_perm()
    {
       return array(
    "amministra contenuti miomodulo",
                   
    "crea contenuti miomodulo");
    }
    ?>

    Il valore di $section deve essere verificato posizionando il cursore sul link ‘configura’ della pagina dei blocchi e vedere a quale percorso punta. Generalmente è admin/build/block/configure/MioBlocco/0 e quindi scrivere la funzione miomodulo_help() nel seguente modo:

    <?php
    function miomodulo_help($section = "")
    {
       
    $output = "";
        switch (
    $section)
        {
            case
    "admin/build/block/configure/MioBlocco/0":
                
    $output = "<p>" . t("Descrizione di MioBlocco") . "</p>";
                 break;
           default:
        }
        return
    $output;
    }
    ?>

    Pagina del controllo accessi utenti
    Come definito al paragrafo Accesso ai moduli:permessi, i permessi di accesso ai moduli sono definiti mediante la funzione miomodulo_perm()

    <?php

    function miomodulo_perm()
    {
       return array(
    "amministra contenuti miomodulo",
                   
    "crea contenuti miomodulo");
    }

    ?>

    Style sheet

    Quando un modulo ha fogli di stile propri, questi devono essere caricati prima di visualizzare il contenuto della pagina generata dal modulo. Nella pagina HTML generata da Drupal i file di stile compaiono secondo la sequenza:

    stile/i del modulo corrente
    stile/i del modulo corrente contenuti nel tema corrente
    stili di default di Drupal
    stili del tema corrente

    come di seguito indicato.

    <style type="text/css" media="all">@import "/sites/all/modules/miomodulo/miomodulo.css"</style>
    <style type="text/css" media="all">@import "/sites/all/themes/miotema/miomodulo.css"</style>

    <style type="text/css" media="all">@import "/modules/book/book.css"</style>
    <style type="text/css" media="all">@import "/modules/node/node.css"</style>
    <style type="text/css" media="all">@import "/modules/system/defaults.css"</style>
    <style type="text/css" media="all">@import "/modules/system/system.css"</style>
    <style type="text/css" media="all">@import "/modules/user/user.css"</style>
    ...
    <style type="text/css" media="all">@import"/sites/all/themes/miotema/style.css"</style>


    Per fare questo è utilizzata la funzione drupal_add_css() secondo il codice riportato.
    L'esempio riporta il codice necessario per caricare il foglio di stile miomodulo.css.
    Questo codice deve essere chiamato dalle funzioni del modulo che preparano codice HTML.

    function miomodulo_css_file() {
           $css_files = array();    // array in cui definire i file css
            // Definisce i percorsi dei file di stile
           $file_css_modulo          = drupal_get_path('module', 'miomodulo') . '/miomodulo.css';
           $file_css_modulo_in tema  = path_to_theme() .  '/miomodulo.css'; // se esistente
           // Definisce nell'array lo stile di default del modulo 
           $css_files[] = array('file' => $file_css_modulo, 'type' => 'module', );
            /* 
           Definisce nell'array lo stile ripetuto nella directory del tema corrente
           Se esiste un file di stile nella directory del tema corrente
           con lo stesso nome dello stile del modulo lo carica. 
           */
           if (file_exists($file_css_modulo_in tema) {
               $css_files[] = array('file' => $file_css_modulo_in tema, 'type' => 'theme', );
           }
           // Avvisa Drupal di caricare i fogli definiti
           foreach ($css_files as $css_file)
           {
               drupal_add_css($css_file['file'], $css_file['type'], 'all', false);
           }
    }

    Tabelle

    Tabella BLOCKS

    La tabella BLOCKS contiene le informazioni sui blocchi:tipo, regole di accesso, tema , regione etc.

    Tabella BLOCKS
    I campi sono i seguenti:
    
    
    moduleTindica da quale modulo è gestito il blocco
    deltaTidentificativo univoco del blocco in riferimento al proprio modulo
    themeTindica che il blocco può essere visualizzato per il tema
    statusN=1 il blocco è abilitato
    weightNordine di visualizzazione del blocco
    regionTindica la regione in cui deve essere visualizzato
    customT
    throttleT
    visibilityNindica il tipo di visualizzazione delle pagine
    pagesTelenco delle pagine in cui è vera il tipo di visibility
    titleTtitolo del blocco
    bidNidentificativo univoco del blocco
    cacheNassume valore 1 o -1
    La chiave primaria è PRIMARY KEY bid, UNIQUE KEY theme,module,delta

    Tabella BLOCK_ROLES

    La tabella BLOCK_ROLES riporta l'identificativo rid (roles identifier) che indica il ruolo necessario per
    visualizzare il blocco. I ruoli sono definiti nella tabella dei ruoli "role"

    Tabella BLOCK_ROLES
    I campi sono i seguenti:
    
    
    moduleTindica da quale modulo è gestito il blocco
    deltaTidentificativo univoco del blocco in riferimento al proprio modulo
    ridNiidentificativo univoco del ruolo (vedi tabella role)
    PRIMARY KEY module,delta,rid

    Tabella BOXES

    La tabella BOXES contiene il contenuti dei blocchi gestiti dal modulo block.

    Tabella BOXES
    I campi sono i seguenti:
    
    
    bidNiidentificativo univoco del blocco
    bodyTil contenuto del blocco
    infoTripete il titolo del blocco
    formatNtipo di formato (da tabella FILTER_FORMATS)
    PRIMARY KEY bid UNIQUE KEY info

    La tabella MENU_CUSTOM contiene l'elenco di tutti i menu definiti dall'utente oltre ai menu di navigazione 'navigation', 'primary-links' e 'secondary-links'.

    Tabella menu_custom
    I campi sono i seguenti:
    
    
    menu_name T identificativo interno del menu
    title T titolo del menu visualizzato
    description T descrizione del menu
    La chiave primaria è: PRIMARY KEY = menu_name
  • Tabella MENU_LINKS
  • La tabella MENU_LINKS contiene informazioni relative alla struttura del albero del menu con tanti record quante sono le voci del menu. Per ogni voce è definita l' url a cui punta (link_path).

    Tabella menu_links
    I campi sono i seguenti:
    
    
    menu_name T nome del menu
    mlid N identificativo univoco della voce all'interno del
    plid N identificativo univoco del padre
    link_path T path a cui punta la voce del menu
    router_path T path a cui punta la voce del menu definito in MENU
    link_title T titolo della voce
    options T valori degli attributi in forma serializzata
    module T nome del modulo che gestisce il menu
    hidden N =1 la voce del menu deve essere nascosta
    external N =1 la voce del menu punta a una URL esterna al sit
    has_children N =1 la voce ha figli
    expanded N =1 la voce deve essere espansa
    weight N ordine della voce all'interno del meni
    depth N profondita della voce
    customized N
    p1 N identificativo del nodo radice dell'albero
    p2 N identificativo del padre di secondo livello
    p3 N identificativo del padre di terzo livello
    p4 N identificativo del padre di quarto livello
    p5 N identificativo del padre di quinto livello
    p6 N identificativo del padre di sesto livello
    p7 N identificativo del padre di settimo livello
    p8 N identificativo del padre di ottavo livello
    p9 N identificativo del padre di nono livello
    updated N
    La chiave primaria è: PRIMARY KEY = mlid

    La tabella MENU_ROUTER contiene le informazioni sulle funzioni da attivare per raggiungere la pagina richiesta nel menu

    Tabella menu_router
    I campi sono i seguenti:
    
    
    path T percorso paramentrizzato a cui puntare (Es: node/%/edit)
    load_functions T funzione di caricamento (load)
    to_arg_functions T argomenti della funzione di caricamento
    access_callback T funzione che controlla l'accesso al menu
    access_arguments T argomenti della funzione di accesso
    page_callback T funzione di visualizzazione della pagina richiesta
    page_arguments T argomenti della funzione di visualizzazione
    fit N ordine in cui vengono selezionati i possibili path [vedi menu_get_item()]
    number_parts N uso interno
    tab_parent T ??
    tab_root T ??
    title T titolo della voce di menu
    title_callback T funzione di conversione del titolo [t(); check_plain() etc.]
    title_arguments T ??
    type N ??
    block_callback T ??
    description T descrizione della voce
    position T ??
    weight N ordine di visualizzazione
    file T eventuale file di template da caricare prima di chiamare la page_callback
    La chiave primaria è: PRIMARY KEY = path

    Tabella NODE

    La tabella NODE contiene l'elenco di tutti i nodi inseriti nel sistema. Per un sito multilingua ogni traduzione introduce un nuovo nodo che si riferisce alla lingua di traduzione.

    Tabella node
    I campi sono i seguenti:
    
    
    nid N identificativo univoco del nodo
    vid N identificativo nel numero di revisione nella tabella NODE_REVISONS
    type T tipo del nodo. Tabella di codifica NODE_TYPE
    title T titolo del nodo
    uid N identificativo utente del proprietario del nodo
    status N =0 non visibile; =1 visibile
    created N timestamp della data di creazione del nodo
    changed N timestamp della data di modifica del nodo
    comment N identificativo utente dell'ultimo commento
    promote N =1 il nodo è visualizzato in prima pagina
    moderate N =1 il nodo deve essere controllato prima della pubblicazione
    sticky N numero d'ordine del nodo nella prima pagina
    language T lingua del contenuto:'it' , 'en', 'fr', …
    tnid N identificativo univoco del nodo sorgente per le traduzioni
    translate N =1 deve essere aggiornata la traduzione. Il nodo sorgente è cambiato
    La chiave primaria è: PRIMARY KEY = nid
  • Tabella NODE_REVISIONS
  • Tabella NODE_REVISIONS

    La tabella NODE_REVISIONS contiene le informazioni sul contenuto principale dei nodi (body) , sul sommario (teaser) , il titolo (title) e le revisioni eseguite. Inoltre il campo format indica come il contenuto deve essere filtrato, prima di visualizzarlo. Ogni nodo ha quindi più record indicatii dall'identificativo univoco del nodo stesso (nid) e dall'identificativo della revisione (vid).

    Tabella node_revisions
    I campi sono i seguenti:
    
    
    nid N identificativo univoco del nodo
    vid N identificativo del numero di revisione
    uid N identificativo utente del proprietario del nodo
    title T titolo del nodo per la revisione corrente
    body T contenuto del nodo per la revisione corrente
    teaser T sommario del nodo per la revisione corrente
    log T Messaggio di log contenente le modifiche eseguite
    timestamp N data di modifica del nodo
    format N formato del nodo da tabella FILTERS_FORMAT
    La chiave primaria è: PRIMARY KEY = vid

    Tabella ROLE

    La tabella ROLE indica i ruoli che possono essere assegnati ad un utente. Ad esempio, amministratore, webmaster, etc
    Mediante i ruoli possono essere nascosti contenuti, blocchi e menu.

    Tabella ROLE
    I campi sono i seguenti:
    
    
    ridNiidentificativo univoco del ruolo
    name Tnome del ruolo
    PRIMARY KEY rid UNIQUE KEY name

    Tabella URL_ALIAS

    La tabella URL_ALIAS definisce la tabella di corrispondenza tra un percorso interno al sistema e un alias del percorso definito dall'utente

    Tabella url_alias
    I campi sono i seguenti:
    
    
    pid N identificativo univoco del path
    src T percorso originale
    dst T alias del percorso
    language T linguaggio associato all'alias del percorso
    La chiave primaria è: PRIMARY KEY = pid

    Tabella USERS

    La tabella USERS contiene informazioni sugli utenti

    Tabella users
    I campi sono i seguenti:
    
    
    uid N identificativo utente
    name T nome utente
    pass T password utente
    mail T mail utente
    mode N modo di visualizzazione del commento:threaded o flat
    sort N modo per l'ordinamento dei commenti
    threshold N non più usato
    theme T tema di default
    signature T firma utente
    created N timestamp della data di creazione del nodo
    access N timestamp ultimo accesso
    login N timestamp ultimo login utente
    status N =0 utente bloccato, =1 utente attivo
    timezone T timezone dell'utente
    language T lingua di default
    picture T percorso all'immagine utente
    init T email forniti al momento della registrazione
    data T serializzazione di un array che rappresenta i campi dela form utente
    timezone_name T nome timezone tipo Europe/Rome
    La chiave primaria è: PRIMARY KEY = uid

    Tabella USERS_ROLES

    La tabella USERS_ROLES indica i ruoli assegnati a ciascun utente. Nella visualizzazione dei blocchi , questo permette di nascondere i blocchi agli utenti senza il ruolo richiesto per la visualizzazione

    Tabella USERS_ROLES
    I campi sono i seguenti:
    
    
    uidNidentificativo univoco dell'utente
    ridNiidentificativo univoco del ruolo
    PRIMARY KEY uid,rid

    Definizioni

    Sono riportati in questo capitolo alcuni concetti che saranno utilizzati nel proseguo di questa documentazione.

    Contenuti

    In questa documentazione sarà indicato con il termine di contenuto l'informazione archiviata in un sistema CMS come Drupal.

    L'informazione pubblicata è orientata alla diffusione di conoscenza , idee, proposte e altro che gli ideatori del sito hanno come loro missione. L'informazione è resa disponibile nel sito web sotto forma di articoli, libri, forum e ancora con il supporto di immagini , video e suoni.
    Tutto questo è quello che chiameremo contenuto primario del sito.

    Ma oltre al contenuto primario, nel sito sono presenti altri contenuti come i menu per la navigazione, maschere per l'interazione con l'utente, commenti agli argomenti lasciati dai visitatori o utenti del sito, pubblicità e tutto ciò che può essere necessario per raggiungere lo scopo finale per cui il sito è stato pensato.
    Tutto questo è quello che chiameremo contenuto secondario del sito

    Il contenuto primario viene gestito dal Drupal attraverso i NODI.
    Possiamo pensare al nodo come il contenitore della nostra informazione che viene poi visualizzato sul web sotto forma di pagina singola o di pagina di un libro o ancora come contenuto di un singolo intervento in un forum.
    Drupal mette a disposizione dei nodi di base come appunto la creazione di una singola pagina o di un pagina appartenente ad un libro come questa che state leggendo. Ma Drupal consente anche di creare nuove tipologie di nodi. Si potrebbe creare quindi una rubrica telefonica dove ogni nodo è costituito da un singolo nominativo , uno scadenzario, un reportage fotografico e così via.

    Il contenuto secondario viene gestito da Drupal attraverso i BLOCCHI.
    I menu di navigazione sono dei blocchi, l'elenco degli ultimi commenti alle pagine o delle ultime discussioni aperte in un forum sono dei blocchi, la maschera di login è un blocco così come i tag di ricerca delle pagine. In pratica, come detto, tutto ciò che è utile per una buona navigazione e fruibilità del sito va a finire in un blocco.

    Page callback

    Quando viene inviata una richiesta, Drupal mediante la tabella MENU_ROUTER individua la funzione da chiamare per leggere, codificare e visualizzare il contenuto richiesto. Questa specifica funzione viene indicata con il nome di page callback.
    Ad esempio la richiesta di un singolo nodo seleziona la page callback node_page_view() , per la visualizzazione della prima pagina node_page_default().

    URL alias

    Drupal archivia il contenuto primario nei nodi. All'interno del database i nodi sono numerati sequenzialmente.
    Per accedere ad un nodo e quindi al suo contenuto , è necessario indicare a Drupal l'identificativo del nodo che si vuole estrarre dal database. Questa informazione è contenuta nell' URL inserito nel browser.
    Ad esempio:
    URL = www.miosito.com/node/345
    Con questo URL diciamo al sistema di mostrarci il contenuto del nodo 345.
    Questo URL è un po' criptico perchè non dice nulla circa il contenuto del nodo a meno di non ricordarsi che il nodo 345 corrisponde ad un certo contenuto che è molto improbabile.
    Drupal viene in aiuto con gli URL alias.
    In pratica è possibile associare all' URL precedente un qualsiasi altro URL .
    Ad esempio:
    URL = www.miosito.com/contabilita/elenco-fatture/attive
    Si noti che tre voci 'contabilita' 'elenco-fatture' 'attive' sostituiscono due voci 'node' '345'.
    In questo modo non interessa più sapere quale nodo chiamare per avere l'elenco delle fatture attive, in quanto abbiamo un alias più facilmente ricostruibile.
    Sarà compito di Drupal convertire l' URL alias in un URL di sistema e richiamare successivamente la funzioni per visualizzare il contenuto.

    Drupal 6.x - da drupal.org

    In attesa di fornire documentazione alla versione 6, di seguito riporto alcuni link alla documentazione originale in lingua inglese su Drupal.org
    DescrizioneLink
    Conversione temi da 5.x a 6.x
    Anatomia di un tema Drupal
    Struttura del file .info
    Nomi di funzione e template dei temi
    Registrazione del tema
    Screenshots del tema
    Sub-tema:ereditarietà
    Modifica interattiva dei colori
    Funzioni da implementare per temi
    Funzioni per il template.php
    Variabili di base disponibili a tutti i template
    Module developer's guide
    Moduli per slider

    Editor per Drupal

    Riporto alcuni degli editor più diffusi per Drupal