[Résolu] Paramètres indésirables dans un formulaire

Hello,
Je bataille avec deux formulaires de mon site et je m’arrache les cheveux … Quelqu’un aurait une idée ? Merci d’avance !

Le contexte:

J’ai une table OBSERVATIONS contenant des champs id_observation, titre et id_taxref. Je cherche à lier, depuis l’espace public, un ARTICLE à une OBSERVATION en peuplant le champ id_taxref de la valeur de l’id_article correspondant.

J’ai donc créé un formulaire dans une page publique d’article où je présente dans une liste déroulante, les observations candidates, en demandant à l’utilisateur d’en choisir une. Dans la même page, j’ai un second formulaire qui propose de délier les observations déjà liées à l’article. Chacun des deux formulaires redirige vers cette même page à la fin du traitement.

Mon problème:

  • la liaison d’une observation fonctionne
  • la suppression du lien d’une observation fonctionne

mais …

  • l’URL de la page contenant les formulaires perd la référence de l’article au retour de traiter().
  • si je veux lier une seconde observation, ça échoue …
  • idem pour une seconde suppression …

En regardant le source de la page APRES exécution de traiter(), je m’aperçois que l’id_observation de la première opération a été injecté dans les champs hidden de la page !! Pas moyen de comprendre pourquoi …

Exemple:

  • URL initiale : /spip.php?page=espece_admin&id_article=739
  • Je lie avec succès l’observation 13589 et l’article 739,
  • Le redirect du formulaire me renvoie le source ci-dessous pour le formulaire de liaison (même symptôme avec l’autre)
  • quelle que soit l’observation que je choisis maintenant, SPIP tente de lier de nouveau l’observation 13589 à l’article 739 !
<h3>Gestion des liens avec cette espèce</h3>
<div class='formulaire_spip formulaire_editer formulaire_lier_espece'>
   <!-- <br class='bugajaxie' /> -->

   <!-- Le paramètre action est FAUX. Il devrait être
	/spip.php?page=espece_admin&amp;id_article=739
   -->
   <form method='post' 
	action='/spip.php?page=espece_admin&amp;id_observation=13589' 
	enctype='multipart/form-data'>
      <div>
      <span class="form-hidden">
	<input name="page" value="espece_admin" type="hidden">

	<!-- L' input hidden 'id_observation' ci-dessous n'est pas requis par charger() 
	     et n'est pas présent au premier chargement de la page  ! 
	-->
	<input name="id_observation" value="13589" type="hidden">

	<input name='formulaire_action' type='hidden'value='lier_espece'>
	<input name='formulaire_action_args' type='hidden' value='(.. supprimé ..)'>
	<input name='formulaire_action_sign' type='hidden' value='(.. supprimé ..)'>
      </span>
      <input name='id_article' value='739' type='hidden' />
	<ul>
	  <li class="editer_id_observation">
	    <label for="id_observation">Lier une observation</label>    
	     <select name="id_observation">
		<option value="-1" selected="selected">Choisissez une observation</option>
	   
		<option value="6951">Obs 6951 : 1 hyménoptères  - 2019-07-08</option>
		<option value="7444">Obs 7444 : 1 A déterminer - 2020-04-03</option>
		<option value="8908">Obs 8908 : 5 Abeille - 2021-05-30</option>      
             </select>
	   </li>
	 </ul>
	 <p class="spip_bouton">
	   <input type="submit" name="valide" value="Ajouter cette observation"/>
         </p>
      </div>
    </form>
</div>

Salut

j’ai l’impression que tu es victime d’un choix de fonctionnement de SPIP par défaut, souvent bien pratique mais parfois bien gênant : form_hidden insère des hiddens en trop (#3769) · Issues · spip / spip · GitLab qualifié selon les moments de fonctionnement « tordu psychologiquement » et par moment de « pas un bug sinon ça se saurait depuis le temps ».

Selon les cas, pour remédier à cette difficulté, j’utilise

  • une fonction monplugin_form_hidden, qui reprend tout le code de form_hidden sauf la partie fautive qui surajoute les variables en trop :
/*
  * monplugin :  C'est ici la différence avec le form_hidden de spip
  * car urls_decoder_url renvoie un id_truc qui ne vient pas de $action 
  * mais issu de l'url de la page

	// ensuite avec celles du contexte, sans doublonner !
	foreach ($contexte as $var => $val) {
		if (preg_match(',\[\]$,S', $var)) {
			$values[] = array($var, $val);
		} else {
			if (!isset($values[$var])) {
				$values[$var] = array($var, $val);
			}
		}
	}
*/

L’important ici c’est /* au début et */ à la fin. Pour le reste garde le code de form_hidden.

  • Sinon, plus simplement peut être, tu pourrais passer une variable masquée, que tu récupérerais « à la main » là où tu le veux vraiment au lieu de compter sur les automatismes de SPIP.

Ici masquée par un nom différent du vrai nom : utiliser ?id_article_nonauto=123 ou ?id_observation_nonauto=12354 selon ce qui gêne,
et dans le squelette utiliser #ENV{id_article_nonauto} ou #ENV{id_observation_nonauto} aux endroits où il y a besoin de la valeur. Par exemple dans une boucle, le critère {id_article=#ENV{id_article_nonauto}} au lieu de {id_article}
Ainsi SPIP du coup ne pourrait rien faire de nuisible avec son automatisme compulsif dans form_hidden.

Merci pour ces suggestions !
Je teste tout ça (en commençant par la plus simple) et je te fais un retour …

Bingo !

J’ai pris la solution simple. En pratique, j’ai dû protéger les deux paramètres principaux dans mes formulaires:

  • id_observation pour permettre de lier/délier plusieurs observations à la suite (transformé en ref_observation)
  • id_article pour protéger la réécriture de l’URL dans la barre du navigateur (transformé en ref_article)

Un grand merci !

Pour info le source désormais obtenu après une première liaison :

<h3>Gestion des liens avec cette espèce</h3>
<div class='formulaire_spip formulaire_editer formulaire_lier_espece'>
   <!-- <br class='bugajaxie' /> -->
   <form method='post' action='/spip.php?page=espece_admin&amp;id_article=739' enctype='multipart/form-data'><div>
	<span class="form-hidden">
	  <input name="page" value="espece_admin" type="hidden">

	  <!-- Injection automatique par SPIP -->
	  <input name="id_article" value="739" type="hidden">  

          <input name='formulaire_action' type='hidden'value='lier_espece'>
	  <input name='formulaire_action_args' type='hidden' value='(...)'>
	  <input name='formulaire_action_sign' type='hidden' value='(...)'>
        </span>

	<!-- Mon injection via charger() de id_article maquillé en ref_article -->
        <input name='ref_article' value='739' type='hidden' /> 

	<ul>
	  <li class="reponse_formulaire reponse_formulaire_ok">Observation 13590 liée avec succès</li>
	  <li class="editer_id_observation">

	    <!-- Ci dessous le id_observation maquillé en ref_observation -->
	    <label for="ref_observation">Lier une observation</label>  	     
	     <select name="ref_observation">
		<option value="-1" selected="selected">Choisissez une observation</option>

		<option value="6951">Obs 6951 : 1 hyménoptères  - 2019-07-08</option>
		<option value="7444">Obs 7444 : 1 A déterminer - 2020-04-03</option>
		<option value="8908">Obs 8908 : 5 Abeille - 2021-05-30</option>       
             </select>
	   </li>
	 </ul>
	 <p class="spip_bouton"><input type="submit" name="valide" value="Ajouter cette observation"/></p>
   </div></form>
</div>

Cool. Merci pour ce retour.

Ce qui est bien quand même avec les variables en id_ c’est que l’écran de sécurité les protège en restreignant leurs valeurs possibles à des entiers. Je te conseille donc de garder un nom qui commence par id_. id_observation_ref stv.