Completed
Push — master ( bdebb1...f8c6aa )
by cam
04:45
created
ecrire/public/jointures.php 1 patch
Indentation   +379 added lines, -379 removed lines patch added patch discarded remove patch
@@ -17,7 +17,7 @@  discard block
 block discarded – undo
17 17
  **/
18 18
 
19 19
 if (!defined('_ECRIRE_INC_VERSION')) {
20
-	return;
20
+    return;
21 21
 }
22 22
 
23 23
 
@@ -33,11 +33,11 @@  discard block
 block discarded – undo
33 33
  *     Chaine sinon : le nom du champ (non décomposable donc)
34 34
  */
35 35
 function decompose_champ_id_objet($champ) {
36
-	if (($champ !== 'id_objet') and preg_match(',^id_([a-z_]+)$,', $champ, $regs)) {
37
-		return array('id_objet', 'objet', objet_type($champ));
38
-	}
36
+    if (($champ !== 'id_objet') and preg_match(',^id_([a-z_]+)$,', $champ, $regs)) {
37
+        return array('id_objet', 'objet', objet_type($champ));
38
+    }
39 39
 
40
-	return $champ;
40
+    return $champ;
41 41
 }
42 42
 
43 43
 /**
@@ -56,20 +56,20 @@  discard block
 block discarded – undo
56 56
  *     - array(id_objet, objet), si le champ n'existe pas mais qu'on peut décomposer
57 57
  */
58 58
 function trouver_champs_decomposes($champ, $desc) {
59
-	if (!is_array($desc) // on ne se risque pas en conjectures si on ne connait pas la table
60
-		or array_key_exists($champ, $desc['field'])
61
-	) {
62
-		return array($champ);
63
-	}
64
-	// si le champ se décompose, tester que les colonnes décomposées sont présentes
65
-	if (is_array($decompose = decompose_champ_id_objet($champ))) {
66
-		array_pop($decompose);
67
-		if (count(array_intersect($decompose, array_keys($desc['field']))) == count($decompose)) {
68
-			return $decompose;
69
-		}
70
-	}
71
-
72
-	return array($champ);
59
+    if (!is_array($desc) // on ne se risque pas en conjectures si on ne connait pas la table
60
+        or array_key_exists($champ, $desc['field'])
61
+    ) {
62
+        return array($champ);
63
+    }
64
+    // si le champ se décompose, tester que les colonnes décomposées sont présentes
65
+    if (is_array($decompose = decompose_champ_id_objet($champ))) {
66
+        array_pop($decompose);
67
+        if (count(array_intersect($decompose, array_keys($desc['field']))) == count($decompose)) {
68
+            return $decompose;
69
+        }
70
+    }
71
+
72
+    return array($champ);
73 73
 }
74 74
 
75 75
 
@@ -99,23 +99,23 @@  discard block
 block discarded – undo
99 99
  *     Alias de la table de jointure (Lx)
100 100
  */
101 101
 function calculer_jointure(&$boucle, $depart, $arrivee, $col = '', $cond = false, $max_liens = 5) {
102
-	// les jointures minimales sont optimales :
103
-	// on contraint le nombre d'etapes en l'augmentant
104
-	// jusqu'a ce qu'on trouve une jointure ou qu'on atteigne la limite maxi 
105
-	$max = 1;
106
-	$res = false;
107
-	$milieu_exclus = ($col ? $col : array());
108
-	while ($max <= $max_liens and !$res) {
109
-		$res = calculer_chaine_jointures($boucle, $depart, $arrivee, array(), $milieu_exclus, $max);
110
-		$max++;
111
-	}
112
-	if (!$res) {
113
-		return "";
114
-	}
115
-
116
-	list($nom, $desc) = $depart;
117
-
118
-	return fabrique_jointures($boucle, $res, $cond, $desc, $nom, $col);
102
+    // les jointures minimales sont optimales :
103
+    // on contraint le nombre d'etapes en l'augmentant
104
+    // jusqu'a ce qu'on trouve une jointure ou qu'on atteigne la limite maxi 
105
+    $max = 1;
106
+    $res = false;
107
+    $milieu_exclus = ($col ? $col : array());
108
+    while ($max <= $max_liens and !$res) {
109
+        $res = calculer_chaine_jointures($boucle, $depart, $arrivee, array(), $milieu_exclus, $max);
110
+        $max++;
111
+    }
112
+    if (!$res) {
113
+        return "";
114
+    }
115
+
116
+    list($nom, $desc) = $depart;
117
+
118
+    return fabrique_jointures($boucle, $res, $cond, $desc, $nom, $col);
119 119
 }
120 120
 
121 121
 /**
@@ -154,74 +154,74 @@  discard block
 block discarded – undo
154 154
  *     Alias de la table de jointure (Lx)
155 155
  */
156 156
 function fabrique_jointures(&$boucle, $res, $cond = false, $desc = array(), $nom = '', $col = '', $echap = true) {
157
-	static $num = array();
158
-	$id_table = "";
159
-	$cpt = &$num[$boucle->descr['nom']][$boucle->descr['gram']][$boucle->id_boucle];
160
-	foreach ($res as $cle => $r) {
161
-		list($d, $a, $j) = $r;
162
-		if (!$id_table) {
163
-			$id_table = $d;
164
-		}
165
-		$n = ++$cpt;
166
-		if (is_array($j)) { // c'est un lien sur un champ du type id_objet,objet,'article'
167
-			list($j1, $j2, $obj, $type) = $j;
168
-			// trouver de quel cote est (id_objet,objet)
169
-			if ($j1 == "id_$obj") {
170
-				$obj = "$id_table.$obj";
171
-			} else {
172
-				$obj = "L$n.$obj";
173
-			}
174
-			// le where complementaire est envoye dans la jointure et dans le where
175
-			// on utilise une clé qui le relie a la jointure pour que l'optimiseur
176
-			// sache qu'il peut enlever ce where si il enleve la jointure
177
-			$boucle->where["JOIN-L$n"] = array("'='","'$obj'","sql_quote('$type')");
178
-			$boucle->join["L$n"] =
179
-				$echap ?
180
-					array("'$id_table'", "'$j2'", "'$j1'", "'$obj='.sql_quote('$type')")
181
-					:
182
-					array($id_table, $j2, $j1, "$obj=" . sql_quote($type));
183
-		} else {
184
-			$boucle->join["L$n"] = $echap ? array("'$id_table'", "'$j'") : array($id_table, $j);
185
-		}
186
-		$boucle->from[$id_table = "L$n"] = $a[0];
187
-	}
188
-
189
-
190
-	// pas besoin de group by
191
-	// (cf http://article.gmane.org/gmane.comp.web.spip.devel/30555)
192
-	// si une seule jointure et sur une table avec primary key formee
193
-	// de l'index principal et de l'index de jointure (non conditionnel! [6031])
194
-	// et operateur d'egalite (https://core.spip.net/issues/477)
195
-
196
-	if ($pk = (isset($a[1]) && (count($boucle->from) == 2) && !$cond)) {
197
-		$pk = nogroupby_if($desc, $a[1], $col);
198
-	}
199
-
200
-	// pas de group by 
201
-	// si une seule jointure
202
-	// et si l'index de jointure est une primary key a l'arrivee !
203
-	if (!$pk
204
-		and (count($boucle->from) == 2)
205
-		and isset($a[1]['key']['PRIMARY KEY'])
206
-		and ($j == $a[1]['key']['PRIMARY KEY'])
207
-	) {
208
-		$pk = true;
209
-	}
210
-
211
-	// la clause Group by est en conflit avec ORDER BY, a completer
212
-	$groups = liste_champs_jointures($nom, $desc, true);
213
-	if (!$pk) {
214
-		foreach ($groups as $id_prim) {
215
-			$id_field = $nom . '.' . $id_prim;
216
-			if (!in_array($id_field, $boucle->group)) {
217
-				$boucle->group[] = $id_field;
218
-			}
219
-		}
220
-	}
221
-
222
-	$boucle->modificateur['lien'] = true;
223
-
224
-	return "L$n";
157
+    static $num = array();
158
+    $id_table = "";
159
+    $cpt = &$num[$boucle->descr['nom']][$boucle->descr['gram']][$boucle->id_boucle];
160
+    foreach ($res as $cle => $r) {
161
+        list($d, $a, $j) = $r;
162
+        if (!$id_table) {
163
+            $id_table = $d;
164
+        }
165
+        $n = ++$cpt;
166
+        if (is_array($j)) { // c'est un lien sur un champ du type id_objet,objet,'article'
167
+            list($j1, $j2, $obj, $type) = $j;
168
+            // trouver de quel cote est (id_objet,objet)
169
+            if ($j1 == "id_$obj") {
170
+                $obj = "$id_table.$obj";
171
+            } else {
172
+                $obj = "L$n.$obj";
173
+            }
174
+            // le where complementaire est envoye dans la jointure et dans le where
175
+            // on utilise une clé qui le relie a la jointure pour que l'optimiseur
176
+            // sache qu'il peut enlever ce where si il enleve la jointure
177
+            $boucle->where["JOIN-L$n"] = array("'='","'$obj'","sql_quote('$type')");
178
+            $boucle->join["L$n"] =
179
+                $echap ?
180
+                    array("'$id_table'", "'$j2'", "'$j1'", "'$obj='.sql_quote('$type')")
181
+                    :
182
+                    array($id_table, $j2, $j1, "$obj=" . sql_quote($type));
183
+        } else {
184
+            $boucle->join["L$n"] = $echap ? array("'$id_table'", "'$j'") : array($id_table, $j);
185
+        }
186
+        $boucle->from[$id_table = "L$n"] = $a[0];
187
+    }
188
+
189
+
190
+    // pas besoin de group by
191
+    // (cf http://article.gmane.org/gmane.comp.web.spip.devel/30555)
192
+    // si une seule jointure et sur une table avec primary key formee
193
+    // de l'index principal et de l'index de jointure (non conditionnel! [6031])
194
+    // et operateur d'egalite (https://core.spip.net/issues/477)
195
+
196
+    if ($pk = (isset($a[1]) && (count($boucle->from) == 2) && !$cond)) {
197
+        $pk = nogroupby_if($desc, $a[1], $col);
198
+    }
199
+
200
+    // pas de group by 
201
+    // si une seule jointure
202
+    // et si l'index de jointure est une primary key a l'arrivee !
203
+    if (!$pk
204
+        and (count($boucle->from) == 2)
205
+        and isset($a[1]['key']['PRIMARY KEY'])
206
+        and ($j == $a[1]['key']['PRIMARY KEY'])
207
+    ) {
208
+        $pk = true;
209
+    }
210
+
211
+    // la clause Group by est en conflit avec ORDER BY, a completer
212
+    $groups = liste_champs_jointures($nom, $desc, true);
213
+    if (!$pk) {
214
+        foreach ($groups as $id_prim) {
215
+            $id_field = $nom . '.' . $id_prim;
216
+            if (!in_array($id_field, $boucle->group)) {
217
+                $boucle->group[] = $id_field;
218
+            }
219
+        }
220
+    }
221
+
222
+    $boucle->modificateur['lien'] = true;
223
+
224
+    return "L$n";
225 225
 }
226 226
 
227 227
 /**
@@ -236,16 +236,16 @@  discard block
 block discarded – undo
236 236
  * @return bool
237 237
  */
238 238
 function nogroupby_if($depart, $arrivee, $col) {
239
-	$pk = $arrivee['key']['PRIMARY KEY'];
240
-	if (!$pk) {
241
-		return false;
242
-	}
243
-	$id_primary = $depart['key']['PRIMARY KEY'];
244
-	if (is_array($col)) {
245
-		$col = implode(', *', $col);
246
-	} // cas id_objet, objet
247
-	return (preg_match("/^$id_primary, *$col$/", $pk) or
248
-		preg_match("/^$col, *$id_primary$/", $pk));
239
+    $pk = $arrivee['key']['PRIMARY KEY'];
240
+    if (!$pk) {
241
+        return false;
242
+    }
243
+    $id_primary = $depart['key']['PRIMARY KEY'];
244
+    if (is_array($col)) {
245
+        $col = implode(', *', $col);
246
+    } // cas id_objet, objet
247
+    return (preg_match("/^$id_primary, *$col$/", $pk) or
248
+        preg_match("/^$col, *$id_primary$/", $pk));
249 249
 }
250 250
 
251 251
 /**
@@ -263,46 +263,46 @@  discard block
 block discarded – undo
263 263
  */
264 264
 function liste_champs_jointures($nom, $desc, $primary = false) {
265 265
 
266
-	static $nojoin = array('idx', 'maj', 'date', 'statut');
266
+    static $nojoin = array('idx', 'maj', 'date', 'statut');
267 267
 
268
-	// si cle primaire demandee, la privilegier
269
-	if ($primary && isset($desc['key']['PRIMARY KEY'])) {
270
-		return split_key($desc['key']['PRIMARY KEY']);
271
-	}
268
+    // si cle primaire demandee, la privilegier
269
+    if ($primary && isset($desc['key']['PRIMARY KEY'])) {
270
+        return split_key($desc['key']['PRIMARY KEY']);
271
+    }
272 272
 
273
-	// les champs declares explicitement pour les jointures
274
-	if (isset($desc['join'])) {
275
-		return $desc['join'];
276
-	}
277
-	/*elseif (isset($GLOBALS['tables_principales'][$nom]['join'])) return $GLOBALS['tables_principales'][$nom]['join'];
273
+    // les champs declares explicitement pour les jointures
274
+    if (isset($desc['join'])) {
275
+        return $desc['join'];
276
+    }
277
+    /*elseif (isset($GLOBALS['tables_principales'][$nom]['join'])) return $GLOBALS['tables_principales'][$nom]['join'];
278 278
 	elseif (isset($GLOBALS['tables_auxiliaires'][$nom]['join'])) return $GLOBALS['tables_auxiliaires'][$nom]['join'];*/
279 279
 
280
-	// si pas de cle, c'est fichu
281
-	if (!isset($desc['key'])) {
282
-		return array();
283
-	}
284
-
285
-	// si cle primaire
286
-	if (isset($desc['key']['PRIMARY KEY'])) {
287
-		return split_key($desc['key']['PRIMARY KEY']);
288
-	}
289
-
290
-	// ici on se rabat sur les cles secondaires, 
291
-	// en eliminant celles qui sont pas pertinentes (idx, maj)
292
-	// si jamais le resultat n'est pas pertinent pour une table donnee,
293
-	// il faut declarer explicitement le champ 'join' de sa description
294
-
295
-	$join = array();
296
-	foreach ($desc['key'] as $v) {
297
-		$join = split_key($v, $join);
298
-	}
299
-	foreach ($join as $k) {
300
-		if (in_array($k, $nojoin)) {
301
-			unset($join[$k]);
302
-		}
303
-	}
304
-
305
-	return $join;
280
+    // si pas de cle, c'est fichu
281
+    if (!isset($desc['key'])) {
282
+        return array();
283
+    }
284
+
285
+    // si cle primaire
286
+    if (isset($desc['key']['PRIMARY KEY'])) {
287
+        return split_key($desc['key']['PRIMARY KEY']);
288
+    }
289
+
290
+    // ici on se rabat sur les cles secondaires, 
291
+    // en eliminant celles qui sont pas pertinentes (idx, maj)
292
+    // si jamais le resultat n'est pas pertinent pour une table donnee,
293
+    // il faut declarer explicitement le champ 'join' de sa description
294
+
295
+    $join = array();
296
+    foreach ($desc['key'] as $v) {
297
+        $join = split_key($v, $join);
298
+    }
299
+    foreach ($join as $k) {
300
+        if (in_array($k, $nojoin)) {
301
+            unset($join[$k]);
302
+        }
303
+    }
304
+
305
+    return $join;
306 306
 }
307 307
 
308 308
 /**
@@ -313,14 +313,14 @@  discard block
 block discarded – undo
313 313
  * @return array
314 314
  */
315 315
 function split_key($v, $join = array()) {
316
-	foreach (preg_split('/,\s*/', $v) as $k) {
317
-		if (strpos($k, '(') !== false) {
318
-			$k = explode('(', $k);
319
-			$k = trim(reset($k));
320
-		}
321
-		$join[$k] = $k;
322
-	}
323
-	return $join;
316
+    foreach (preg_split('/,\s*/', $v) as $k) {
317
+        if (strpos($k, '(') !== false) {
318
+            $k = explode('(', $k);
319
+            $k = trim(reset($k));
320
+        }
321
+        $join[$k] = $k;
322
+    }
323
+    return $join;
324 324
 }
325 325
 
326 326
 /**
@@ -343,126 +343,126 @@  discard block
 block discarded – undo
343 343
  * @return array
344 344
  */
345 345
 function calculer_chaine_jointures(
346
-	&$boucle,
347
-	$depart,
348
-	$arrivee,
349
-	$vu = array(),
350
-	$milieu_exclus = array(),
351
-	$max_liens = 5
346
+    &$boucle,
347
+    $depart,
348
+    $arrivee,
349
+    $vu = array(),
350
+    $milieu_exclus = array(),
351
+    $max_liens = 5
352 352
 ) {
353
-	static $trouver_table;
354
-	if (!$trouver_table) {
355
-		$trouver_table = charger_fonction('trouver_table', 'base');
356
-	}
357
-
358
-	if (is_string($milieu_exclus)) {
359
-		$milieu_exclus = array($milieu_exclus);
360
-	}
361
-	// quand on a exclus id_objet comme cle de jointure, il faut aussi exclure objet
362
-	// faire une jointure sur objet tout seul n'a pas de sens
363
-	if (in_array('id_objet', $milieu_exclus) and !in_array('objet', $milieu_exclus)) {
364
-		$milieu_exclus[] = 'objet';
365
-	}
366
-
367
-	list($dnom, $ddesc) = $depart;
368
-	list($anom, $adesc) = $arrivee;
369
-	if (!count($vu)) {
370
-		$vu[] = $dnom; // ne pas oublier la table de depart
371
-		$vu[] = $anom; // ne pas oublier la table d'arrivee
372
-	}
373
-
374
-	$akeys = array();
375
-	foreach ($adesc['key'] as $k) {
376
-		// respecter l'ordre de $adesc['key'] pour ne pas avoir id_trad en premier entre autres...
377
-		$akeys = array_merge($akeys, preg_split('/,\s*/', $k));
378
-	}
379
-
380
-	// enlever les cles d'arrivee exclues par l'appel
381
-	$akeys = array_diff($akeys, $milieu_exclus);
382
-
383
-	// cles candidates au depart
384
-	$keys = liste_champs_jointures($dnom, $ddesc);
385
-	// enlever les cles dde depart exclues par l'appel
386
-	$keys = array_diff($keys, $milieu_exclus);
387
-
388
-	$v = !$keys ? false : array_intersect(array_values($keys), $akeys);
389
-
390
-	if ($v) {
391
-		return array(array($dnom, array($adesc['table'], $adesc), array_shift($v)));
392
-	}
393
-
394
-	// regarder si l'on a (id_objet,objet) au depart et si on peut le mapper sur un id_xx
395
-	if (count(array_intersect(array('id_objet', 'objet'), $keys)) == 2) {
396
-		// regarder si l'une des cles d'arrivee peut se decomposer en 
397
-		// id_objet,objet
398
-		// si oui on la prend
399
-		foreach ($akeys as $key) {
400
-			$v = decompose_champ_id_objet($key);
401
-			if (is_array($v)) {
402
-				$objet = array_shift($v); // objet,'article'
403
-				array_unshift($v, $key); // id_article,objet,'article'
404
-				array_unshift($v, $objet); // id_objet,id_article,objet,'article'
405
-				return array(array($dnom, array($adesc['table'], $adesc), $v));
406
-			}
407
-		}
408
-	} else {
409
-		// regarder si l'une des cles de depart peut se decomposer en 
410
-		// id_objet,objet a l'arrivee
411
-		// si oui on la prend
412
-		foreach ($keys as $key) {
413
-			if (count($v = trouver_champs_decomposes($key, $adesc)) > 1) {
414
-				if (count($v) == count(array_intersect($v, $akeys))) {
415
-					$v = decompose_champ_id_objet($key); // id_objet,objet,'article'
416
-					array_unshift($v, $key); // id_article,id_objet,objet,'article'
417
-					return array(array($dnom, array($adesc['table'], $adesc), $v));
418
-				}
419
-			}
420
-		}
421
-	}
422
-	// si l'on voulait une jointure direct, c'est rate !
423
-	if ($max_liens <= 1) {
424
-		return array();
425
-	}
426
-
427
-	// sinon essayer de passer par une autre table
428
-	$new = $vu;
429
-	foreach ($boucle->jointures as $v) {
430
-		if ($v
431
-			and !in_array($v, $vu)
432
-			and $def = $trouver_table($v, $boucle->sql_serveur)
433
-			and !in_array($def['table_sql'], $vu)
434
-		) {
435
-			// ne pas tester les cles qui sont exclues a l'appel
436
-			// ie la cle de la jointure precedente
437
-			$test_cles = $milieu_exclus;
438
-			$new[] = $v;
439
-			$max_iter = 50; // securite
440
-			while (count($jointure_directe_possible = calculer_chaine_jointures($boucle, $depart, array($v, $def), $vu,
441
-					$test_cles, 1))
442
-				and $max_iter--) {
443
-				$jointure_directe_possible = reset($jointure_directe_possible);
444
-				$milieu = end($jointure_directe_possible);
445
-				$exclure_fin = $milieu_exclus;
446
-				if (is_string($milieu)) {
447
-					$exclure_fin[] = $milieu;
448
-					$test_cles[] = $milieu;
449
-				} else {
450
-					$exclure_fin = array_merge($exclure_fin, $milieu);
451
-					$test_cles = array_merge($test_cles, $milieu);
452
-				}
453
-				// essayer de rejoindre l'arrivee a partir de cette etape intermediaire
454
-				// sans repasser par la meme cle milieu, ni une cle deja vue !
455
-				$r = calculer_chaine_jointures($boucle, array($v, $def), $arrivee, $new, $exclure_fin, $max_liens - 1);
456
-				if ($r) {
457
-					array_unshift($r, $jointure_directe_possible);
458
-
459
-					return $r;
460
-				}
461
-			}
462
-		}
463
-	}
464
-
465
-	return array();
353
+    static $trouver_table;
354
+    if (!$trouver_table) {
355
+        $trouver_table = charger_fonction('trouver_table', 'base');
356
+    }
357
+
358
+    if (is_string($milieu_exclus)) {
359
+        $milieu_exclus = array($milieu_exclus);
360
+    }
361
+    // quand on a exclus id_objet comme cle de jointure, il faut aussi exclure objet
362
+    // faire une jointure sur objet tout seul n'a pas de sens
363
+    if (in_array('id_objet', $milieu_exclus) and !in_array('objet', $milieu_exclus)) {
364
+        $milieu_exclus[] = 'objet';
365
+    }
366
+
367
+    list($dnom, $ddesc) = $depart;
368
+    list($anom, $adesc) = $arrivee;
369
+    if (!count($vu)) {
370
+        $vu[] = $dnom; // ne pas oublier la table de depart
371
+        $vu[] = $anom; // ne pas oublier la table d'arrivee
372
+    }
373
+
374
+    $akeys = array();
375
+    foreach ($adesc['key'] as $k) {
376
+        // respecter l'ordre de $adesc['key'] pour ne pas avoir id_trad en premier entre autres...
377
+        $akeys = array_merge($akeys, preg_split('/,\s*/', $k));
378
+    }
379
+
380
+    // enlever les cles d'arrivee exclues par l'appel
381
+    $akeys = array_diff($akeys, $milieu_exclus);
382
+
383
+    // cles candidates au depart
384
+    $keys = liste_champs_jointures($dnom, $ddesc);
385
+    // enlever les cles dde depart exclues par l'appel
386
+    $keys = array_diff($keys, $milieu_exclus);
387
+
388
+    $v = !$keys ? false : array_intersect(array_values($keys), $akeys);
389
+
390
+    if ($v) {
391
+        return array(array($dnom, array($adesc['table'], $adesc), array_shift($v)));
392
+    }
393
+
394
+    // regarder si l'on a (id_objet,objet) au depart et si on peut le mapper sur un id_xx
395
+    if (count(array_intersect(array('id_objet', 'objet'), $keys)) == 2) {
396
+        // regarder si l'une des cles d'arrivee peut se decomposer en 
397
+        // id_objet,objet
398
+        // si oui on la prend
399
+        foreach ($akeys as $key) {
400
+            $v = decompose_champ_id_objet($key);
401
+            if (is_array($v)) {
402
+                $objet = array_shift($v); // objet,'article'
403
+                array_unshift($v, $key); // id_article,objet,'article'
404
+                array_unshift($v, $objet); // id_objet,id_article,objet,'article'
405
+                return array(array($dnom, array($adesc['table'], $adesc), $v));
406
+            }
407
+        }
408
+    } else {
409
+        // regarder si l'une des cles de depart peut se decomposer en 
410
+        // id_objet,objet a l'arrivee
411
+        // si oui on la prend
412
+        foreach ($keys as $key) {
413
+            if (count($v = trouver_champs_decomposes($key, $adesc)) > 1) {
414
+                if (count($v) == count(array_intersect($v, $akeys))) {
415
+                    $v = decompose_champ_id_objet($key); // id_objet,objet,'article'
416
+                    array_unshift($v, $key); // id_article,id_objet,objet,'article'
417
+                    return array(array($dnom, array($adesc['table'], $adesc), $v));
418
+                }
419
+            }
420
+        }
421
+    }
422
+    // si l'on voulait une jointure direct, c'est rate !
423
+    if ($max_liens <= 1) {
424
+        return array();
425
+    }
426
+
427
+    // sinon essayer de passer par une autre table
428
+    $new = $vu;
429
+    foreach ($boucle->jointures as $v) {
430
+        if ($v
431
+            and !in_array($v, $vu)
432
+            and $def = $trouver_table($v, $boucle->sql_serveur)
433
+            and !in_array($def['table_sql'], $vu)
434
+        ) {
435
+            // ne pas tester les cles qui sont exclues a l'appel
436
+            // ie la cle de la jointure precedente
437
+            $test_cles = $milieu_exclus;
438
+            $new[] = $v;
439
+            $max_iter = 50; // securite
440
+            while (count($jointure_directe_possible = calculer_chaine_jointures($boucle, $depart, array($v, $def), $vu,
441
+                    $test_cles, 1))
442
+                and $max_iter--) {
443
+                $jointure_directe_possible = reset($jointure_directe_possible);
444
+                $milieu = end($jointure_directe_possible);
445
+                $exclure_fin = $milieu_exclus;
446
+                if (is_string($milieu)) {
447
+                    $exclure_fin[] = $milieu;
448
+                    $test_cles[] = $milieu;
449
+                } else {
450
+                    $exclure_fin = array_merge($exclure_fin, $milieu);
451
+                    $test_cles = array_merge($test_cles, $milieu);
452
+                }
453
+                // essayer de rejoindre l'arrivee a partir de cette etape intermediaire
454
+                // sans repasser par la meme cle milieu, ni une cle deja vue !
455
+                $r = calculer_chaine_jointures($boucle, array($v, $def), $arrivee, $new, $exclure_fin, $max_liens - 1);
456
+                if ($r) {
457
+                    array_unshift($r, $jointure_directe_possible);
458
+
459
+                    return $r;
460
+                }
461
+            }
462
+        }
463
+    }
464
+
465
+    return array();
466 466
 }
467 467
 
468 468
 /**
@@ -473,18 +473,18 @@  discard block
 block discarded – undo
473 473
  * @return array
474 474
  */
475 475
 function trouver_cles_table($keys) {
476
-	$res = array();
477
-	foreach ($keys as $v) {
478
-		if (!strpos($v, ",")) {
479
-			$res[$v] = 1;
480
-		} else {
481
-			foreach (preg_split("/\s*,\s*/", $v) as $k) {
482
-				$res[$k] = 1;
483
-			}
484
-		}
485
-	}
486
-
487
-	return array_keys($res);
476
+    $res = array();
477
+    foreach ($keys as $v) {
478
+        if (!strpos($v, ",")) {
479
+            $res[$v] = 1;
480
+        } else {
481
+            foreach (preg_split("/\s*,\s*/", $v) as $k) {
482
+                $res[$k] = 1;
483
+            }
484
+        }
485
+    }
486
+
487
+    return array_keys($res);
488 488
 }
489 489
 
490 490
 
@@ -511,33 +511,33 @@  discard block
 block discarded – undo
511 511
  *     - 'alias' : alias utilisé pour la table (si pertinent. ie: avec `$boucle->from` transmis par exemple)
512 512
  */
513 513
 function chercher_champ_dans_tables($cle, $tables, $connect, $checkarrivee = false) {
514
-	static $trouver_table = '';
515
-	if (!$trouver_table) {
516
-		$trouver_table = charger_fonction('trouver_table', 'base');
517
-	}
518
-
519
-	if (!is_array($cle)) {
520
-		$cle = array($cle);
521
-	}
522
-
523
-	foreach ($tables as $k => $table) {
524
-		if ($table && $desc = $trouver_table($table, $connect)) {
525
-			if (isset($desc['field'])
526
-				// verifier que toutes les cles cherchees sont la
527
-				and (count(array_intersect($cle, array_keys($desc['field']))) == count($cle))
528
-				// si on sait ou on veut arriver, il faut que ca colle
529
-				and ($checkarrivee == false || $checkarrivee == $desc['table'])
530
-			) {
531
-				return array(
532
-					'desc' => $desc,
533
-					'table' => $desc['table'],
534
-					'alias' => $k,
535
-				);
536
-			}
537
-		}
538
-	}
539
-
540
-	return false;
514
+    static $trouver_table = '';
515
+    if (!$trouver_table) {
516
+        $trouver_table = charger_fonction('trouver_table', 'base');
517
+    }
518
+
519
+    if (!is_array($cle)) {
520
+        $cle = array($cle);
521
+    }
522
+
523
+    foreach ($tables as $k => $table) {
524
+        if ($table && $desc = $trouver_table($table, $connect)) {
525
+            if (isset($desc['field'])
526
+                // verifier que toutes les cles cherchees sont la
527
+                and (count(array_intersect($cle, array_keys($desc['field']))) == count($cle))
528
+                // si on sait ou on veut arriver, il faut que ca colle
529
+                and ($checkarrivee == false || $checkarrivee == $desc['table'])
530
+            ) {
531
+                return array(
532
+                    'desc' => $desc,
533
+                    'table' => $desc['table'],
534
+                    'alias' => $k,
535
+                );
536
+            }
537
+        }
538
+    }
539
+
540
+    return false;
541 541
 }
542 542
 
543 543
 /**
@@ -563,52 +563,52 @@  discard block
 block discarded – undo
563 563
  */
564 564
 function trouver_champ_exterieur($cle, $joints, &$boucle, $checkarrivee = false) {
565 565
 
566
-	// support de la recherche multi champ :
567
-	// si en seconde etape on a decompose le champ id_xx en id_objet,objet
568
-	// on reentre ici soit en cherchant une table les 2 champs id_objet,objet
569
-	// soit une table avec les 3 champs id_xx, id_objet, objet
570
-	if (!is_array($cle)) {
571
-		$cle = array($cle);
572
-	}
573
-
574
-	if ($infos = chercher_champ_dans_tables($cle, $joints, $boucle->sql_serveur, $checkarrivee)) {
575
-		return array($infos['table'], $infos['desc'], $cle);
576
-	}
577
-
578
-	// au premier coup, on essaye de decomposer, si possible
579
-	if (count($cle) == 1
580
-		and $c = reset($cle)
581
-		and is_array($decompose = decompose_champ_id_objet($c))
582
-	) {
583
-
584
-		$desc = $boucle->show;
585
-
586
-		// cas 1 : la cle id_xx est dans la table de depart
587
-		// -> on cherche uniquement id_objet,objet a l'arrivee
588
-		if (isset($desc['field'][$c])) {
589
-			$cle = array();
590
-			$cle[] = array_shift($decompose); // id_objet
591
-			$cle[] = array_shift($decompose); // objet
592
-			return trouver_champ_exterieur($cle, $joints, $boucle, $checkarrivee);
593
-		}
594
-		// cas 2 : la cle id_xx n'est pas dans la table de depart
595
-		// -> il faut trouver une cle de depart zzz telle que
596
-		// id_objet,objet,zzz soit a l'arrivee
597
-		else {
598
-			$depart = liste_champs_jointures((isset($desc['table']) ? $desc['table'] : ''), $desc);
599
-			foreach ($depart as $d) {
600
-				$cle = array();
601
-				$cle[] = array_shift($decompose); // id_objet
602
-				$cle[] = array_shift($decompose); // objet
603
-				$cle[] = $d;
604
-				if ($ext = trouver_champ_exterieur($cle, $joints, $boucle, $checkarrivee)) {
605
-					return $ext;
606
-				}
607
-			}
608
-		}
609
-	}
610
-
611
-	return "";
566
+    // support de la recherche multi champ :
567
+    // si en seconde etape on a decompose le champ id_xx en id_objet,objet
568
+    // on reentre ici soit en cherchant une table les 2 champs id_objet,objet
569
+    // soit une table avec les 3 champs id_xx, id_objet, objet
570
+    if (!is_array($cle)) {
571
+        $cle = array($cle);
572
+    }
573
+
574
+    if ($infos = chercher_champ_dans_tables($cle, $joints, $boucle->sql_serveur, $checkarrivee)) {
575
+        return array($infos['table'], $infos['desc'], $cle);
576
+    }
577
+
578
+    // au premier coup, on essaye de decomposer, si possible
579
+    if (count($cle) == 1
580
+        and $c = reset($cle)
581
+        and is_array($decompose = decompose_champ_id_objet($c))
582
+    ) {
583
+
584
+        $desc = $boucle->show;
585
+
586
+        // cas 1 : la cle id_xx est dans la table de depart
587
+        // -> on cherche uniquement id_objet,objet a l'arrivee
588
+        if (isset($desc['field'][$c])) {
589
+            $cle = array();
590
+            $cle[] = array_shift($decompose); // id_objet
591
+            $cle[] = array_shift($decompose); // objet
592
+            return trouver_champ_exterieur($cle, $joints, $boucle, $checkarrivee);
593
+        }
594
+        // cas 2 : la cle id_xx n'est pas dans la table de depart
595
+        // -> il faut trouver une cle de depart zzz telle que
596
+        // id_objet,objet,zzz soit a l'arrivee
597
+        else {
598
+            $depart = liste_champs_jointures((isset($desc['table']) ? $desc['table'] : ''), $desc);
599
+            foreach ($depart as $d) {
600
+                $cle = array();
601
+                $cle[] = array_shift($decompose); // id_objet
602
+                $cle[] = array_shift($decompose); // objet
603
+                $cle[] = $d;
604
+                if ($ext = trouver_champ_exterieur($cle, $joints, $boucle, $checkarrivee)) {
605
+                    return $ext;
606
+                }
607
+            }
608
+        }
609
+    }
610
+
611
+    return "";
612 612
 }
613 613
 
614 614
 /**
@@ -640,21 +640,21 @@  discard block
 block discarded – undo
640 640
  * @return string
641 641
  */
642 642
 function trouver_jointure_champ($champ, &$boucle, $jointures = false, $cond = false, $checkarrivee = false) {
643
-	if ($jointures === false) {
644
-		$jointures = $boucle->jointures;
645
-	}
646
-	// TODO : aberration, on utilise $jointures pour trouver le champ
647
-	// mais pas poour construire la jointure ensuite
648
-	$arrivee = trouver_champ_exterieur($champ, $jointures, $boucle, $checkarrivee);
649
-	if ($arrivee) {
650
-		$desc = $boucle->show;
651
-		array_pop($arrivee); // enlever la cle en 3eme argument
652
-		$cle = calculer_jointure($boucle, array($desc['id_table'], $desc), $arrivee, '', $cond);
653
-		if ($cle) {
654
-			return $cle;
655
-		}
656
-	}
657
-	spip_log("trouver_jointure_champ: $champ inconnu");
658
-
659
-	return '';
643
+    if ($jointures === false) {
644
+        $jointures = $boucle->jointures;
645
+    }
646
+    // TODO : aberration, on utilise $jointures pour trouver le champ
647
+    // mais pas poour construire la jointure ensuite
648
+    $arrivee = trouver_champ_exterieur($champ, $jointures, $boucle, $checkarrivee);
649
+    if ($arrivee) {
650
+        $desc = $boucle->show;
651
+        array_pop($arrivee); // enlever la cle en 3eme argument
652
+        $cle = calculer_jointure($boucle, array($desc['id_table'], $desc), $arrivee, '', $cond);
653
+        if ($cle) {
654
+            return $cle;
655
+        }
656
+    }
657
+    spip_log("trouver_jointure_champ: $champ inconnu");
658
+
659
+    return '';
660 660
 }
Please login to merge, or discard this patch.