[PLUGINS] +les plugins de bases
[ptitvelo/web/www.git] / www / plugins / saisies / inc / saisies.php
1 <?php
2
3 /**
4 * Gestion de l'affichage des saisies
5 *
6 * @return SPIP\Saisies\Saisies
7 **/
8
9 // Sécurité
10 if (!defined('_ECRIRE_INC_VERSION')) return;
11
12 /*
13 * Une librairie pour manipuler ou obtenir des infos sur un tableau de saisies
14 *
15 * saisies_lister_par_nom()
16 * saisies_lister_champs()
17 * saisies_lister_valeurs_defaut()
18 * saisies_charger_champs()
19 * saisies_chercher()
20 * saisies_supprimer()
21 * saisies_inserer()
22 * saisies_deplacer()
23 * saisies_modifier()
24 * saisies_verifier()
25 * saisies_comparer()
26 * saisies_generer_html()
27 * saisies_generer_vue()
28 * saisies_generer_nom()
29 * saisies_inserer_html()
30 * saisies_lister_disponibles()
31 * saisies_autonomes()
32 */
33
34 // Différentes méthodes pour trouver les saisies
35 include_spip('inc/saisies_lister');
36
37 // Différentes méthodes pour manipuler une liste de saisies
38 include_spip('inc/saisies_manipuler');
39
40 // Les outils pour afficher les saisies et leur vue
41 include_spip('inc/saisies_afficher');
42
43 /*
44 * Cherche la description des saisies d'un formulaire CVT dont on donne le nom
45 *
46 * @param string $form Nom du formulaire dont on cherche les saisies
47 * @return array Retourne les saisies du formulaire sinon false
48 */
49 function saisies_chercher_formulaire($form, $args){
50 if ($fonction_saisies = charger_fonction('saisies', 'formulaires/'.$form, true)
51 and $saisies = call_user_func_array($fonction_saisies, $args)
52 and is_array($saisies)
53 // On passe les saisies dans un pipeline normé comme pour CVT
54 and $saisies = pipeline(
55 'formulaire_saisies',
56 array(
57 'args' => array('form' => $form, 'args' => $args),
58 'data' => $saisies
59 )
60 )
61 // Si c'est toujours un tableau après le pipeline
62 and is_array($saisies)
63 ){
64 return $saisies;
65 }
66 else{
67 return false;
68 }
69 }
70
71 /*
72 * Cherche une saisie par son id, son nom ou son chemin et renvoie soit la saisie, soit son chemin
73 *
74 * @param array $saisies Un tableau décrivant les saisies
75 * @param unknown_type $id_ou_nom_ou_chemin L'identifiant ou le nom de la saisie à chercher ou le chemin sous forme d'une liste de clés
76 * @param bool $retourner_chemin Indique si on retourne non pas la saisie mais son chemin
77 * @return array Retourne soit la saisie, soit son chemin, soit null
78 */
79 function saisies_chercher($saisies, $id_ou_nom_ou_chemin, $retourner_chemin=false){
80
81 if (is_array($saisies) and $id_ou_nom_ou_chemin){
82 if (is_string($id_ou_nom_ou_chemin)){
83 $nom = $id_ou_nom_ou_chemin;
84 // identifiant ? premier caractere @
85 $id = ($nom[0] == '@');
86
87 foreach($saisies as $cle => $saisie){
88 $chemin = array($cle);
89 // notre saisie est la bonne ?
90 if ($nom == ($id ? $saisie['identifiant'] : $saisie['options']['nom'])) {
91 return $retourner_chemin ? $chemin : $saisie;
92 // sinon a telle des enfants ? et si c'est le cas, cherchons dedans
93 } elseif (isset($saisie['saisies']) and is_array($saisie['saisies']) and $saisie['saisies']
94 and ($retour = saisies_chercher($saisie['saisies'], $nom, $retourner_chemin))) {
95 return $retourner_chemin ? array_merge($chemin, array('saisies'), $retour) : $retour;
96 }
97
98 }
99 }
100 elseif (is_array($id_ou_nom_ou_chemin)){
101 $chemin = $id_ou_nom_ou_chemin;
102 $saisie = $saisies;
103 // On vérifie l'existence quand même
104 foreach ($chemin as $cle){
105 if (isset($saisie[$cle])) $saisie = $saisie[$cle];
106 else return null;
107 }
108 // Si c'est une vraie saisie
109 if ($saisie['saisie'] and $saisie['options']['nom'])
110 return $retourner_chemin ? $chemin : $saisie;
111 }
112 }
113
114 return null;
115 }
116
117 /**
118 * Génère un nom unique pour un champ d'un formulaire donné
119 *
120 * @param array $formulaire
121 * Le formulaire à analyser
122 * @param string $type_saisie
123 * Le type de champ dont on veut un identifiant
124 * @return string
125 * Un nom unique par rapport aux autres champs du formulaire
126 */
127 function saisies_generer_nom($formulaire, $type_saisie){
128 $champs = saisies_lister_champs($formulaire);
129
130 // Tant que type_numero existe, on incrémente le compteur
131 $compteur = 1;
132 while (array_search($type_saisie.'_'.$compteur, $champs) !== false)
133 $compteur++;
134
135 // On a alors un compteur unique pour ce formulaire
136 return $type_saisie.'_'.$compteur;
137 }
138
139 /*
140 * Crée un identifiant Unique
141 * pour toutes les saisies donnees qui n'en ont pas
142 *
143 * @param Array $saisies Tableau de saisies
144 * @param Bool $regenerer_id Régénère un nouvel identifiant pour toutes les saisies ?
145 * @return Array Tableau de saisies complété des identifiants
146 */
147 function saisies_identifier($saisies, $regenerer = false) {
148 if (!is_array($saisies)) {
149 return array();
150 }
151 foreach ($saisies as $k => $saisie) {
152 $saisies[$k] = saisie_identifier($saisie, $regenerer);
153 }
154 return $saisies;
155 }
156
157 /**
158 * Crée un identifiant Unique
159 * pour la saisie donnee si elle n'en a pas
160 * (et pour ses sous saisies éventuels)
161 *
162 * @param Array $saisie Tableau d'une saisie
163 * @param Bool $regenerer_id Régénère un nouvel identifiant pour la saisie ?
164 * @return Array Tableau de la saisie complété de l'identifiant
165 **/
166 function saisie_identifier($saisie, $regenerer = false) {
167 if (!isset($saisie['identifiant']) OR !$saisie['identifiant']) {
168 $saisie['identifiant'] = uniqid('@');
169 } elseif ($regenerer) {
170 $saisie['identifiant'] = uniqid('@');
171 }
172 if (isset($saisie['saisies']) AND is_array($saisie['saisies'])) {
173 $saisie['saisies'] = saisies_identifier($saisie['saisies'], $regenerer);
174 }
175 return $saisie;
176 }
177
178 /*
179 * Vérifier tout un formulaire tel que décrit avec les Saisies
180 *
181 * @param array $formulaire Le contenu d'un formulaire décrit dans un tableau de Saisies
182 * @param bool $saisies_masquees_nulles Si TRUE, les saisies masquées selon afficher_si ne seront pas verifiées, leur valeur étant forcée a NULL. Cette valeur NULL est transmise à traiter (via set_request).
183 * @return array Retourne un tableau d'erreurs
184 */
185 function saisies_verifier($formulaire, $saisies_masquees_nulles=true){
186 include_spip('inc/verifier');
187 $erreurs = array();
188 $verif_fonction = charger_fonction('verifier','inc',true);
189
190 if ($saisies_masquees_nulles)
191 $formulaire = saisies_verifier_afficher_si($formulaire);
192
193 $saisies = saisies_lister_par_nom($formulaire);
194 foreach ($saisies as $saisie){
195 $obligatoire = isset($saisie['options']['obligatoire']) ? $saisie['options']['obligatoire'] : '';
196 $champ = $saisie['options']['nom'];
197 $file = ($saisie['saisie'] == 'input' and isset($saisie['options']['type']) and $saisie['options']['type'] == 'file');
198 $verifier = isset($saisie['verifier']) ? $saisie['verifier'] : false;
199
200 // Si le nom du champ est un tableau indexé, il faut parser !
201 if (preg_match('/([\w]+)((\[[\w]+\])+)/', $champ, $separe)){
202 $valeur = _request($separe[1]);
203 preg_match_all('/\[([\w]+)\]/', $separe[2], $index);
204 // On va chercher au fond du tableau
205 foreach($index[1] as $cle){
206 $valeur = isset($valeur[$cle]) ? $valeur[$cle] : null;
207 }
208 }
209 // Sinon la valeur est juste celle du nom
210 else
211 $valeur = _request($champ);
212
213 // On regarde d'abord si le champ est obligatoire
214 if ($obligatoire
215 and $obligatoire != 'non'
216 and (
217 ($file and !$_FILES[$champ]['name'])
218 or (!$file and (
219 is_null($valeur)
220 or (is_string($valeur) and trim($valeur) == '')
221 or (is_array($valeur) and count($valeur) == 0)
222 ))
223 )
224 ) {
225 $erreurs[$champ] =
226 (isset($saisie['options']['erreur_obligatoire']) and $saisie['options']['erreur_obligatoire'])
227 ? $saisie['options']['erreur_obligatoire']
228 : _T('info_obligatoire');
229 }
230
231 // On continue seulement si ya pas d'erreur d'obligation et qu'il y a une demande de verif
232 if ((!isset($erreurs[$champ]) or !$erreurs[$champ]) and is_array($verifier) and $verif_fonction){
233 $normaliser = null;
234 // Si le champ n'est pas valide par rapport au test demandé, on ajoute l'erreur
235 $options = isset($verifier['options']) ? $verifier['options'] : array();
236 if ($erreur_eventuelle = $verif_fonction($valeur, $verifier['type'], $options, $normaliser)) {
237 $erreurs[$champ] = $erreur_eventuelle;
238 // S'il n'y a pas d'erreur et que la variable de normalisation a été remplie, on l'injecte dans le POST
239 } elseif (!is_null($normaliser)) {
240 set_request($champ, $normaliser);
241 }
242 }
243 }
244
245 return $erreurs;
246 }
247
248 /*
249 * Transforme une chaine en tableau avec comme principe :
250 * - une ligne devient une case
251 * - si la ligne est de la forme truc|bidule alors truc est la clé et bidule la valeur
252 *
253 * @param string $chaine Une chaine à transformer
254 * @return array Retourne un tableau PHP
255 */
256 function saisies_chaine2tableau($chaine, $separateur="\n"){
257 if ($chaine and is_string($chaine)){
258 $tableau = array();
259 // On découpe d'abord en lignes
260 $lignes = explode($separateur, $chaine);
261 foreach ($lignes as $i=>$ligne){
262 $ligne = trim(trim($ligne), '|');
263 // Si ce n'est pas une ligne sans rien
264 if ($ligne !== ''){
265 // Si on trouve un découpage dans la ligne on fait cle|valeur
266 if (strpos($ligne, '|') !== false){
267 list($cle,$valeur) = explode('|', $ligne, 2);
268 // permettre les traductions de valeurs au passage
269 $tableau[$cle] = _T_ou_typo($valeur, 'multi');
270 }
271 // Sinon on génère la clé
272 else{
273 $tableau[$i] = $ligne;
274 }
275 }
276 }
277 return $tableau;
278 }
279 // Si c'est déjà un tableau on lui applique _T_ou_typo (qui fonctionne de manière récursive avant de le renvoyer
280 elseif (is_array($chaine)){
281 return _T_ou_typo($chaine, 'multi');
282 }
283 else{
284 return array();
285 }
286 }
287
288 /*
289 * Transforme un tableau en chaine de caractères avec comme principe :
290 * - une case de vient une ligne de la chaine
291 * - chaque ligne est générée avec la forme cle|valeur
292 */
293 function saisies_tableau2chaine($tableau){
294 if ($tableau and is_array($tableau)){
295 $chaine = '';
296
297 foreach($tableau as $cle=>$valeur){
298 $ligne = trim("$cle|$valeur");
299 $chaine .= "$ligne\n";
300 }
301 $chaine = trim($chaine);
302
303 return $chaine;
304 }
305 // Si c'est déjà une chaine on la renvoie telle quelle
306 elseif (is_string($tableau)){
307 return $tableau;
308 }
309 else{
310 return '';
311 }
312 }
313
314
315
316
317 /**
318 * Passe une valeur en tableau d'élements si ce n'en est pas une
319 *
320 * entrée :
321 * cle|valeur
322 * cle|valeur
323 *
324 * Sinon :
325 * valeur,valeur
326 *
327 * @param mixed $valeur
328 * @return array Tableau de valeurs
329 **/
330 function saisies_valeur2tableau($valeur, $sinon_separateur="") {
331 if (is_array($valeur)) {
332 return $valeur;
333 }
334
335 if (!strlen($valeur)) {
336 return array();
337 }
338
339 $t = saisies_chaine2tableau($valeur);
340 if (count($t) > 1) {
341 return $t;
342 }
343
344 // qu'une seule valeur, c'est qu'elle a peut etre un separateur a virgule
345 // et a donc une cle est 0 dans ce cas la d'ailleurs
346 if (isset($t[0])) {
347 $t = saisies_chaine2tableau($t[0], ',');
348 }
349
350 return $t;
351 }
352
353
354
355
356 /*
357 * Génère une page d'aide listant toutes les saisies et leurs options
358 */
359 function saisies_generer_aide(){
360 // On a déjà la liste par saisie
361 $saisies = saisies_lister_disponibles();
362
363 // On construit une liste par options
364 $options = array();
365 foreach ($saisies as $type_saisie=>$saisie){
366 $options_saisie = saisies_lister_par_nom($saisie['options'], false);
367 foreach ($options_saisie as $nom=>$option){
368 // Si l'option n'existe pas encore
369 if (!isset($options[$nom])){
370 $options[$nom] = _T_ou_typo($option['options']);
371 }
372 // On ajoute toujours par qui c'est utilisé
373 $options[$nom]['utilisee_par'][] = $type_saisie;
374 }
375 ksort($options_saisie);
376 $saisies[$type_saisie]['options'] = $options_saisie;
377 }
378 ksort($options);
379
380 return recuperer_fond(
381 'inclure/saisies_aide',
382 array(
383 'saisies' => $saisies,
384 'options' => $options
385 )
386 );
387 }
388
389 /*
390 * Le tableau de saisies a-t-il une option afficher_si ?
391 *
392 * @param array $saisies Un tableau de saisies
393 * @return boolean
394 */
395
396 function saisies_afficher_si($saisies) {
397 $saisies = saisies_lister_par_nom($saisies,true);
398 // Dès qu'il y a au moins une option afficher_si, on l'active
399 foreach ($saisies as $saisie) {
400 if (isset($saisie['options']['afficher_si']))
401 return true;
402 }
403 return false;
404 }
405
406 ?>