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:
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.
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()
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.
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.
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;
...
}
?>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).
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.