Comment lier un noeud/une page à un menu

Catégories:

Bonjour,

la question peut vous paraître saugrenue au premier abord.

Ce que je cherche à faire en résumé : rattacher un noeud ou une page à un menu afin que celui-ci reste ouvert lorsque mon noeud ou ma page est affiché(e).

Je ne veux pas avoir à modifier l’arborescence des menus de manière permanente, celle-ci étant déjà suffisamment chargée à mon goût. L’idéal serait de pouvoir faire en sorte que l’élément soit rattaché au menu juste le temps de l’affichage de la page afin que celui-ci soit ouvert.

Pour illustrer ce que je cherche à faire, prenons le cas d’un menu de cantine.

Le menu de gauche est ouvert sur la page de la restauration scolaire mais pas sur la page du menu (ça fait beaucoup de menu dans une seule phrase).

La solution de rattacher chaque noeud au menu n’est pas viable : le menu étant tellement chargé, c’est tout de suite très ch… lassant de le sélectionner dans l’interminable liste déroulante. De plus ce sont des informations qui deviennent vite périmées.

Je voudrais pouvoir le faire également pour des pages générées dynamiquement.

Quelqu’un a une idée ?

#

La fonction menu_set_active_item() sert à cela. Une des manières de faire est de l’appeler dans une page de type PHP.

#

J’ai déjà essayée cette fonction mais elle ne m’avait pas vraiment donné satisfaction. En fait j’ai essayé pas mal de fonctions et de façons mais sans résultat probant.

Je vais approfondir du côté de menu_set_active_item alors !

#

Au moment où cette fonction est appelée, peut être que Drupal a déjà fait son choix de menu (il en a besoin de toutes façons pour afficher un noeud).

Essaye donc avec menu_set_location(). Tu as un exemple dans forum_view(). Dans ton cas quelque chose comme cela devrait marcher :

<?php
$breadcrumb
= array();
$breadcrumb[] = array('path' => 'restaurationscolaire', 'title' => 'Restauration');
$breadcrumb[] = array('path' => 'node/'.$GLOBALS['node']->nid);
menu_set_location($breadcrumb);
?>

En écrivant cela, je me demande si le module taxonomy_context ne pourrait pas t’être utile dans ce cas (entre autres, il modifie le breadcrumb).

#

Après essai, je n’obtiens pas ce que je recherche :

  • le menu ne se déroule pas
  • le fil d’ariane n’est pas le bon

Voici le code que j’ai installé dans mon template (page.tpl.php ou template.php) :

<?php
$rfr_base
=$_SERVER['REQUEST_URI'];
if(
strpos($rfr_base,'ecole/restaurationscolaire/mn')!==FALSE) {
 
menu_set_active_item('ecole/restaurationscolaire');
}
?>

J’ai vérifié que menu_set_active_item était bien appelé.

Pour l’exemple que j’ai donné, je veux avoir Accueil » École » Restauration scolaire comme fil d’ariane et le menu ouvert sur Restauration scolaire.

Avec mon code, le menu est complètement refermé (argh) et le fil d’ariane est Accueil » École (ce qui me paraît logique si on dit à Drupal que l’élément actif est Restauration scolaire).

Peut-être est-ce ma façon d’utiliser menu_set_active_item, la documentation n’étant pas très loquace sur cette fonction.

#

Hello Zigazou,

Personnellement, je ne suis pas non plus convaincu de l’intérêt (ou de l’usage ?) de menu_set_active_item(). Ayant été confronté à la même problématique que toi, voilà comment je m’en étais sorti :

<?php
function toto_nodeapi(&$node, $op, $teaser = NULL, $page = NULL) {
  if (
$node->type == 'story' && $op == 'view' && $page) {
    global
$_menu;
   
$path = 'path/to/attach';                              // (1)
   
$mid = $_menu['items'][menu_get_active_item()]['pid']; // (2)
   
$pid = $_menu['path index'][$path];                    // (3)
   
$_menu['items'][$mid]['pid'] = $pid;                   // (4)
 
}
}
?>

On suppose donc que tu as un module «toto» dans lequel tu implémentes le hook_nodeapi(). Ce hook permet d’appeler facilement notre modif à chaque fois qu’on visualise un node de type «story» en mode PAGE.

En gros :

  • (1) je définis le chemin auquel je veux rattacher mon node
  • (2) je chope l’id de l’actuel parent de mon node dans la structure du menu
  • (3) je chope l’id du futur parent de mon node dans la structure du menu
  • (4) je remplace l’actuel parent par le nouveau

Et le tour est joué : à l’affichage du node, le menu s’affichera en conséquence. C’est pas très clean dans la mesure où ça manipule directement une variable interne à Drupal ($_menu) mais je n’ai pas trouvé mieux, et ça marche nickel (fil d’Ariane + menu ouvert).

Vincent

Formations Drupal pour WEBMASTERS, DESIGNERS et DÉVELOPPEURS.

#

Merci à Damz et Drupalfrance !

Bon, je suis finalement parvenu à une solution : je recrée le chemin avec menu_set_location en me basant sur l’URL dans template.php.

Le temps de déboguer tout ça et je posterai ma solution ici.

#

OK, avec plaisir

Vincent

Formations Drupal pour WEBMASTERS, DESIGNERS et DÉVELOPPEURS.

#

La voici, la voilà, la mdzpmlmddalv (la méthode de Zigazou pour modifier le menu de Drupal à la volée).

  • Le code doit être inséré dans le template.php d’un thème sous PHPTemplate, dans _phptemplate_variables (c’est la fonction phptemplate_definit_menu qui doit être appelée)
  • Il peut être appelé plusieurs fois mais n’agira qu’une seule
  • Il doit bien sûr être adapté en fonction de vos besoins
  • Il utilise la fonction menu_set_location
  • Il ne touche pas aux variables internes de Drupal
  • Il est plus compliqué que les solutions proposées ci-dessus
  • Il gère 2 cas
    • Si le noeud est d’un type particulier, on le rattache à une rubrique particulière
    • Si le noeud n’est pas rattaché au menu désigné, on recrée l’arborescence à partir de son URL (ne fonctionne qu’avec l’URL rewriting)

Note :

  • menu_set_location nécessite l’utilisation de chemins système d’où l’emploi de drupal_get_normal_path
  • désolé, ça fait beaucoup de code et de commentaires…

<?php
function phptemplate_get_active_menu() {
 
// Recherche l'identifiant du menu (=identifiant de l'élément racine)
 
  // Récupère l'élément actif
 
$mid      =menu_get_active_item();
 
$menu_item=menu_get_item($mid);

  // Remonte jusqu'à tomber sur un élément n'ayant pas de parent (=racine)
 
while(array_key_exists('pid',$menu_item) and $menu_item['pid']!=0) {
   
// Récupère le parent de l'élément
   
$mid      =$menu_item['pid'];
   
$menu_item=menu_get_item($mid);
  }

  return $mid;
}

function phptemplate_definit_menu($nid,$chemin_rubrique) {
  static
$deja_defini =FALSE;
  static
$types_noeuds=array('content_brve','content_tablissement'); // Types à mettre dans des rubriques
 
static $menus       =array('84','242'); // Menus auxquels doivent se rattacher les éléments si possible

  // La fonction ne peut être appelée qu'une seule fois par page 
  if($deja_defini) return;

  // Teste si le type est un de ceux recherchés
 
if(is_numeric($nid) and $nid>0) { // La page affichée est un noeud
    // Charge le noeud pour avoir son type
   
$node=node_load($nid);

    // Recherche le type du noeud dans la liste
   
if(in_array($node->type,$types_noeuds)) {
     
// Le type a été trouvé, on rattache le noeud à la rubrique
      // On veut avoir Accueil >> Rubrique
     
      // Le premier élément c'est la rubrique
     
$menu_rubrique=menu_get_item(NULL,drupal_get_normal_path($chemin_rubrique));
     
$location     =array();
     
$location[]   =array('path'=>$menu_rubrique['path'],'title'=>$menu_rubrique['title']);
     
     
// Le second élément c'est le noeud lui-même
     
$menu_noeud   =menu_get_item(menu_get_active_nontask_item());
     
$location[]   =array('path'=>$menu_noeud['path'],'title'=>$menu_noeud['title']);

      menu_set_location($location);

      $deja_defini=TRUE;
      return;
    }

    // Le type du noeud n'est pas dans la liste
    // On détermine s'il appartient au menu principal
   
$racine=phptemplate_get_active_menu();

    if(!in_array($racine,$menus)) {
     
// On recrée une arborescence à partir de l'URL
     
$rfr_base=trim($_SERVER['REQUEST_URI'],'/'); // Supprime le '/' de début ou de fin
     
$chemins =explode('/',$rfr_base);
     
$mid     =0;
     
$actuel  =drupal_get_normal_path($rfr_base); // Garde en mémoire le chemin actuel
     
array_pop($chemins); // Enlève le chemin puisqu'il ne donne pas le bon menu

      // Recherche un chemin ayant un menu permanent (non temporaire)
      while(count($chemins)>0 and $mid<=0) {
       
// Reconstitue un chemin à partir des éléments restants
       
$chemin=implode('/',$chemins);

        // Recherche un chemin système pour ce chemin
       
$source=drupal_get_normal_path($chemin);
        if(
$source) {
         
// Recherche un menu pour le chemin système trouvé
         
$menu_item=menu_get_item(NULL,$source);

          // Teste si un menu a été trouvé
         
if(count($menu_item)!=0) {
           
// On reconstitue l'arborescence à l'envers en partant de la feuille
           
$location=array();

            // La feuille correspond au menu actif
           
$menu_noeud=menu_get_item(menu_get_active_nontask_item());
           
$location[]=array('path'=>$menu_noeud['path'],'title'=>$menu_noeud['title']);

            $mid=-1;
            while(
$mid!=0) {
             
$location[]=array(
               
'path' =>$menu_item['path' ],
               
'title'=>$menu_item['title']
              );
             
$mid=$menu_item['pid'];
             
$menu_item=menu_get_item($mid);
            }

            // L'arborescence est à l'envers, on la remet à l'endroit
           
$location=array_reverse($location);
           
menu_set_location($location);
            break;
          }
        }

        // Enlève le dernier élément du chemin
       
array_pop($chemins);
      }

      $deja_defini=TRUE;
      return;
    }
  }
}
?>

Syndiquer le contenu