spip_nursit/ecrire/iterateur/sql.php

223 lines
4.5 KiB
PHP
Raw Permalink Normal View History

2023-06-01 15:30:12 +00:00
<?php
/***************************************************************************\
* SPIP, Systeme de publication pour l'internet *
* *
* Copyright (c) 2001-2019 *
* 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. *
\***************************************************************************/
/**
* Gestion de l'itérateur SQL
*
* @package SPIP\Core\Iterateur\SQL
**/
if (!defined('_ECRIRE_INC_VERSION')) {
return;
}
/**
* Itérateur SQL
*
* Permet d'itérer sur des données en base de données
*/
class IterateurSQL implements Iterator {
/**
* ressource sql
*
* @var resource|bool
*/
protected $sqlresult = false;
/**
* row sql courante
*
* @var array|null
*/
protected $row = null;
protected $firstseek = false;
/**
* Erreur presente ?
*
* @var bool
**/
public $err = false;
/**
* Calcul du total des elements
*
* @var int|null
**/
public $total = null;
/**
* selectionner les donnees, ie faire la requete SQL
*
* @return void
*/
protected function select() {
$this->row = null;
$v = &$this->command;
$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->err = !$this->sqlresult;
$this->firstseek = false;
$this->pos = -1;
// pas d'init a priori, le calcul ne sera fait qu'en cas de besoin (provoque une double requete souvent inutile en sqlite)
//$this->total = $this->count();
}
/*
* array command: les commandes d'initialisation
* array info: les infos sur le squelette
*/
public function __construct($command, $info = array()) {
$this->type = 'SQL';
$this->command = $command;
$this->info = $info;
$this->select();
}
/**
* Rembobiner
*
* @return bool
*/
public function rewind() {
return ($this->pos > 0)
? $this->seek(0)
: true;
}
/**
* Verifier l'etat de l'iterateur
*
* @return bool
*/
public function valid() {
if ($this->err) {
return false;
}
if (!$this->firstseek) {
$this->next();
}
return is_array($this->row);
}
/**
* Valeurs sur la position courante
*
* @return array
*/
public function current() {
return $this->row;
}
public function key() {
return $this->pos;
}
/**
* Sauter a une position absolue
*
* @param int $n
* @param null|string $continue
* @return bool
*/
public function seek($n = 0, $continue = null) {
if (!sql_seek($this->sqlresult, $n, $this->command['connect'], $continue)) {
// SQLite ne sait pas seek(), il faut relancer la query
// si la position courante est apres la position visee
// il faut relancer la requete
if ($this->pos > $n) {
$this->free();
$this->select();
$this->valid();
}
// et utiliser la methode par defaut pour se deplacer au bon endroit
// (sera fait en cas d'echec de cette fonction)
return false;
}
$this->row = sql_fetch($this->sqlresult, $this->command['connect']);
$this->pos = min($n, $this->count());
return true;
}
/**
* Avancer d'un cran
*
* @return void
*/
public function next() {
$this->row = sql_fetch($this->sqlresult, $this->command['connect']);
$this->pos++;
$this->firstseek |= true;
}
/**
* Avancer et retourner les donnees pour le nouvel element
*
* @return array|bool|null
*/
public function fetch() {
if ($this->valid()) {
$r = $this->current();
$this->next();
} else {
$r = false;
}
return $r;
}
/**
* liberer les ressources
*
* @return bool
*/
public function free() {
if (!$this->sqlresult) {
return true;
}
$a = sql_free($this->sqlresult, $this->command['connect']);
$this->sqlresult = null;
return $a;
}
/**
* Compter le nombre de resultats
*
* @return int
*/
public function count() {
if (is_null($this->total)) {
if (!$this->sqlresult) {
$this->total = 0;
} else {
# cas count(*)
if (in_array('count(*)', $this->command['select'])) {
$this->valid();
$s = $this->current();
$this->total = $s['count(*)'];
} else {
$this->total = sql_count($this->sqlresult, $this->command['connect']);
}
}
}
return $this->total;
}
}