From bddbb03fc8815787996ff9d896ee85ced5622a58 Mon Sep 17 00:00:00 2001
From: Fil <fil@rezo.net>
Date: Sat, 11 Dec 2010 18:17:49 +0000
Subject: [PATCH] un peu de nettoyage et un debut de boucle POUR definie sous
 forme d'iterateur ; ce que je ne vois pas encore bien comment structurer,
 c'est la possibilite d'aller chercher un iterateur dans un plugin

---
 .gitattributes                      |   1 +
 ecrire/public/compiler.php          |  16 +++-
 ecrire/public/composer.php          |   2 +-
 ecrire/public/creer_boucle_pour.php |  28 +++++++
 ecrire/public/interfaces.php        |   2 +
 ecrire/public/iterateur.php         | 123 +++++++++++++++++++++++++++-
 6 files changed, 165 insertions(+), 7 deletions(-)
 create mode 100644 ecrire/public/creer_boucle_pour.php

diff --git a/.gitattributes b/.gitattributes
index 59c27ec16c..2997230f17 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -297,6 +297,7 @@ ecrire/plugins/get_infos.php -text
 ecrire/plugins/verifie_conformite.php -text
 ecrire/prive.php -text
 ecrire/public/aiguiller.php -text
+ecrire/public/creer_boucle_pour.php -text
 ecrire/public/decompiler.php -text
 ecrire/public/format_html.php -text
 ecrire/public/index.php -text
diff --git a/ecrire/public/compiler.php b/ecrire/public/compiler.php
index 35b7a0c778..e839b7c31b 100644
--- a/ecrire/public/compiler.php
+++ b/ecrire/public/compiler.php
@@ -242,7 +242,7 @@ function calculer_boucle_rec($id_boucle, &$boucles, $trace) {
 define('CODE_CORPS_BOUCLE', '%s
 	$t0 = "";
 	// REQUETE
-	$iter = new Iter("SQL");
+	$iter = new %s();
 	$iter->init( array(
 		"select"=>$select,
 		"from"=>$from,
@@ -401,7 +401,7 @@ function calculer_boucle_nonrec($id_boucle, &$boucles, $trace) {
 	. calculer_requete_sql($boucles[$id_boucle]);
 
 	$contexte = memoriser_contexte_compil($boucle);
-	$a = sprintf(CODE_CORPS_BOUCLE, $init, $contexte, $nums, $init_lang, $corps, $fin_lang, $trace);
+	$a = sprintf(CODE_CORPS_BOUCLE, $init, $boucle->iterateur, $contexte, $nums, $init_lang, $corps, $fin_lang, $trace);
 
 #	var_dump($a);exit;
 	return $a;
@@ -880,14 +880,22 @@ function compiler_squelette($squelette, $boucles, $nom, $descr, $sourcefile, $co
 			// si la table n'existe pas avec le connecteur par defaut, 
 			// c'est peut etre une table qui necessite son connecteur dedie fourni
 			// permet une ecriture allegee (GEO) -> (geo:GEO)
-			if (!$show AND $show=$trouver_table($type, strtolower($type)))
+			if (!$show
+			AND $show=$trouver_table($type, strtolower($type))) {
 				$boucles[$id]->sql_serveur = strtolower($type);
-			if ($show) {
+			}
+
+			if ($g = charger_fonction(
+			'creer_boucle_'.$boucle->type_requete, 'public', true)) {
+				$boucles[$id] = $g($boucle);
+
+			} else if ($show) {
 				$boucles[$id]->show = $show;
 				// recopie les infos les plus importantes
 				$boucles[$id]->primary = $show['key']["PRIMARY KEY"];
 				$boucles[$id]->id_table = $x = $show['id_table'];
 				$boucles[$id]->from[$x] = $nom_table = $show['table'];
+				$boucles[$id]->iterateur = 'IterSQL';
 
 				$boucles[$id]->descr = &$descr;
 				if ((!$boucles[$id]->jointures)
diff --git a/ecrire/public/composer.php b/ecrire/public/composer.php
index ecc139cdcc..1393a8fa92 100644
--- a/ecrire/public/composer.php
+++ b/ecrire/public/composer.php
@@ -12,12 +12,12 @@
 
 if (!defined("_ECRIRE_INC_VERSION")) return;
 
-include_spip('public/iterateur');
 include_spip('inc/texte');
 include_spip('inc/documents');
 include_spip('inc/distant');
 include_spip('inc/rubriques'); # pour calcul_branche (cf critere branche)
 include_spip('inc/acces'); // Gestion des acces pour ical
+include_spip('public/iterateur');
 include_spip('public/interfaces');
 include_spip('public/quete');
 
diff --git a/ecrire/public/creer_boucle_pour.php b/ecrire/public/creer_boucle_pour.php
new file mode 100644
index 0000000000..cd5a559663
--- /dev/null
+++ b/ecrire/public/creer_boucle_pour.php
@@ -0,0 +1,28 @@
+<?php
+
+/***************************************************************************\
+ *  SPIP, Systeme de publication pour l'internet                           *
+ *                                                                         *
+ *  Copyright (c) 2001-2010                                                *
+ *  Arnaud Martin, Antoine Pitrou, Philippe Riviere, Emmanuel Saint-James  *
+ *                                                                         *
+ *  Ce programme est un logiciel libre distribue sous licence GNU/GPL.     *
+ *  Pour plus de details voir le fichier COPYING.txt ou l'aide en ligne.   *
+\***************************************************************************/
+
+//
+// creer une boucle sur un iterateur POUR
+// definir les "champs" existants pour le compilo
+//
+function public_creer_boucle_POUR_dist($b) {
+	$b->iterateur = 'IterPOUR'; # designe la classe d'iterateur
+	$b->show = array(
+		'field' => array(
+			'tableau' => 'ARRAY',
+			'cle' => 'STRING',
+			'valeur' => 'STRING',
+		)
+	);
+	return $b;
+}
+
diff --git a/ecrire/public/interfaces.php b/ecrire/public/interfaces.php
index b1da7b90a1..002870b5ae 100644
--- a/ecrire/public/interfaces.php
+++ b/ecrire/public/interfaces.php
@@ -83,6 +83,8 @@ class Boucle {
 
 	var $modificateur = array(); // table pour stocker les modificateurs de boucle tels que tout, plat ..., utilisable par les plugins egalement
 
+	var $iterateur = ''; // type d'iterateur
+
 	// obsoletes, conserves provisoirement pour compatibilite
 	var $tout = false;
 	var $plat = false;
diff --git a/ecrire/public/iterateur.php b/ecrire/public/iterateur.php
index 419b470d49..2ce263bc19 100644
--- a/ecrire/public/iterateur.php
+++ b/ecrire/public/iterateur.php
@@ -24,10 +24,31 @@ class Iter {
 
 	private $result = false;
 
+	public function Iter() {
+		$this->type = '??';
+	}
 
-	public function Iter($type) {
-		$this->type = $type;
+	/*
+	 * array command: les commandes d'initialisation
+	 * array info: les infos sur le squelette
+	 */
+	public function init($command, $info=array()) {
+		$this->command = $command;
+		$this->info = $info;
 	}
+	public function seek($n=0, $continue=null) {}
+	public function next() {}
+	public function free() {}
+	public function count() {}
+}
+
+class IterSQL extends Iter {
+	var $ok = false;
+	var $type;
+	var $command;
+	var $info;
+
+	private $result = false;
 
 	private function select() {
 		$v = &$this->command;
@@ -40,6 +61,7 @@ class Iter {
 	 * array info: les infos sur le squelette
 	 */
 	public function init($command, $info=array()) {
+		$this->type='SQL';
 		$this->command = $command;
 		$this->info = $info;
 		$this->select();
@@ -64,6 +86,103 @@ class Iter {
 	}
 }
 
+class IterPOUR extends Iter {
+	var $ok = false;
+	var $type;
+	var $command;
+	var $info;
+
+	var $tableau = array();
+	var $filtre = array();
+
+	private $result = false;
+
+	/*
+	 * array command: les commandes d'initialisation
+	 * array info: les infos sur le squelette
+	 */
+	public function init($command, $info=array()) {
+		$this->type='POUR';
+		$this->command = $command;
+		$this->info = $info;
+
+		// les commandes connues pour l'iterateur POUR
+		// sont : tableau=#ARRAY ; cle=...; valeur=...
+		if (is_array($this->command['where']))
+		foreach ($this->command['where'] as $k => $com) {
+			switch($com[1]) {
+				case 'tableau':
+					if ($com[0] !== '=') {
+						// erreur
+					}
+					# sql_quote a l'envers : pas propre...
+					$x = null;
+					eval ('$x = '.str_replace('\"', '"', $com[2]).';');
+					if (is_array($x) OR is_array($x = @unserialize($x))) {
+						$this->tableau = $x;
+						$this->ok = true;
+					}
+					else
+						{
+							// erreur
+						}
+					break;
+				case 'cle':
+				case 'valeur':
+					unset($op);
+					if ($com[0] == 'REGEXP')
+						$this->filtre[] = 'preg_match("/". '.str_replace('\"', '"', $com[2]).'."/", $'.$com[1].')';
+					else if ($com[0] == '=')
+						$op = '==';
+					else if (in_array($com[0], array('<','<=', '>', '>=')))
+						$op = $com[0];
+
+					if ($op)
+						$this->filtre[] = '$'.$com[1].$op.str_replace('\"', '"', $com[2]);
+
+					break;
+			}
+
+		}
+
+		// Appliquer les filtres sur (cle,valeur)
+		if ($this->filtre) {
+			$filtre = create_function('$cle,$valeur', $b = 'return ('.join(') AND (', $this->filtre).');');
+			#var_dump($b);
+			foreach($this->tableau as $cle=>$valeur) {
+				if (!$filtre($cle,$valeur))
+					unset($this->tableau[$cle]);
+			}
+		}
+
+		// critere {2,7}
+		if ($this->command['limit']) {
+			$limit = explode(',',$this->command['limit']);
+			$this->tableau = array_slice($this->tableau,
+				$limit[0],$limit[1],true);
+		}
+
+
+		reset($this->tableau);
+		#var_dump($this->tableau);
+	}
+	public function seek($n=0, $continue=null) {
+		reset($this->tableau);
+		while($n-->0 AND list($cle, $valeur) = each($this->tableau)){};
+		return true;
+	}
+	public function next(){
+		if (list($cle, $valeur) = each($this->tableau)) {
+			return array('cle' => $cle, 'valeur' => $valeur);
+		}
+	}
+	public function free(){
+	}
+	public function count() {
+		return count($this->tableau);
+	}
+}
+
 
 
 ?>
-- 
GitLab