Valider 084372dc rédigé par Fil's avatar Fil
Parcourir les fichiers

reecriture de tous les iterateurs sur le mode de la class Iterator de PHP

http://php.net/manual/fr/class.iterator.php

il devient possible de faire :

{{{
<?php
$s = new IterSQL(

array (
    'select' => 
    array (
      0 => 'articles.date',
      1 => 'articles.id_article',
      2 => 'articles.id_rubrique',
      3 => 'articles.titre',
      5 => 'articles.descriptif',
      6 => 'articles.chapo',
      7 => 'articles.lang',
    ),
    'from' => 
    array (
      'articles' => 'spip_articles',
    ),
    'type' => 
    array (
    ),
    'where' => 
    array (
      0 => 
      array (
        0 => '=',
        1 => 'articles.statut',
        2 => '\'publie\'',
      ),
      1 => '1=1',
    ),
    'join' => 
    array (
    ),
    'groupby' => 
    array (
    ),
    'orderby' => 
    array (
      0 => 'articles.date DESC',
    ),
    'limit' => '0,1',
    'having' => 
    array (
    ),
    'table' => 'articles',
    'id' => '_articles_recents',
    'connect' => '',
  )

);

foreach ($s as $k=>$v) {
	var_dump($v);
}

?>
}}}

mais aussi :

{{{
<?php

$s = new IterDATA(
	array (
	'source' => 'http://rezo.net/backend/',
	'sourcemode' => 'rss'
  )
);

foreach ($s as $k=>$v) {
	var_dump($v);
}

?>
}}}
parent 403a3446
Chargement en cours
Chargement en cours
Chargement en cours
Chargement en cours
+4 −4
Numéro de ligne d'origine Numéro de ligne de diff Ligne de diff
@@ -362,7 +362,7 @@ define('CODE_CORPS_BOUCLE', '%s
		%s,
		array(%s)
	);
	if ($iter->ok) {
	if ($iter->valid()) {
	%s%s$SP++;
	// RESULTATS
	%s
@@ -472,7 +472,7 @@ function calculer_boucle_nonrec($id_boucle, &$boucles, $trace) {
			$boucle->numrows = true;
			$corps = "\n\t\$t0 = str_repeat($corps, \$Numrows['$id_boucle']['total']);";
		}
	} else $corps = "while (\$Pile[\$SP] = \$iter->next()) {\n$corps\n	}"; 
	} else $corps = "while (\$Pile[\$SP]=\$iter->fetch()) {\n$corps\n	}"; 

	$count = '';
	if (!$boucle->select) {
@@ -490,7 +490,7 @@ function calculer_boucle_nonrec($id_boucle, &$boucles, $trace) {
	if ($boucle->numrows OR $boucle->mode_partie) {
		if ($count == 'count(*)')
			$count = "array_shift(\$iter->next())";
		else $count = "\$iter->count()";
		else $count = "\$iter->total()";
		$nums .= "\$Numrows['$id_boucle']['total'] = @intval($count);"
		. $boucle->mode_partie
		. "\n\t";
@@ -523,7 +523,7 @@ function calculer_boucle_nonrec($id_boucle, &$boucles, $trace) {
		)';
			break;

		case 'IterPOUR':
		case 'IterDATA':
		case 'IterENUM':
			$command = 'array("where" => $where, "source"=>$source, "sourcemode"=>$sourcemode, "limit" => $limit)';
			break;
+1 −1
Numéro de ligne d'origine Numéro de ligne de diff Ligne de diff
@@ -15,7 +15,7 @@
// annonce au compilo les "champs" disponibles
//
function public_creer_boucle_DATA_dist($b) {
	$b->iterateur = 'IterPOUR'; # designe la classe d'iterateur
	$b->iterateur = 'IterDATA'; # designe la classe d'iterateur
	$b->show = array(
		'field' => array(
			'cle' => 'STRING',
+1 −0
Numéro de ligne d'origine Numéro de ligne de diff Ligne de diff
@@ -18,6 +18,7 @@ function public_creer_boucle_ENUM_dist($b) {
	$b->iterateur = 'IterENUM'; # designe la classe d'iterateur
	$b->show = array(
		'field' => array(
			'cle' => 'STRING',
			'valeur' => 'STRING',
		)
	);
+1 −1
Numéro de ligne d'origine Numéro de ligne de diff Ligne de diff
@@ -15,7 +15,7 @@
// annonce au compilo les "champs" disponibles
//
function public_creer_boucle_POUR_dist($b) {
	$b->iterateur = 'IterPOUR'; # designe la classe d'iterateur
	$b->iterateur = 'IterDATA'; # designe la classe d'iterateur
	$b->show = array(
		'field' => array(
			'tableau' => 'ARRAY',
+138 −93
Numéro de ligne d'origine Numéro de ligne de diff Ligne de diff
@@ -16,91 +16,108 @@
// Iterateur SQL
//

class Iter {
	var $ok = false;
	var $type;
	var $command;
	var $info;

	private $result = false;

	/*
	 * array command: les commandes d'initialisation
	 * array info: les infos sur le squelette
	 */
	public function Iter($command, $info=array()) {
		$this->type = '??';
		$this->command = $command;
		$this->info = $info;
class Iter implements Iterator {
	# http://php.net/manual/fr/class.iterator.php
	public function __construct() {} // initialise
	public function rewind() {} // revient au depart
	public function valid() {} // avons-nous un element
	public function current() {} // quel est sa valeur
	public function key() {} // quelle est sa cle
	public function next() {} // avancer d'un cran

	# Iter SPIP
	var $type; # type de l'iterateur
	var $command; # parametres de l'iterateur
	var $info; # infos de compilateur

	// avancer en position n
	public function seek($n=0, $continue=null) {
		$this->rewind();
		while($n-->0 AND $this->valid()) $this->next();
		return true;
	}
	public function fetch() {
		if ($this->valid()) {
			$r = array('cle' => $this->key(), 'valeur' => $this->current());
			$this->next();
		} else
			$r = false;
		return $r;
	}
	public function seek($n=0, $continue=null) {}
	public function next() {}
	public function free() {}
	public function count() {}
	public function free() {} // liberer la ressource
	public function total() {} // #TOTAL_BOUCLE
}

class IterSQL extends Iter {
	var $ok = false;
	var $type;
	var $command;
	var $info;

	private $result = false;
	private $sqlresult = false; # ressource sql
	private $row = null; # row sql courante

	private function select() {
		$v = &$this->command;
		$this->result = calculer_select($v['select'], $v['from'], $v['type'], $v['where'], $v['join'], $v['groupby'], $v['orderby'], $v['limit'], $v['having'], $v['table'], $v['id'], $v['connect'], $this->info);
		$this->ok = !!$this->result;
		$this->sqlresult = calculer_select($v['select'], $v['from'], $v['type'], $v['where'], $v['join'], $v['groupby'], $v['orderby'], $v['limit'], $v['having'], $v['table'], $v['id'], $v['connect'], $this->info);
		$this->ok = !!$this->sqlresult;
		if ($this->ok)
			$this->row = sql_fetch($this->sqlresult, $this->command['connect']);
	}

	/*
	 * array command: les commandes d'initialisation
	 * array info: les infos sur le squelette
	 */
	public function IterSQL($command, $info=array()) {
	public function __construct($command, $info=array()) {
		$this->type='SQL';
		$this->command = $command;
		$this->info = $info;
		$this->select();
	}
	public function rewind() {
		return $this->seek(0);
	}
	public function valid() {
		return is_array($this->row);
	}
	public function current() {
		return $this->row;
	}
	public function seek($n=0, $continue=null) {
		# SQLite ne sait pas seek(), il faut relancer la query
		if (!$a = sql_seek($this->result, $this->command['connect'], $n, $continue)) {
		if (!$a = sql_seek($this->sqlresult, $this->command['connect'], $n, $continue)) {
			$this->free();
			$this->select();
			return true; # ??
			return true;
		}
		return $a;
	}
	public function next(){
		return sql_fetch($this->result, $this->command['connect']);
		$this->row = sql_fetch($this->sqlresult, $this->command['connect']);
	}
	public function fetch(){
		if ($this->valid()) {
			$r = $this->current();
			$this->next();
		} else
			$r = false;
		return $r;
	}
	public function free(){
		return sql_free($this->result, $this->command['connect']);
		return sql_free($this->sqlresult, $this->command['connect']);
	}
	public function count() {
		return sql_count($this->result, $this->command['connect']);
	public function total() {
		return sql_count($this->sqlresult, $this->command['connect']);
	}
}

class IterENUM extends Iter {
	var $ok = true;
	var $type;
	var $command;
	var $info;

	var $n = 0;
	var $max = 1000000;

	var $filtre = array();

	private $result = false;

	/*
	 * array command: les commandes d'initialisation
	 * array info: les infos sur le squelette
	 */
	public function IterENUM($command, $info=array()) {
	private $n = 0;
	private $pos = 0;
	private $start = 0;
	private $offset = 0;
	private $total = 1000000;
	private $max = 1000000;
	private $filtre = array();

	public function __construct($command=array(), $info=array()) {
		$this->type='ENUM';
		$this->command = $command;
		$this->info = $info;
@@ -128,60 +145,82 @@ class IterENUM extends Iter {
		// critere {2,7}
		if ($this->command['limit']) {
			$limit = explode(',',$this->command['limit']);
			$this->n = $limit[0];
			$this->max = $limit[0]+$limit[1]-1;
			$this->offset = $limit[0];
			$this->total = $limit[1];
		}


		// Appliquer les filtres sur (valeur)
		if ($this->filtre) {
			$this->filtre = create_function('$valeur', $b = 'return ('.join(') AND (', $this->filtre).');');
			$this->filtre = create_function('$cle,$valeur', $b = 'return ('.join(') AND (', $this->filtre).');');
		}

	}
	public function seek($n=0, $continue=null) {
		$this->n = $n;
		return true;
	public function rewind() {
		$this->n = $this->start-1;
		$this->pos = -1;
		for ($i=0; $i<=$this->offset; $i++) {
			$this->next(); # pour filtre
			$this->pos=0;
		}
	}
	public function valid(){
		return
			$this->n <= $this->max
			AND $this->pos < $this->total;
	}
	public function current() {
		return $this->n;
	}
	public function key() {
		return $this->pos;
	}
	public function next() {
		$this->pos++;
		$this->n++;
		if ($f = $this->filtre) {
			while (
			$this->n < $this->max
			AND !$f($a = $this->n++)){};
		} else
			$a = $this->n++;
			$this->n <= $this->max
			AND !$f($this->pos,$this->n)) {
				$this->n++;
			}
		}
	}

		if ($this->n <= 1+$this->max)
			return array('valeur' => $a);
	public function seek($n=0, $continue=null) {
		$this->n = $this->start-1;
		$this->pos = -1;
		for ($i=0; $i<=$n; $i++) {
			$this->next(); # pour filtre
		}
	public function free(){
		return true;
	}
	public function count() {
		return $this->max;
	public function total() {
		return $this->total;
	}
}


class IterPOUR extends Iter {
	var $ok = false;
	var $type;
	var $command;
	var $info;

	var $tableau = array();
	var $filtre = array();
class IterDATA extends Iter {
	private $tableau = array();
	private $filtre = array();
	private $cle = null;
	private $valeur = null;

	private $result = false;

	/*
	 * array command: les commandes d'initialisation
	 * array info: les infos sur le squelette
	 */
	public function IterPOUR($command, $info=array()) {
		$this->type='POUR';
	public function __construct($command, $info=array()) {
		$this->type='DATA';
		$this->command = $command;
		$this->info = $info;

		$this->select($command);
	}

	public function rewind() {
		reset($this->tableau);
		list($this->cle, $this->valeur) = each($this->tableau);
	}

	private function select($command) {
		// les commandes connues pour l'iterateur POUR
		// sont : tableau=#ARRAY ; cle=...; valeur=...
		// source URL
@@ -305,23 +344,29 @@ class IterPOUR extends Iter {
				$limit[0],$limit[1],true);
		}


		reset($this->tableau);
		$this->rewind();
		#var_dump($this->tableau);
	}
	public function seek($n=0, $continue=null) {
		reset($this->tableau);
		while($n-->0 AND list($cle, $valeur) = each($this->tableau)){};
		$this->rewind();
		while($n-->0
		AND list($this->cle, $this->valeur) = each($this->tableau)){};
		return true;
	}
	public function next(){
		if (list($cle, $valeur) = each($this->tableau)) {
			return array('cle' => $cle, 'valeur' => $valeur);
	public function valid(){
		return !is_null($this->cle);
	}
	public function current() {
		return $this->valeur;
	}
	public function free(){
	public function key() {
		return $this->cle;
	}
	public function next(){
		if ($this->valid())
			list($this->cle, $this->valeur) = each($this->tableau);
	}
	public function count() {
	public function total() {
		return count($this->tableau);
	}
}