Forum CMS Made Simple FR
[Résolu] Créer un lien vers une page dans un événement CGCalendar - Version imprimable

+- Forum CMS Made Simple FR (https://forum.cmsmadesimple.fr)
+-- Forum : Général (https://forum.cmsmadesimple.fr/forum-3.html)
+--- Forum : Modules, Tags (https://forum.cmsmadesimple.fr/forum-14.html)
+--- Sujet : [Résolu] Créer un lien vers une page dans un événement CGCalendar (/thread-4146.html)



[Résolu] Créer un lien vers une page dans un événement CGCalendar - cyrcle - 07/04/2018

Plus précisément, je souhaite créer, dans la partie admin d'un événement CGCalendar, une liste déroulante des pages enfants d'une rubrique qui s'appelle "Projets".
Pour chaque page, il me faut son "id" et son "titre" pour pouvoir créer par ailleurs un lien avec {cms_selflink page=$idPage}.

Pour cela, je pourrais créer une balise utilisateur (UDT), mais j'ai des doutes sur la requête SQL à écrire pour obtenir les informations qu'il me faut.
Je tente donc d'utiliser le module {Navigator} avec un gabarit personnalisé pour me fournir une chaîne de caractères qui me permettra de créer un tableau associatif.
La doc Smarty m'indique que je dois obtenir de {Navigator} la partie de la chaîne en gras ci-dessous :
{assign var=foo value=['idPage1'=>'Titre page 1','idPage2'=>'Titre page 2']}

Mon arborescence de pages est celle-ci :
Projets
— Projets associatifs
—— Projet 1
—— Projet 2
—— Projet 3
— Projets éducatifs
—— Projet 4
—— Projet 5
—— Projet 6

[h]1. Ma méthode fonctionne quand je fournis moi-même la chaîne à ma variable Smarty[/h]
Le code suivant me permet de créer mon tableau associatif :
{assign var=tableau_pages value=['Projets associatifs'=>['29'=>'Projet 1','15'=>'Projet 2','28'=>'Projet 3'],'Projets éducatifs'=>['10'=>'Projet 4','33'=>'Projet 5','34'=>'Projet 6']]}

Puis, le code suivant me permet de créer ma liste d'options à partir de ma variable Smarty $tableau_pages :
{html_options name="m1_field_LienInterne" options=$tableau_pages selected=28}

J'obtiens bien le code html attendu :
<select name="m1_field_LienInterne">
<optgroup label="Projets associatifs">
<option value="29">Projet 1</option>
<option value="15">Projet 2</option>
<option value="28" selected="selected">Projet 3</option>
</optgroup>
<optgroup label="Projets éducatifs">
<option value="10">Projet 4</option>
<option value="33">Projet 5</option>
<option value="34">Projet 6</option>
</optgroup>
</select>

[h]2. Ma méthode ne fonctionne plus quand ma chaîne de caractères vient de Navigator[/h]
Mon appel au module Navigator avec mon gabarit personnalisé :
{cms_module module="Navigator" template="Dropdown Pages" number_of_levels=2 childrenof="projets"}
Note : À cette étape, depuis un autre module (ici CGCalendar), il faut appeler Navigator avec le code {cms_module module="Navigator" …} et non {Navigator …} sinon on a une page blanche.

Me retourne bien la chaîne attendue :
['Projets associatifs'=>['29'=>'Projet 1','15'=>'Projet 2','28'=>'Projet 3'],'Projets éducatifs'=>['10'=>'Projet 4','33'=>'Projet 5','34'=>'Projet 6']]

Ensuite, je veux créer mon tableau associatif avec le code suivant :
{assign var=tableau_pages value={cms_module module="Navigator" template="Dropdown Pages" number_of_levels=2 childrenof="projets"}}

Mais là, la chaîne retournée par Navigator n'est pas transformée en tableau associatif (Array) elle reste une chaîne (String).

Le code suivant :
{html_options name="m1_field_LienInterne" options=$tableau_pages selected=28}

Me retourne ce code html :
<select name="m1_field_LienInterne">
<option value="0">['Projets associatifs'=>['29'=>'Projet 1','15'=>'Projet 2','28'=>'Projet 3'],'Projets éducatifs'=>['10'=>'Projet 4','33'=>'Projet 5','34'=>'Projet 6']]</option>
</select>

Quelqu'un peut-il me dire pourquoi ma chaîne n'est pas transformée en tableau associatif quand elle arrive de Navigator alors qu'elle est identique que celle utilisée à l'étape 1 ?
Merci.


[Résolu] Créer un lien vers une page dans un événement CGCalendar - airelibre - 13/04/2018

Bonjour,

en premier lieu, je te conseille l'option UDT qui reste plus simple à mettre en oeuvre, et qui garantit surtout la compatibilité avec les mises à jour - Dans cette solution, tu devras adapter ton gabarit d'édition d'évènement d'agenda si celui-ci change lors d'une mise à jour.

Cela étant, le problème de ta solution vient du fait que tu tentes de faire passer une chaine de caractères :
Code :
['Projets associatifs'=>['29'=>'Projet 1','15'=>'Projet 2','28'=>'Projet 3'],'Projets éducatifs'=>['10'=>'Projet 4','33'=>'Projet 5','34'=>'Projet 6']]

... pour un tableau.

C'est la différence entre :
Code :
{assign var='var' value="['mon','tableau']"}
et
Code :
{assign var='var' value=['mon','tableau']}

Je pense que la balise {setlist} peut t'aider car elle permet de transformer une chaine en tableau associatif. Regarde l'aide dans Extensions / Balises

Donnes-nous la solution quand tu auras fini Wink


[Résolu] Créer un lien vers une page dans un événement CGCalendar - cyrcle - 13/04/2018

Merci pour la balise {setlist} qui me donne la solution la plus simple 100% Smarty.
Pour résumé, j'ai trouvé 3 solutions à mon problème.


[h]Solution 1 avec une UDT utilisant eval()[/h]

Code :
{assign var=liste_pages value={cms_module module="Navigator" template="Pages List in ArrayString" number_of_levels=2 childrenof="projets"}}
{eval_string_to_be_array liste_pages=$liste_pages}
{html_options name="m1_field_LienInterne" options=$tableau_pages selected=28}

Détail de mon gabarit Pages List in ArrayString de type Navigator::Navigation :
Code :
{strip}
{* simple navigation / Note : function can only be defined once *}

{function name=Liste_pages depth=1}
[
{foreach $data as $node}{* build the menu item node *}
  {if $node->type == 'sectionheader'}
  {else if $node->type == 'separator'}
  {else}{* regular item *}
   {if $depth==0}{* 1er niveau *}
    {if $node@index != 1},{/if}'{$node->menutext|escape:"quotes"}'=>
   {elseif $depth==1}{* les enfants projets-associatifs et projets-educatifs *}
    '{$node->id}'=>'{$node->menutext|escape:"quotes"}'{if !$node@last},{/if}{*"\n"*}
   {/if}
   {if isset($node->children)}
    {Liste_pages data=$node->children depth=$depth+1}
   {/if}
  {/if}
{/foreach}
]
{/function}

{if isset($nodes)}
{Liste_pages data=$nodes depth=0}
{/if}
{/strip}

Retourne une chaîne de la forme "['Projets associatifs'=>['29'=>'Projet 1','15'=>'Projet 2','28'=>'Projet 3'],'Projets éducatifs'=>['10'=>'Projet 4','33'=>'Projet 5','34'=>'Projet 6']]" pour créer un tableau de valeurs qui est utilisé dans l'admin pour créer un menu déroulant des pages projets avec {html_options} dans CGCalendar.
Smarty n'arrivant pas à créer un tableau avec cette chaîne, il faut utiliser l'UDT {eval_string_to_be_array liste_pages=$liste_pages} contenant eval("\$resultat = array($myVar);"); pour forcer l'évaluation de la chaine et la stocker sous forme de tableau dans $tableau_pages.

Détail de mon UDT {eval_string_to_be_array} :
Code :
[== PHP ==]
/* récupère $liste_pages créé avec {assign var=liste_pages value={cms_module module="Navigator" template="Pages List in ArrayString" number_of_levels=2 childrenof="projets"}}
** et retourne $tableau_pages avec {eval_string_to_be_array liste_pages=$liste_pages}
*/

if (!empty($params['liste_pages'])) {
  $string = $params['liste_pages'];
  eval("\$resultat = $string;"); //force l'évaluation de la chaîne en tableau et la stocke dans $resultat
  $smarty->assign('tableau_pages', $resultat);
}
 

[h]Solution 2 avec une UDT utilisant 2 boucles foreach pour découper ma chaîne[/h]

Code :
{assign var=liste_pages value={cms_module module="Navigator" template="Pages List in CustomString" number_of_levels=2 childrenof="projets"}}
{custom_string_to_array liste_pages=$liste_pages}
{html_options name="m1_field_LienInterne" options=$tableau_pages selected=28}

Détail de mon gabarit Pages List in CustomString de type Navigator::Navigation :
Code :
{strip}
{* simple navigation / Note : function can only be defined once *}

{function name=Liste_pages depth=1}
{foreach $data as $node}{* build the menu item node *}
  {if $node->type == 'sectionheader'}
  {else if $node->type == 'separator'}
  {else}{* regular item *}
   {if $depth==0}{* 1er niveau *}
    {if $node@index != 1}‡A‡{/if}{$node->menutext|escape:"quotes"}‡B‡
   {elseif $depth==1}{* les enfants de projets-associatifs et projets-educatifs *}
    {$node->id}‡C‡{$node->menutext|escape:"quotes"}{if !$node@last}‡B‡{/if}{*"\n"*}
   {/if}
   {if isset($node->children)}
    {Liste_pages data=$node->children depth=$depth+1}
   {/if}
  {/if}
{/foreach}
{/function}

{if isset($nodes)}
{Liste_pages data=$nodes depth=0}
{/if}
{/strip}

Retourne une chaîne de la forme "Projets associatifs‡B‡29‡C‡Projet 1‡B‡15‡C‡Projet 2‡B‡28‡C‡Projet 3‡A‡Projets éducatifs‡B‡10‡C‡Projet 4‡B‡33‡C‡Projet 5‡B‡34‡C‡Projet 6" pour créer un tableau de valeurs qui est utilisé dans l'admin pour créer un menu déroulant des pages projets avec {html_options} dans CGCalendar.
Comme séparateur j'utilise ‡A‡ pour le niveau 1, ‡B‡ pour le niveau 2, ‡C‡ entre "idPage" et "Titre page".
Il faut utiliser l'UDT {custom_string_to_array liste_pages=$liste_pages} pour segmenter la chaine et la retourner sous forme de tableau dans $tableau_pages.

Détail de mon UDT {custom_string_to_array} :
Code :
[== PHP ==]
/* récupère $liste_pages créé avec {assign var=liste_pages value={cms_module module="Navigator" template="Pages List in CustomString" number_of_levels=2 childrenof="projets"}}
** et retourne $tableau_pages avec {custom_string_to_array liste_pages=$liste_pages}
*/

if (!empty($params['liste_pages'])) {
  //$string = $params['liste_pages'];
  $niv1 = explode("‡A‡",$params['liste_pages']);
  $resultat = array();
  foreach($niv1 as $item){
    $resultat2 = array();
    $niv2 = explode("‡B‡",$item);
    foreach($niv2 as $key=>$item2){
      if ($key > 0){
        $niv3 = explode("‡C‡",$item2);
        $resultat2[$niv3[0]] = $niv3[1];
      }
    }
    $resultat[$niv2[0]] = $resultat2;
  }
  $smarty->assign('tableau_pages', $resultat);
}
 

[h]Solution 3 : 100% Smarty[/h]
Code :
{setlist var=tableau_pages value={cms_module module="Navigator" template="Pages List in JSONString" number_of_levels=2 childrenof="projets"}}
{html_options name="m1_field_LienInterne" options=$tableau_pages selected=28}

Détail de mon gabarit Pages List in JSONString de type Navigator::Navigation :
Code :
{strip}
{* simple navigation / Note : function can only be defined once *}

{function name=Liste_pages depth=1}
{ldelim}
{foreach $data as $node}{* build the menu item node *}
  {if $node->type == 'sectionheader'}
  {else if $node->type == 'separator'}
  {else}{* regular item *}
   {if $depth==0}{* 1er niveau *}
    {if $node@index != 1},{/if}"{$node->menutext|escape:"quotes"}":
   {elseif $depth==1}{* les enfants projets-associatifs et projets-educatifs *}
    "{$node->id}":"{$node->menutext|escape:"quotes"}"{if !$node@last},{/if}{*"\n"*}
   {/if}
   {if isset($node->children)}
    {Liste_pages data=$node->children depth=$depth+1}
   {/if}
  {/if}
{/foreach}
{rdelim}
{/function}

{if isset($nodes)}
{Liste_pages data=$nodes depth=0}
{/if}
{/strip}

Retourne une chaîne JSON de la forme '{"Projets associatifs":{"29":"Projet 1","15":"Projet 2","28":"Projet 3"},"Projets éducatifs":{"10":"Projet 4","33":"Projet 5","34":"Projet 6"}}' utilisée par {setlist} pour créer un tableau de valeurs utilisé dans l'admin pour créer un menu déroulant des pages projets avec {html_options} dans CGCalendar.


[Résolu] Créer un lien vers une page dans un événement CGCalendar - airelibre - 13/04/2018

Beau travail et merci pour la solution qui pourra aiguiller d'autres visiteurs ! Merci de marquer le message en [Résolu] si tel est le cas Wink