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 {
|
|
}
|
|
}
|