SPIP-Contrib

SPIP-Contrib

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

286 Plugins, 197 contribs sur SPIP-Zone, 328 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.

Zip - 1.8 ko
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 :

PNG - 13.3 ko

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

  • Mailsubscribers

    16 janvier 2013 – 274 commentaires

    Ce plugin permet de gérer les inscriptions (ou abonnements) à la diffusion de contenu par email. Mailsubscribers permet de gérer les inscriptions par Opt-in simple ou double et la désinscription par URL. Ce plugin gère également plusieurs listes (...)

  • noiZetier v2

    9 novembre 2012 – 36 commentaires

    Le noiZetier offre une interface d’administration permettant d’insérer au choix des éléments modulaires de squelettes (noisettes) et de les ajouter ainsi à ses squelettes. Compatibilité La version 2 du noizetier fonctionne sous SPIP 3. Elle est (...)

  • cirr : plugin « rédacteur restreint »

    29 octobre 2010 – 60 commentaires

    Ce plugin « cirr : rédacteur restreint » permet d’affecter des rubriques aux rédacteurs et modifie les droits afin qu’un rédacteur restreint (ou un administrateur restreint) voit dans l’espace privé uniquement les rubriques qui lui sont affectées (et leur (...)

  • Un retour d’expérience d’utilisation de Formidable

    26 octobre – commentaires

    Il s’agissait de créer un formulaire d’inscription à un évènement modérer les inscriptions dans le privé publier les inscriptions dans le public Nous avons discuté de cette présentation lors de l’apéro SPIP du 15 février 2016 à la Cantine (...)

  • Métas +

    3 décembre – 14 commentaires

    Améliorez l’indexation de vos articles dans les moteurs et leur affichage sur les réseaux sociaux grâce aux métadonnées Dublin Core, Open Graph et Twitter Card. Installation Activer le plugin dans le menu dédié. Dans le panel de configuration, (...)

Ça spipe par là