195 lines
		
	
	
		
			5.1 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
			
		
		
	
	
			195 lines
		
	
	
		
			5.1 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
<?php
 | 
						|
namespace nur\v\bs3\vc;
 | 
						|
 | 
						|
use Iterator;
 | 
						|
use nur\A;
 | 
						|
use nur\b\coll\BaseArray;
 | 
						|
use nur\b\params\IParametrable;
 | 
						|
use nur\b\params\Tparametrable1;
 | 
						|
use nur\b\ValueException;
 | 
						|
use nur\data\types\md_utils;
 | 
						|
use nur\data\types\Metadata;
 | 
						|
use nur\func;
 | 
						|
use nur\iter;
 | 
						|
use nur\v\base\ComponentPrintable;
 | 
						|
use Traversable;
 | 
						|
 | 
						|
class _CItemList extends ComponentPrintable implements IParametrable {
 | 
						|
  use Tparametrable1;
 | 
						|
 | 
						|
  /** @var ?array schéma des informations supplémentaires */
 | 
						|
  const DATA_SCHEMA = null;
 | 
						|
 | 
						|
  const SHOW_EMPTY = null;
 | 
						|
  const AUTOPRINT = null;
 | 
						|
 | 
						|
  const PARAMETRABLE_PARAMS_SCHEMA = [
 | 
						|
    "items" => ["?iterable", null, "source des éléments à afficher"],
 | 
						|
    "filter_func" => ["?callable", null, "fonction permettant de filtrer les éléments à afficher"],
 | 
						|
    "map_func" => ["?callable", null, "fonction permettant de mapper les éléments"],
 | 
						|
    "show_empty" => ["bool", false, "afficher même s'il n'y a pas d'éléments?"],
 | 
						|
    "autoprint" => ["bool", false, "faut-il afficher automatiquement les éléments"],
 | 
						|
    "data" => ["?array", null, "donnés supplémentaires utilisées pour l'affichage"],
 | 
						|
  ];
 | 
						|
 | 
						|
  function __construct(?iterable $items=null, ?array $params=null) {
 | 
						|
    self::set_parametrable_params_defaults($params, [
 | 
						|
      "show_empty" => static::SHOW_EMPTY,
 | 
						|
      "autoprint" => static::AUTOPRINT,
 | 
						|
    ]);
 | 
						|
    A::set_nn($params, "items", $items);
 | 
						|
    [$params, $data] = $this->splitParametrableParams($params);
 | 
						|
    A::merge($params["data"], $data);
 | 
						|
    $this->initParametrableParams($params);
 | 
						|
    if ($this->ppItems === null) $this->ppItems = $this->ITEMS();
 | 
						|
    if ($this->ppAutoprint) $this->print();
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * retourner la liste des éléments à afficher si elle n'est pas fournie par
 | 
						|
   * l'utilisateur
 | 
						|
   */
 | 
						|
  protected function ITEMS(): ?iterable {
 | 
						|
    return null;
 | 
						|
  }
 | 
						|
 | 
						|
  /** @var ?iterable */
 | 
						|
  protected $ppItems;
 | 
						|
 | 
						|
  /** @var array */
 | 
						|
  protected $filterCtx;
 | 
						|
 | 
						|
  function pp_setFilterFunc(?callable $filterFunc): void {
 | 
						|
    if ($filterFunc === null) $this->filterCtx = null;
 | 
						|
    else $this->filterCtx = func::_prepare($filterFunc);
 | 
						|
  }
 | 
						|
 | 
						|
  /** @var array */
 | 
						|
  protected $mapCtx;
 | 
						|
 | 
						|
  function pp_setMapFunc(?callable $mapFunc): void {
 | 
						|
    if ($mapFunc === null) $this->mapCtx = null;
 | 
						|
    else $this->mapCtx = func::_prepare($mapFunc);
 | 
						|
  }
 | 
						|
 | 
						|
  /** @var bool */
 | 
						|
  protected $ppShowEmpty;
 | 
						|
 | 
						|
  /** @var bool */
 | 
						|
  protected $ppAutoprint;
 | 
						|
 | 
						|
  /** @var Metadata */
 | 
						|
  private $dataSchema;
 | 
						|
 | 
						|
  /** @var mixed données supplémentaires utilisées pour l'affichage */
 | 
						|
  protected $data;
 | 
						|
 | 
						|
  function pp_setData($data): self {
 | 
						|
    $dataSchema = static::DATA_SCHEMA;
 | 
						|
    if ($dataSchema !== null && $this->dataSchema === null) {
 | 
						|
      md_utils::ensure_md($this->dataSchema, $dataSchema);
 | 
						|
    }
 | 
						|
    if ($this->dataSchema !== null) {
 | 
						|
      $this->dataSchema->ensureSchema($data);
 | 
						|
    }
 | 
						|
    $this->data = $data;
 | 
						|
    return $this;
 | 
						|
  }
 | 
						|
 | 
						|
  /** @var iterable */
 | 
						|
  protected $items;
 | 
						|
 | 
						|
  /**
 | 
						|
   * construire la liste brute effective des éléments. le filtrage et le mapping
 | 
						|
   * se fait dans print()
 | 
						|
   */
 | 
						|
  protected function buildItems(): void {
 | 
						|
    $this->items = $this->ppItems;
 | 
						|
  }
 | 
						|
 | 
						|
  function haveItems(): bool {
 | 
						|
    if ($this->items === null) {
 | 
						|
      return false;
 | 
						|
    } elseif ($this->items instanceof Traversable) {
 | 
						|
      # on doit forcer l'énumération pour savoir s'il y a des éléments
 | 
						|
      $this->items = iterator_to_array($this->items);
 | 
						|
    }
 | 
						|
    return boolval($this->items);
 | 
						|
  }
 | 
						|
 | 
						|
  protected function rewindItems(): bool {
 | 
						|
    return iter::rewind($this->items);
 | 
						|
  }
 | 
						|
 | 
						|
  protected function validItem(): bool {
 | 
						|
    return iter::valid($this->items);
 | 
						|
  }
 | 
						|
 | 
						|
  protected function currentItem(&$key=null) {
 | 
						|
    return iter::current($this->items, $key);
 | 
						|
  }
 | 
						|
 | 
						|
  protected function nextItem(): void {
 | 
						|
    iter::next($this->items);
 | 
						|
  }
 | 
						|
 | 
						|
  protected function ensureArray($item): array {
 | 
						|
    if (!is_array($item)) {
 | 
						|
      if ($item instanceof BaseArray) $item = $item->array();
 | 
						|
      elseif ($item instanceof Iterator) $item = iterator_to_array($item);
 | 
						|
      else throw ValueException::unexpected_type("array", $item);
 | 
						|
    }
 | 
						|
    return $item;
 | 
						|
  }
 | 
						|
 | 
						|
  /** @var int index de l'élément courant */
 | 
						|
  protected $index;
 | 
						|
 | 
						|
  /** @var string|int clé de l'élément courant */
 | 
						|
  protected $key;
 | 
						|
 | 
						|
  function print(): void {
 | 
						|
    $this->buildItems();
 | 
						|
    $filterCtx = $this->filterCtx;
 | 
						|
    $mapCtx = $this->mapCtx;
 | 
						|
    $this->rewindItems();
 | 
						|
    $this->index = 0;
 | 
						|
    $first = true;
 | 
						|
    while ($this->validItem()) {
 | 
						|
      try {
 | 
						|
        $item = $this->currentItem($this->key);
 | 
						|
        if ($filterCtx !== null) {
 | 
						|
          if (!func::_call($filterCtx, [$item, $this->key])) continue;
 | 
						|
        }
 | 
						|
        if ($mapCtx !== null) $item = func::_call($mapCtx, [$item, $this->key]);
 | 
						|
        else $item = $this->ensureArray($item);
 | 
						|
 | 
						|
        if ($first) {
 | 
						|
          $first = false;
 | 
						|
          $this->printStartContainer();
 | 
						|
        }
 | 
						|
        $this->printItem($item);
 | 
						|
        $this->index++;
 | 
						|
      } finally {
 | 
						|
        $this->nextItem();
 | 
						|
      }
 | 
						|
    }
 | 
						|
    if ($first && $this->ppShowEmpty) {
 | 
						|
      $first = false;
 | 
						|
      $this->printStartContainer();
 | 
						|
    }
 | 
						|
    if (!$first) {
 | 
						|
      $this->printEndContainer();
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  function printStartContainer(): void {
 | 
						|
  }
 | 
						|
 | 
						|
  function printItem($item): void {
 | 
						|
  }
 | 
						|
 | 
						|
  function printEndContainer(): void {
 | 
						|
  }
 | 
						|
}
 |