SPIP-Contrib

SPIP-Contrib

عربي | Deutsch | English | Español | français | italiano | Nederlands

288 Plugins, 197 contribs sur SPIP-Zone, 192 visiteurs en ce moment

Accueil > Navigation > Navigation transversale > Polyhierarchie > Trouver l’ensemble des chemins d’un article polyhiérachique

Trouver l’ensemble des chemins d’un article polyhiérachique

13 août 2012 – par Maïeul – commentaires

2 votes

Ceci est une « contribution pédagogique », qui montre par l’exemple comment développer une nouvelle fonctionnalité pour SPIP.

Le plugin Polyhierarchie permet d’avoir plusieurs parents par rubrique ou par article. Il propose un certain nombre de critères pour parcourir ces parents. Comment en tirer profit pour afficher tout les chemins menant à un article ? C’est l’objet de cet article, qui implique une bonne connaissance du mécanisme des boucles de SPIP.

Structure de test

La structure de test adoptée pour ce tutoriel est celle du schéma de Polyhiérarchie.

Les cercles tout en bas du schéma sont les articles. XS et YS sont les secteurs.

Exemple de polyhiérarchie

Une base de donnée exemple est jointe à l’article (dump SPIP 3, sans auteurs, avec juste les rubriques et les articles). Voilà la structure :

Rubriques
IDTitre
1 xs
2 d
3 b
6 ys
7 g
8 d’
10 g’
11 f’
Articles
IDTitre
1 f
2 a
3 c
4 e
5 h

Ce qui donne le schéma suivant :

Les exemples que nous donnerons se baseront sur la recherche des chemins de l’article 5.

Principe général

Nous allons remonter les différentes hiérarchies depuis l’article jusqu’à la racine. Nous stockerons ces hiérarchies dans un tableau #ARRAY. Chaque entrée du tableau correspondant à un chemin possible, sous la forme rxryrx, où x, y, z sont les numéros de rubriques.

Puis nous bouclerons sur ce tableau, pour pouvoir gérer l’affichage des chemins. Chaque entrée sous la forme rxryrx sera transformée en tableau sur lequel nous bouclerons à l’envers (pour avoir une hiérarchie depuis le haut vers le bas, et non du bas vers le haut). Cela nous permettra d’afficher les chemins.

Nous utiliserons donc les outils les plus avancés du langage de squelette de SPIP :

-  #ARRAY,#SET,#GET pour gérer le tableau.
-  La boucle (POUR)
-  Les boucles imbriquées pour pouvoir remonter entièrement la hiérarchie.

Je précise que cette contribution a été testée sous SPIP 3. Pour SPIP 2.1, il vous faudra installer le plugin BONUX.

Initialisation du tableau des chemins

Nous allons initialiser un tableau vide, où nous stockerons les différents chemins. Tout notre code devra être situé à l’intérieur d’une boucle ARTICLE.

Toujours à l’intérieur de cette boucle, nous allons initialiser une variable niveau qui nous permettra d’analyser à quelle niveau de hiérarchie nous sommes. Plus nous remonterons dans la hiérarchie, plus le niveau sera élevé. Nous partons du niveau 0.

  1. <BOUCLE_article(ARTICLES){critères}>
  2. #SET{chemins,#ARRAY}
  3. #SET{niveau,0}
  4. </BOUCLE_article>

Télécharger

Remplissage du tableau, au premier niveau

Insérons maintenant dans cette boucle, après #SET{niveau,0} le code pour remplir le tableau pour le premier niveau de hiérarchie (comme toujours, en partant du bas) :

  1. <BOUCLE_article(ARTICLES){critères}>
  2. #SET{chemins,#ARRAY}
  3. #SET{niveau,0}
  4. <BOUCLE_parents(RUBRIQUES){parents}{par titre}>
  5. #SET{n0,r#ID_RUBRIQUE}
  6. #SET{chemins,#GET{chemins}|array_merge{#ARRAY{
  7. #GET{n0},
  8. #GET{n0},
  9. }
  10. }}
  11. </BOUCLE_parents>
  12. </BOUCLE_article>

Télécharger

Explications :
-  nous stockons temporairement dans la variable n0 la valeur du chemin courant. En effet, nous en aurons besoin pour construire les chemins « au dessus » de cette rubrique.
-  nous ajoutons dans le tableau, pour chaque rubriques « mère », une entrée dont la clef est rXXX et la valeur rXXX, où XXX représente le numéro de rubrique.

Pourquoi me direz vous dupliquer ainsi l’information ? Parce que si la rubrique courante a elle même des ancêtres, alors nous n’aurons pas un chemin complet. Par conséquence, il faudra effacer le "demi-chemin". Nous en parlons plus loins. Chaque chose en son temps.

Pour le moment, notre tableau chemins se compose ainsi :

ClefValeur
r7 r7
r10 r10

Remonter la hiérarchie

Dans notre boucle _parents nous allons appeler une boucle _grands_parents, qui s’appellera de manière récursive, afin de remonter toute la hiérarchie.

Avant de rentrer dans cette boucle, nous allons augmenter la variable niveau de 1, et la rediminuer en sortant. Ainsi, nous saurons systématiquement à quelle niveau nous nous trouvons dans l’aborescence.

  1. <BOUCLE_article(ARTICLES){critères}>
  2. #SET{chemins,#ARRAY}
  3. #SET{niveau,0}
  4.  
  5.  
  6. <BOUCLE_parents(RUBRIQUES){parents}{par titre}>
  7. #SET{n0,r#ID_RUBRIQUE}
  8. #SET{chemins,#GET{chemins}|array_merge{#ARRAY{
  9. #GET{n0},
  10. #GET{n0}
  11. }
  12. }}
  13.  
  14. #SET{niveau,#GET{niveau}|plus{1}}
  15. <BOUCLE_grands_parents(RUBRIQUES){parents}{par titre}>
  16. #SET{n#GET{niveau},#GET{n#GET{niveau}|moins{1}}r#ID_RUBRIQUE}
  17. #SET{chemins,#GET{chemins}|array_merge{#ARRAY{
  18. #GET{n#GET{niveau}},
  19. #GET{n#GET{niveau}}
  20. }
  21. }}
  22. #SET{niveau,#GET{niveau}|plus{1}}
  23. <BOUCLE_ancetres(Boucle_grands_parents) />
  24. #SET{niveau,#GET{niveau}|moins{1}}
  25.  
  26. </BOUCLE_grands_parents>
  27. #SET{niveau,#GET{niveau}|moins{1}}
  28.  
  29. </BOUCLE_parents>
  30.  

Télécharger

Pour chaque niveau, noté x, nous allons créer une variable nx : c’est le #SET{n#GET{niveau},.

Cette variable reprendre la valeur de la variable nx-1, en ajoutant à la fin r#ID_RUBRIQUE : c’est le #GET{n#GET{niveau}|moins{1}}r#ID_RUBRIQUE.

Nous ajoutons ensuite la valeur de la variable nx comme couple entrée/valeur dans le tableau des chemins.

Enfin, nous remontons tout en haut de la hiérarchie par récursion, en appelant la boucle ancetres : voyez la documentation sur les boucles récursives.

Deux remarques pour prévenir les questions :

  1. Nous ne pouvons pas mettre le changement de la variable niveau dans la partie optionelle des boucles, car cette partie est interprétée après le contenu de la boucle.
  2. On pourrait se dire qu’il serait possible de commencer au niveau de la boucle grand_parents et se passer de parents. Nous avons testé et obtenu des erreurs de récursions à l’infini, empêchant l’affichage de la page.

Notre tableau à maintenant le contenu suivant :

r7 r7
r7r2 r7r2
r7r2r1 r7r2r1
r10 r10
r10r8 r10r8
r10r8r6 r10r8r6

Filtrer les chemins incomplets

Les chemins r7,r7r2,r10, r10r8 ne sont pas complets : ils ne remontent pas jusqu’à la racine. Il nous faut donc les filtrer.

Pour ce faire, nous allons effacer la valeur de la clef correspondante, en mettant le code suivant dans la partie optionelle de nos boucles parents et grand_parents :

#SET{chemins,#GET{chemins}|array_merge{#ARRAY{
           #GET{n#GET{niveau}|moins{1}},
           ''
       }
       }}

Cela donc donc :

  1. <BOUCLE_article(ARTICLES){critères}>
  2. #SET{chemins,#ARRAY}
  3. #SET{niveau,0}
  4.  
  5.  
  6. <BOUCLE_parents(RUBRIQUES){parents}{par titre}>
  7. #SET{n0,r#ID_RUBRIQUE}
  8. #SET{chemins,#GET{chemins}|array_merge{#ARRAY{
  9. #GET{n0},
  10. #GET{n0}
  11. }
  12. }}
  13.  
  14. #SET{niveau,#GET{niveau}|plus{1}}
  15. <BOUCLE_grands_parents(RUBRIQUES){parents}{par titre}>
  16. #SET{n#GET{niveau},#GET{n#GET{niveau}|moins{1}}r#ID_RUBRIQUE}
  17. #SET{chemins,#GET{chemins}|array_merge{#ARRAY{
  18. #GET{n#GET{niveau}},
  19. #GET{n#GET{niveau}}
  20. }
  21. }}
  22. #SET{niveau,#GET{niveau}|plus{1}}
  23. <BOUCLE_ancetres(Boucle_grands_parents) />
  24. #SET{niveau,#GET{niveau}|moins{1}}
  25. }}
  26. </BOUCLE_grands_parents>
  27. #SET{chemins,#GET{chemins}|array_merge{#ARRAY{
  28. #GET{n#GET{niveau}|moins{1}},
  29. ''
  30. }
  31. }}
  32. </B_grands_parents>
  33. #SET{niveau,#GET{niveau}|moins{1}}
  34.  
  35.  
  36. </BOUCLE_parents>
  37. #SET{chemins,#GET{chemins}|array_merge{#ARRAY{
  38. #GET{n#GET{niveau}|moins{1}},
  39. ''
  40. }
  41. }}
  42. </B_parents>
  43. </BOUCLE_article>

Télécharger

Et on a le tableau des chemins suivant :

ClefValeur
r7
r7r2
r7r2r1 r7r2r1
r10
r7r2r8
r7r2r8r6 r7r2r8r6

Afficher tout les chemins

L’essentiel est fait : il ne nous reste plus qu’à boucler sur le tableau des chemins, en excluant ceux dont la valeur est vide :

  1. <B_chemins>
  2. <ul>
  3. <BOUCLE_chemins(POUR){tableau #GET{chemins}}{valeur!=''}>
  4. <li>#VALEUR</li>
  5. </BOUCLE_chemins>
  6. </ul>
  7. </B_chemins>

Télécharger

Cela produit :

  1. <ul>
  2.  
  3. <li>r7r2r1</li>
  4.  
  5. <li>r10</li>
  6.  
  7. <li>r7r2r8r6</li>
  8.  
  9. </ul>

Télécharger

Chaque li correspond à un chemin. Il nous faut donc l’afficher.

Pour ce faire, nous allons :
-  exploser la chaînes rxryrz pour obtenir un tableau, en utilisant r comme séparateur.
-  boucler sur ce tableau, en insérant une symbole de séparation entre chaque entrée, en évitant les entrées vides (liées au fait que nous n’avons pas de r à la fin de nos chemin) et en inversant l’ordre (pour avoir une hiérarchie allant de haut en bas et non de bas en haut)
-  dans la boucle, récupérer le titre la rubrique avec la balise #INFO_TITRE, et son URL avec #URL_RUBRIQUE{x}
.

Ce qui donne :

  1. <B_chemins>
  2. <ul>
  3. <BOUCLE_chemins(POUR){tableau #GET{chemins}}{valeur!=''}>
  4. <B_chemin>
  5. <li>
  6. <a href="#URL_SITE_SPIP">#NOM_SITE_SPIP</a> &gt;
  7. <BOUCLE_chemin(POUR){tableau #VALEUR|explode{r}}{inverse}{valeur!=''}{" &gt; "}>
  8. <a href="#URL_RUBRIQUE{#VALEUR}">#INFO_TITRE{rubrique,#VALEUR}</a>
  9. </BOUCLE_chemin>
  10. &gt; #TITRE [(#REM)<!-- correspond au titre de l'article-->]
  11. </li>
  12. </B_chemin>
  13. </BOUCLE_chemins>
  14. </ul>
  15. </B_chemins>

Télécharger

Et en HTML produit :

  1. <ul>
  2.  
  3.  
  4. <li>
  5. <a href="http://poly.dev">Mon site SPIP</a> &gt;
  6.  
  7. <a href="-rubrique1-.html">xs</a>
  8. &gt;
  9. <a href="-rubrique2-.html">d</a>
  10. &gt;
  11. <a href="-rubrique7-.html">g</a>
  12.  
  13. &gt; h
  14. </li>
  15.  
  16.  
  17.  
  18. <li>
  19. <a href="http://poly.dev">Mon site SPIP</a> &gt;
  20.  
  21. <a href="-rubrique6-.html">ys</a>
  22. &gt;
  23. <a href="-rubrique8-.html">d&#8217;</a>
  24. &gt;
  25. <a href="-rubrique10-.html">g&#8217;</a>
  26.  
  27. &gt; h
  28. </li>
  29.  
  30.  
  31. </ul>

Télécharger

Mettre en exergue le chemin principal

Il serait pratique que le chemin principal s’affiche en premier, avec une classe spéciale. Pour ce faire, nous allons utiliser une boucle HIERARCHIE classique, qui affichera le chemin avant, et stockera dans une variable cheminp ce chemin, afin de pouvoir l’exclure des chemins sur lesquelles on boucle.

Le remplissage de cette variable et l’affichage du chemin se fait donc ainsi :

  1. <B_cheminp>
  2. <div class='cheminp'>
  3. <a href="#URL_SITE_SPIP">#NOM_SITE_SPIP</a> &gt;
  4. <BOUCLE_cheminp(HIERARCHIE){id_article}{" &gt; "}>
  5. <a href="#URL_RUBRIQUE}">#TITRE</a>[(#SET{cheminp,[r(#ID_RUBRIQUE)][(#GET{cheminp})]})]
  6. </BOUCLE_cheminp>
  7. &gt; #TITRE [(#REM)<!-- correspond au titre de l'article-->]
  8. </div>
  9. </B_cheminp>

Télécharger

Nous allons donc exclure de la boucle chemins le chemin dont la valeur est égale à #GET{cheminp}.

Ce qui donne :

  1. <B_chemins>
  2. <ul>
  3. <BOUCLE_chemins(POUR){tableau #GET{chemins}}{valeur!=''}{valeur!=#GET{cheminp}}>
  4. <B_chemin>
  5. <li>
  6. <a href="#URL_SITE_SPIP">#NOM_SITE_SPIP</a> &gt;
  7. <BOUCLE_chemin(POUR){tableau #VALEUR|explode{r}}{inverse}{valeur!=''}{" &gt; "}>
  8. <a href="#URL_RUBRIQUE{#VALEUR}">#INFO_TITRE{rubrique,#VALEUR}</a>
  9. </BOUCLE_chemin>
  10. &gt; #TITRE [(#REM)<!-- correspond au titre de l'article-->]
  11. </li>
  12. </B_chemin>
  13. </BOUCLE_chemins>
  14. </ul>
  15. </B_chemins>

Télécharger

Au final

Nous avons donc au final un ensemble de boucles qui s’écrivent ainsi :

  1. <BOUCLE_article(ARTICLES){critères}>
  2. #SET{chemins,#ARRAY}
  3. #SET{niveau,0}
  4.  
  5.  
  6. <BOUCLE_parents(RUBRIQUES){parents}{par titre}>
  7. #SET{n0,r#ID_RUBRIQUE}
  8. #SET{chemins,#GET{chemins}|array_merge{#ARRAY{
  9. #GET{n0},
  10. #GET{n0}
  11. }
  12. }}
  13.  
  14. #SET{niveau,#GET{niveau}|plus{1}}
  15. <BOUCLE_grands_parents(RUBRIQUES){parents}{par titre}>
  16. #SET{n#GET{niveau},#GET{n#GET{niveau}|moins{1}}r#ID_RUBRIQUE}
  17. #SET{chemins,#GET{chemins}|array_merge{#ARRAY{
  18. #GET{n#GET{niveau}},
  19. #GET{n#GET{niveau}}
  20. }
  21. }}
  22. #SET{niveau,#GET{niveau}|plus{1}}
  23. <BOUCLE_ancetres(Boucle_grands_parents) />
  24. #SET{niveau,#GET{niveau}|moins{1}}
  25.  
  26. </BOUCLE_grands_parents>
  27. #SET{chemins,#GET{chemins}|array_merge{#ARRAY{
  28. #GET{n#GET{niveau}|moins{1}},
  29. ''
  30. }
  31. }}
  32. </B_grands_parents>
  33. #SET{niveau,#GET{niveau}|moins{1}}
  34.  
  35.  
  36. </BOUCLE_parents>
  37. #SET{chemins,#GET{chemins}|array_merge{#ARRAY{
  38. #GET{n#GET{niveau}|moins{1}},
  39. ''
  40. }
  41. }}
  42. </B_parents>
  43.  
  44. #SET{cheminp,''}
  45. <B_cheminp>
  46. <div class='cheminp'>
  47. <a href="#URL_SITE_SPIP">#NOM_SITE_SPIP</a> &gt;
  48. <BOUCLE_cheminp(HIERARCHIE){id_article}{" &gt; "}>
  49. <a href="#URL_RUBRIQUE}">#TITRE</a>[(#SET{cheminp,[r(#ID_RUBRIQUE)][(#GET{cheminp})]})]
  50. </BOUCLE_cheminp>
  51. &gt; #TITRE [(#REM)<!-- correspond au titre de l'article-->]
  52. </div>
  53. </B_cheminp>
  54.  
  55. <B_chemins>
  56. <ul>
  57. <BOUCLE_chemins(POUR){tableau #GET{chemins}}{valeur!=''}{valeur!=#GET{cheminp}}>
  58. <B_chemin>
  59. <li>
  60. <a href="#URL_SITE_SPIP">#NOM_SITE_SPIP</a> &gt;
  61. <BOUCLE_chemin(POUR){tableau #VALEUR|explode{r}}{inverse}{valeur!=''}{" &gt; "}>
  62. <a href="#URL_RUBRIQUE{#VALEUR}">#INFO_TITRE{rubrique,#VALEUR}</a>
  63. </BOUCLE_chemin>
  64. &gt; #TITRE [(#REM)<!-- correspond au titre de l'article-->]
  65. </li>
  66. </B_chemin>
  67. </BOUCLE_chemins>
  68. </ul>
  69. </B_chemins>
  70. </BOUCLE_article>

Télécharger

Ce qui donne en HTML

  1. <div class='cheminp'>
  2. <a href="http://poly.dev">Mon site SPIP</a> &gt;
  3.  
  4. <a href="-rubrique6-.html}">ys</a>
  5. &gt;
  6. <a href="-rubrique8-.html}">d&#8217;</a>
  7. &gt;
  8. <a href="-rubrique10-.html}">g&#8217;</a>
  9.  
  10. &gt; h
  11. </div>
  12.  
  13.  
  14.  
  15. <ul>
  16.  
  17.  
  18. <li>
  19. <a href="http://poly.dev">Mon site SPIP</a> &gt;
  20.  
  21. <a href="-rubrique1-.html">xs</a>
  22. &gt;
  23. <a href="-rubrique2-.html">d</a>
  24. &gt;
  25. <a href="-rubrique7-.html">g</a>
  26.  
  27. &gt; h
  28. </li>
  29.  
  30.  
  31. </ul>

Télécharger

Le reste n’est plus qu’affaire de maîtrise du CSS / HTML.

Dernière modification de cette page le 27 septembre 2012

Retour en haut de la page

Vos commentaires

Répondre à cet article

Qui êtes-vous ?

Pour afficher votre trombine avec votre message, enregistrez-la d’abord sur gravatar.com (gratuit et indolore) et n’oubliez pas d’indiquer votre adresse e-mail ici.

Ajoutez votre commentaire ici Les choses à faire avant de poser une question (Prolégomènes aux rapports de bugs. )
Ajouter un document

Retour en haut de la page

Ça discute par ici

  • Formidable, le générateur de formulaires

    23 janvier 2012 – 2189 commentaires

    Un générateur de formulaires facilement configurable pour les non-informaticiens et facilement extensible pour les développeurs. Introduction L’objectif était de créer un plugin permettant de générer des formulaires. Historiquement, 2 plugins (...)

  • Crayons : Contrôleurs et Vues

    1er mai 2007 – 22 commentaires

    Cet article est en cours de rédaction (donc incomplet), merci si vous avez : des corrections, des compléments, des exemples (simples si possible), des captures d’écran ou videos de démo, une traduction à proposer, n’hésitez (...)

  • Le Couteau Suisse

    4 mai 2007 – 1794 commentaires

    Ce plugin propose d’introduire facilement de simples fonctionnalités supplémentaires à SPIP et qui s’avèrent rapidement indispensables ! Par exemple : le contrôle de nombreuses variables « cachées » de SPIP, des améliorations ou facilités typographiques, (...)

  • Incarner

    11 juillet 2016 – 14 commentaires

    Permet aux webmestres de se connecter en tant qu’un autre auteur très facilement. Pendant la phase de développement, c’est très pratique pour diagnostiquer des problèmes d’autorisations sans avoir à se reloguer tout le temps. Ce plugin permet de se (...)

  • LangOnet - Présentation générale

    20 août 2010 – 17 commentaires

    Un outil destiné aux développeurs pour vérifier, générer, éditier ou afficher les items de langue d’un plugin, d’un squelette ou des fichiers originaux de SPIP. Objectif La mise au point des fichiers de langue d’un plugin ou d’un squelette est (...)