source: spip-zone/_plugins_/roles/trunk/formulaires/editer_liens.php @ 88403

Last change on this file since 88403 was 88403, checked in by cedric@…, 4 years ago

Le role vide est un role acceptable. Ne pas confondre avec le role non defini (null) qu'on traite alors soit comme tous '*' ou comme le role par defaut selon les cas

File size: 13.4 KB
Line 
1<?php
2/***************************************************************************\
3 *  SPIP, Systeme de publication pour l'internet                           *
4 *                                                                         *
5 *  Copyright (c) 2001-2014                                                *
6 *  Arnaud Martin, Antoine Pitrou, Philippe Riviere, Emmanuel Saint-James  *
7 *                                                                         *
8 *  Ce programme est un logiciel libre distribue sous licence GNU/GPL.     *
9 *  Pour plus de details voir le fichier COPYING.txt ou l'aide en ligne.   *
10 * \***************************************************************************/
11
12/**
13 * Gestion du formulaire d'édition de liens
14 *
15 * @package SPIP\Formulaires
16 **/
17if (!defined('_ECRIRE_INC_VERSION')) return;
18
19
20/**
21 * Retrouve la source et l'objet de la liaison
22 *
23 * À partir des 3 premiers paramètres transmis au formulaire,
24 * la fonction retrouve :
25 * - l'objet dont on utilise sa table de liaison (table_source)
26 * - l'objet et id_objet sur qui on lie des éléments (objet, id_objet)
27 * - l'objet que l'on veut lier dessus (objet_lien)
28 *
29 * @param string $a
30 * @param string|int $b
31 * @param int|string $c
32 * @return array
33 *   ($table_source,$objet,$id_objet,$objet_lien)
34 */
35function determine_source_lien_objet($a, $b, $c){
36        $table_source = $objet_lien = $objet = $id_objet = null;
37        // auteurs, article, 23 :
38        // associer des auteurs à l'article 23, sur la table pivot spip_auteurs_liens
39        if (is_numeric($c) AND !is_numeric($b)){
40                $table_source = table_objet($a);
41                $objet_lien = objet_type($a);
42                $objet = objet_type($b);
43                $id_objet = $c;
44        }
45        // article, 23, auteurs
46        // associer des auteurs à l'article 23, sur la table pivot spip_articles_liens
47        if (is_numeric($b) AND !is_numeric($c)){
48                $table_source = table_objet($c);
49                $objet_lien = objet_type($a);
50                $objet = objet_type($a);
51                $id_objet = $b;
52        }
53
54        return array($table_source, $objet, $id_objet, $objet_lien);
55}
56
57/**
58 * Chargement du formulaire d'édition de liens
59 *
60 * #FORMULAIRE_EDITER_LIENS{auteurs,article,23}
61 *   pour associer des auteurs à l'article 23, sur la table pivot spip_auteurs_liens
62 * #FORMULAIRE_EDITER_LIENS{article,23,auteurs}
63 *   pour associer des auteurs à l'article 23, sur la table pivot spip_articles_liens
64 * #FORMULAIRE_EDITER_LIENS{articles,auteur,12}
65 *   pour associer des articles à l'auteur 12, sur la table pivot spip_articles_liens
66 * #FORMULAIRE_EDITER_LIENS{auteur,12,articles}
67 *   pour associer des articles à l'auteur 12, sur la table pivot spip_auteurs_liens
68 *
69 * @param string $a
70 * @param string|int $b
71 * @param int|string $c
72 * @param bool $editable
73 * @return array
74 */
75function formulaires_editer_liens_charger_dist($a, $b, $c, $editable = true){
76
77        list($table_source, $objet, $id_objet, $objet_lien) = determine_source_lien_objet($a, $b, $c);
78        if (!$table_source OR !$objet OR !$objet_lien OR !$id_objet)
79                return false;
80
81        $objet_source = objet_type($table_source);
82        $table_sql_source = table_objet_sql($objet_source);
83
84        // verifier existence de la table xxx_liens
85        include_spip('action/editer_liens');
86        if (!objet_associable($objet_lien))
87                return false;
88
89        // L'éditabilité :) est définie par un test permanent (par exemple "associermots") ET le 4ème argument
90        include_spip('inc/autoriser');
91        $editable = ($editable and autoriser('associer' . $table_source, $objet, $id_objet) and autoriser('modifier', $objet, $id_objet));
92
93        if (!$editable AND !count(objet_trouver_liens(array($objet_lien => '*'), array(($objet_lien==$objet_source ? $objet : $objet_source) => '*'))))
94                return false;
95
96        // squelettes de vue et de d'association
97        // ils sont différents si des rôles sont définis.
98        $skel_vue = $table_source . "_lies";
99        $skel_ajout = $table_source . "_associer";
100
101        // description des roles
102        include_spip('inc/roles');
103        if ($roles = roles_presents($objet_source, $objet)){
104                // on demande de nouveaux squelettes en conséquence
105                $skel_vue = $table_source . "_roles_lies";
106                $skel_ajout = $table_source . "_roles_associer";
107        }
108
109        $valeurs = array(
110                'id' => "$table_source-$objet-$id_objet-$objet_lien", // identifiant unique pour les id du form
111                '_vue_liee' => $skel_vue,
112                '_vue_ajout' => $skel_ajout,
113                '_objet_lien' => $objet_lien,
114                'id_lien_ajoute' => _request('id_lien_ajoute'),
115                'objet' => $objet,
116                'id_objet' => $id_objet,
117                'objet_source' => $objet_source,
118                'table_source' => $table_source,
119                'recherche' => '',
120                'visible' => 0,
121                'ajouter_lien' => '',
122                'supprimer_lien' => '',
123                'qualifier_lien' => '',
124                '_roles' => $roles, # description des roles
125                '_oups' => _request('_oups'),
126                'editable' => $editable,
127        );
128
129        return $valeurs;
130}
131
132/**
133 * Traiter le post des informations d'édition de liens
134 *
135 * Les formulaires peuvent poster dans quatre variables
136 * - ajouter_lien et supprimer_lien
137 * - remplacer_lien
138 * - qualifier_lien
139 *
140 * Les deux premières peuvent être de trois formes différentes :
141 * ajouter_lien[]="objet1-id1-objet2-id2"
142 * ajouter_lien[objet1-id1-objet2-id2]="nimportequoi"
143 * ajouter_lien['clenonnumerique']="objet1-id1-objet2-id2"
144 * Dans ce dernier cas, la valeur ne sera prise en compte
145 * que si _request('clenonnumerique') est vrai (submit associé a l'input)
146 *
147 * remplacer_lien doit être de la forme
148 * remplacer_lien[objet1-id1-objet2-id2]="objet3-id3-objet2-id2"
149 * ou objet1-id1 est celui qu'on enleve et objet3-id3 celui qu'on ajoute
150 *
151 * qualifier_lien doit être de la forme, et sert en complément de ajouter_lien
152 * qualifier_lien[objet1-id1-objet2-id2][role] = array("role1", "autre_role")
153 * qualifier_lien[objet1-id1-objet2-id2][valeur] = array("truc", "chose")
154 * produira 2 liens chacun avec array("role"=>"role1","valeur"=>"truc") et array("role"=>"autre_role","valeur"=>"chose")
155 *
156 * @param string $a
157 * @param string|int $b
158 * @param int|string $c
159 * @param bool $editable
160 * @return array
161 */
162function formulaires_editer_liens_traiter_dist($a, $b, $c, $editable = true){
163        $res = array('editable' => $editable ? true : false);
164        list($table_source, $objet, $id_objet, $objet_lien) = determine_source_lien_objet($a, $b, $c);
165        if (!$table_source OR !$objet OR !$objet_lien)
166                return $res;
167
168
169        if (_request('tout_voir'))
170                set_request('recherche', '');
171
172        include_spip('inc/autoriser');
173        if (autoriser('modifier', $objet, $id_objet)){
174                // annuler les suppressions du coup d'avant !
175                if (_request('annuler_oups')
176                        AND $oups = _request('_oups')
177                        AND $oups = unserialize($oups)
178                ){
179                        if ($oups_objets = charger_fonction("editer_liens_oups_{$table_source}_{$objet}_{$objet_lien}", "action", true)){
180                                $oups_objets($oups);
181                        }
182                        else {
183                                $objet_source = objet_type($table_source);
184                                include_spip('action/editer_liens');
185                                foreach ($oups as $oup){
186                                        if ($objet_lien==$objet_source)
187                                                objet_associer(array($objet_source => $oup[$objet_source]), array($objet => $oup[$objet]), $oup);
188                                        else
189                                                objet_associer(array($objet => $oup[$objet]), array($objet_source => $oup[$objet_source]), $oup);
190                                }
191                        }
192                        # oups ne persiste que pour la derniere action, si suppression
193                        set_request('_oups');
194                }
195
196                $supprimer = _request('supprimer_lien');
197                $ajouter = _request('ajouter_lien');
198
199                // il est possible de preciser dans une seule variable un remplacement :
200                // remplacer_lien[old][new]
201                if ($remplacer = _request('remplacer_lien')){
202                        foreach ($remplacer as $k => $v){
203                                if ($old = lien_verifier_action($k, '')){
204                                        foreach (is_array($v) ? $v : array($v) as $kn => $vn)
205                                                if ($new = lien_verifier_action($kn, $vn)){
206                                                        $supprimer[$old] = 'x';
207                                                        $ajouter[$new] = '+';
208                                                }
209                                }
210                        }
211                }
212
213                if ($supprimer){
214                        if ($supprimer_objets = charger_fonction("editer_liens_supprimer_{$table_source}_{$objet}_{$objet_lien}", "action", true)){
215                                $oups = $supprimer_objets($supprimer);
216                        }
217                        else {
218                                include_spip('action/editer_liens');
219                                $oups = array();
220
221                                foreach ($supprimer as $k => $v){
222                                        if ($lien = lien_verifier_action($k, $v)){
223                                                $lien = explode("-", $lien);
224                                                list($objet_source, $ids, $objet_lie, $idl, $role) = $lien;
225                                                // appliquer une condition sur le rôle si défini ('*' pour tous les roles)
226                                                $cond = (!is_null($role) ? array('role' => $role) : array());
227                                                if ($objet_lien==$objet_source){
228                                                        $oups = array_merge($oups, objet_trouver_liens(array($objet_source => $ids), array($objet_lie => $idl), $cond));
229                                                        objet_dissocier(array($objet_source => $ids), array($objet_lie => $idl), $cond);
230                                                } else {
231                                                        $oups = array_merge($oups, objet_trouver_liens(array($objet_lie => $idl), array($objet_source => $ids), $cond));
232                                                        objet_dissocier(array($objet_lie => $idl), array($objet_source => $ids), $cond);
233                                                }
234                                        }
235                                }
236                        }
237                        set_request('_oups', $oups ? serialize($oups) : null);
238                }
239
240                if ($ajouter){
241                        if ($ajouter_objets = charger_fonction("editer_liens_ajouter_{$table_source}_{$objet}_{$objet_lien}", "action", true)){
242                                $ajout_ok = $ajouter_objets($ajouter);
243                        }
244                        else {
245                                $ajout_ok = false;
246                                include_spip('action/editer_liens');
247                                foreach ($ajouter as $k => $v){
248                                        if ($lien = lien_verifier_action($k, $v)){
249                                                $ajout_ok = true;
250                                                list($objet1, $ids, $objet2, $idl) = explode("-", $lien);
251                                                $qualifs = lien_retrouver_qualif($objet_lien, $lien);
252                                                if ($objet_lien==$objet1){
253                                                        lien_ajouter_liaisons($objet1, $ids, $objet2, $idl, $qualifs);
254                                                } else {
255                                                        lien_ajouter_liaisons($objet2, $idl, $objet1, $ids, $qualifs);
256                                                }
257                                                set_request('id_lien_ajoute', $ids);
258                                        }
259                                }
260                        }
261                        # oups ne persiste que pour la derniere action, si suppression
262                        # une suppression suivie d'un ajout dans le meme hit est un remplacement
263                        # non annulable !
264                        if ($ajout_ok)
265                                set_request('_oups');
266                }
267        }
268
269
270        return $res;
271}
272
273
274/**
275 * Retrouver l'action de liaision demandée
276 *
277 * Les formulaires envoient une action dans un tableau ajouter_lien
278 * ou supprimer_lien
279 *
280 * L'action est de la forme : objet1-id1-objet2-id2
281 * ou de la forme : objet1-id1-objet2-id2-role
282 *
283 * L'action peut-être indiquée dans la clé ou dans la valeur.
284 * Si elle est indiquee dans la valeur et que la clé est non numérique,
285 * on ne la prend en compte que si un submit avec la clé a été envoyé
286 *
287 * @internal
288 * @param string $k Clé du tableau
289 * @param string $v Valeur du tableau
290 * @return string Action demandée si trouvée, sinon ''
291 */
292function lien_verifier_action($k, $v){
293        $action = '';
294        if (preg_match(",^\w+-[\w*]+-[\w*]+-[\w*]+(-[\w*])?,", $k))
295                $action = $k;
296        if (preg_match(",^\w+-[\w*]+-[\w*]+-[\w*]+(-[\w*])?,", $v)){
297                if (is_numeric($k))
298                        $action = $v;
299                if (_request($k))
300                        $action = $v;
301        }
302        // ajout un role null fictif (plus pratique) si pas défini
303        if ($action and count(explode("-", $action))==4){
304                $action .= '-';
305        }
306        return $action;
307}
308
309
310/**
311 * Retrouve le ou les qualificatifs postés avec une liaison demandée
312 *
313 * @internal
314 * @param string $objet_lien
315 *    objet qui porte le lien
316 * @param string $lien
317 *   Action du lien
318 * @return array
319 *   Liste des qualifs pour chaque lien. Tableau vide s'il n'y en a pas.
320 **/
321function lien_retrouver_qualif($objet_lien, $lien){
322        // un role est défini dans la liaison
323        $defs = explode('-', $lien);
324        list($objet1, , $objet2, , $role) = $defs;
325        if ($objet_lien==$objet1){
326                $colonne_role = roles_colonne($objet1, $objet2);
327        }
328        else {
329                $colonne_role = roles_colonne($objet2, $objet1);
330        }
331
332        // cas ou le role est defini en 5e argument de l'action sur le lien (suppression, ajout rapide sans autre attribut)
333        if ($role) {
334                return array(
335                        // un seul lien avec ce role
336                        array($colonne_role=>$role)
337                );
338        }
339
340        // retrouver les rôles postés pour cette liaison, s'il y en a.
341        $qualifier_lien = _request('qualifier_lien');
342        if (!$qualifier_lien OR !is_array($qualifier_lien)){
343                return array();
344        }
345
346        // pas avec l'action complete (incluant le role)
347        $qualif = array();
348        if ((!isset($qualifier_lien[$lien]) OR !$qualif = $qualifier_lien[$lien])
349          AND count($defs)==5){
350                // on tente avec l'action sans le role
351                array_pop($defs);
352                $lien = implode('-', $defs);
353                if (!isset($qualifier_lien[$lien]) OR !$qualif = $qualifier_lien[$lien]){
354                        $qualif = array();
355                }
356        }
357
358        // $qualif de la forme array(role=>array(...),valeur=>array(...),....)
359        // on le reforme en array(array(role=>..,valeur=>..,..),array(role=>..,valeur=>..,..),...)
360        $qualifs = array();
361        while (count($qualif)){
362                $q = array();
363                foreach($qualif as $att=>$values){
364                        if (is_array($values)){
365                                $q[$att] = array_shift($qualif[$att]);
366                                if (!count($qualif[$att])){
367                                        unset($qualif[$att]);
368                                }
369                        }
370                        else {
371                                $q[$att] = $values;
372                                unset($qualif[$att]);
373                        }
374                }
375                // pas de rôle vide
376                if (!$colonne_role OR !isset($q[$colonne_role]) OR $q[$colonne_role])
377                        $qualifs[] = $q;
378        }
379
380        return $qualifs;
381}
382
383/**
384 * Ajoute les liens demandés en prenant éventuellement en compte le rôle
385 *
386 * Appelle la fonction objet_associer. L'appelle autant de fois qu'il y
387 * a de rôles demandés pour cette liaison.
388 *
389 * @internal
390 * @param string $objet_source Objet source de la liaison (qui a la table de liaison)
391 * @param array|string $ids Identifiants pour l'objet source
392 * @param string $objet_lien Objet à lier
393 * @param array|string $idl Identifiants pour l'objet lié
394 * @param array $qualifs
395 * @return void
396 **/
397function lien_ajouter_liaisons($objet_source, $ids, $objet_lien, $idl, $qualifs){
398
399        // retrouver la colonne de roles s'il y en a a lier
400        if (is_array($qualifs) and count($qualifs)){
401                foreach ($qualifs as $qualif){
402                        objet_associer(array($objet_source => $ids), array($objet_lien => $idl), $qualif);
403                }
404        } else {
405                objet_associer(array($objet_source => $ids), array($objet_lien => $idl));
406        }
407}
408
Note: See TracBrowser for help on using the repository browser.