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

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

Reports du core (extensibilite, inclusions)

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