source: spip-zone/_plugins_/champs_extras_core/trunk/cextras_pipelines.php @ 114869

Last change on this file since 114869 was 114869, checked in by rastapopoulos@…, 22 months ago

Dans pre_edition, on ne fait des choses que quand action=modifier, et non pas en permanence. Il semblerait qu'historiquement ça a été ajouté quand il n'y avait pas vraiment cette distinction possible (enfin pile quand ça venait être ajouté). Mais on arrête, histoire de ne pas faire plusieurs fois la même chose dans un même hit d'édition !

File size: 16.6 KB
Line 
1<?php
2
3/**
4 * Utilisations de pipelines
5 *
6 * @package SPIP\Cextras\Pipelines
7**/
8
9// sécurité
10if (!defined("_ECRIRE_INC_VERSION")) return;
11
12/**
13 * Retourne la liste des saisies de champs extras concernant un objet donné
14 *
15 * @pipeline_appel declarer_champs_extras
16 * @param string $table
17 *     Nom d'une table SQL éditoriale
18 * @return array
19 *     Liste des saisies de champs extras de l'objet
20**/
21function champs_extras_objet($table) {
22        static $saisies_tables = array();
23        if (!$saisies_tables) {
24                include_spip('public/interfaces');
25                $saisies_tables = pipeline('declarer_champs_extras', array());
26        }
27        return isset($saisies_tables[$table]) ? $saisies_tables[$table] : array();
28}
29
30/**
31 * Filtrer par autorisation les saisies transmises
32 *
33 * Chacune des saisies est parcourue et si le visiteur n'a pas l'autorisation
34 * de la voir, elle est enlevée de la liste.
35 * La fonction ne retourne donc que la liste des saisies que peut voir
36 * la personne.
37 *
38 * @param string $faire
39 *     Type d'autorisation testée : 'voir', 'modifier'
40 * @param string $quoi
41 *     Type d'objet tel que 'article'
42 * @param array $saisies
43 *     Liste des saisies à filtrer
44 * @param array $args
45 *     Arguments pouvant être utiles à l'autorisation
46 * @return array
47 *     Liste des saisies filtrées
48**/
49function champs_extras_autorisation($faire, $quoi='', $saisies=array(), $args=array()) {
50        if (!$saisies) return array();
51        include_spip('inc/autoriser');
52
53        foreach ($saisies as $cle => $saisie) {
54                $id = isset($args['id']) ? $args['id'] : $args['id_objet'];
55                if (!autoriser($faire . 'extra', $quoi, $id, '', array(
56                        'type' => $quoi,
57                        'id_objet' => $id,
58                        'contexte' => isset($args['contexte']) ? $args['contexte'] : array(),
59                        'table' => table_objet_sql($quoi),
60                        'saisie' => $saisie,
61                        'champ' => $saisie['options']['nom'],
62                ))) {
63                        // on n'est pas autorise
64                        unset($saisies[$cle]);
65                }
66                else
67                {
68                        // on est autorise
69                        // on teste les sous-elements
70                        if (!empty($saisie['saisies'])) {
71                                $saisies[$cle]['saisies'] = champs_extras_autorisation($faire, $quoi, $saisie['saisies'], $args);
72                        }
73                }
74        }
75        return $saisies;
76}
77
78/**
79 * Ajoute pour chaque saisie de type SQL un drapeau (input hidden)
80 * permettant de retrouver les saisies editées.
81 *
82 * Particulièrement utile pour les checkbox qui ne renvoient
83 * rien si on les décoche.
84 *
85 * @param array $saisies
86 *     Liste de saisies
87 * @return array $saisies
88 *     Saisies complétées des drapeaux d'édition
89**/
90function champs_extras_ajouter_drapeau_edition($saisies) {
91        $saisies_sql = champs_extras_saisies_lister_avec_sql($saisies);
92        foreach ($saisies_sql as $saisie) {
93                $nom = $saisie['options']['nom'];
94                $saisies[] = array(
95                        'saisie' => 'hidden',
96                        'options' => array(
97                                'nom' => "cextra_$nom",
98                                'defaut' => 1 
99                        )
100                );
101        }
102        return $saisies;
103}
104
105// ---------- pipelines -----------
106
107
108/**
109 * Ajouter les champs extras sur les formulaires CVT editer_xx
110 *
111 * Liste les champs extras de l'objet, et s'il y en a les ajoute
112 * sur le formulaire d'édition en ayant filtré uniquement les saisies
113 * que peut voir le visiteur et en ayant ajouté des champs hidden
114 * servant à champs extras.
115 *
116 * @pipeline editer_contenu_objet
117 * @param array $flux Données du pipeline
118 * @return array      Données du pipeline
119**/ 
120function cextras_editer_contenu_objet($flux){
121        // recuperer les saisies de l'objet en cours
122        $objet = $flux['args']['type'];
123        include_spip('inc/cextras');
124        if ($saisies = champs_extras_objet( table_objet_sql($objet) )) {
125                // filtrer simplement les saisies que la personne en cours peut voir
126                $saisies = champs_extras_autorisation('modifier', $objet, $saisies, $flux['args']);
127                // pour chaque saisie presente, de type champs extras (hors fieldset et autres)
128                // ajouter un flag d'edition
129                $saisies = champs_extras_ajouter_drapeau_edition($saisies);
130                // ajouter au formulaire
131                $ajout = recuperer_fond('inclure/generer_saisies', array_merge($flux['args']['contexte'], array('saisies'=>$saisies)));
132
133                // div par défaut en 3.1+, mais avant ul / li
134                $balise = saisie_balise_structure_formulaire('ul');
135                $flux['data'] = preg_replace(
136                        '%(<!--extra-->)%is',
137                        "<$balise class='editer-groupe champs_extras'>$ajout</$balise>\n" . '$1',
138                        $flux['data']
139                );
140        }
141
142        return $flux;
143}
144
145
146/**
147 * Ajouter les champs extras soumis par les formulaire CVT editer_xx
148 *
149 * Pour chaque champs extras envoyé par le formulaire d'édition,
150 * ajoute les valeurs dans l'enregistrement à effectuer.
151 *
152 * @pipeline pre_edition
153 * @param array $flux Données du pipeline
154 * @return array      Données du pipeline
155**/ 
156function cextras_pre_edition($flux){
157        include_spip('inc/cextras');
158        include_spip('inc/saisies_lister');
159        if (
160                $flux['args']['action'] == 'modifier'
161                and $table = $flux['args']['table']
162                and $saisies = champs_extras_objet($table)
163        ) {
164                // Restreindre les champs postés en fonction des autorisations de les modifier
165                // au cas où un malin voudrait en envoyer plus que le formulaire ne demande
166                $saisies = champs_extras_autorisation('modifier', objet_type($table), $saisies, $flux['args']);
167                $saisies = champs_extras_saisies_lister_avec_sql($saisies);
168                foreach ($saisies as $saisie) {
169                        $nom = $saisie['options']['nom'];
170                        if (_request('cextra_' .  $nom)) {
171                                $extra = _request($nom);
172                                if (is_array($extra)) {
173                                        $extra = join(',' , $extra);
174                                }
175                                $flux['data'][$nom] = corriger_caracteres($extra);
176                        }
177                }
178        }
179
180        return $flux;
181}
182
183
184/**
185 * Ajouter les champs extras sur la visualisation de l'objet
186 *
187 * S'il y a des champs extras sur l'objet, la fonction les ajoute
188 * à la vue de l'objet, en enlevant les saisies que la personne n'a
189 * pas l'autorisation de voir.
190 *
191 * @pipeline afficher_contenu_objet
192 * @param array $flux Données du pipeline
193 * @return array      Données du pipeline
194**/ 
195function cextras_afficher_contenu_objet($flux){
196        // recuperer les saisies de l'objet en cours
197        $objet = $flux['args']['type'];
198        include_spip('cextras_fonctions');
199        $contexte = isset($flux['args']['contexte']) ? $flux['args']['contexte'] : array();
200        if ($html = champs_extras_voir_saisies($objet, $flux['args']['id_objet'], $contexte)) {
201                $flux['data'] .= $html;
202        }
203        return $flux;
204}
205
206/**
207 * Pour les saisies transmises, appliquer les traitements sur leurs contenus
208 *
209 * On applique les eventuels traitements definis pour chaque saisie,
210 * dans l'option 'traitements'. Si la valeur de l'option correspond
211 * à une constante connue (tel que `_TRAITEMENTS_RACCOURCIS`), ce
212 * sera la valeur de la constante qui sera utilisée, sinon
213 * directement le texte écrit. Il faut absolument `%s` pour que cela fonctionne.
214 *
215 * @note
216 *     La `saisies-vues/_base` applique le filtre `|propre` par défaut si
217 *     elle ne trouve pas de saisie. Dans ce cas, certains traitements peuvent
218 *     être effectués 2 fois !
219 *
220 * @param array $saisies
221 *      Liste décrivant les saisies
222 * @param array $valeurs
223 *      Couples (champ => valeur)
224 * @return array
225 *      Couples (champ => valeur traitée, le cas échéant)
226 */
227function cextras_appliquer_traitements_saisies($saisies, $valeurs) {
228        $saisies = saisies_lister_avec_traitements($saisies);
229
230        // Fournir $connect et $Pile[0] au traitement si besoin (l'evil eval)
231        $connect = '';
232        $Pile = array(0 => (isset($flux['args']['contexte']) ? $flux['args']['contexte'] : array()));
233
234        foreach ($saisies as $saisie) {
235                $traitement = $saisie['options']['traitements'];
236                $traitement = defined($traitement) ? constant($traitement) : $traitement;
237                $nom = $saisie['options']['nom'];
238                list($avant, $apres) = explode('%s', $traitement);
239                eval('$val = ' . $avant . ' $valeurs[$nom] ' . $apres . ';');
240                $valeurs[$nom] = $val;
241        }
242
243        return $valeurs;
244}
245
246/**
247 * Vérification de la validité des champs extras
248 *
249 * Lorsqu'un formulaire 'editer_xx' se présente, la fonction effectue,
250 * pour chaque champs extra les vérifications prévues dans la
251 * définition de la saisie, et retourne les éventuelles erreurs rencontrées.
252 *
253 * @pipeline formulaire_verifier
254 * @param array $flux Données du pipeline
255 * @return array      Données du pipeline
256**/ 
257function cextras_formulaire_verifier($flux){
258        $form = $flux['args']['form'];
259       
260        if (strncmp($form, 'editer_', 7) !== 0) {
261                return $flux;
262        }
263       
264        $objet = substr($form, 7);
265        if ($saisies = champs_extras_objet( $table = table_objet_sql($objet) )) {
266                include_spip('inc/autoriser');
267                include_spip('inc/saisies');
268
269                // restreindre les saisies selon les autorisations
270                $id_objet = $flux['args']['args'][0]; // ? vraiment toujours ?
271                $saisies = champs_extras_autorisation('modifier', $objet, $saisies, array_merge($flux['args'], array(
272                        'id' => $id_objet,
273                        'contexte' => array()))); // nous ne connaissons pas le contexte dans ce pipeline
274
275                // restreindre les vérifications aux saisies enregistrables
276                $saisies = champs_extras_saisies_lister_avec_sql($saisies);
277
278                foreach ($saisies as $saisie) {
279                        $nom = $saisie['options']['nom'];
280                        $normaliser = null;
281                        $erreur = cextras_verifier_saisie($saisie, _request($nom), $normaliser);
282                        if ($erreur) {
283                                $flux['data'][$nom] = $erreur;
284                        } elseif (!is_null($normaliser)) {
285                                set_request($nom, $normaliser);
286                        }
287                }
288        }
289        return $flux;
290}
291
292/**
293 * Vérifie qu'une valeur est acceptée par la déclaration de saisie transmise.
294 *
295 * Peut aussi normaliser (la formater d'une certaine manière pour le format attendu
296 * dans la base de donnée). Dans ce cas la valeur normalisée est placée dans `$normaliser`
297 *
298 * @param array $saisie
299 * @param mixed $valeur
300 * @param mixed $normaliser Valeur normalisée, le cas échéant
301 * @param bool $depuis_crayons true si en provenance d'une vérification par Crayons.
302 * @return false|string Message d'erreur, le cas echéant.
303 */
304function cextras_verifier_saisie($saisie, $valeur, &$normaliser = null, $depuis_crayons = false) {
305        static $verifier = null;
306
307        // Si le plugin verifier est présent.
308        if (is_null($verifier)) {
309                $verifier = charger_fonction('verifier', 'inc', true);
310        }
311
312        // verifier obligatoire
313        if (
314                isset($saisie['options']['obligatoire'])
315                and $saisie['options']['obligatoire']
316                and !$valeur
317        ) {
318                return _T('info_obligatoire');
319        }
320
321        // verifier (api) + normalisation
322        if (
323                $verifier
324                AND isset($saisie['verifier']['type'])
325                AND $verif = $saisie['verifier']['type']
326        ) {
327                $options = isset($saisie['verifier']['options']) ? $saisie['verifier']['options'] : array();
328                $erreur = $verifier($valeur, $verif, $options, $normaliser);
329                if ($erreur) {
330                        return $erreur;
331                }
332
333                // Si une valeur normalisée a ete transmise, c'est tout bon.
334                if (!is_null($normaliser)) {
335                        return false;
336                }
337
338                // [FIXME] exceptions connues de vérifications (pour les dates entre autres)
339                // en attendant une meilleure solution !
340                //
341                // Lorsque le champ n'est pas rempli dans le formulaire
342                // alors qu'une normalisation est demandée,
343                // verifier() sort sans indiquer d'erreur (c'est normal).
344                //
345                // Sauf que la donnée alors soumise à SQL sera une chaine vide,
346                // ce qui ne correspond pas toujours à ce qui est attendu.
347                if ((is_string($valeur) and !strlen($valeur) or (is_array($valeur) and $saisie['saisie']=='date'))
348                        and isset($options['normaliser'])
349                        and $norme = $options['normaliser']) {
350                        // Charger la fonction de normalisation théoriquement dans verifier/date
351                        // et si on en trouve une, obtenir la valeur normalisée
352                        // qui est théoriquement la valeur par défaut, puisque $valeur est vide
353                        include_spip("verifier/$verif");
354                        if ($f_normaliser = charger_fonction("${verif}_${norme}", "normaliser", true)) {
355                                $erreur = null;
356                                $normaliser = $f_normaliser($valeur, $options, $erreur);
357                                if (!is_null($erreur)) {
358                                        return $erreur;
359                                }
360                                // On suppose la normalisation OK.
361                                return false;
362                        } else {
363                                include_spip('inc/cextras');
364                                extras_log("Fonction de normalisation pour ${verif}_${norme} introuvable");
365                        }
366                }
367        }
368        return false;
369}
370
371
372/**
373 * Insertion dans le pipeline revisions_chercher_label (Plugin révisions)
374 * Trouver le bon label à afficher sur les champs dans les listes de révisions
375 *
376 * Si un champ est un champ extra, son label correspond au label défini du champs extra
377 *
378 * @pipeline revisions_chercher_label
379 * @param array $flux Données du pipeline
380 * @return array      Données du pipeline
381**/
382function cextras_revisions_chercher_label($flux) {
383        $table = table_objet_sql($flux['args']['objet']);
384        $saisies_tables = champs_extras_objet($table);
385        foreach($saisies_tables as $champ){
386                if($champ['options']['nom'] == $flux['args']['champ']){
387                        $flux['data'] = $champ['options']['label'];
388                        break;
389                }
390        }
391        return $flux;
392}
393
394
395/**
396 * Ajouter les saisies de champs extras sur des formulaires spécifiques
397 *
398 * Les champs extras s'ajoutent déjà automatiquement sur les formulaires d'édition
399 * des objets éditoriaux. Pour d'autres formulaires plus spécifiques, tel
400 * que des formulaires d'inscriptions, il est possible d'envoyer,
401 * dans la partie 'charger' du formulaire en question la clé
402 * `_champs_extras_saisies`, listant les saisies à afficher dedans.
403 *
404 * Elles seront ajoutées automatiquement à l'endroit où le code
405 * html `<!--extra-->` est présent dans le formulaire.
406 *
407 * @see cextras_obtenir_saisies_champs_extras() qui aide à récupérer les saisies.
408 *
409 * @pipeline formulaire_fond
410 * @param array $flux
411 * @return array
412**/
413function cextras_formulaire_fond($flux) {
414        if (!empty($flux['args']['contexte']['_champs_extras_saisies'])) {
415                $saisies = $flux['args']['contexte']['_champs_extras_saisies'];
416
417                // ajouter au formulaire
418                $ajout = recuperer_fond('inclure/generer_saisies', array_merge($flux['args']['contexte'], array('saisies' => $saisies)));
419
420                // div par défaut en 3.1+, mais avant ul / li
421                $balise = saisie_balise_structure_formulaire('ul');
422                $flux['data'] = preg_replace(
423                        '%(<!--extra-->)%is',
424                        "<$balise class='editer-groupe champs_extras'>$ajout</$balise>\n" . '$1',
425                        $flux['data']
426                );
427        }
428        return $flux;
429}
430
431
432/**
433 * Définir une fonction de contrôleur pour Crayons si on tente d'éditer un champs extras.
434 *
435 * Si on édite un champs extras avec Crayons, sans avoir créé manuellement de contrôleur spécifique
436 * pour le champ en question, Crayons propose soit un textarea, soit un input.
437 *
438 * Vu que l'on connaît les déclarations de nos champs extras, on va les utiliser pour créer
439 * un formulaire d'édition plus adapté à notre champ.
440 *
441 * @pipeline crayons_controleur
442 * @param array $flux
443 * @return array
444 */
445function cextras_crayons_controleur($flux) {
446        // si Crayons a déjà trouvé de contrôleur PHP, on ne fait rien
447        if ($flux['data'] != 'controleur_dist') {
448                return $flux;
449        }
450
451        $type = $flux['args']['type'];
452        $champ = $flux['args']['champ'];
453
454        // controleur_dist teste aussi la présence des controleurs html…
455        if (find_in_path(($controleur = 'controleurs/' . $type . '_' . $champ) . '.html')) {
456                return $flux;
457        }
458        if (find_in_path(($controleur = 'controleurs/' . $champ) .'.html')) {
459                return $flux;
460        }
461
462        $id = $flux['args']['id'];
463        $table = table_objet_sql($type);
464
465        include_spip('inc/cextras');
466        // Il n'existe pas de controleur spécifique pour ce champ. Voyons si ce champ est un champs extra
467        $saisies = champs_extras_objet($table);
468        // Restreindre aux vrais champs en bdd
469        $saisies_sql = champs_extras_saisies_lister_avec_sql($saisies);
470        if (!empty($saisies_sql[$champ])) {
471                $flux['data'] = charger_fonction('champs_extras', 'controleurs');
472        } else {
473                // Ou un fieldset de champs extras
474                $saisies_fieldset = saisies_lister_avec_type($saisies, 'fieldset');
475                if (!empty($saisies_fieldset[$champ])) {
476                        $flux['data'] = charger_fonction('champs_extras_fieldset', 'controleurs');
477                }
478        }
479
480        return $flux;
481}
482
483/**
484 * Vérifier une saisie envoyée depuis un formulaire de Crayons.
485 *
486 * @pipeline crayons_verifier
487 * @param array $flux
488 * @return array
489 */
490function cextras_crayons_verifier($flux) {
491        // Le nom du modèle envoyé par le controleur/champs_extras.
492        if ($flux['args']['modele'] != 'champs_extras') {
493                return $flux;
494        }
495
496        $type = $flux['args']['type'];
497        $table = table_objet_sql($type);
498        $valeurs = $flux['args']['content'];
499
500        // Récupérer les saisies SQL de la table
501        $saisies = champs_extras_objet($table);
502        $saisies = champs_extras_saisies_lister_avec_sql($saisies);
503
504        foreach ($valeurs as $champ => $valeur) {
505                if ($saisie = saisies_chercher($saisies, $champ)) {
506                        $nom = $saisie['options']['nom'];
507
508                        // Crayons applatit les name envoyés sous forme de tableau (lorsque name="truc[]").
509                        // On récupère les véritables valeurs dans ce cas. Autrement la saisie 'date'
510                        // n'arrive pas à retrouver ses petits
511                        $key = 'content_' . $flux['args']['wid'] . '_' . $champ;
512                        $valeur = _request($key);
513
514                        $normaliser = null;
515                        $erreur = cextras_verifier_saisie($saisie, $valeur, $normaliser, true);
516                        if ($erreur) {
517                                $flux['data']['erreurs'][$nom] = $erreur;
518                        } elseif (!is_null($normaliser)) {
519                                $flux['data']['normaliser'][$nom] = $normaliser;
520                        }
521                }
522        }
523
524        return $flux;
525}
Note: See TracBrowser for help on using the repository browser.