Come separare i termini di più vocabolari in Drupal

Come separare i termini di più vocabolari in Drupal

L'output di un nodo Drupal mostra tutti i termini dei vocabolari in una unica lista. Non sempre, però, questo è il comportamento desiderato. Può capitare di avere due vocabolari, categorie e tag, ad esempio, e di voler elencare i termini in due liste separate, una per vocabolario, per poterle distinguere visivamente. In questa breve guida per Drupal vi spiegherò come dividere i termini di più vocabolari.

Per farlo ci sono diversi metodi. Descriverò due esempi che prevedono entrambi la modifica dei file del template Drupal, ciò significa che quando si cambia il tema è anche necessario riportare le personalizzazioni.

1) Riscrivere la variabile $terms

Il primo esempio consiste nello riscrivere la variabile $terms separando con degli span, o dei div, le liste di termini.

Nel file template.php si deve aggiungere una funzione, phptemplate_preprocess_node(&$vars), che:

  1. Carica tutti i termini associati al nodo
  2. Estrae i vocabolari che contengono i nodi
  3. Ricostruisce la variabile $terms ciclando i vocabolari ed i termini associati al nodo

Il terzo passaggio utilizza la funzione theme() per generare l'output HTML di una singola lista.

Ecco il codice sorgente:

function phptemplate_preprocess_node(&$vars) {
  if ($vars['node']->taxonomy) {
    foreach ($vars['node']->taxonomy as $term) {
      $vocabweight = taxonomy_vocabulary_load($term->vid)->weight;
      $vocabulary[$vocabweight][$term->vid]['taxonomy_term_'. $term->tid]  = array(
        'title' => $term->name,
        'href' => taxonomy_term_path($term),
        'attributes' => array(
          'rel' => 'tag',
          'title' => strip_tags($term->description),
        ),
      );
    }
    ksort($vocabulary, SORT_NUMERIC);
    unset($vars['terms']);
    foreach ($vocabulary as $vocabweight => $vid) {
      foreach($vid as $vid => $terms) {
        $name = taxonomy_vocabulary_load($vid)->name;
        $terms = theme('links', $terms, array('class' => 'links inline'));
        $vars['terms'] .= '<span class="vocabulary taxonomy_vid_';
        $vars['terms'] .= $vid;
        $vars['terms'] .= '">';
        $vars['terms'] .= $name;
        $vars['terms'] .= ':&nbsp;';
        $vars['terms'] .= $terms;
        $vars['terms'] .= '</span>';
      }
    }
  }
}

Questo codice, inoltre, visualizza gli elenchi seguendo l'ordine dei vocabolari in base a come sono ordinati nell'interfaccia di amministrazione. Ogni vocabolario sarà incluso in uno span distinto da una classe CSS per poterlo personalizzare anche a livello grafico.

Nel file node.tpl.php si può quindi continuare ad usare la variabile $terms senza ulteriori modifiche.

2) Sostituire la variabile $terms con un array di termini per vocabolario

Se gli elenchi di termini vanno stampati in posizioni diverse nel template, l'approccio appena descritto non è applicabile e si deve procedere diversamente.

Una soluzione molto semplice è quella di creare un vettore di elenchi così da poterlo richiamare nel node.tpl.php in più punti.

Il primo passo è quello di modificare il file template.php del tema Drupal in uso aggiungendo una nuova funzione: nomedeltemplate_separate_terms($node_taxonomy). Al posto di "nomedeltemplate" va messo il nome del template che si sta modificando.

  1. Per ogni termine associato al nodo si estrae il vocabolario a cui esso appartiene
  2. Si associa alla variabile $terms un vettore che conterrà le liste di termini
function nomedeltemplate_separate_terms($node_taxonomy) {
  foreach ($node_taxonomy AS $term) {
    $links[$term->vid]['taxonomy_term_'. $term->tid] = array(
      'title' => $term->name,
      'href' => taxonomy_term_path($term),
      'attributes' => array(
      'rel' => 'tag',
      'title' => strip_tags($term->description)
      ),
    );
  }
  foreach ($links AS $key => $vid) {
    $terms[$key] = theme_links($vid, array('class' => 'links inline'));
  }
  return $terms;
}

Il secondo passo è la modifica del file node.tpl.php dove si deve sostituire il classico <php print $terms ?> con la stampa del vettore. Riprendendo l'esempio dell'introduzione, se abbiamo due vocabolari, uno per le categorie ed uno per le etichette, il codice sarà:

<div class="voc-category">Categorie: <?php print $terms[1]; ?></div>
<div class="voc-tags">Etichette: <?php print $terms[2]; ?> </div>

Gli indici dell'array sono gli ID dei vocabolari (vid). Chiaramente possiamo posizionare queste righe dove più ci piace all'interno del nodo.

L'ultimo passaggio è la riscrittura della variabile $terms con quella generata dalla funzione nomedeltemplate_separate_terms($node_taxonomy). Tale operazione può essere svolta nel file template.php usando una tecnica analoga al primo esempio, oppure nel file node.tpl.php aggiungendo all'inizio:

<?php $terms = nomedeltemplate_separate_terms($node->taxonomy); ?>

Come spesso accade, le strade che si possono intraprendere durante lo sviluppo in Drupal sono molteplici, alcune più semplici, altre magari un po' più complesse ma, nella maggior parte dei casi l'API di Drupal e sufficientemente potente e flessibile per realizzare delle soluzioni eleganti e funzionali.

Ho provato la seconda soluzione, solo che mi da il seguente errore:

Parse error: syntax error, unexpected ';' in C:\xampp\htdocs\intranet\themes\garland\template.php on line 124

Ti riporto il contenuto da linea 112 a 127

112.function garland_separate_terms($node_taxonomy) {
113. foreach ($node_taxonomy AS $term) {
114. $links[$term->vid]['taxonomy_term_'. $term->tid] = array(
115. 'title' => $term->name,
116. 'href' => taxonomy_term_path($term),
117. 'attributes' => array(
118. 'rel' => 'tag',
119. 'title' => strip_tags($term->description)
120. ),
121. );
122. }
123. foreach ($links AS $key => $vid) {
124. $terms[$key] = theme_links($vid, array('class' => 'links inline');
125. }
126. return $terms;
127. }

Se non è troppo, potresti spiegarmi come faccio a legare il vocabolario al tipo di contenuto?
Mi spiego meglio, ho tre tipi diversi di contentuo, per ogni tipo ho due o tre vocabolari diversi e vorrei far sì che nel caso del tipo contenuto 1 vengano visualizzati i vocabolari Fonte e Categoria; per il tipo contenuto due i vocabolari Fonte, Categoria e Classificazione, ecc. ecc.
Grazie mille per l'attenzione...
Lello

Ciao Lello, manca una parentesi in fondo alla riga 124.