support des colonnes

This commit is contained in:
Jephté Clain 2025-03-04 06:53:19 +04:00
parent 2812046b4b
commit 1a5ca79ef7
2 changed files with 79 additions and 14 deletions

View File

@ -2,6 +2,7 @@
namespace nur\sery\wip\php\coll; namespace nur\sery\wip\php\coll;
use Iterator; use Iterator;
use IteratorAggregate;
use nulib\cl; use nulib\cl;
use nulib\php\func; use nulib\php\func;
use nur\sery\wip\php\iter; use nur\sery\wip\php\iter;
@ -33,7 +34,7 @@ class Cursor implements Iterator {
* alors retourner le tableau * alors retourner le tableau
* ["a" => $row["a"], "b" => $row["x"], "c" => "y", "d" => null] * ["a" => $row["a"], "b" => $row["x"], "c" => "y", "d" => null]
*/ */
private static function map_row(array $row, ?array $map): array { protected static function map_row(array $row, ?array $map): array {
if ($map === null) return $row; if ($map === null) return $row;
$index = 0; $index = 0;
$mapped = []; $mapped = [];
@ -48,7 +49,7 @@ class Cursor implements Iterator {
$mapped[$key] = $func->invoke([$value, $key, $row]); $mapped[$key] = $func->invoke([$value, $key, $row]);
} else { } else {
if ($value === null) $mapped[$key] = null; if ($value === null) $mapped[$key] = null;
else $mapped[$key] = cl::get($row, $key); else $mapped[$key] = cl::get($row, $value);
} }
} }
return $mapped; return $mapped;
@ -67,7 +68,7 @@ class Cursor implements Iterator {
* - une valeur associative $key => $value indique que la clé correspondante * - une valeur associative $key => $value indique que la clé correspondante
* doit exiter avec la valeur spécifiée * doit exiter avec la valeur spécifiée
*/ */
private static function filter_row(array $row, $filter): bool { protected static function filter_row(array $row, $filter): bool {
if ($filter === null) return false; if ($filter === null) return false;
if (!is_array($filter)) $filter = [$filter]; if (!is_array($filter)) $filter = [$filter];
if (!$filter) return false; if (!$filter) return false;
@ -79,12 +80,12 @@ class Cursor implements Iterator {
if (!array_key_exists($value, $row)) return false; if (!array_key_exists($value, $row)) return false;
} elseif (is_bool($value)) { } elseif (is_bool($value)) {
if ($value) { if ($value) {
if (!array_key_exists($value, $row)) return false; if (!array_key_exists($key, $row)) return false;
} else { } else {
if (array_key_exists($value, $row)) return false; if (array_key_exists($key, $row)) return false;
} }
} else { } else {
if (!array_key_exists($value, $row)) return false; if (!array_key_exists($key, $row)) return false;
if ($row[$key] !== $value) return false; if ($row[$key] !== $value) return false;
} }
} }
@ -114,6 +115,11 @@ class Cursor implements Iterator {
$this->rowsGenerator = $rowsGenerator; $this->rowsGenerator = $rowsGenerator;
$this->rowsFunc = $rowsFunc; $this->rowsFunc = $rowsFunc;
$this->cols = $params["cols"] ?? null;
$colsFunc = $params["cols_func"] ?? null;
if ($colsFunc !== null) $colsFunc = func::with($colsFunc);
$this->colsFunc = $colsFunc;
$map = $params["map"] ?? null; $map = $params["map"] ?? null;
$mapFunc = $params["map_func"] ?? null; $mapFunc = $params["map_func"] ?? null;
if ($mapFunc !== null) { if ($mapFunc !== null) {
@ -140,16 +146,16 @@ class Cursor implements Iterator {
/** un générateur de lignes */ /** un générateur de lignes */
private ?Traversable $rowsGenerator; private ?Traversable $rowsGenerator;
/** une fonction de signature <code>function(Cursor):?iterable</code> */ /** une fonction de signature <code>function(Cursor): ?iterable</code> */
private ?func $rowsFunc; private ?func $rowsFunc;
/** une fonction de signature <code>function(Cursor):?array</code> */ /** une fonction de signature <code>function(Cursor): ?array</code> */
private ?func $colsFunc; private ?func $colsFunc;
/** une fonction de signature <code>function(Cursor):?array</code> */ /** une fonction de signature <code>function(Cursor): ?array</code> */
private ?func $mapFunc; private ?func $mapFunc;
/** une fonction de signature <code>function(Cursor):bool</code> */ /** une fonction de signature <code>function(Cursor): bool</code> */
private ?func $filterFunc; private ?func $filterFunc;
protected ?iterable $rows; protected ?iterable $rows;
@ -173,6 +179,10 @@ class Cursor implements Iterator {
return null; return null;
} }
protected function cols(): ?array {
return $this->row !== null? array_keys($this->row): null;
}
protected function filter(): bool { protected function filter(): bool {
return false; return false;
} }
@ -185,20 +195,24 @@ class Cursor implements Iterator {
# Iterator # Iterator
function rewind() { function rewind() {
$this->cols = null;
$this->index = 0; $this->index = 0;
$this->origIndex = 0; $this->origIndex = 0;
$this->key = null; $this->key = null;
$this->raw = null; $this->raw = null;
$this->row = null; $this->row = null;
if ($this->rowsGenerator !== null) { if ($this->rowsGenerator !== null) {
$this->rows = $this->rowsGenerator; $rows = $this->rowsGenerator;
$this->rows->rewind(); if ($rows instanceof IteratorAggregate) $rows = $rows->getIterator();
$rows->rewind();
$this->rows = $rows;
} else { } else {
$this->rows = $this->rowsFunc->invoke(); $this->rows = $this->rowsFunc->invoke();
} }
} }
function valid() { function valid(): bool {
$cols = $this->colsFunc;
$filter = $this->filterFunc; $filter = $this->filterFunc;
$map = $this->mapFunc; $map = $this->mapFunc;
while ($valid = iter::valid($this->rows)) { while ($valid = iter::valid($this->rows)) {
@ -210,6 +224,10 @@ class Cursor implements Iterator {
if (!$filtered) { if (!$filtered) {
if ($map === null) $this->row = $this->map(); if ($map === null) $this->row = $this->map();
else $this->row = $map->invoke([$this]); else $this->row = $map->invoke([$this]);
if ($this->cols === null) {
if ($cols === null) $this->cols = $this->cols();
else $this->cols = $cols->invoke([$this]);
}
break; break;
} else { } else {
iter::next($this->rows); iter::next($this->rows);
@ -219,6 +237,7 @@ class Cursor implements Iterator {
if (!$valid) { if (!$valid) {
iter::close($this->rows); iter::close($this->rows);
$this->rows = null; $this->rows = null;
$this->cols = null;
$this->index = -1; $this->index = -1;
$this->origIndex = -1; $this->origIndex = -1;
$this->key = null; $this->key = null;
@ -228,7 +247,7 @@ class Cursor implements Iterator {
return $valid; return $valid;
} }
function current() { function current(): ?array {
return $this->row; return $this->row;
} }

View File

@ -13,6 +13,43 @@ class CursorTest extends TestCase {
msg::set_messenger(new StdMessenger()); msg::set_messenger(new StdMessenger());
} }
function test_map_row() {
$cursor = new class extends Cursor {
function mapRow(array $row, ?array $map): array {
return self::map_row($row, $map);
}
};
$row = ["a" => 1, "b" => 2, "c" => 3, "x" => 99];
$map = ["a", "b" => "x", "c" => function() { return "y"; }, "d" => null];
self::assertSame([
"a" => $row["a"],
"b" => $row["x"],
"c" => "y",
"d" => null
], $cursor->mapRow($row, $map));
}
function test_filter_row() {
$cursor = new class extends Cursor {
function filterRow(array $row, $filter): bool {
return self::filter_row($row, $filter);
}
};
$row = ["a" => 1, "b" => 2, "c" => 3, "x" => 99];
self::assertTrue($cursor->filterRow($row, "a"));
self::assertTrue($cursor->filterRow($row, ["a"]));
self::assertTrue($cursor->filterRow($row, ["a" => true]));
self::assertFalse($cursor->filterRow($row, ["a" => false]));
self::assertTrue($cursor->filterRow($row, ["a" => 1]));
self::assertFalse($cursor->filterRow($row, ["a" => 2]));
self::assertFalse($cursor->filterRow($row, "z"));
self::assertFalse($cursor->filterRow($row, ["z"]));
self::assertFalse($cursor->filterRow($row, ["z" => true]));
self::assertTrue($cursor->filterRow($row, ["z" => false]));
self::assertFalse($cursor->filterRow($row, ["z" => 1]));
}
const SCALARS = [0, 1, 2, 3, 4]; const SCALARS = [0, 1, 2, 3, 4];
function generator() { function generator() {
@ -41,6 +78,15 @@ class CursorTest extends TestCase {
return cl::all($c); return cl::all($c);
}); });
$c = new Cursor(null, [
"rows" => $this->generator(),
]);
self::assertSame([[0], [1], [2], [3], [4]], cl::all($c));
self::assertException(Exception::class, function() use ($c) {
// pas possible de rewind un générateur
return cl::all($c);
});
$c = new Cursor(null, [ $c = new Cursor(null, [
"rows_func" => function() { "rows_func" => function() {
return self::SCALARS; return self::SCALARS;