|
1
|
|
|
<?php |
|
2
|
|
|
|
|
3
|
|
|
/***************************************************************************\ |
|
4
|
|
|
* SPIP, Systeme de publication pour l'internet * |
|
5
|
|
|
* * |
|
6
|
|
|
* Copyright (c) 2001-2019 * |
|
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
|
|
|
* API d'édition de liens |
|
15
|
|
|
* |
|
16
|
|
|
* Cette API gère la création, modification et suppressions de liens |
|
17
|
|
|
* entre deux objets éditoriaux par l'intermédiaire de tables de liaison |
|
18
|
|
|
* tel que spip_xx_liens. |
|
19
|
|
|
* |
|
20
|
|
|
* L'unicité est assurée dans les fonctions sur le trio (id_x, objet, id_objet) |
|
21
|
|
|
* par défaut, ce qui correspond à la déclaration de clé primaire. |
|
22
|
|
|
* |
|
23
|
|
|
* Des rôles peuvent être déclarés pour des liaisons. À ce moment là, |
|
24
|
|
|
* une colonne spécifique doit être présente dans la table de liens |
|
25
|
|
|
* et l'unicité est alors assurée sur le quatuor (id_x, objet, id_objet, role) |
|
26
|
|
|
* et la clé primaire adaptée en conséquence. |
|
27
|
|
|
* |
|
28
|
|
|
* @package SPIP\Core\Liens\API |
|
29
|
|
|
*/ |
|
30
|
|
|
|
|
31
|
|
|
if (!defined('_ECRIRE_INC_VERSION')) { |
|
32
|
|
|
return; |
|
33
|
|
|
} |
|
34
|
|
|
|
|
35
|
|
|
// charger la gestion les rôles sur les objets |
|
36
|
|
|
include_spip('inc/roles'); |
|
37
|
|
|
|
|
38
|
|
|
|
|
39
|
|
|
/** |
|
40
|
|
|
* Teste l'existence de la table de liaison xxx_liens d'un objet |
|
41
|
|
|
* |
|
42
|
|
|
* @api |
|
43
|
|
|
* @param string $objet |
|
44
|
|
|
* Objet à tester |
|
45
|
|
|
* @return array|bool |
|
|
|
|
|
|
46
|
|
|
* - false si l'objet n'est pas associable. |
|
47
|
|
|
* - array(clé primaire, nom de la table de lien) si associable |
|
48
|
|
|
*/ |
|
49
|
|
|
function objet_associable($objet) { |
|
50
|
|
|
$trouver_table = charger_fonction('trouver_table', 'base'); |
|
51
|
|
|
$table_sql = table_objet_sql($objet); |
|
52
|
|
|
|
|
53
|
|
|
$l = ""; |
|
54
|
|
|
if ($primary = id_table_objet($objet) |
|
55
|
|
|
and $trouver_table($l = $table_sql . "_liens") |
|
56
|
|
|
and !preg_match(',[^\w],', $primary) |
|
57
|
|
|
and !preg_match(',[^\w],', $l) |
|
58
|
|
|
) { |
|
59
|
|
|
return array($primary, $l); |
|
60
|
|
|
} |
|
61
|
|
|
|
|
62
|
|
|
spip_log("Objet $objet non associable : ne dispose pas d'une cle primaire $primary OU d'une table liens $l"); |
|
63
|
|
|
|
|
64
|
|
|
return false; |
|
65
|
|
|
} |
|
66
|
|
|
|
|
67
|
|
|
/** |
|
68
|
|
|
* Associer un ou des objets à des objets listés |
|
69
|
|
|
* |
|
70
|
|
|
* `$objets_source` et `$objets_lies` sont de la forme |
|
71
|
|
|
* `array($objet=>$id_objets,...)` |
|
72
|
|
|
* `$id_objets` peut lui même être un scalaire ou un tableau pour une liste d'objets du même type |
|
73
|
|
|
* ou de la forme `array("NOT", $id_objets)` pour une sélection par exclusion |
|
74
|
|
|
* |
|
75
|
|
|
* Les objets sources sont les pivots qui portent les liens |
|
76
|
|
|
* et pour lesquels une table spip_xxx_liens existe |
|
77
|
|
|
* (auteurs, documents, mots) |
|
78
|
|
|
* |
|
79
|
|
|
* On peut passer optionnellement une qualification du (des) lien(s) qui sera |
|
80
|
|
|
* alors appliquée dans la foulée. |
|
81
|
|
|
* En cas de lot de liens, c'est la même qualification qui est appliquée a tous |
|
82
|
|
|
* |
|
83
|
|
|
* @api |
|
84
|
|
|
* @param array $objets_source |
|
85
|
|
|
* @param array|string $objets_lies |
|
86
|
|
|
* @param array $qualif |
|
|
|
|
|
|
87
|
|
|
* @return bool|int |
|
|
|
|
|
|
88
|
|
|
*/ |
|
89
|
|
|
function objet_associer($objets_source, $objets_lies, $qualif = null) { |
|
90
|
|
|
$modifs = objet_traiter_liaisons('lien_insert', $objets_source, $objets_lies, $qualif); |
|
|
|
|
|
|
91
|
|
|
|
|
92
|
|
|
if ($qualif) { |
|
93
|
|
|
objet_qualifier_liens($objets_source, $objets_lies, $qualif); |
|
94
|
|
|
} |
|
95
|
|
|
|
|
96
|
|
|
return $modifs; // pas d'erreur |
|
97
|
|
|
} |
|
98
|
|
|
|
|
99
|
|
|
|
|
100
|
|
|
/** |
|
101
|
|
|
* Dissocier un (ou des) objet(s) des objets listés |
|
102
|
|
|
* |
|
103
|
|
|
* `$objets_source` et `$objets_lies` sont de la forme |
|
104
|
|
|
* `array($objet=>$id_objets,...)` |
|
105
|
|
|
* `$id_objets` peut lui-même être un scalaire ou un tableau pour une liste d'objets du même type |
|
106
|
|
|
* |
|
107
|
|
|
* Les objets sources sont les pivots qui portent les liens |
|
108
|
|
|
* et pour lesquels une table spip_xxx_liens existe |
|
109
|
|
|
* (auteurs, documents, mots) |
|
110
|
|
|
* |
|
111
|
|
|
* un * pour $objet, $id_objet permet de traiter par lot |
|
112
|
|
|
* seul le type de l'objet source ne peut pas accepter de joker et doit etre explicite |
|
113
|
|
|
* |
|
114
|
|
|
* S'il y a des rôles possibles entre les 2 objets, et qu'aucune condition |
|
115
|
|
|
* sur la colonne du rôle n'est transmise, on ne supprime que les liens |
|
116
|
|
|
* avec le rôle par défaut. Si on veut supprimer tous les rôles, |
|
117
|
|
|
* il faut spécifier $cond => array('role' => '*') |
|
118
|
|
|
* |
|
119
|
|
|
* @api |
|
120
|
|
|
* @param array $objets_source |
|
121
|
|
|
* @param array|string $objets_lies |
|
122
|
|
|
* @param array|null $cond |
|
123
|
|
|
* Condition du where supplémentaires |
|
124
|
|
|
* |
|
125
|
|
|
* À l'exception de l'index 'role' qui permet de sélectionner un rôle |
|
126
|
|
|
* ou tous les rôles (*), en s'affranchissant du vrai nom de la colonne. |
|
127
|
|
|
* @return bool|int |
|
|
|
|
|
|
128
|
|
|
*/ |
|
129
|
|
|
function objet_dissocier($objets_source, $objets_lies, $cond = null) { |
|
130
|
|
|
return objet_traiter_liaisons('lien_delete', $objets_source, $objets_lies, $cond); |
|
|
|
|
|
|
131
|
|
|
} |
|
132
|
|
|
|
|
133
|
|
|
|
|
134
|
|
|
/** |
|
135
|
|
|
* Qualifier le lien entre un (ou des) objet(s) et des objets listés |
|
136
|
|
|
* |
|
137
|
|
|
* $objets_source et $objets sont de la forme |
|
138
|
|
|
* array($objet=>$id_objets,...) |
|
139
|
|
|
* $id_objets peut lui meme etre un scalaire ou un tableau pour une liste d'objets du meme type |
|
140
|
|
|
* |
|
141
|
|
|
* Les objets sources sont les pivots qui portent les liens |
|
142
|
|
|
* et pour lesquels une table spip_xxx_liens existe |
|
143
|
|
|
* (auteurs, documents, mots) |
|
144
|
|
|
* |
|
145
|
|
|
* un * pour $objet,$id_objet permet de traiter par lot |
|
146
|
|
|
* seul le type de l'objet source ne peut pas accepter de joker et doit etre explicite |
|
147
|
|
|
* |
|
148
|
|
|
* @api |
|
149
|
|
|
* @param array $objets_source |
|
150
|
|
|
* @param array|string $objets_lies |
|
151
|
|
|
* @param array $qualif |
|
152
|
|
|
* @return bool|int |
|
|
|
|
|
|
153
|
|
|
*/ |
|
154
|
|
|
function objet_qualifier_liens($objets_source, $objets_lies, $qualif) { |
|
155
|
|
|
return objet_traiter_liaisons('lien_set', $objets_source, $objets_lies, $qualif); |
|
|
|
|
|
|
156
|
|
|
} |
|
157
|
|
|
|
|
158
|
|
|
|
|
159
|
|
|
/** |
|
160
|
|
|
* Trouver les liens entre objets |
|
161
|
|
|
* |
|
162
|
|
|
* $objets_source et $objets sont de la forme |
|
163
|
|
|
* array($objet=>$id_objets,...) |
|
164
|
|
|
* $id_objets peut lui meme etre un scalaire ou un tableau pour une liste d'objets du meme type |
|
165
|
|
|
* |
|
166
|
|
|
* Les objets sources sont les pivots qui portent les liens |
|
167
|
|
|
* et pour lesquels une table spip_xxx_liens existe |
|
168
|
|
|
* (auteurs, documents, mots) |
|
169
|
|
|
* |
|
170
|
|
|
* un * pour $objet,$id_objet permet de traiter par lot |
|
171
|
|
|
* seul le type de l'objet source ne peut pas accepter de joker et doit etre explicite |
|
172
|
|
|
* |
|
173
|
|
|
* renvoie une liste de tableaux decrivant chaque lien |
|
174
|
|
|
* dans lequel objet_source et objet_lie sont aussi affectes avec l'id de chaque |
|
175
|
|
|
* par facilite |
|
176
|
|
|
* ex : |
|
177
|
|
|
* array( |
|
178
|
|
|
* array('id_document'=>23,'objet'=>'article','id_objet'=>12,'vu'=>'oui', |
|
179
|
|
|
* 'document'=>23,'article'=>12) |
|
180
|
|
|
* ) |
|
181
|
|
|
* |
|
182
|
|
|
* @api |
|
183
|
|
|
* @param array $objets_source Couples (objets_source => identifiants) (objet qui a la table de lien) |
|
184
|
|
|
* @param array|string $objets_lies Couples (objets_lies => identifiants) |
|
185
|
|
|
* @param array|null $cond Condition du where supplémentaires |
|
186
|
|
|
* @return array |
|
|
|
|
|
|
187
|
|
|
* Liste des trouvailles |
|
188
|
|
|
*/ |
|
189
|
|
|
function objet_trouver_liens($objets_source, $objets_lies, $cond = null) { |
|
190
|
|
|
return objet_traiter_liaisons('lien_find', $objets_source, $objets_lies, $cond); |
|
|
|
|
|
|
191
|
|
|
} |
|
192
|
|
|
|
|
193
|
|
|
|
|
194
|
|
|
/** |
|
195
|
|
|
* Nettoyer les liens morts vers des objets qui n'existent plus |
|
196
|
|
|
* |
|
197
|
|
|
* $objets_source et $objets sont de la forme |
|
198
|
|
|
* array($objet=>$id_objets,...) |
|
199
|
|
|
* $id_objets peut lui meme etre un scalaire ou un tableau pour une liste d'objets du meme type |
|
200
|
|
|
* |
|
201
|
|
|
* Les objets sources sont les pivots qui portent les liens |
|
202
|
|
|
* et pour lesquels une table spip_xxx_liens existe |
|
203
|
|
|
* (auteurs, documents, mots) |
|
204
|
|
|
* |
|
205
|
|
|
* un * pour $objet,$id_objet permet de traiter par lot |
|
206
|
|
|
* seul le type de l'objet source ne peut pas accepter de joker et doit etre explicite |
|
207
|
|
|
* |
|
208
|
|
|
* @api |
|
209
|
|
|
* @param array $objets_source |
|
210
|
|
|
* @param array|string $objets_lies |
|
211
|
|
|
* @return int |
|
|
|
|
|
|
212
|
|
|
*/ |
|
213
|
|
|
function objet_optimiser_liens($objets_source, $objets_lies) { |
|
214
|
|
|
return objet_traiter_liaisons('lien_optimise', $objets_source, $objets_lies); |
|
|
|
|
|
|
215
|
|
|
} |
|
216
|
|
|
|
|
217
|
|
|
|
|
218
|
|
|
/** |
|
219
|
|
|
* Dupliquer tous les liens entrant ou sortants d'un objet |
|
220
|
|
|
* vers un autre (meme type d'objet, mais id different) |
|
221
|
|
|
* si $types est fourni, seuls les liens depuis/vers les types listes seront copies |
|
222
|
|
|
* si $exclure_types est fourni, les liens depuis/vers les types listes seront ignores |
|
223
|
|
|
* |
|
224
|
|
|
* @api |
|
225
|
|
|
* @param string $objet |
|
226
|
|
|
* @param int $id_source |
|
227
|
|
|
* @param int $id_cible |
|
228
|
|
|
* @param array $types |
|
|
|
|
|
|
229
|
|
|
* @param array $exclure_types |
|
|
|
|
|
|
230
|
|
|
* @return int |
|
231
|
|
|
* Nombre de liens copiés |
|
232
|
|
|
*/ |
|
233
|
|
|
function objet_dupliquer_liens($objet, $id_source, $id_cible, $types = null, $exclure_types = null) { |
|
234
|
|
|
include_spip('base/objets'); |
|
235
|
|
|
$tables = lister_tables_objets_sql(); |
|
236
|
|
|
$n = 0; |
|
237
|
|
|
foreach ($tables as $table_sql => $infos) { |
|
|
|
|
|
|
238
|
|
|
if ( |
|
239
|
|
|
(is_null($types) or in_array($infos['type'], $types)) |
|
240
|
|
|
and (is_null($exclure_types) or !in_array($infos['type'], $exclure_types)) |
|
241
|
|
|
) { |
|
242
|
|
|
if (objet_associable($infos['type'])) { |
|
243
|
|
|
$liens = (($infos['type'] == $objet) ? |
|
244
|
|
|
objet_trouver_liens(array($objet => $id_source), '*') |
|
245
|
|
|
: |
|
246
|
|
|
objet_trouver_liens(array($infos['type'] => '*'), array($objet => $id_source))); |
|
247
|
|
|
foreach ($liens as $lien) { |
|
|
|
|
|
|
248
|
|
|
$n++; |
|
249
|
|
|
if ($infos['type'] == $objet) { |
|
250
|
|
|
if ( |
|
251
|
|
|
(is_null($types) or in_array($lien['objet'], $types)) |
|
252
|
|
|
and (is_null($exclure_types) or !in_array($lien['objet'], $exclure_types)) |
|
253
|
|
|
) { |
|
254
|
|
|
objet_associer(array($objet => $id_cible), array($lien['objet'] => $lien[$lien['objet']]), $lien); |
|
255
|
|
|
} |
|
256
|
|
|
} else { |
|
257
|
|
|
objet_associer(array($infos['type'] => $lien[$infos['type']]), array($objet => $id_cible), $lien); |
|
258
|
|
|
} |
|
259
|
|
|
} |
|
260
|
|
|
} |
|
261
|
|
|
} |
|
262
|
|
|
} |
|
263
|
|
|
|
|
264
|
|
|
return $n; |
|
265
|
|
|
} |
|
266
|
|
|
|
|
267
|
|
|
/** |
|
268
|
|
|
* Fonctions techniques |
|
269
|
|
|
* ne pas les appeler directement |
|
270
|
|
|
*/ |
|
271
|
|
|
|
|
272
|
|
|
|
|
273
|
|
|
/** |
|
274
|
|
|
* Fonction générique qui |
|
275
|
|
|
* applique une operation de liaison entre un ou des objets et des objets listés |
|
276
|
|
|
* |
|
277
|
|
|
* $objets_source et $objets_lies sont de la forme |
|
278
|
|
|
* array($objet=>$id_objets,...) |
|
279
|
|
|
* $id_objets peut lui meme etre un scalaire ou un tableau pour une liste d'objets du meme type |
|
280
|
|
|
* |
|
281
|
|
|
* Les objets sources sont les pivots qui portent les liens |
|
282
|
|
|
* et pour lesquels une table spip_xxx_liens existe |
|
283
|
|
|
* (auteurs, documents, mots) |
|
284
|
|
|
* |
|
285
|
|
|
* on peut passer optionnellement une qualification du (des) lien(s) qui sera |
|
286
|
|
|
* alors appliquee dans la foulee. |
|
287
|
|
|
* En cas de lot de liens, c'est la meme qualification qui est appliquee a tous |
|
288
|
|
|
* |
|
289
|
|
|
* @internal |
|
290
|
|
|
* @param string $operation |
|
291
|
|
|
* Nom de la fonction PHP qui traitera l'opération |
|
292
|
|
|
* @param array $objets_source |
|
293
|
|
|
* Liste de ou des objets source |
|
294
|
|
|
* De la forme array($objet=>$id_objets,...), où $id_objets peut lui |
|
295
|
|
|
* même être un scalaire ou un tableau pour une liste d'objets du même type |
|
296
|
|
|
* @param array $objets_lies |
|
297
|
|
|
* Liste de ou des objets liés |
|
298
|
|
|
* De la forme array($objet=>$id_objets,...), où $id_objets peut lui |
|
299
|
|
|
* même être un scalaire ou un tableau pour une liste d'objets du même type |
|
300
|
|
|
* @param null|array $set |
|
301
|
|
|
* Liste de coupels champs valeur, soit array(champs => valeur) |
|
302
|
|
|
* En fonction des opérations il peut servir à différentes utilisations |
|
303
|
|
|
* @return bool|int|array |
|
304
|
|
|
*/ |
|
305
|
|
|
function objet_traiter_liaisons($operation, $objets_source, $objets_lies, $set = null) { |
|
306
|
|
|
// accepter une syntaxe minimale pour supprimer tous les liens |
|
307
|
|
|
if ($objets_lies == '*') { |
|
308
|
|
|
$objets_lies = array('*' => '*'); |
|
309
|
|
|
} |
|
310
|
|
|
$modifs = 0; // compter le nombre de modifications |
|
311
|
|
|
$echec = null; |
|
312
|
|
|
foreach ($objets_source as $objet => $ids) { |
|
313
|
|
|
if ($a = objet_associable($objet)) { |
|
314
|
|
|
list($primary, $l) = $a; |
|
315
|
|
|
if (!is_array($ids)) { |
|
316
|
|
|
$ids = array($ids); |
|
317
|
|
|
} elseif (reset($ids) == "NOT") { |
|
318
|
|
|
// si on demande un array('NOT',...) => recuperer la liste d'ids correspondants |
|
319
|
|
|
$where = lien_where($primary, $ids, '*', '*'); |
|
320
|
|
|
$ids = sql_allfetsel($primary, $l, $where); |
|
321
|
|
|
$ids = array_map('reset', $ids); |
|
322
|
|
|
} |
|
323
|
|
|
foreach ($ids as $id) { |
|
324
|
|
|
$res = $operation($objet, $primary, $l, $id, $objets_lies, $set); |
|
325
|
|
|
if ($res === false) { |
|
326
|
|
|
spip_log("objet_traiter_liaisons [Echec] : $operation sur $objet/$primary/$l/$id", _LOG_ERREUR); |
|
327
|
|
|
$echec = true; |
|
328
|
|
|
} else { |
|
329
|
|
|
$modifs = ($modifs ? (is_array($res) ? array_merge($modifs, $res) : $modifs + $res) : $res); |
|
330
|
|
|
} |
|
331
|
|
|
} |
|
332
|
|
|
} else { |
|
333
|
|
|
$echec = true; |
|
334
|
|
|
} |
|
335
|
|
|
} |
|
336
|
|
|
|
|
337
|
|
|
return ($echec ? false : $modifs); // pas d'erreur |
|
338
|
|
|
} |
|
339
|
|
|
|
|
340
|
|
|
|
|
341
|
|
|
/** |
|
342
|
|
|
* Sous fonction insertion |
|
343
|
|
|
* qui traite les liens pour un objet source dont la clé primaire |
|
344
|
|
|
* et la table de lien sont fournies |
|
345
|
|
|
* |
|
346
|
|
|
* $objets et de la forme |
|
347
|
|
|
* array($objet=>$id_objets,...) |
|
348
|
|
|
* |
|
349
|
|
|
* Retourne le nombre d'insertions réalisées |
|
350
|
|
|
* |
|
351
|
|
|
* @internal |
|
352
|
|
|
* @param string $objet_source Objet source de l'insertion (celui qui a la table de liaison) |
|
353
|
|
|
* @param string $primary Nom de la clé primaire de cet objet |
|
354
|
|
|
* @param string $table_lien Nom de la table de lien de cet objet |
|
355
|
|
|
* @param int $id Identifiant de l'objet sur lesquels on va insérer des liaisons |
|
356
|
|
|
* @param array $objets Liste des liaisons à faire, de la forme array($objet=>$id_objets) |
|
357
|
|
|
* @param array $qualif |
|
358
|
|
|
* Liste des qualifications à appliquer (qui seront faites par lien_set()), |
|
359
|
|
|
* dont on cherche un rôle à insérer également. |
|
360
|
|
|
* Si l'objet dispose d'un champ rôle, on extrait des qualifications |
|
361
|
|
|
* le rôle s'il est présent, sinon on applique le rôle par défaut. |
|
362
|
|
|
* @return bool|int |
|
363
|
|
|
* Nombre d'insertions faites, false si échec. |
|
364
|
|
|
*/ |
|
365
|
|
|
function lien_insert($objet_source, $primary, $table_lien, $id, $objets, $qualif) { |
|
366
|
|
|
$ins = 0; |
|
367
|
|
|
$echec = null; |
|
368
|
|
|
if (is_null($qualif)) { |
|
369
|
|
|
$qualif = array(); |
|
370
|
|
|
} |
|
371
|
|
|
|
|
372
|
|
|
foreach ($objets as $objet => $id_objets) { |
|
373
|
|
|
if (!is_array($id_objets)) { |
|
374
|
|
|
$id_objets = array($id_objets); |
|
375
|
|
|
} |
|
376
|
|
|
|
|
377
|
|
|
// role, colonne, where par défaut |
|
378
|
|
|
list($role, $colonne_role, $cond) = |
|
379
|
|
|
roles_trouver_dans_qualif($objet_source, $objet, $qualif); |
|
380
|
|
|
|
|
381
|
|
|
foreach ($id_objets as $id_objet) { |
|
382
|
|
|
$objet = (($objet == '*') ? $objet : objet_type($objet)); # securite |
|
383
|
|
|
|
|
384
|
|
|
$insertions = array( |
|
385
|
|
|
'id_objet' => $id_objet, |
|
386
|
|
|
'objet' => $objet, |
|
387
|
|
|
$primary => $id |
|
388
|
|
|
); |
|
389
|
|
|
// rôle en plus s'il est défini |
|
390
|
|
|
if ($role) { |
|
391
|
|
|
$insertions += array( |
|
392
|
|
|
$colonne_role => $role |
|
393
|
|
|
); |
|
394
|
|
|
} |
|
395
|
|
|
|
|
396
|
|
|
if (lien_triables($table_lien)) { |
|
397
|
|
|
$where = lien_where($primary, $id, $objet, $id_objet); |
|
398
|
|
|
// si il y a deja un lien pour ce couple (avec un autre role?) on reprend le meme rang si non nul |
|
399
|
|
|
if (!$rang = intval(sql_getfetsel('rang_lien', $table_lien, $where))) { |
|
400
|
|
|
$where = lien_where($primary, '*', $objet, $id_objet); |
|
401
|
|
|
$rang = intval(sql_getfetsel('max(rang_lien)', $table_lien, $where)); |
|
402
|
|
|
// si aucun lien n'a de rang, on en introduit pas, on garde zero |
|
403
|
|
|
if ($rang>0) { |
|
404
|
|
|
$rang = intval($rang) + 1; |
|
405
|
|
|
} |
|
406
|
|
|
} |
|
407
|
|
|
$insertions['rang_lien'] = $rang; |
|
408
|
|
|
} |
|
409
|
|
|
|
|
410
|
|
|
$args = array( |
|
411
|
|
|
'table_lien' => $table_lien, |
|
412
|
|
|
'objet_source' => $objet_source, |
|
413
|
|
|
'id_objet_source' => $id, |
|
414
|
|
|
'objet' => $objet, |
|
415
|
|
|
'id_objet' => $id_objet, |
|
416
|
|
|
'role' => $role, |
|
417
|
|
|
'colonne_role' => $colonne_role, |
|
418
|
|
|
'action' => 'insert', |
|
419
|
|
|
); |
|
420
|
|
|
|
|
421
|
|
|
// Envoyer aux plugins |
|
422
|
|
|
$insertions = pipeline('pre_edition_lien', |
|
423
|
|
|
array( |
|
424
|
|
|
'args' => $args, |
|
425
|
|
|
'data' => $insertions |
|
426
|
|
|
) |
|
427
|
|
|
); |
|
428
|
|
|
$args['id_objet'] = $insertions['id_objet']; |
|
429
|
|
|
|
|
430
|
|
|
$where = lien_where($primary, $id, $objet, $id_objet, $cond); |
|
431
|
|
|
|
|
432
|
|
|
if (($id_objet = intval($insertions['id_objet']) or $objet=='site') |
|
433
|
|
|
and !sql_getfetsel($primary, $table_lien, $where) |
|
434
|
|
|
) { |
|
435
|
|
|
|
|
436
|
|
|
if (lien_triables($table_lien) and isset($insertions['rang_lien']) and intval($insertions['rang_lien'])) { |
|
437
|
|
|
// on decale les liens de rang_lien>=la valeur inseree pour faire la place |
|
438
|
|
|
$w = lien_where($primary, '*', $objet, $id_objet, array('rang_lien>='.intval($insertions['rang_lien']),"$primary!=".intval($id))); |
|
439
|
|
|
sql_update($table_lien, array('rang_lien'=>'rang_lien+1'), $w); |
|
440
|
|
|
} |
|
441
|
|
|
|
|
442
|
|
|
$e = sql_insertq($table_lien, $insertions); |
|
443
|
|
|
if ($e !== false) { |
|
444
|
|
|
$ins++; |
|
445
|
|
|
lien_propage_date_modif($objet, $id_objet); |
|
446
|
|
|
lien_propage_date_modif($objet_source, $id); |
|
447
|
|
|
// Envoyer aux plugins |
|
448
|
|
|
pipeline('post_edition_lien', |
|
449
|
|
|
array( |
|
450
|
|
|
'args' => $args, |
|
451
|
|
|
'data' => $insertions |
|
452
|
|
|
) |
|
453
|
|
|
); |
|
454
|
|
|
} else { |
|
455
|
|
|
$echec = true; |
|
456
|
|
|
} |
|
457
|
|
|
} |
|
458
|
|
|
} |
|
459
|
|
|
} |
|
460
|
|
|
// si on a fait des insertions, on reordonne les liens concernes |
|
461
|
|
|
if ($ins>0) { |
|
462
|
|
|
lien_ordonner($objet_source, $primary, $table_lien, $id, $objets); |
|
463
|
|
|
} |
|
464
|
|
|
|
|
465
|
|
|
return ($echec ? false : $ins); |
|
466
|
|
|
} |
|
467
|
|
|
|
|
468
|
|
|
|
|
469
|
|
|
/** |
|
470
|
|
|
* Reordonner les liens sur lesquels on est intervenus |
|
471
|
|
|
* @param string $objet_source |
|
472
|
|
|
* @param string $primary |
|
473
|
|
|
* @param string $table_lien |
|
474
|
|
|
* @param int $id |
|
475
|
|
|
* @param array|string $objets |
|
476
|
|
|
*/ |
|
477
|
|
|
function lien_ordonner($objet_source, $primary, $table_lien, $id, $objets) { |
|
|
|
|
|
|
478
|
|
|
if (!lien_triables($table_lien)) { |
|
479
|
|
|
return; |
|
480
|
|
|
} |
|
481
|
|
|
|
|
482
|
|
|
foreach ($objets as $objet => $id_objets) { |
|
|
|
|
|
|
483
|
|
|
if (!is_array($id_objets)) { |
|
484
|
|
|
$id_objets = array($id_objets); |
|
485
|
|
|
} |
|
486
|
|
|
|
|
487
|
|
|
foreach ($id_objets as $id_objet) { |
|
488
|
|
|
$objet = (($objet == '*') ? $objet : objet_type($objet)); # securite |
|
489
|
|
|
|
|
490
|
|
|
$where = lien_where($primary, '*', $objet, $id_objet); |
|
491
|
|
|
$liens = sql_allfetsel("$primary, id_objet, objet, rang_lien", $table_lien, $where, $primary,"rang_lien"); |
|
492
|
|
|
|
|
493
|
|
|
$rangs = array_column($liens, 'rang_lien'); |
|
494
|
|
|
if (count($rangs) and (max($rangs)>0 or min($rangs)<0)) { |
|
495
|
|
|
$rang = 1; |
|
496
|
|
|
foreach ($liens as $lien) { |
|
497
|
|
|
$where = lien_where($primary, $lien[$primary], $objet, $id_objet, array('rang_lien!='.intval($rang))); |
|
498
|
|
|
sql_updateq($table_lien, array('rang_lien' => $rang), $where); |
|
499
|
|
|
$rang++; |
|
500
|
|
|
} |
|
501
|
|
|
} |
|
502
|
|
|
} |
|
503
|
|
|
} |
|
504
|
|
|
} |
|
505
|
|
|
|
|
506
|
|
|
|
|
507
|
|
|
/** |
|
508
|
|
|
* Une table de lien est-elle triable ? |
|
509
|
|
|
* elle doit disposer d'un champ rang_lien pour cela |
|
510
|
|
|
* @param $table_lien |
|
511
|
|
|
* @return mixed |
|
512
|
|
|
*/ |
|
513
|
|
|
function lien_triables($table_lien) { |
|
514
|
|
|
static $triables = array(); |
|
515
|
|
|
if (!isset($triables[$table_lien])) { |
|
516
|
|
|
$trouver_table = charger_fonction('trouver_table', 'base'); |
|
517
|
|
|
$desc = $trouver_table($table_lien); |
|
518
|
|
|
if ($desc and isset($desc['field']['rang_lien'])) { |
|
519
|
|
|
$triables[$table_lien] = true; |
|
520
|
|
|
} |
|
521
|
|
|
else { |
|
522
|
|
|
$triables[$table_lien] = false; |
|
523
|
|
|
} |
|
524
|
|
|
} |
|
525
|
|
|
return $triables[$table_lien]; |
|
526
|
|
|
} |
|
527
|
|
|
|
|
528
|
|
|
|
|
529
|
|
|
/** |
|
530
|
|
|
* Fabriquer la condition where en tenant compte des jokers * |
|
531
|
|
|
* |
|
532
|
|
|
* @internal |
|
533
|
|
|
* @param string $primary Nom de la clé primaire |
|
534
|
|
|
* @param int|string|array $id_source Identifiant de la clé primaire |
|
535
|
|
|
* @param string $objet Nom de l'objet lié |
|
536
|
|
|
* @param int|string|array $id_objet Identifiant de l'objet lié |
|
537
|
|
|
* @param array $cond Conditions par défaut |
|
538
|
|
|
* @return array Liste des conditions |
|
539
|
|
|
*/ |
|
540
|
|
|
function lien_where($primary, $id_source, $objet, $id_objet, $cond = array()) { |
|
541
|
|
|
if ((!is_array($id_source) and !strlen($id_source)) |
|
542
|
|
|
or !strlen($objet) |
|
543
|
|
|
or (!is_array($id_objet) and !strlen($id_objet)) |
|
544
|
|
|
) { |
|
545
|
|
|
return array("0=1"); |
|
546
|
|
|
} // securite |
|
547
|
|
|
|
|
548
|
|
|
$not = ""; |
|
549
|
|
|
if (is_array($id_source) and reset($id_source) == "NOT") { |
|
550
|
|
|
$not = array_shift($id_source); |
|
551
|
|
|
$id_source = reset($id_source); |
|
552
|
|
|
} |
|
553
|
|
|
|
|
554
|
|
|
$where = $cond; |
|
555
|
|
|
|
|
556
|
|
|
if ($id_source !== '*') { |
|
557
|
|
|
$where[] = (is_array($id_source) ? sql_in(addslashes($primary), array_map('intval', $id_source), |
|
558
|
|
|
$not) : addslashes($primary) . ($not ? "<>" : "=") . intval($id_source)); |
|
559
|
|
|
} elseif ($not) { |
|
560
|
|
|
$where[] = "0=1"; |
|
561
|
|
|
} // idiot mais quand meme |
|
562
|
|
|
|
|
563
|
|
|
$not = ""; |
|
564
|
|
|
if (is_array($id_objet) and reset($id_objet) == "NOT") { |
|
565
|
|
|
$not = array_shift($id_objet); |
|
566
|
|
|
$id_objet = reset($id_objet); |
|
567
|
|
|
} |
|
568
|
|
|
|
|
569
|
|
|
if ($objet !== '*') { |
|
570
|
|
|
$where[] = "objet=" . sql_quote($objet); |
|
571
|
|
|
} |
|
572
|
|
|
if ($id_objet !== '*') { |
|
573
|
|
|
$where[] = (is_array($id_objet) ? sql_in('id_objet', array_map('intval', $id_objet), |
|
574
|
|
|
$not) : "id_objet" . ($not ? "<>" : "=") . intval($id_objet)); |
|
575
|
|
|
} elseif ($not) { |
|
576
|
|
|
$where[] = "0=1"; |
|
577
|
|
|
} // idiot mais quand meme |
|
578
|
|
|
|
|
579
|
|
|
return $where; |
|
580
|
|
|
} |
|
581
|
|
|
|
|
582
|
|
|
/** |
|
583
|
|
|
* Sous fonction suppression |
|
584
|
|
|
* qui traite les liens pour un objet source dont la clé primaire |
|
585
|
|
|
* et la table de lien sont fournies |
|
586
|
|
|
* |
|
587
|
|
|
* $objets et de la forme |
|
588
|
|
|
* array($objet=>$id_objets,...) |
|
589
|
|
|
* un * pour $id,$objet,$id_objets permet de traiter par lot |
|
590
|
|
|
* |
|
591
|
|
|
* On supprime tous les liens entre les objets indiqués par défaut, |
|
592
|
|
|
* sauf s'il y a des rôles déclarés entre ces 2 objets, auquel cas on ne |
|
593
|
|
|
* supprime que les liaisons avec le role déclaré par défaut si rien n'est |
|
594
|
|
|
* précisé dans $cond. Il faut alors passer $cond=array('role'=>'*') pour |
|
595
|
|
|
* supprimer tous les roles, ou array('role'=>'un_role') pour un role précis. |
|
596
|
|
|
* |
|
597
|
|
|
* @internal |
|
598
|
|
|
* @param string $objet_source |
|
599
|
|
|
* @param string $primary |
|
600
|
|
|
* @param string $table_lien |
|
601
|
|
|
* @param int $id |
|
602
|
|
|
* @param array $objets |
|
603
|
|
|
* @param array|null $cond |
|
604
|
|
|
* Conditions where par défaut. |
|
605
|
|
|
* Un cas particulier est géré lorsque l'index 'role' est présent (ou absent) |
|
606
|
|
|
* @return bool|int |
|
|
|
|
|
|
607
|
|
|
*/ |
|
608
|
|
|
function lien_delete($objet_source, $primary, $table_lien, $id, $objets, $cond = null) { |
|
609
|
|
|
|
|
610
|
|
|
$retire = array(); |
|
611
|
|
|
$dels = 0; |
|
612
|
|
|
$echec = false; |
|
613
|
|
|
if (is_null($cond)) { |
|
614
|
|
|
$cond = array(); |
|
615
|
|
|
} |
|
616
|
|
|
|
|
617
|
|
|
foreach ($objets as $objet => $id_objets) { |
|
618
|
|
|
$objet = ($objet == '*') ? $objet : objet_type($objet); # securite |
|
619
|
|
View Code Duplication |
if (!is_array($id_objets) or reset($id_objets) == "NOT") { |
|
|
|
|
|
|
620
|
|
|
$id_objets = array($id_objets); |
|
621
|
|
|
} |
|
622
|
|
|
foreach ($id_objets as $id_objet) { |
|
623
|
|
|
list($cond, $colonne_role, $role) = roles_creer_condition_role($objet_source, $objet, $cond); |
|
|
|
|
|
|
624
|
|
|
// id_objet peut valoir '*' |
|
625
|
|
|
$where = lien_where($primary, $id, $objet, $id_objet, $cond); |
|
626
|
|
|
|
|
627
|
|
|
// lire les liens existants pour propager la date de modif |
|
628
|
|
|
$select = "$primary,id_objet,objet"; |
|
629
|
|
|
if ($colonne_role) { |
|
630
|
|
|
$select .= ",$colonne_role"; |
|
631
|
|
|
} |
|
632
|
|
|
$liens = sql_allfetsel($select, $table_lien, $where); |
|
633
|
|
|
|
|
634
|
|
|
// iterer sur les liens pour permettre aux plugins de gerer |
|
635
|
|
|
foreach ($liens as $l) { |
|
636
|
|
|
|
|
637
|
|
|
$args = array( |
|
638
|
|
|
'table_lien' => $table_lien, |
|
639
|
|
|
'objet_source' => $objet_source, |
|
640
|
|
|
'id_objet_source' => $l[$primary], |
|
641
|
|
|
'objet' => $l['objet'], |
|
642
|
|
|
'id_objet' => $l['id_objet'], |
|
643
|
|
|
'colonne_role' => $colonne_role, |
|
644
|
|
|
'role' => ($colonne_role ? $l[$colonne_role] : ''), |
|
645
|
|
|
'action' => 'delete', |
|
646
|
|
|
); |
|
647
|
|
|
|
|
648
|
|
|
// Envoyer aux plugins |
|
649
|
|
|
$l = pipeline('pre_edition_lien', |
|
650
|
|
|
array( |
|
651
|
|
|
'args' => $args, |
|
652
|
|
|
'data' => $l |
|
653
|
|
|
) |
|
654
|
|
|
); |
|
655
|
|
|
$args['id_objet'] = $id_o = $l['id_objet']; |
|
|
|
|
|
|
656
|
|
|
|
|
657
|
|
|
if ($id_o = intval($l['id_objet']) or $l['objet'] == 'site') { |
|
658
|
|
|
$where = lien_where($primary, $l[$primary], $l['objet'], $id_o, $cond); |
|
659
|
|
|
$e = sql_delete($table_lien, $where); |
|
660
|
|
|
if ($e !== false) { |
|
661
|
|
|
$dels += $e; |
|
662
|
|
|
lien_propage_date_modif($l['objet'], $id_o); |
|
663
|
|
|
lien_propage_date_modif($objet_source, $l[$primary]); |
|
664
|
|
|
} else { |
|
665
|
|
|
$echec = true; |
|
666
|
|
|
} |
|
667
|
|
|
$retire[] = array( |
|
668
|
|
|
'source' => array($objet_source => $l[$primary]), |
|
669
|
|
|
'lien' => array($l['objet'] => $id_o), |
|
670
|
|
|
'type' => $l['objet'], |
|
671
|
|
|
'role' => ($colonne_role ? $l[$colonne_role] : ''), |
|
672
|
|
|
'id' => $id_o |
|
673
|
|
|
); |
|
674
|
|
|
// Envoyer aux plugins |
|
675
|
|
|
pipeline('post_edition_lien', |
|
676
|
|
|
array( |
|
677
|
|
|
'args' => $args, |
|
678
|
|
|
'data' => $l |
|
679
|
|
|
) |
|
680
|
|
|
); |
|
681
|
|
|
} |
|
682
|
|
|
} |
|
683
|
|
|
} |
|
684
|
|
|
} |
|
685
|
|
|
// si on a supprime des liens, on reordonne les liens concernes |
|
686
|
|
|
if ($dels) { |
|
687
|
|
|
lien_ordonner($objet_source, $primary, $table_lien, $id, $objets); |
|
688
|
|
|
} |
|
689
|
|
|
|
|
690
|
|
|
pipeline('trig_supprimer_objets_lies', $retire); |
|
691
|
|
|
|
|
692
|
|
|
return ($echec ? false : $dels); |
|
693
|
|
|
} |
|
694
|
|
|
|
|
695
|
|
|
|
|
696
|
|
|
/** |
|
697
|
|
|
* Sous fonction optimisation |
|
698
|
|
|
* qui nettoie les liens morts (vers un objet inexistant) |
|
699
|
|
|
* pour un objet source dont la clé primaire |
|
700
|
|
|
* et la table de lien sont fournies |
|
701
|
|
|
* |
|
702
|
|
|
* $objets et de la forme |
|
703
|
|
|
* array($objet=>$id_objets,...) |
|
704
|
|
|
* un * pour $id,$objet,$id_objets permet de traiter par lot |
|
705
|
|
|
* |
|
706
|
|
|
* @internal |
|
707
|
|
|
* @param string $objet_source |
|
708
|
|
|
* @param string $primary |
|
709
|
|
|
* @param string $table_lien |
|
710
|
|
|
* @param int $id |
|
711
|
|
|
* @param array $objets |
|
712
|
|
|
* @return bool|int |
|
|
|
|
|
|
713
|
|
|
*/ |
|
714
|
|
|
function lien_optimise($objet_source, $primary, $table_lien, $id, $objets) { |
|
715
|
|
|
include_spip('genie/optimiser'); |
|
716
|
|
|
$echec = false; |
|
717
|
|
|
$dels = 0; |
|
718
|
|
|
foreach ($objets as $objet => $id_objets) { |
|
719
|
|
|
$objet = ($objet == '*') ? $objet : objet_type($objet); # securite |
|
720
|
|
View Code Duplication |
if (!is_array($id_objets) or reset($id_objets) == "NOT") { |
|
|
|
|
|
|
721
|
|
|
$id_objets = array($id_objets); |
|
722
|
|
|
} |
|
723
|
|
|
foreach ($id_objets as $id_objet) { |
|
724
|
|
|
$where = lien_where($primary, $id, $objet, $id_objet); |
|
725
|
|
|
# les liens vers un objet inexistant |
|
726
|
|
|
$r = sql_select("DISTINCT objet", $table_lien, $where); |
|
727
|
|
|
while ($t = sql_fetch($r)) { |
|
728
|
|
|
$type = $t['objet']; |
|
729
|
|
|
$spip_table_objet = table_objet_sql($type); |
|
730
|
|
|
$id_table_objet = id_table_objet($type); |
|
731
|
|
|
$res = sql_select("L.$primary AS id,L.id_objet", |
|
732
|
|
|
// la condition de jointure inclue L.objet='xxx' pour ne joindre que les bonnes lignes |
|
733
|
|
|
// du coups toutes les lignes avec un autre objet ont un id_xxx=NULL puisque LEFT JOIN |
|
734
|
|
|
// il faut les eliminier en repetant la condition dans le where L.objet='xxx' |
|
735
|
|
|
"$table_lien AS L |
|
736
|
|
|
LEFT JOIN $spip_table_objet AS O |
|
737
|
|
|
ON (O.$id_table_objet=L.id_objet AND L.objet=" . sql_quote($type) . ")", |
|
738
|
|
|
"L.objet=" . sql_quote($type) . " AND O.$id_table_objet IS NULL"); |
|
739
|
|
|
// sur une cle primaire composee, pas d'autres solutions que de virer un a un |
|
740
|
|
|
while ($row = sql_fetch($res)) { |
|
741
|
|
|
if ($primary === 'id_document' and $type === 'site' and !intval($row['id_objet'])) { |
|
742
|
|
|
continue; // gaffe, c'est le logo du site ! |
|
743
|
|
|
} |
|
744
|
|
|
$e = sql_delete($table_lien, |
|
745
|
|
|
array("$primary=" . $row['id'], "id_objet=" . $row['id_objet'], "objet=" . sql_quote($type))); |
|
746
|
|
|
if ($e != false) { |
|
747
|
|
|
$dels += $e; |
|
748
|
|
|
spip_log("Entree " . $row['id'] . "/" . $row['id_objet'] . "/$type supprimee dans la table $table_lien", |
|
749
|
|
|
_LOG_INFO_IMPORTANTE); |
|
750
|
|
|
} |
|
751
|
|
|
} |
|
752
|
|
|
} |
|
753
|
|
|
|
|
754
|
|
|
# les liens depuis un objet inexistant |
|
755
|
|
|
$table_source = table_objet_sql($objet_source); |
|
756
|
|
|
// filtrer selon $id, $objet, $id_objet eventuellement fournis |
|
757
|
|
|
// (en general '*' pour chaque) |
|
758
|
|
|
$where = lien_where("L.$primary", $id, $objet, $id_objet); |
|
759
|
|
|
$where[] = "O.$primary IS NULL"; |
|
760
|
|
|
$res = sql_select("L.$primary AS id", |
|
761
|
|
|
"$table_lien AS L LEFT JOIN $table_source AS O ON L.$primary=O.$primary", |
|
762
|
|
|
$where); |
|
763
|
|
|
$dels += optimiser_sansref($table_lien, $primary, $res); |
|
764
|
|
|
} |
|
765
|
|
|
} |
|
766
|
|
|
|
|
767
|
|
|
return ($echec ? false : $dels); |
|
768
|
|
|
} |
|
769
|
|
|
|
|
770
|
|
|
|
|
771
|
|
|
/** |
|
772
|
|
|
* Sous fonction qualification |
|
773
|
|
|
* qui traite les liens pour un objet source dont la clé primaire |
|
774
|
|
|
* et la table de lien sont fournies |
|
775
|
|
|
* |
|
776
|
|
|
* $objets et de la forme |
|
777
|
|
|
* array($objet=>$id_objets,...) |
|
778
|
|
|
* un * pour $id,$objet,$id_objets permet de traiter par lot |
|
779
|
|
|
* |
|
780
|
|
|
* exemple : |
|
781
|
|
|
* $qualif = array('vu'=>'oui'); |
|
782
|
|
|
* |
|
783
|
|
|
* @internal |
|
784
|
|
|
* @param string $objet_source Objet source de l'insertion (celui qui a la table de liaison) |
|
785
|
|
|
* @param string $primary Nom de la clé primaire de cet objet |
|
786
|
|
|
* @param string $table_lien Nom de la table de lien de cet objet |
|
787
|
|
|
* @param int $id Identifiant de l'objet sur lesquels on va insérer des liaisons |
|
788
|
|
|
* @param array $objets Liste des liaisons à faire, de la forme array($objet=>$id_objets) |
|
789
|
|
|
* @param array $qualif |
|
790
|
|
|
* Liste des qualifications à appliquer. |
|
791
|
|
|
* |
|
792
|
|
|
* Si l'objet dispose d'un champ rôle, on extrait des qualifications |
|
793
|
|
|
* le rôle s'il est présent, sinon on applique les qualifications |
|
794
|
|
|
* sur le rôle par défaut. |
|
795
|
|
|
* @return bool|int |
|
|
|
|
|
|
796
|
|
|
* Nombre de modifications faites, false si échec. |
|
797
|
|
|
*/ |
|
798
|
|
|
function lien_set($objet_source, $primary, $table_lien, $id, $objets, $qualif) { |
|
799
|
|
|
$echec = null; |
|
800
|
|
|
$ok = 0; |
|
801
|
|
|
$reordonner = false; |
|
802
|
|
|
if (!$qualif) { |
|
|
|
|
|
|
803
|
|
|
return false; |
|
804
|
|
|
} |
|
805
|
|
|
// nettoyer qualif qui peut venir directement d'un objet_trouver_lien : |
|
806
|
|
|
unset($qualif[$primary]); |
|
807
|
|
|
unset($qualif[$objet_source]); |
|
808
|
|
|
if (isset($qualif['objet'])) { |
|
809
|
|
|
unset($qualif[$qualif['objet']]); |
|
810
|
|
|
} |
|
811
|
|
|
unset($qualif['objet']); |
|
812
|
|
|
unset($qualif['id_objet']); |
|
813
|
|
|
foreach ($objets as $objet => $id_objets) { |
|
814
|
|
|
|
|
815
|
|
|
// role, colonne, where par défaut |
|
816
|
|
|
list($role, $colonne_role, $cond) = |
|
817
|
|
|
roles_trouver_dans_qualif($objet_source, $objet, $qualif); |
|
818
|
|
|
|
|
819
|
|
|
$objet = ($objet == '*') ? $objet : objet_type($objet); # securite |
|
820
|
|
View Code Duplication |
if (!is_array($id_objets) or reset($id_objets) == "NOT") { |
|
|
|
|
|
|
821
|
|
|
$id_objets = array($id_objets); |
|
822
|
|
|
} |
|
823
|
|
|
foreach ($id_objets as $id_objet) { |
|
824
|
|
|
|
|
825
|
|
|
$args = array( |
|
826
|
|
|
'table_lien' => $table_lien, |
|
827
|
|
|
'objet_source' => $objet_source, |
|
828
|
|
|
'id_objet_source' => $id, |
|
829
|
|
|
'objet' => $objet, |
|
830
|
|
|
'id_objet' => $id_objet, |
|
831
|
|
|
'role' => $role, |
|
832
|
|
|
'colonne_role' => $colonne_role, |
|
833
|
|
|
'action' => 'modifier', |
|
834
|
|
|
); |
|
835
|
|
|
|
|
836
|
|
|
// Envoyer aux plugins |
|
837
|
|
|
$qualif = pipeline('pre_edition_lien', |
|
838
|
|
|
array( |
|
839
|
|
|
'args' => $args, |
|
840
|
|
|
'data' => $qualif, |
|
841
|
|
|
) |
|
842
|
|
|
); |
|
843
|
|
|
$args['id_objet'] = $id_objet; |
|
844
|
|
|
|
|
845
|
|
|
if (lien_triables($table_lien) and isset($qualif['rang_lien'])) { |
|
846
|
|
|
if (intval($qualif['rang_lien'])) { |
|
847
|
|
|
// on decale les liens de rang_lien>=la valeur inseree pour faire la place |
|
848
|
|
|
$w = lien_where($primary, '*', $objet, $id_objet, array('rang_lien>='.intval($qualif['rang_lien']),"$primary!=".intval($id))); |
|
849
|
|
|
sql_update($table_lien, array('rang_lien'=>'rang_lien+1'), $w); |
|
850
|
|
|
} |
|
851
|
|
|
// tous les liens de même rôle recoivent le rang indiqué aussi |
|
852
|
|
|
if (roles_colonne($objet_source, $objet)) { |
|
853
|
|
|
$w = lien_where($primary, $id, $objet, $id_objet); |
|
854
|
|
|
sql_updateq($table_lien, array('rang_lien' => intval($qualif['rang_lien'])), $w); |
|
855
|
|
|
} |
|
856
|
|
|
$reordonner = true; |
|
857
|
|
|
} |
|
858
|
|
|
|
|
859
|
|
|
$where = lien_where($primary, $id, $objet, $id_objet, $cond); |
|
860
|
|
|
$e = sql_updateq($table_lien, $qualif, $where); |
|
861
|
|
|
|
|
862
|
|
|
if ($e === false) { |
|
863
|
|
|
$echec = true; |
|
864
|
|
|
} else { |
|
865
|
|
|
// Envoyer aux plugins |
|
866
|
|
|
pipeline('post_edition_lien', |
|
867
|
|
|
array( |
|
868
|
|
|
'args' => $args, |
|
869
|
|
|
'data' => $qualif |
|
870
|
|
|
) |
|
871
|
|
|
); |
|
872
|
|
|
$ok++; |
|
873
|
|
|
} |
|
874
|
|
|
} |
|
875
|
|
|
} |
|
876
|
|
|
// si on a fait des modif de rang, on reordonne les liens concernes |
|
877
|
|
|
if ($reordonner) { |
|
878
|
|
|
lien_ordonner($objet_source, $primary, $table_lien, $id, $objets); |
|
879
|
|
|
} |
|
880
|
|
|
|
|
881
|
|
|
return ($echec ? false : $ok); |
|
882
|
|
|
} |
|
883
|
|
|
|
|
884
|
|
|
/** |
|
885
|
|
|
* Sous fonction trouver |
|
886
|
|
|
* qui cherche les liens pour un objet source dont la clé primaire |
|
887
|
|
|
* et la table de lien sont fournies |
|
888
|
|
|
* |
|
889
|
|
|
* $objets et de la forme |
|
890
|
|
|
* array($objet=>$id_objets,...) |
|
891
|
|
|
* un * pour $id,$objet,$id_objets permet de traiter par lot |
|
892
|
|
|
* |
|
893
|
|
|
* Le tableau de condition peut avoir un index 'role' indiquant de |
|
894
|
|
|
* chercher un rôle précis, ou * pour tous les roles (alors équivalent |
|
895
|
|
|
* à l'absence de l'index) |
|
896
|
|
|
* |
|
897
|
|
|
* @internal |
|
898
|
|
|
* @param string $objet_source |
|
899
|
|
|
* @param string $primary |
|
900
|
|
|
* @param string $table_lien |
|
901
|
|
|
* @param int $id |
|
902
|
|
|
* @param array $objets |
|
903
|
|
|
* @param array|null $cond |
|
904
|
|
|
* Condition du where par défaut |
|
905
|
|
|
* |
|
906
|
|
|
* On peut passer un index 'role' pour sélectionner uniquement |
|
907
|
|
|
* le role défini dedans (et '*' pour tous les rôles). |
|
908
|
|
|
* @return array |
|
909
|
|
|
*/ |
|
910
|
|
|
function lien_find($objet_source, $primary, $table_lien, $id, $objets, $cond = null) { |
|
911
|
|
|
$trouve = array(); |
|
912
|
|
|
foreach ($objets as $objet => $id_objets) { |
|
913
|
|
|
$objet = ($objet == '*') ? $objet : objet_type($objet); # securite |
|
914
|
|
|
// gerer les roles s'il y en a dans $cond |
|
915
|
|
|
list($cond) = roles_creer_condition_role($objet_source, $objet, $cond, true); |
|
916
|
|
|
// lien_where prend en charge les $id_objets sous forme int ou array |
|
917
|
|
|
$where = lien_where($primary, $id, $objet, $id_objets, $cond); |
|
918
|
|
|
$liens = sql_allfetsel('*', $table_lien, $where); |
|
919
|
|
|
// ajouter les entrees objet_source et objet cible par convenance |
|
920
|
|
|
foreach ($liens as $l) { |
|
921
|
|
|
$l[$objet_source] = $l[$primary]; |
|
922
|
|
|
$l[$l['objet']] = $l['id_objet']; |
|
923
|
|
|
$trouve[] = $l; |
|
924
|
|
|
} |
|
925
|
|
|
} |
|
926
|
|
|
|
|
927
|
|
|
return $trouve; |
|
928
|
|
|
} |
|
929
|
|
|
|
|
930
|
|
|
/** |
|
931
|
|
|
* Propager la date_modif sur les objets dont un lien a été modifié |
|
932
|
|
|
* |
|
933
|
|
|
* @internal |
|
934
|
|
|
* @param string $objet |
|
935
|
|
|
* @param array|int $ids |
|
936
|
|
|
*/ |
|
937
|
|
|
function lien_propage_date_modif($objet, $ids) { |
|
938
|
|
|
static $done = array(); |
|
939
|
|
|
$hash = md5($objet . serialize($ids)); |
|
940
|
|
|
|
|
941
|
|
|
// sql_updateq, peut être un rien lent. |
|
942
|
|
|
// On évite de l'appeler 2 fois sur les mêmes choses |
|
943
|
|
|
if (isset($done[$hash])) { |
|
944
|
|
|
return; |
|
945
|
|
|
} |
|
946
|
|
|
|
|
947
|
|
|
$trouver_table = charger_fonction('trouver_table', 'base'); |
|
948
|
|
|
|
|
949
|
|
|
$table = table_objet_sql($objet); |
|
950
|
|
|
if ($desc = $trouver_table($table) |
|
951
|
|
|
and isset($desc['field']['date_modif']) |
|
952
|
|
|
) { |
|
953
|
|
|
$primary = id_table_objet($objet); |
|
954
|
|
|
$where = (is_array($ids) ? sql_in($primary, array_map('intval', $ids)) : "$primary=" . intval($ids)); |
|
955
|
|
|
sql_updateq($table, array('date_modif' => date('Y-m-d H:i:s')), $where); |
|
956
|
|
|
} |
|
957
|
|
|
|
|
958
|
|
|
$done[$hash] = true; |
|
959
|
|
|
} |
|
960
|
|
|
|
This check looks for the generic type
arrayas a return type and suggests a more specific type. This type is inferred from the actual code.