Completed
Push — master ( 2389a5...e0e29f )
by cam
04:23
created
ecrire/public/jointures.php 2 patches
Indentation   +383 added lines, -383 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,78 +154,78 @@  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"] =
178
-				$echap ?
179
-					array("'='","'$obj'","sql_quote('$type')")
180
-					:
181
-					array("=","$obj",sql_quote($type));
182
-			$boucle->join["L$n"] =
183
-				$echap ?
184
-					array("'$id_table'", "'$j2'", "'$j1'", "'$obj='.sql_quote('$type')")
185
-					:
186
-					array($id_table, $j2, $j1, "$obj=" . sql_quote($type));
187
-		} else {
188
-			$boucle->join["L$n"] = $echap ? array("'$id_table'", "'$j'") : array($id_table, $j);
189
-		}
190
-		$boucle->from[$id_table = "L$n"] = $a[0];
191
-	}
192
-
193
-
194
-	// pas besoin de group by
195
-	// (cf http://article.gmane.org/gmane.comp.web.spip.devel/30555)
196
-	// si une seule jointure et sur une table avec primary key formee
197
-	// de l'index principal et de l'index de jointure (non conditionnel! [6031])
198
-	// et operateur d'egalite (https://core.spip.net/issues/477)
199
-
200
-	if ($pk = (isset($a[1]) && (count($boucle->from) == 2) && !$cond)) {
201
-		$pk = nogroupby_if($desc, $a[1], $col);
202
-	}
203
-
204
-	// pas de group by 
205
-	// si une seule jointure
206
-	// et si l'index de jointure est une primary key a l'arrivee !
207
-	if (!$pk
208
-		and (count($boucle->from) == 2)
209
-		and isset($a[1]['key']['PRIMARY KEY'])
210
-		and ($j == $a[1]['key']['PRIMARY KEY'])
211
-	) {
212
-		$pk = true;
213
-	}
214
-
215
-	// la clause Group by est en conflit avec ORDER BY, a completer
216
-	$groups = liste_champs_jointures($nom, $desc, true);
217
-	if (!$pk) {
218
-		foreach ($groups as $id_prim) {
219
-			$id_field = $nom . '.' . $id_prim;
220
-			if (!in_array($id_field, $boucle->group)) {
221
-				$boucle->group[] = $id_field;
222
-			}
223
-		}
224
-	}
225
-
226
-	$boucle->modificateur['lien'] = true;
227
-
228
-	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"] =
178
+                $echap ?
179
+                    array("'='","'$obj'","sql_quote('$type')")
180
+                    :
181
+                    array("=","$obj",sql_quote($type));
182
+            $boucle->join["L$n"] =
183
+                $echap ?
184
+                    array("'$id_table'", "'$j2'", "'$j1'", "'$obj='.sql_quote('$type')")
185
+                    :
186
+                    array($id_table, $j2, $j1, "$obj=" . sql_quote($type));
187
+        } else {
188
+            $boucle->join["L$n"] = $echap ? array("'$id_table'", "'$j'") : array($id_table, $j);
189
+        }
190
+        $boucle->from[$id_table = "L$n"] = $a[0];
191
+    }
192
+
193
+
194
+    // pas besoin de group by
195
+    // (cf http://article.gmane.org/gmane.comp.web.spip.devel/30555)
196
+    // si une seule jointure et sur une table avec primary key formee
197
+    // de l'index principal et de l'index de jointure (non conditionnel! [6031])
198
+    // et operateur d'egalite (https://core.spip.net/issues/477)
199
+
200
+    if ($pk = (isset($a[1]) && (count($boucle->from) == 2) && !$cond)) {
201
+        $pk = nogroupby_if($desc, $a[1], $col);
202
+    }
203
+
204
+    // pas de group by 
205
+    // si une seule jointure
206
+    // et si l'index de jointure est une primary key a l'arrivee !
207
+    if (!$pk
208
+        and (count($boucle->from) == 2)
209
+        and isset($a[1]['key']['PRIMARY KEY'])
210
+        and ($j == $a[1]['key']['PRIMARY KEY'])
211
+    ) {
212
+        $pk = true;
213
+    }
214
+
215
+    // la clause Group by est en conflit avec ORDER BY, a completer
216
+    $groups = liste_champs_jointures($nom, $desc, true);
217
+    if (!$pk) {
218
+        foreach ($groups as $id_prim) {
219
+            $id_field = $nom . '.' . $id_prim;
220
+            if (!in_array($id_field, $boucle->group)) {
221
+                $boucle->group[] = $id_field;
222
+            }
223
+        }
224
+    }
225
+
226
+    $boucle->modificateur['lien'] = true;
227
+
228
+    return "L$n";
229 229
 }
230 230
 
231 231
 /**
@@ -240,16 +240,16 @@  discard block
 block discarded – undo
240 240
  * @return bool
241 241
  */
242 242
 function nogroupby_if($depart, $arrivee, $col) {
243
-	$pk = $arrivee['key']['PRIMARY KEY'];
244
-	if (!$pk) {
245
-		return false;
246
-	}
247
-	$id_primary = $depart['key']['PRIMARY KEY'];
248
-	if (is_array($col)) {
249
-		$col = implode(', *', $col);
250
-	} // cas id_objet, objet
251
-	return (preg_match("/^$id_primary, *$col$/", $pk) or
252
-		preg_match("/^$col, *$id_primary$/", $pk));
243
+    $pk = $arrivee['key']['PRIMARY KEY'];
244
+    if (!$pk) {
245
+        return false;
246
+    }
247
+    $id_primary = $depart['key']['PRIMARY KEY'];
248
+    if (is_array($col)) {
249
+        $col = implode(', *', $col);
250
+    } // cas id_objet, objet
251
+    return (preg_match("/^$id_primary, *$col$/", $pk) or
252
+        preg_match("/^$col, *$id_primary$/", $pk));
253 253
 }
254 254
 
255 255
 /**
@@ -267,46 +267,46 @@  discard block
 block discarded – undo
267 267
  */
268 268
 function liste_champs_jointures($nom, $desc, $primary = false) {
269 269
 
270
-	static $nojoin = array('idx', 'maj', 'date', 'statut');
270
+    static $nojoin = array('idx', 'maj', 'date', 'statut');
271 271
 
272
-	// si cle primaire demandee, la privilegier
273
-	if ($primary && isset($desc['key']['PRIMARY KEY'])) {
274
-		return split_key($desc['key']['PRIMARY KEY']);
275
-	}
272
+    // si cle primaire demandee, la privilegier
273
+    if ($primary && isset($desc['key']['PRIMARY KEY'])) {
274
+        return split_key($desc['key']['PRIMARY KEY']);
275
+    }
276 276
 
277
-	// les champs declares explicitement pour les jointures
278
-	if (isset($desc['join'])) {
279
-		return $desc['join'];
280
-	}
281
-	/*elseif (isset($GLOBALS['tables_principales'][$nom]['join'])) return $GLOBALS['tables_principales'][$nom]['join'];
277
+    // les champs declares explicitement pour les jointures
278
+    if (isset($desc['join'])) {
279
+        return $desc['join'];
280
+    }
281
+    /*elseif (isset($GLOBALS['tables_principales'][$nom]['join'])) return $GLOBALS['tables_principales'][$nom]['join'];
282 282
 	elseif (isset($GLOBALS['tables_auxiliaires'][$nom]['join'])) return $GLOBALS['tables_auxiliaires'][$nom]['join'];*/
283 283
 
284
-	// si pas de cle, c'est fichu
285
-	if (!isset($desc['key'])) {
286
-		return array();
287
-	}
288
-
289
-	// si cle primaire
290
-	if (isset($desc['key']['PRIMARY KEY'])) {
291
-		return split_key($desc['key']['PRIMARY KEY']);
292
-	}
293
-
294
-	// ici on se rabat sur les cles secondaires, 
295
-	// en eliminant celles qui sont pas pertinentes (idx, maj)
296
-	// si jamais le resultat n'est pas pertinent pour une table donnee,
297
-	// il faut declarer explicitement le champ 'join' de sa description
298
-
299
-	$join = array();
300
-	foreach ($desc['key'] as $v) {
301
-		$join = split_key($v, $join);
302
-	}
303
-	foreach ($join as $k) {
304
-		if (in_array($k, $nojoin)) {
305
-			unset($join[$k]);
306
-		}
307
-	}
308
-
309
-	return $join;
284
+    // si pas de cle, c'est fichu
285
+    if (!isset($desc['key'])) {
286
+        return array();
287
+    }
288
+
289
+    // si cle primaire
290
+    if (isset($desc['key']['PRIMARY KEY'])) {
291
+        return split_key($desc['key']['PRIMARY KEY']);
292
+    }
293
+
294
+    // ici on se rabat sur les cles secondaires, 
295
+    // en eliminant celles qui sont pas pertinentes (idx, maj)
296
+    // si jamais le resultat n'est pas pertinent pour une table donnee,
297
+    // il faut declarer explicitement le champ 'join' de sa description
298
+
299
+    $join = array();
300
+    foreach ($desc['key'] as $v) {
301
+        $join = split_key($v, $join);
302
+    }
303
+    foreach ($join as $k) {
304
+        if (in_array($k, $nojoin)) {
305
+            unset($join[$k]);
306
+        }
307
+    }
308
+
309
+    return $join;
310 310
 }
311 311
 
312 312
 /**
@@ -317,14 +317,14 @@  discard block
 block discarded – undo
317 317
  * @return array
318 318
  */
319 319
 function split_key($v, $join = array()) {
320
-	foreach (preg_split('/,\s*/', $v) as $k) {
321
-		if (strpos($k, '(') !== false) {
322
-			$k = explode('(', $k);
323
-			$k = trim(reset($k));
324
-		}
325
-		$join[$k] = $k;
326
-	}
327
-	return $join;
320
+    foreach (preg_split('/,\s*/', $v) as $k) {
321
+        if (strpos($k, '(') !== false) {
322
+            $k = explode('(', $k);
323
+            $k = trim(reset($k));
324
+        }
325
+        $join[$k] = $k;
326
+    }
327
+    return $join;
328 328
 }
329 329
 
330 330
 /**
@@ -347,126 +347,126 @@  discard block
 block discarded – undo
347 347
  * @return array
348 348
  */
349 349
 function calculer_chaine_jointures(
350
-	&$boucle,
351
-	$depart,
352
-	$arrivee,
353
-	$vu = array(),
354
-	$milieu_exclus = array(),
355
-	$max_liens = 5
350
+    &$boucle,
351
+    $depart,
352
+    $arrivee,
353
+    $vu = array(),
354
+    $milieu_exclus = array(),
355
+    $max_liens = 5
356 356
 ) {
357
-	static $trouver_table;
358
-	if (!$trouver_table) {
359
-		$trouver_table = charger_fonction('trouver_table', 'base');
360
-	}
361
-
362
-	if (is_string($milieu_exclus)) {
363
-		$milieu_exclus = array($milieu_exclus);
364
-	}
365
-	// quand on a exclus id_objet comme cle de jointure, il faut aussi exclure objet
366
-	// faire une jointure sur objet tout seul n'a pas de sens
367
-	if (in_array('id_objet', $milieu_exclus) and !in_array('objet', $milieu_exclus)) {
368
-		$milieu_exclus[] = 'objet';
369
-	}
370
-
371
-	list($dnom, $ddesc) = $depart;
372
-	list($anom, $adesc) = $arrivee;
373
-	if (!count($vu)) {
374
-		$vu[] = $dnom; // ne pas oublier la table de depart
375
-		$vu[] = $anom; // ne pas oublier la table d'arrivee
376
-	}
377
-
378
-	$akeys = array();
379
-	foreach ($adesc['key'] as $k) {
380
-		// respecter l'ordre de $adesc['key'] pour ne pas avoir id_trad en premier entre autres...
381
-		$akeys = array_merge($akeys, preg_split('/,\s*/', $k));
382
-	}
383
-
384
-	// enlever les cles d'arrivee exclues par l'appel
385
-	$akeys = array_diff($akeys, $milieu_exclus);
386
-
387
-	// cles candidates au depart
388
-	$keys = liste_champs_jointures($dnom, $ddesc);
389
-	// enlever les cles dde depart exclues par l'appel
390
-	$keys = array_diff($keys, $milieu_exclus);
391
-
392
-	$v = !$keys ? false : array_intersect(array_values($keys), $akeys);
393
-
394
-	if ($v) {
395
-		return array(array($dnom, array($adesc['table'], $adesc), array_shift($v)));
396
-	}
397
-
398
-	// regarder si l'on a (id_objet,objet) au depart et si on peut le mapper sur un id_xx
399
-	if (count(array_intersect(array('id_objet', 'objet'), $keys)) == 2) {
400
-		// regarder si l'une des cles d'arrivee peut se decomposer en 
401
-		// id_objet,objet
402
-		// si oui on la prend
403
-		foreach ($akeys as $key) {
404
-			$v = decompose_champ_id_objet($key);
405
-			if (is_array($v)) {
406
-				$objet = array_shift($v); // objet,'article'
407
-				array_unshift($v, $key); // id_article,objet,'article'
408
-				array_unshift($v, $objet); // id_objet,id_article,objet,'article'
409
-				return array(array($dnom, array($adesc['table'], $adesc), $v));
410
-			}
411
-		}
412
-	} else {
413
-		// regarder si l'une des cles de depart peut se decomposer en 
414
-		// id_objet,objet a l'arrivee
415
-		// si oui on la prend
416
-		foreach ($keys as $key) {
417
-			if (count($v = trouver_champs_decomposes($key, $adesc)) > 1) {
418
-				if (count($v) == count(array_intersect($v, $akeys))) {
419
-					$v = decompose_champ_id_objet($key); // id_objet,objet,'article'
420
-					array_unshift($v, $key); // id_article,id_objet,objet,'article'
421
-					return array(array($dnom, array($adesc['table'], $adesc), $v));
422
-				}
423
-			}
424
-		}
425
-	}
426
-	// si l'on voulait une jointure direct, c'est rate !
427
-	if ($max_liens <= 1) {
428
-		return array();
429
-	}
430
-
431
-	// sinon essayer de passer par une autre table
432
-	$new = $vu;
433
-	foreach ($boucle->jointures as $v) {
434
-		if ($v
435
-			and !in_array($v, $vu)
436
-			and $def = $trouver_table($v, $boucle->sql_serveur)
437
-			and !in_array($def['table_sql'], $vu)
438
-		) {
439
-			// ne pas tester les cles qui sont exclues a l'appel
440
-			// ie la cle de la jointure precedente
441
-			$test_cles = $milieu_exclus;
442
-			$new[] = $v;
443
-			$max_iter = 50; // securite
444
-			while (count($jointure_directe_possible = calculer_chaine_jointures($boucle, $depart, array($v, $def), $vu,
445
-					$test_cles, 1))
446
-				and $max_iter--) {
447
-				$jointure_directe_possible = reset($jointure_directe_possible);
448
-				$milieu = end($jointure_directe_possible);
449
-				$exclure_fin = $milieu_exclus;
450
-				if (is_string($milieu)) {
451
-					$exclure_fin[] = $milieu;
452
-					$test_cles[] = $milieu;
453
-				} else {
454
-					$exclure_fin = array_merge($exclure_fin, $milieu);
455
-					$test_cles = array_merge($test_cles, $milieu);
456
-				}
457
-				// essayer de rejoindre l'arrivee a partir de cette etape intermediaire
458
-				// sans repasser par la meme cle milieu, ni une cle deja vue !
459
-				$r = calculer_chaine_jointures($boucle, array($v, $def), $arrivee, $new, $exclure_fin, $max_liens - 1);
460
-				if ($r) {
461
-					array_unshift($r, $jointure_directe_possible);
462
-
463
-					return $r;
464
-				}
465
-			}
466
-		}
467
-	}
468
-
469
-	return array();
357
+    static $trouver_table;
358
+    if (!$trouver_table) {
359
+        $trouver_table = charger_fonction('trouver_table', 'base');
360
+    }
361
+
362
+    if (is_string($milieu_exclus)) {
363
+        $milieu_exclus = array($milieu_exclus);
364
+    }
365
+    // quand on a exclus id_objet comme cle de jointure, il faut aussi exclure objet
366
+    // faire une jointure sur objet tout seul n'a pas de sens
367
+    if (in_array('id_objet', $milieu_exclus) and !in_array('objet', $milieu_exclus)) {
368
+        $milieu_exclus[] = 'objet';
369
+    }
370
+
371
+    list($dnom, $ddesc) = $depart;
372
+    list($anom, $adesc) = $arrivee;
373
+    if (!count($vu)) {
374
+        $vu[] = $dnom; // ne pas oublier la table de depart
375
+        $vu[] = $anom; // ne pas oublier la table d'arrivee
376
+    }
377
+
378
+    $akeys = array();
379
+    foreach ($adesc['key'] as $k) {
380
+        // respecter l'ordre de $adesc['key'] pour ne pas avoir id_trad en premier entre autres...
381
+        $akeys = array_merge($akeys, preg_split('/,\s*/', $k));
382
+    }
383
+
384
+    // enlever les cles d'arrivee exclues par l'appel
385
+    $akeys = array_diff($akeys, $milieu_exclus);
386
+
387
+    // cles candidates au depart
388
+    $keys = liste_champs_jointures($dnom, $ddesc);
389
+    // enlever les cles dde depart exclues par l'appel
390
+    $keys = array_diff($keys, $milieu_exclus);
391
+
392
+    $v = !$keys ? false : array_intersect(array_values($keys), $akeys);
393
+
394
+    if ($v) {
395
+        return array(array($dnom, array($adesc['table'], $adesc), array_shift($v)));
396
+    }
397
+
398
+    // regarder si l'on a (id_objet,objet) au depart et si on peut le mapper sur un id_xx
399
+    if (count(array_intersect(array('id_objet', 'objet'), $keys)) == 2) {
400
+        // regarder si l'une des cles d'arrivee peut se decomposer en 
401
+        // id_objet,objet
402
+        // si oui on la prend
403
+        foreach ($akeys as $key) {
404
+            $v = decompose_champ_id_objet($key);
405
+            if (is_array($v)) {
406
+                $objet = array_shift($v); // objet,'article'
407
+                array_unshift($v, $key); // id_article,objet,'article'
408
+                array_unshift($v, $objet); // id_objet,id_article,objet,'article'
409
+                return array(array($dnom, array($adesc['table'], $adesc), $v));
410
+            }
411
+        }
412
+    } else {
413
+        // regarder si l'une des cles de depart peut se decomposer en 
414
+        // id_objet,objet a l'arrivee
415
+        // si oui on la prend
416
+        foreach ($keys as $key) {
417
+            if (count($v = trouver_champs_decomposes($key, $adesc)) > 1) {
418
+                if (count($v) == count(array_intersect($v, $akeys))) {
419
+                    $v = decompose_champ_id_objet($key); // id_objet,objet,'article'
420
+                    array_unshift($v, $key); // id_article,id_objet,objet,'article'
421
+                    return array(array($dnom, array($adesc['table'], $adesc), $v));
422
+                }
423
+            }
424
+        }
425
+    }
426
+    // si l'on voulait une jointure direct, c'est rate !
427
+    if ($max_liens <= 1) {
428
+        return array();
429
+    }
430
+
431
+    // sinon essayer de passer par une autre table
432
+    $new = $vu;
433
+    foreach ($boucle->jointures as $v) {
434
+        if ($v
435
+            and !in_array($v, $vu)
436
+            and $def = $trouver_table($v, $boucle->sql_serveur)
437
+            and !in_array($def['table_sql'], $vu)
438
+        ) {
439
+            // ne pas tester les cles qui sont exclues a l'appel
440
+            // ie la cle de la jointure precedente
441
+            $test_cles = $milieu_exclus;
442
+            $new[] = $v;
443
+            $max_iter = 50; // securite
444
+            while (count($jointure_directe_possible = calculer_chaine_jointures($boucle, $depart, array($v, $def), $vu,
445
+                    $test_cles, 1))
446
+                and $max_iter--) {
447
+                $jointure_directe_possible = reset($jointure_directe_possible);
448
+                $milieu = end($jointure_directe_possible);
449
+                $exclure_fin = $milieu_exclus;
450
+                if (is_string($milieu)) {
451
+                    $exclure_fin[] = $milieu;
452
+                    $test_cles[] = $milieu;
453
+                } else {
454
+                    $exclure_fin = array_merge($exclure_fin, $milieu);
455
+                    $test_cles = array_merge($test_cles, $milieu);
456
+                }
457
+                // essayer de rejoindre l'arrivee a partir de cette etape intermediaire
458
+                // sans repasser par la meme cle milieu, ni une cle deja vue !
459
+                $r = calculer_chaine_jointures($boucle, array($v, $def), $arrivee, $new, $exclure_fin, $max_liens - 1);
460
+                if ($r) {
461
+                    array_unshift($r, $jointure_directe_possible);
462
+
463
+                    return $r;
464
+                }
465
+            }
466
+        }
467
+    }
468
+
469
+    return array();
470 470
 }
471 471
 
472 472
 /**
@@ -477,18 +477,18 @@  discard block
 block discarded – undo
477 477
  * @return array
478 478
  */
479 479
 function trouver_cles_table($keys) {
480
-	$res = array();
481
-	foreach ($keys as $v) {
482
-		if (!strpos($v, ",")) {
483
-			$res[$v] = 1;
484
-		} else {
485
-			foreach (preg_split("/\s*,\s*/", $v) as $k) {
486
-				$res[$k] = 1;
487
-			}
488
-		}
489
-	}
490
-
491
-	return array_keys($res);
480
+    $res = array();
481
+    foreach ($keys as $v) {
482
+        if (!strpos($v, ",")) {
483
+            $res[$v] = 1;
484
+        } else {
485
+            foreach (preg_split("/\s*,\s*/", $v) as $k) {
486
+                $res[$k] = 1;
487
+            }
488
+        }
489
+    }
490
+
491
+    return array_keys($res);
492 492
 }
493 493
 
494 494
 
@@ -515,33 +515,33 @@  discard block
 block discarded – undo
515 515
  *     - 'alias' : alias utilisé pour la table (si pertinent. ie: avec `$boucle->from` transmis par exemple)
516 516
  */
517 517
 function chercher_champ_dans_tables($cle, $tables, $connect, $checkarrivee = false) {
518
-	static $trouver_table = '';
519
-	if (!$trouver_table) {
520
-		$trouver_table = charger_fonction('trouver_table', 'base');
521
-	}
522
-
523
-	if (!is_array($cle)) {
524
-		$cle = array($cle);
525
-	}
526
-
527
-	foreach ($tables as $k => $table) {
528
-		if ($table && $desc = $trouver_table($table, $connect)) {
529
-			if (isset($desc['field'])
530
-				// verifier que toutes les cles cherchees sont la
531
-				and (count(array_intersect($cle, array_keys($desc['field']))) == count($cle))
532
-				// si on sait ou on veut arriver, il faut que ca colle
533
-				and ($checkarrivee == false || $checkarrivee == $desc['table'])
534
-			) {
535
-				return array(
536
-					'desc' => $desc,
537
-					'table' => $desc['table'],
538
-					'alias' => $k,
539
-				);
540
-			}
541
-		}
542
-	}
543
-
544
-	return false;
518
+    static $trouver_table = '';
519
+    if (!$trouver_table) {
520
+        $trouver_table = charger_fonction('trouver_table', 'base');
521
+    }
522
+
523
+    if (!is_array($cle)) {
524
+        $cle = array($cle);
525
+    }
526
+
527
+    foreach ($tables as $k => $table) {
528
+        if ($table && $desc = $trouver_table($table, $connect)) {
529
+            if (isset($desc['field'])
530
+                // verifier que toutes les cles cherchees sont la
531
+                and (count(array_intersect($cle, array_keys($desc['field']))) == count($cle))
532
+                // si on sait ou on veut arriver, il faut que ca colle
533
+                and ($checkarrivee == false || $checkarrivee == $desc['table'])
534
+            ) {
535
+                return array(
536
+                    'desc' => $desc,
537
+                    'table' => $desc['table'],
538
+                    'alias' => $k,
539
+                );
540
+            }
541
+        }
542
+    }
543
+
544
+    return false;
545 545
 }
546 546
 
547 547
 /**
@@ -567,52 +567,52 @@  discard block
 block discarded – undo
567 567
  */
568 568
 function trouver_champ_exterieur($cle, $joints, &$boucle, $checkarrivee = false) {
569 569
 
570
-	// support de la recherche multi champ :
571
-	// si en seconde etape on a decompose le champ id_xx en id_objet,objet
572
-	// on reentre ici soit en cherchant une table les 2 champs id_objet,objet
573
-	// soit une table avec les 3 champs id_xx, id_objet, objet
574
-	if (!is_array($cle)) {
575
-		$cle = array($cle);
576
-	}
577
-
578
-	if ($infos = chercher_champ_dans_tables($cle, $joints, $boucle->sql_serveur, $checkarrivee)) {
579
-		return array($infos['table'], $infos['desc'], $cle);
580
-	}
581
-
582
-	// au premier coup, on essaye de decomposer, si possible
583
-	if (count($cle) == 1
584
-		and $c = reset($cle)
585
-		and is_array($decompose = decompose_champ_id_objet($c))
586
-	) {
587
-
588
-		$desc = $boucle->show;
589
-
590
-		// cas 1 : la cle id_xx est dans la table de depart
591
-		// -> on cherche uniquement id_objet,objet a l'arrivee
592
-		if (isset($desc['field'][$c])) {
593
-			$cle = array();
594
-			$cle[] = array_shift($decompose); // id_objet
595
-			$cle[] = array_shift($decompose); // objet
596
-			return trouver_champ_exterieur($cle, $joints, $boucle, $checkarrivee);
597
-		}
598
-		// cas 2 : la cle id_xx n'est pas dans la table de depart
599
-		// -> il faut trouver une cle de depart zzz telle que
600
-		// id_objet,objet,zzz soit a l'arrivee
601
-		else {
602
-			$depart = liste_champs_jointures((isset($desc['table']) ? $desc['table'] : ''), $desc);
603
-			foreach ($depart as $d) {
604
-				$cle = array();
605
-				$cle[] = array_shift($decompose); // id_objet
606
-				$cle[] = array_shift($decompose); // objet
607
-				$cle[] = $d;
608
-				if ($ext = trouver_champ_exterieur($cle, $joints, $boucle, $checkarrivee)) {
609
-					return $ext;
610
-				}
611
-			}
612
-		}
613
-	}
614
-
615
-	return "";
570
+    // support de la recherche multi champ :
571
+    // si en seconde etape on a decompose le champ id_xx en id_objet,objet
572
+    // on reentre ici soit en cherchant une table les 2 champs id_objet,objet
573
+    // soit une table avec les 3 champs id_xx, id_objet, objet
574
+    if (!is_array($cle)) {
575
+        $cle = array($cle);
576
+    }
577
+
578
+    if ($infos = chercher_champ_dans_tables($cle, $joints, $boucle->sql_serveur, $checkarrivee)) {
579
+        return array($infos['table'], $infos['desc'], $cle);
580
+    }
581
+
582
+    // au premier coup, on essaye de decomposer, si possible
583
+    if (count($cle) == 1
584
+        and $c = reset($cle)
585
+        and is_array($decompose = decompose_champ_id_objet($c))
586
+    ) {
587
+
588
+        $desc = $boucle->show;
589
+
590
+        // cas 1 : la cle id_xx est dans la table de depart
591
+        // -> on cherche uniquement id_objet,objet a l'arrivee
592
+        if (isset($desc['field'][$c])) {
593
+            $cle = array();
594
+            $cle[] = array_shift($decompose); // id_objet
595
+            $cle[] = array_shift($decompose); // objet
596
+            return trouver_champ_exterieur($cle, $joints, $boucle, $checkarrivee);
597
+        }
598
+        // cas 2 : la cle id_xx n'est pas dans la table de depart
599
+        // -> il faut trouver une cle de depart zzz telle que
600
+        // id_objet,objet,zzz soit a l'arrivee
601
+        else {
602
+            $depart = liste_champs_jointures((isset($desc['table']) ? $desc['table'] : ''), $desc);
603
+            foreach ($depart as $d) {
604
+                $cle = array();
605
+                $cle[] = array_shift($decompose); // id_objet
606
+                $cle[] = array_shift($decompose); // objet
607
+                $cle[] = $d;
608
+                if ($ext = trouver_champ_exterieur($cle, $joints, $boucle, $checkarrivee)) {
609
+                    return $ext;
610
+                }
611
+            }
612
+        }
613
+    }
614
+
615
+    return "";
616 616
 }
617 617
 
618 618
 /**
@@ -644,21 +644,21 @@  discard block
 block discarded – undo
644 644
  * @return string
645 645
  */
646 646
 function trouver_jointure_champ($champ, &$boucle, $jointures = false, $cond = false, $checkarrivee = false) {
647
-	if ($jointures === false) {
648
-		$jointures = $boucle->jointures;
649
-	}
650
-	// TODO : aberration, on utilise $jointures pour trouver le champ
651
-	// mais pas poour construire la jointure ensuite
652
-	$arrivee = trouver_champ_exterieur($champ, $jointures, $boucle, $checkarrivee);
653
-	if ($arrivee) {
654
-		$desc = $boucle->show;
655
-		array_pop($arrivee); // enlever la cle en 3eme argument
656
-		$cle = calculer_jointure($boucle, array($desc['id_table'], $desc), $arrivee, '', $cond);
657
-		if ($cle) {
658
-			return $cle;
659
-		}
660
-	}
661
-	spip_log("trouver_jointure_champ: $champ inconnu");
662
-
663
-	return '';
647
+    if ($jointures === false) {
648
+        $jointures = $boucle->jointures;
649
+    }
650
+    // TODO : aberration, on utilise $jointures pour trouver le champ
651
+    // mais pas poour construire la jointure ensuite
652
+    $arrivee = trouver_champ_exterieur($champ, $jointures, $boucle, $checkarrivee);
653
+    if ($arrivee) {
654
+        $desc = $boucle->show;
655
+        array_pop($arrivee); // enlever la cle en 3eme argument
656
+        $cle = calculer_jointure($boucle, array($desc['id_table'], $desc), $arrivee, '', $cond);
657
+        if ($cle) {
658
+            return $cle;
659
+        }
660
+    }
661
+    spip_log("trouver_jointure_champ: $champ inconnu");
662
+
663
+    return '';
664 664
 }
Please login to merge, or discard this patch.
Spacing   +4 added lines, -4 removed lines patch added patch discarded remove patch
@@ -176,14 +176,14 @@  discard block
 block discarded – undo
176 176
 			// sache qu'il peut enlever ce where si il enleve la jointure
177 177
 			$boucle->where["JOIN-L$n"] =
178 178
 				$echap ?
179
-					array("'='","'$obj'","sql_quote('$type')")
179
+					array("'='", "'$obj'", "sql_quote('$type')")
180 180
 					:
181
-					array("=","$obj",sql_quote($type));
181
+					array("=", "$obj", sql_quote($type));
182 182
 			$boucle->join["L$n"] =
183 183
 				$echap ?
184 184
 					array("'$id_table'", "'$j2'", "'$j1'", "'$obj='.sql_quote('$type')")
185 185
 					:
186
-					array($id_table, $j2, $j1, "$obj=" . sql_quote($type));
186
+					array($id_table, $j2, $j1, "$obj=".sql_quote($type));
187 187
 		} else {
188 188
 			$boucle->join["L$n"] = $echap ? array("'$id_table'", "'$j'") : array($id_table, $j);
189 189
 		}
@@ -216,7 +216,7 @@  discard block
 block discarded – undo
216 216
 	$groups = liste_champs_jointures($nom, $desc, true);
217 217
 	if (!$pk) {
218 218
 		foreach ($groups as $id_prim) {
219
-			$id_field = $nom . '.' . $id_prim;
219
+			$id_field = $nom.'.'.$id_prim;
220 220
 			if (!in_array($id_field, $boucle->group)) {
221 221
 				$boucle->group[] = $id_field;
222 222
 			}
Please login to merge, or discard this patch.