From 5105a66b4029866270b64bc6395233c85b3fa65e Mon Sep 17 00:00:00 2001
From: "Committo,Ergo:sum" <esj@rezo.net>
Date: Mon, 27 Jun 2005 22:18:35 +0000
Subject: [PATCH] =?UTF-8?q?mauvais=20retour=20de=20boucles=20r=C3=A9cursiv?=
 =?UTF-8?q?es=20(nic;o=20&=20paolo);=20code=20gourmand,=20mort=20ou=20mal?=
 =?UTF-8?q?=20structur=C3=A9=20dans=20le=20calcul=20des=20champs=20SQL=20p?=
 =?UTF-8?q?ar=20le=20compilateur?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 ecrire/inc_index.php3  |  20 +++------
 inc-boucles.php3       |   2 -
 inc-compilo-api.php3   |   2 +-
 inc-compilo-index.php3 |   6 ++-
 inc-compilo.php3       | 100 ++++++++++++++++++-----------------------
 inc-criteres.php3      |  29 ++++++------
 6 files changed, 69 insertions(+), 90 deletions(-)

diff --git a/ecrire/inc_index.php3 b/ecrire/inc_index.php3
index 59e969b397..1b57a94f5b 100644
--- a/ecrire/inc_index.php3
+++ b/ecrire/inc_index.php3
@@ -617,25 +617,19 @@ function prepare_recherche($recherche, $type = 'id_article', $table='articles')
 		arsort($points, SORT_NUMERIC);
 
 		# calculer le {id_article IN()} et le {... as points}
-		if (count($points)) {
+		if (!count($points)) {
+			$cache[$type][$recherche] = array('', '');
+		} else {
 			$ids = array();
-			$expr = '';
+			$select = '0';
 			foreach ($points as $id => $p)
 				$listes_ids[$p] .= ','.$id;
 			foreach ($listes_ids as $p => $liste_ids)
-				$expr .= "+$p*(".calcul_mysql_in("$table.$type", substr($liste_ids, 1)).") ";
-			if ($expr = substr($expr,1))
-				$select = "$expr as points";
-			else
-				$select = "0 as points";
+				$select .= "+$p*(".calcul_mysql_in("$table.$type", substr($liste_ids, 1)).") ";
 
-			$where = '('.calcul_mysql_in("$table.$type", join(',',array_keys($points))).')';
-		} else {
-			$select = '';
-			$where = '';
+			$cache[$type][$recherche] = array($select, 
+							  '('.calcul_mysql_in("$table.$type", join(',',array_keys($points))).')');
 		}
-
-		$cache[$type][$recherche] = array($select, $where);
 	}
 
 	return $cache[$type][$recherche];
diff --git a/inc-boucles.php3 b/inc-boucles.php3
index 1da2f5d2ef..045343e5a1 100644
--- a/inc-boucles.php3
+++ b/inc-boucles.php3
@@ -280,8 +280,6 @@ function boucle_SYNDIC_ARTICLES_dist($id_boucle, &$boucles) {
 			$boucle->where['statut'] = "$id_table.statut IN ('publie','prop')";
 	}
 
-	$boucle->select[]='syndic.nom_site AS nom_site'; # derogation zarbi
-	$boucle->select[]='syndic.url_site AS url_site'; # idem
 	return calculer_boucle($id_boucle, $boucles); 
 }
 
diff --git a/inc-compilo-api.php3 b/inc-compilo-api.php3
index 0775a7e019..2b90e401ca 100644
--- a/inc-compilo-api.php3
+++ b/inc-compilo-api.php3
@@ -62,7 +62,7 @@ class Boucle {
 	var $order = '';
 	var $default_order = '';
 	var $date = 'date' ;
-	var $hash = false ;
+	var $hash = "" ;
 	var $lien = false;
 	var $sous_requete = false;
 	var $hierarchie = '';
diff --git a/inc-compilo-index.php3 b/inc-compilo-index.php3
index 7b78726525..c68e23697a 100644
--- a/inc-compilo-index.php3
+++ b/inc-compilo-index.php3
@@ -90,8 +90,10 @@ function index_pile($idb, $nom_champ, &$boucles, $explicite='') {
 
 		// On l'a trouve
 		if ($e) {
-			$boucles[$idb]->select[] = $t . "." . $e;
-			return '$Pile[$SP' . ($i ? "-$i" : "") . '][\'' . $c . '\']';
+		  $t .= ".$e";
+		  if (!in_array($t, $boucles[$idb]->select))
+		    $boucles[$idb]->select[] = $t;
+		  return '$Pile[$SP' . ($i ? "-$i" : "") . '][\'' . $c . '\']';
 		}
 #		spip_log("On remonte vers $i");
 		// Sinon on remonte d'un cran
diff --git a/inc-compilo.php3 b/inc-compilo.php3
index b7c1943f24..198d9fad18 100644
--- a/inc-compilo.php3
+++ b/inc-compilo.php3
@@ -19,6 +19,8 @@
 if (defined("_INC_COMPILO")) return;
 define("_INC_COMPILO", "1");
 
+// reperer un code ne calculant rien, meme avec commentaire
+define('CODE_MONOTONE', "^(\n//[^\n]*\n)?\(?'([^'])*'\)?$");
 
 // Definition de la structure $p, et fonctions de recherche et de reservation
 // dans l'arborescence des boucles
@@ -83,20 +85,16 @@ function calculer_inclure($struct, $descr, &$boucles, $id_boucle) {
 //
 function calculer_boucle($id_boucle, &$boucles) {
 
-	$boucle = &$boucles[$id_boucle];
-	$return = $boucle->return;
-	$type_boucle = $boucle->type_requete;
-
-	if ($type_boucle == 'boucle')
-	    return "\n	\$t0 = " . $return . ";";
+  $boucle = &$boucles[$id_boucle];
+  $return = $boucle->return;
+  $type_boucle = $boucle->type_requete;
 
+  if ($type_boucle == 'boucle') {
+	    $corps = "\n	\$t0 = " . $return . ";";
+	    $init = "";
+  } else {
 	$id_table = $boucle->id_table;
 	$primary = $boucle->primary;
-	if($p = strpos($primary, ',')) {
-		$id_field = $id_table . "." . substr($primary, 0, $p);
-	} else {
-		$id_field = $id_table . "." . $primary;
-	}
 
 	// La boucle doit-elle selectionner la langue ?
 	// 1. par defaut, les boucles suivantes le font
@@ -114,33 +112,26 @@ function calculer_boucle($id_boucle, &$boucles) {
 	if ($boucle->lang_select == 'oui') $lang_select = 'oui';
 	if ($boucle->lang_select == 'non') $lang_select = false;
 
-	// Penser a demander le champ lang
+	// Penser a demander le champ lang au serveur SQL
 	if ($lang_select)
-		$boucle->select[] = 
-			// cas des tables SPIP
-			($id_table ? $id_table.'.' : '')
-			// cas general ({lang_select} sur une table externe)
-			. 'lang';
+	  index_pile($id_boucle, 'lang', $boucles);
 
 	// Calculer les invalideurs si c'est une boucle non constante
-	$constant = ereg("^\(?'[^']*'\)?$",$return);
-
+	$constant = ereg(CODE_MONOTONE,$return);
 	if ((!$primary) || $constant)
 		$invalide = '';
 	else {
-		$boucle->select[] = $id_field;
-
-		$invalide = "\n			\$Cache['$primary']";
-		if ($primary != 'id_forum')
-			$invalide .= "[\$Pile[\$SP]['$primary']] = 1;";
-		else
-			$invalide .= "[calcul_index_forum(" . 
-				// Retournera 4 [$SP] mais force la demande du champ a MySQL
-				index_pile($id_boucle, 'id_article', $boucles) . ',' .
-				index_pile($id_boucle, 'id_breve', $boucles) .  ',' .
-				index_pile($id_boucle, 'id_rubrique', $boucles) .',' .
-				index_pile($id_boucle, 'id_syndic', $boucles) .  ")] = 1;";
-		$invalide .= ' // invalideurs';
+		$invalide = "\n			\$Cache['$primary'][" .
+		  (($primary != 'id_forum')  ? 
+		   index_pile($id_boucle, $primary, $boucles) :
+		   ("calcul_index_forum(" . 
+		// Retournera 4 [$SP] mais force la demande du champ a MySQL
+		    index_pile($id_boucle, 'id_article', $boucles) . ',' .
+		    index_pile($id_boucle, 'id_breve', $boucles) .  ',' .
+		    index_pile($id_boucle, 'id_rubrique', $boucles) .',' .
+		    index_pile($id_boucle, 'id_syndic', $boucles) .
+		    ")")) .
+		  '] = 1; // invalideurs';
 	}
 
 	// Cas {1/3} {1,4} {n-2,1}...
@@ -181,7 +172,6 @@ function calculer_boucle($id_boucle, &$boucles) {
 	  $code_sep = ("'" . ereg_replace("'","\'",join('',$boucle->separateur)) . "'"); 
 
 	// gestion optimale des separateurs et des boucles constantes
-
 	$corps = $debut . 
 		((!$boucle->separateur) ? 
 			(($constant && !$debut) ? $return :
@@ -197,29 +187,27 @@ function calculer_boucle($id_boucle, &$boucles) {
 	if ($boucle->mode_partie)
 		$corps .= "\n		}\n";
 
-	$texte = '';
+	$init = '';
 
 	// Gestion de la hierarchie (voir inc-boucles.php3)
 	if ($boucle->hierarchie)
-		$texte .= "\n	".$boucle->hierarchie;
-
+		$init .= "\n	".$boucle->hierarchie;
 
 	// si le corps est une constante, ne pas appeler le serveur N fois!
-	if (ereg("^\(?'[^']*'\)?$",$corps)) {
-		// vide ?
-		if (($corps == "''") || ($corps == "('')")) {
+	if (ereg(CODE_MONOTONE,$corps, $r)) {
+		if (!$r[2]) {
 			if (!$boucle->numrows)
 				return 'return "";';
 			else
 				$corps = "";
 		} else {
 			$boucle->numrows = true;
-			$corps = "\n		".'for($x=$Numrows["'.$id_boucle.'"]["total"];$x>0;$x--)
+			$corps = "\n	".'for($x=$Numrows["'.$id_boucle.'"]["total"];$x>0;$x--)
 			$t0 .= ' . $corps .';';
 		}
 	} else {
 
-	$corps = '
+		$corps = '
 
 	// RESULTATS
 	while ($Pile[$SP] = @spip_abstract_fetch($result,"' .
@@ -229,7 +217,7 @@ function calculer_boucle($id_boucle, &$boucles) {
 
 		// Memoriser la langue avant la boucle pour la restituer apres
 		if ($lang_select) {
-			$texte .= "\n	\$old_lang = \$GLOBALS['spip_lang'];";
+			$init .= "\n	\$old_lang = \$GLOBALS['spip_lang'];";
 			$corps .= "\n	\$GLOBALS['spip_lang'] = \$old_lang;";
 		}
 	}
@@ -238,26 +226,21 @@ function calculer_boucle($id_boucle, &$boucles) {
 	// Requete
 	//
 
-	// hack critere recherche : ignorer la requete en cas de hash vide
-	// Recherche : recuperer les hash a partir de la chaine de recherche
-	if ($boucle->hash)
-		$init =  '
-	// RECHERCHE
-	list($rech_select, $rech_where) = prepare_recherche($GLOBALS["recherche"], "'.$boucle->primary.'", "'.$boucle->id_table.'");
-	if ($rech_select) ';
-
 	if (!$order = $boucle->order
 	AND !$order = $boucle->default_order)
 		$order = "''";
 
-	$init .= "\n\n	// REQUETE
+	$init .= $boucle->hash . 
+	  "\n\n	// REQUETE
 	\$result = spip_abstract_select(\n\t\tarray(\"". 
 		# En absence de champ c'est un decompte : 
 	  	# prendre la primary pour avoir qqch
 	  	# (COUNT incompatible avec le cas general
-		(($boucle->select) ? 
-			join("\",\n\t\t\"", array_unique($boucle->select)) :
-			$id_field) .
+		($boucle->select ? 
+		 join("\",\n\t\t\"", $boucle->select) :
+		 ($id_table . "." .
+		 (($p = strpos($primary, ',')) ?
+		  substr($primary, 0, $p) : $primary))) .
 		'"), # SELECT
 		array("' .
 		join('","', array_unique($boucle->from)) .
@@ -297,15 +280,18 @@ function calculer_boucle($id_boucle, &$boucles) {
 	//
 	// Conclusion et retour
 	//
-	$conclusion = "\n	@spip_abstract_free(\$result,'" .
-	  $boucle->sql_serveur . "');" .
+	$corps .= "\n	@spip_abstract_free(\$result,'" .
+	     $boucle->sql_serveur . "');";
 
+  }
+
+  return $init . $corps . 
 	## inserer le code d'envoi au debusqueur du resultat de la fonction
 	(($GLOBALS['var_mode_affiche'] != 'resultat') ? "" : "
 		boucle_debug_resultat('$id_boucle', 'resultat', \$t0);") .
 	  "\n	return \$t0;";
 
-	return $texte . $init . $corps . $conclusion;
+
 }
 
 
diff --git a/inc-criteres.php3 b/inc-criteres.php3
index fa11e7cce8..fa4a0df15a 100644
--- a/inc-criteres.php3
+++ b/inc-criteres.php3
@@ -94,18 +94,18 @@ function critere_recherche_dist($idb, &$boucles, $crit) {
 
 	$boucle = &$boucles[$idb];
 
-	$table = $boucle->id_table;	#articles
-	$id_table = 'id_'.preg_replace('/s$/', '', $table); 	#id_article
+	// Ne pas executer la requete en cas de hash vide
+	$boucle->hash =  '
+	// RECHERCHE
+	list($rech_select, $rech_where) = prepare_recherche($GLOBALS["recherche"], "'.$boucle->primary.'", "'.$boucle->id_table.'");
+	if ($rech_where) ';
 
-	// horrible hack du aux id_forum = spip_forum et id_article=spip_articleS
-	// en fait il faudrait la fonction inverse de table_objet()
-	$id = 'id_'.preg_replace('/s$/', '', $boucle->id_table);
-
-	$boucle->select[] = $boucle->id_table . '.' . $boucle->primary; # pour postgres, neuneu ici
-	$boucle->select[] = '$rech_select'; # pour les ... as points
+	$boucle->select[]= $boucle->id_table . '.' . $boucle->primary; # pour postgres, neuneu ici
+	$boucle->select[]= '$rech_select as points';
 
 	// et la recherche trouve
 	$boucle->where[] = '$rech_where';
+
 }
 
 // {inverse}
@@ -216,12 +216,12 @@ function critere_par_dist($idb, &$boucles, $crit) {
 		// tester si cette version de MySQL accepte la commande RAND()
 		// sinon faire un gloubi-boulga maison avec de la mayonnaise.
 		  if (spip_query("SELECT RAND()"))
-			$boucle->select[] = "RAND() AS alea";
+			$tri = "RAND()";
 		  else
-			$boucle->select[] = "MOD(".$boucle->id_table.'.'.$boucle->primary
-			." * UNIX_TIMESTAMP(),32767) & UNIX_TIMESTAMP() AS alea";
-
-		$order = "'alea'";
+			$tri = "MOD(".$boucle->id_table.'.'.$boucle->primary
+			  ." * UNIX_TIMESTAMP(),32767) & UNIX_TIMESTAMP()";
+		  $boucle->select[]= $tri . " AS alea";
+		  $order = "'alea'";
 		}
 
 	// par titre_mot
@@ -559,8 +559,7 @@ function calculer_critere_DEFAUT($idb, &$boucles, $crit) {
 		$where = "NOT ($where)";
 	      } else {
 			$boucle->default_order = 'rang';
-			$boucle->select[] =
-				"FIND_IN_SET($ct, \\\"'\" . " . $val . ' . "\'\\") AS rang';
+			$boucle->select[]= "FIND_IN_SET($ct, \\\"'\" . " . $val . ' . "\'\\") AS rang';
 	      }
 	    } else {
 		  if ($op == '==') $op = 'REGEXP';
-- 
GitLab