178 lines
		
	
	
		
			4.7 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
			
		
		
	
	
			178 lines
		
	
	
		
			4.7 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
<?php
 | 
						|
namespace nur\m\base;
 | 
						|
 | 
						|
use nur\b\coll\BaseArray;
 | 
						|
use nur\iter;
 | 
						|
use nur\m\IRowIterator;
 | 
						|
 | 
						|
abstract class AbstractRowIterator extends BaseArray implements IRowIterator {
 | 
						|
  /**
 | 
						|
   * @var bool faut-il réinitialiser l'itérateur après l'appel des méthodes
 | 
						|
   * {@link first()} et {@link one()}
 | 
						|
   */
 | 
						|
  const AUTO_REWIND = true;
 | 
						|
 | 
						|
  private $setup = false;
 | 
						|
  private $valid = false;
 | 
						|
  private $toredown = true;
 | 
						|
 | 
						|
  private $index = -1;
 | 
						|
  private $key = null;
 | 
						|
  private $row = null;
 | 
						|
 | 
						|
  function __construct() {
 | 
						|
    # ne pas appeler le constructeur parent, $data sera initialisé dans les
 | 
						|
    # classes dérivées
 | 
						|
    #parent::__construct(null);
 | 
						|
  }
 | 
						|
 | 
						|
  /** initialiser cet objet et les resources dont il a besoin */
 | 
						|
  protected function _setup(): void {}
 | 
						|
 | 
						|
  /**
 | 
						|
   * retourner l'élément suivant, ou false s'il n'y a plus d'éléments
 | 
						|
   * disponibles
 | 
						|
   */
 | 
						|
  abstract protected function _next();
 | 
						|
 | 
						|
  /**
 | 
						|
   * corriger le cas échéant un élément avant de le présenter à l'utilisateur.
 | 
						|
   * si $key est initialisé, alors cette valeur sera retournée en tant que clé
 | 
						|
   * à l'utilisateur
 | 
						|
   */
 | 
						|
  protected function _cook(&$row, &$key): void {}
 | 
						|
 | 
						|
  /** retourner la clé associée à l'élément courant */
 | 
						|
  function _key() {
 | 
						|
    $key = $this->key;
 | 
						|
    return $key !== null? $key: $this->index;
 | 
						|
  }
 | 
						|
 | 
						|
  /** retourner l'élément courant */
 | 
						|
  function _current() { return $this->row; }
 | 
						|
 | 
						|
  /** fermer toutes les resources utilisées par cet objet */
 | 
						|
  protected function _teardown(): void {}
 | 
						|
 | 
						|
  /**
 | 
						|
   * méthode appelée avant l'initialisation de l'objet par {@link _setup()}.
 | 
						|
   *
 | 
						|
   * Cette méthode est prévue pour être surchargée par l'utilisateur
 | 
						|
   */
 | 
						|
  protected function beforeSetup(): void {}
 | 
						|
 | 
						|
  /**
 | 
						|
   * méthode appelée avant le début de l'itération: après l'initialisation de
 | 
						|
   * l'objet par {@link _setup()} mais avant que le premier élément soit
 | 
						|
   * retourné par {@link _next()}.
 | 
						|
   *
 | 
						|
   * Cette méthode est prévue pour être surchargée par l'utilisateur
 | 
						|
   */
 | 
						|
  protected function beforeIter(): void {}
 | 
						|
 | 
						|
  /**
 | 
						|
   * méthode appelée pour corriger le cas échéant les lignes retournées.
 | 
						|
   *
 | 
						|
   * Cette méthode est prévue pour être surchargée par l'utilisateur
 | 
						|
   */
 | 
						|
  protected function cook(&$row, &$key): void {}
 | 
						|
 | 
						|
  function rewind() {
 | 
						|
    if ($this->setup) {
 | 
						|
      if (!$this->toredown) $this->_teardown();
 | 
						|
      $this->setup = false;
 | 
						|
      $this->valid = false;
 | 
						|
      $this->toredown = true;
 | 
						|
      $this->index = -1;
 | 
						|
      $this->key = null;
 | 
						|
      $this->row = null;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  function next() {
 | 
						|
    if ($this->toredown) return;
 | 
						|
    $key = null;
 | 
						|
    $row = $this->_next();
 | 
						|
    if ($row !== false) {
 | 
						|
      $this->key = null;
 | 
						|
      $this->_cook($row, $key);
 | 
						|
      $this->cook($row, $key);
 | 
						|
      $this->index++;
 | 
						|
      $this->key = $key;
 | 
						|
      $this->row = $row;
 | 
						|
      $this->valid = true;
 | 
						|
    } else {
 | 
						|
      $this->_teardown();
 | 
						|
      $this->valid = false;
 | 
						|
      $this->toredown = true;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  function valid() {
 | 
						|
    if (!$this->setup) {
 | 
						|
      $this->beforeSetup();
 | 
						|
      $this->_setup();
 | 
						|
      $this->setup = true;
 | 
						|
      $this->toredown = false;
 | 
						|
      $this->beforeIter();
 | 
						|
      $this->next();
 | 
						|
    }
 | 
						|
    return $this->valid;
 | 
						|
  }
 | 
						|
 | 
						|
  function isClosed(): bool {
 | 
						|
    return $this->toredown;
 | 
						|
  }
 | 
						|
 | 
						|
  function all(): array {
 | 
						|
    return iterator_to_array($this, true);
 | 
						|
  }
 | 
						|
 | 
						|
  function allVals(?string $name=null): array {
 | 
						|
    return rows::vals($this->all(), $name);
 | 
						|
  }
 | 
						|
 | 
						|
  function first($default=null) {
 | 
						|
    return iter::first($this, $default);
 | 
						|
  }
 | 
						|
 | 
						|
  function firstVal(?string $name=null, $default=null) {
 | 
						|
    return rows::val($this->first(), $name, $default);
 | 
						|
  }
 | 
						|
 | 
						|
  function numRows(): int {
 | 
						|
    return $this->first()["num_rows"];
 | 
						|
  }
 | 
						|
 | 
						|
  function insertId(): int {
 | 
						|
    return $this->first()["insert_id"];
 | 
						|
  }
 | 
						|
 | 
						|
  function one($default=null, ?bool $rewind=null): array {
 | 
						|
    if ($rewind === null) $rewind = static::AUTO_REWIND;
 | 
						|
    return iter::one($this, $default, $rewind);
 | 
						|
  }
 | 
						|
 | 
						|
  function peek($default=null, ?bool $rewind=false): array {
 | 
						|
    if ($rewind === null) $rewind = static::AUTO_REWIND;
 | 
						|
    return iter::peek($this, $default, $rewind);
 | 
						|
  }
 | 
						|
 | 
						|
  # BaseArray
 | 
						|
  function has($key): bool { return $this->_has($key); }
 | 
						|
  function &get($key, $default=null) { return $this->_get($key, $default); }
 | 
						|
  function set($key, $value): self { return $this->_set($key, $value); }
 | 
						|
  function add($value): self { return $this->_set(null, $value); }
 | 
						|
  function del($key): self { return $this->_del($key); }
 | 
						|
 | 
						|
  # Modèle d'implémentation dans une classe dérivée:
 | 
						|
  ## Iterator
 | 
						|
  #function key(): KeyType { return $this->_key(); }
 | 
						|
  #function current(): ?ValueType { return $this->_current(); }
 | 
						|
 | 
						|
  # Par exemple, pour un iterateur générique, on aurait:
 | 
						|
  ## Iterator
 | 
						|
  #function key() { return $this->_key(); }
 | 
						|
  #function current() { return $this->_current(); }
 | 
						|
}
 |