Utente: Anonymous

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.