[PLUGINS] +clavettes et dependances
[lhc/web/clavette_www.git] / www / plugins / saisies / inc / saisies_afficher.php
1 <?php
2
3 /**
4 * Gestion de l'affichage des saisies
5 *
6 * @return SPIP\Saisies\Afficher
7 **/
8
9 // Sécurité
10 if (!defined('_ECRIRE_INC_VERSION')) return;
11
12 /**
13 * Indique si une saisie peut être affichée.
14 *
15 * On s'appuie sur l'éventuelle clé "editable" du $champ.
16 * Si editable vaut :
17 * - absent : le champ est éditable
18 * - 1, le champ est éditable
19 * - 0, le champ n'est pas éditable
20 * - -1, le champ est éditable s'il y a du contenu dans le champ (l'environnement)
21 * ou dans un de ses enfants (fieldsets)
22 *
23 * @param array $champ
24 * Tableau de description de la saisie
25 * @param array $env
26 * Environnement transmis à la saisie, certainement l'environnement du formulaire
27 * @param bool $utiliser_editable
28 * - false pour juste tester le cas -1
29 *
30 * @return bool
31 * Retourne un booléen indiquant l'état éditable ou pas :
32 * - true si la saisie est éditable (peut être affichée)
33 * - false sinon
34 */
35 function saisie_editable($champ, $env, $utiliser_editable=true) {
36 if ($utiliser_editable) {
37 // si le champ n'est pas éditable, on sort.
38 if (!isset($champ['editable'])) {
39 return true;
40 }
41 $editable = $champ['editable'];
42
43 if ($editable > 0) {
44 return true;
45 }
46 if ($editable == 0) {
47 return false;
48 }
49 }
50
51 // cas -1
52 // name de la saisie
53 if (isset($champ['options']['nom'])) {
54 // si on a le name dans l'environnement, on le teste
55 $nom = $champ['options']['nom'];
56 if (isset($env[$nom])) {
57 return $env[$nom] ? true : false ;
58 }
59 }
60 // sinon, si on a des sous saisies
61 if (isset($champ['saisies']) and is_array($champ['saisies'])) {
62 foreach($champ['saisies'] as $saisie) {
63 if (saisie_editable($saisie, $env, false)) {
64 return true;
65 }
66 }
67 }
68
69 // aucun des paramètres demandés n'avait de contenu
70 return false;
71 }
72
73 /**
74 * Génère une saisie à partir d'un tableau la décrivant et de l'environnement
75 *
76 * @param array $champ
77 * Description de la saisie.
78 * Le tableau doit être de la forme suivante :
79 * array(
80 * 'saisie' => 'input',
81 * 'options' => array(
82 * 'nom' => 'le_name',
83 * 'label' => 'Un titre plus joli',
84 * 'obligatoire' => 'oui',
85 * 'explication' => 'Remplissez ce champ en utilisant votre clavier.'
86 * )
87 * )
88 * @param array $env
89 * Environnement du formulaire
90 * Permet de savoir les valeurs actuelles des contenus des saisies,
91 * les erreurs eventuelles présentes...
92 * @return string
93 * Code HTML des saisies de formulaire
94 */
95 function saisies_generer_html($champ, $env=array()){
96 // Si le parametre n'est pas bon, on genere du vide
97 if (!is_array($champ))
98 return '';
99
100 // Si la saisie n'est pas editable, on sort aussi.
101 if (!saisie_editable($champ, $env)) {
102 return '';
103 }
104
105 $contexte = array();
106
107 // On sélectionne le type de saisie
108 $contexte['type_saisie'] = $champ['saisie'];
109 // Identifiant unique de saisie, si present
110 if (isset($champ['identifiant'])) {
111 $contexte['id_saisie'] = $champ['identifiant'];
112 }
113
114 // Peut-être des transformations à faire sur les options textuelles
115 $options = $champ['options'];
116 foreach ($options as $option => $valeur){
117 if ($option == 'datas') {
118 // exploser une chaine datas en tableau (applique _T_ou_typo sur chaque valeur)
119 $options[$option] = saisies_chaine2tableau($valeur);
120 } else {
121 $options[$option] = _T_ou_typo($valeur, 'multi');
122 }
123 }
124
125 // On ajoute les options propres à la saisie
126 $contexte = array_merge($contexte, $options);
127
128 // Si env est définie dans les options ou qu'il y a des enfants, on ajoute tout l'environnement
129 if (isset($contexte['env']) or (isset($champ['saisies']) AND is_array($champ['saisies']))) {
130 unset($contexte['env']);
131
132 // on sauve l'ancien environnement
133 // car les sous-saisies ne doivent pas être affectees
134 // par les modification sur l'environnement servant à generer la saisie mère
135 $contexte['_env'] = $env;
136
137 // À partir du moment où on passe tout l'environnement, il faut enlever certains éléments qui ne doivent absolument provenir que des options
138 unset($env['inserer_debut']);
139 unset($env['inserer_fin']);
140 $saisies_disponibles = saisies_lister_disponibles();
141 if (isset($saisies_disponibles[$contexte['type_saisie']]) and is_array($saisies_disponibles[$contexte['type_saisie']]['options'])) {
142 $options_a_supprimer = saisies_lister_champs($saisies_disponibles[$contexte['type_saisie']]['options']);
143 foreach ($options_a_supprimer as $option_a_supprimer){
144 unset($env[$option_a_supprimer]);
145 }
146 }
147
148 $contexte = array_merge($env, $contexte);
149 }
150 // Sinon on ne sélectionne que quelques éléments importants
151 else{
152 // On récupère la liste des erreurs
153 $contexte['erreurs'] = $env['erreurs'];
154 // On ajoute toujours le bon self
155 $contexte['self'] = self();
156 }
157
158 // Dans tous les cas on récupère de l'environnement la valeur actuelle du champ
159 // Si le nom du champ est un tableau indexé, il faut parser !
160 if (preg_match('/([\w]+)((\[[\w]+\])+)/', $contexte['nom'], $separe)){
161 $contexte['valeur'] = $env[$separe[1]];
162 preg_match_all('/\[([\w]+)\]/', $separe[2], $index);
163 // On va chercher au fond du tableau
164 foreach($index[1] as $cle){
165 $contexte['valeur'] = isset($contexte['valeur'][$cle]) ? $contexte['valeur'][$cle] : null;
166 }
167 }
168 // Sinon la valeur est juste celle du nom
169 else {
170 $contexte['valeur'] = (isset($env[$contexte['nom']]) ? $env[$contexte['nom']] : null);
171 }
172
173 // Si ya des enfants on les remonte dans le contexte
174 if (isset($champ['saisies']) and is_array($champ['saisies']))
175 $contexte['saisies'] = $champ['saisies'];
176
177 // On génère la saisie
178 return recuperer_fond(
179 'saisies/_base',
180 $contexte
181 );
182 }
183
184 /**
185 * Génère une vue d'une saisie à partir d'un tableau la décrivant
186 *
187 * @see saisies_generer_html()
188 * @param array $saisie
189 * Tableau de description d'une saisie
190 * @param array $env
191 * L'environnement, contenant normalement la réponse à la saisie
192 * @param array $env_obligatoire
193 * ???
194 * @return string
195 * Code HTML de la vue de la saisie
196 */
197 function saisies_generer_vue($saisie, $env=array(), $env_obligatoire=array()){
198 // Si le paramètre n'est pas bon, on génère du vide
199 if (!is_array($saisie))
200 return '';
201
202 $contexte = array();
203
204 // On sélectionne le type de saisie
205 $contexte['type_saisie'] = $saisie['saisie'];
206
207 // Peut-être des transformations à faire sur les options textuelles
208 $options = $saisie['options'];
209 foreach ($options as $option => $valeur){
210 if ($option == 'datas') {
211 // exploser une chaine datas en tableau (applique _T_ou_typo sur chaque valeur)
212 $options[$option] = saisies_chaine2tableau($valeur);
213 } else {
214 $options[$option] = _T_ou_typo($valeur, 'multi');
215 }
216 }
217
218 // On ajoute les options propres à la saisie
219 $contexte = array_merge($contexte, $options);
220
221 // Si env est définie dans les options ou qu'il y a des enfants, on ajoute tout l'environnement
222 if (isset($contexte['env']) or (isset($saisie['saisies']) AND is_array($saisie['saisies']))){
223 unset($contexte['env']);
224
225 // on sauve l'ancien environnement
226 // car les sous-saisies ne doivent pas être affectees
227 // par les modification sur l'environnement servant à generer la saisie mère
228 $contexte['_env'] = $env;
229
230 // À partir du moment où on passe tout l'environnement, il faut enlever
231 // certains éléments qui ne doivent absolument provenir que des options
232 $saisies_disponibles = saisies_lister_disponibles();
233 if (is_array($saisies_disponibles[$contexte['type_saisie']]['options'])){
234 $options_a_supprimer = saisies_lister_champs($saisies_disponibles[$contexte['type_saisie']]['options']);
235 foreach ($options_a_supprimer as $option_a_supprimer){
236 unset($env[$option_a_supprimer]);
237 }
238 }
239
240 $contexte = array_merge($env, $contexte);
241 }
242
243 // Dans tous les cas on récupère de l'environnement la valeur actuelle du champ
244
245 // On regarde en priorité s'il y a un tableau listant toutes les valeurs
246 if ($env['valeurs'] and is_array($env['valeurs']) and isset($env['valeurs'][$contexte['nom']])){
247 $contexte['valeur'] = $env['valeurs'][$contexte['nom']];
248 }
249 // Si le nom du champ est un tableau indexé, il faut parser !
250 elseif (preg_match('/([\w]+)((\[[\w]+\])+)/', $contexte['nom'], $separe)){
251 $contexte['valeur'] = $env[$separe[1]];
252 preg_match_all('/\[([\w]+)\]/', $separe[2], $index);
253 // On va chercher au fond du tableau
254 foreach($index[1] as $cle){
255 $contexte['valeur'] = $contexte['valeur'][$cle];
256 }
257 }
258 // Sinon la valeur est juste celle du nom
259 else {
260 // certains n'ont pas de nom (fieldset)
261 $contexte['valeur'] = isset($env[$contexte['nom']]) ? $env[$contexte['nom']] : '';
262 }
263
264 // Si ya des enfants on les remonte dans le contexte
265 if (isset($saisie['saisies']) AND is_array($saisie['saisies']))
266 $contexte['saisies'] = $saisie['saisies'];
267
268 if (is_array($env_obligatoire)) {
269 $contexte = array_merge($contexte, $env_obligatoire);
270 }
271
272 // On génère la saisie
273 return recuperer_fond(
274 'saisies-vues/_base',
275 $contexte
276 );
277 }
278
279 /**
280 * Génère, à partir d'un tableau de saisie le code javascript ajouté à la fin de #GENERER_SAISIES
281 * pour produire un affichage conditionnel des saisies ayant une option afficher_si ou afficher_si_remplissage.
282 *
283 * @param array $saisies
284 * Tableau de descriptions des saisies
285 * @param string $id_form
286 * Identifiant unique pour le formulaire
287 * @return text
288 * Code javascript
289 */
290 function saisies_generer_js_afficher_si($saisies,$id_form){
291 $i = 0;
292 $saisies = saisies_lister_par_nom($saisies,true);
293 $code = '';
294 $code .= '(function($){';
295 $code .= '$(document).ready(function(){chargement=true;';
296 $code .= 'verifier_saisies_'.$id_form." = function(form){\n";
297 foreach ($saisies as $saisie) {
298 // on utilise comme selecteur l'identifiant de saisie en priorite s'il est connu
299 // parce que li_class = 'tableau[nom][option]' ne fonctionne evidement pas
300 // lorsque le name est un tableau
301 if (isset($saisie['options']['afficher_si']) or isset($saisie['options']['afficher_si_remplissage'])) {
302 $i++;
303 // retrouver la classe css probable
304 switch ($saisie['saisie']) {
305 case 'fieldset':
306 $class_li = 'fieldset_'.$saisie['options']['nom'];
307 break;
308 case 'explication':
309 $class_li = 'explication_'.$saisie['options']['nom'];
310 break;
311 default:
312 $class_li = 'editer_'.$saisie['options']['nom'];
313 }
314 $afficher_si = isset($saisie['options']['afficher_si']) ? $saisie['options']['afficher_si'] : '';
315 $afficher_si_remplissage = isset($saisie['options']['afficher_si_remplissage']) ? $saisie['options']['afficher_si_remplissage'] : '';
316 $condition = join("\n", array_filter(array($afficher_si, $afficher_si_remplissage)));
317 // retrouver l'identifiant
318 $identifiant = '';
319 if (isset($saisie['identifiant']) and $saisie['identifiant']) {
320 $identifiant = $saisie['identifiant'];
321 }
322 // On gère le cas @plugin:non_plugin@
323 preg_match_all('#@plugin:(.+)@#U', $condition, $matches);
324 foreach ($matches[1] as $plug) {
325 if (defined('_DIR_PLUGIN_'.strtoupper($plug)))
326 $condition = preg_replace('#@plugin:'.$plug.'@#U', 'true', $condition);
327 else
328 $condition = preg_replace('#@plugin:'.$plug.'@#U', 'false', $condition);
329 }
330 // On gère le cas @config:plugin:meta@ suivi d'un test
331 preg_match_all('#@config:(.+):(.+)@#U', $condition, $matches);
332 foreach ($matches[1] as $plugin) {
333 $config = lire_config($plugin);
334 $condition = preg_replace('#@config:'.$plugin.':'.$matches[2][0].'@#U', '"'.$config[$matches[2][0]].'"', $condition);
335 }
336 // On transforme en une condition valide
337 preg_match_all('#@(.+)@#U', $condition, $matches);
338 foreach ($matches[1] as $nom) {
339 switch($saisies[$nom]['saisie']) {
340 case 'radio':
341 case 'oui_non':
342 $condition = preg_replace('#@'.preg_quote($nom).'@#U', '$(form).find("[name=\''.$nom.'\']:checked").val()', $condition);
343 break;
344 case 'case':
345 $condition = preg_replace('#@'.preg_quote($nom).'@#U', '($(form).find(".checkbox[name=\''.$nom.'\']").is(":checked") ? $(form).find(".checkbox[name=\''.$nom.'\']").val() : "")', $condition);
346 break;
347 case 'checkbox':
348 preg_match_all('#@(.+)@\s*==\s*"(.*)"$#U', $condition, $matches2);
349 foreach ($matches2[2] as $value) {
350 $condition = preg_replace('#@'.preg_quote($nom).'@#U', '($(form).find(".checkbox[name=\''.$nom.'[]\'][value='.$value.']").is(":checked") ? $(form).find(".checkbox[name=\''.$nom.'[]\'][value='.$value.']").val() : "")', $condition);
351 }
352 break;
353 default:
354 $condition = preg_replace('#@'.preg_quote($nom).'@#U', '$(form).find("[name=\''.$nom.'\']").val()', $condition);
355 }
356 }
357 if ($identifiant) {
358 $sel = "li[data-id='$identifiant']";
359 } else {
360 $sel = "li.$class_li";
361 }
362 $code .= "\tif (".$condition.') {$(form).find("'.$sel.'").show(400);} '."\n\t";
363 $code .= 'else {if (chargement==true) {$(form).find("'.$sel.'").hide(400).css("display","none");} else {$(form).find("'.$sel.'").hide(400);};} '."\n";
364 }
365 }
366 $code .= "};";
367 $code .= '$("li#afficher_si_'.$id_form.'").parents("form").each(function(){verifier_saisies_'.$id_form.'(this);});';
368 $code .= '$("li#afficher_si_'.$id_form.'").parents("form").change(function(){verifier_saisies_'.$id_form.'(this);});';
369 $code .= 'chargement=false;})';
370 $code .= '})(jQuery);';
371 return $i>0 ? $code : '';
372 }
373
374 /**
375 * Lorsque l'on affiche les saisies (#VOIR_SAISIES), les saisies ayant une option afficher_si
376 * et dont les conditions ne sont pas remplies doivent être retirées du tableau de saisies.
377 *
378 * Cette fonction sert aussi lors de la vérification des saisies avec saisies_verifier().
379 * À ce moment là, les saisies non affichées sont retirées de _request
380 * (on passe leur valeur à NULL).
381 *
382 * @param array $saisies
383 * Tableau de descriptions de saisies
384 * @param array|null $env
385 * Tableau d'environnement transmis dans inclure/voi_saisies.html,
386 * NULL si on doit rechercher dans _request (pour saisies_verifier()).
387 * @return array
388 * Tableau de descriptions de saisies
389 */
390 function saisies_verifier_afficher_si($saisies, $env=NULL) {
391 // eviter une erreur par maladresse d'appel :)
392 if (!is_array($saisies)) {
393 return array();
394 }
395 foreach ($saisies as $cle => $saisie) {
396 if (isset($saisie['options']['afficher_si'])) {
397 $condition = $saisie['options']['afficher_si'];
398 // On gère le cas @plugin:non_plugin@
399 preg_match_all('#@plugin:(.+)@#U', $condition, $matches);
400 foreach ($matches[1] as $plug) {
401 if (defined('_DIR_PLUGIN_'.strtoupper($plug)))
402 $condition = preg_replace('#@plugin:'.$plug.'@#U', 'true', $condition);
403 else
404 $condition = preg_replace('#@plugin:'.$plug.'@#U', 'false', $condition);
405 }
406 // On gère le cas @config:plugin:meta@ suivi d'un test
407 preg_match_all('#@config:(.+):(.+)@#U', $condition, $matches);
408 foreach ($matches[1] as $plugin) {
409 $config = lire_config($plugin);
410 $condition = preg_replace('#@config:'.$plugin.':'.$matches[2][0].'@#U', '"'.$config[$matches[2][0]].'"', $condition);
411 }
412 // On transforme en une condition valide
413 if (is_null($env))
414 $condition = preg_replace('#@(.+)@#U', '_request(\'$1\')', $condition);
415 else
416 $condition = preg_replace('#@(.+)@#U', '$env["valeurs"][\'$1\']', $condition);
417 eval('$ok = '.$condition.';');
418 if (!$ok) {
419 unset($saisies[$cle]);
420 if (is_null($env)) set_request($saisie['options']['nom'],NULL);
421 }
422 }
423 if (isset($saisies[$cle]['saisies'])) // S'il s'agit d'un fieldset ou equivalent, verifier les sous-saisies
424 $saisies[$cle]['saisies'] = saisies_verifier_afficher_si($saisies[$cle]['saisies'], $env);
425 }
426 return $saisies;
427 }
428
429 ?>