diff --git a/src/php/coll/Cursor.php b/src/php/coll/Cursor.php
index f1ec9d9..b10d011 100644
--- a/src/php/coll/Cursor.php
+++ b/src/php/coll/Cursor.php
@@ -2,6 +2,7 @@
namespace nur\sery\wip\php\coll;
use Iterator;
+use IteratorAggregate;
use nulib\cl;
use nulib\php\func;
use nur\sery\wip\php\iter;
@@ -33,7 +34,7 @@ class Cursor implements Iterator {
* alors retourner le tableau
* ["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;
$index = 0;
$mapped = [];
@@ -48,7 +49,7 @@ class Cursor implements Iterator {
$mapped[$key] = $func->invoke([$value, $key, $row]);
} else {
if ($value === null) $mapped[$key] = null;
- else $mapped[$key] = cl::get($row, $key);
+ else $mapped[$key] = cl::get($row, $value);
}
}
return $mapped;
@@ -67,7 +68,7 @@ class Cursor implements Iterator {
* - une valeur associative $key => $value indique que la clé correspondante
* 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 (!is_array($filter)) $filter = [$filter];
if (!$filter) return false;
@@ -79,12 +80,12 @@ class Cursor implements Iterator {
if (!array_key_exists($value, $row)) return false;
} elseif (is_bool($value)) {
if ($value) {
- if (!array_key_exists($value, $row)) return false;
+ if (!array_key_exists($key, $row)) return false;
} else {
- if (array_key_exists($value, $row)) return false;
+ if (array_key_exists($key, $row)) return false;
}
} else {
- if (!array_key_exists($value, $row)) return false;
+ if (!array_key_exists($key, $row)) return false;
if ($row[$key] !== $value) return false;
}
}
@@ -114,6 +115,11 @@ class Cursor implements Iterator {
$this->rowsGenerator = $rowsGenerator;
$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;
$mapFunc = $params["map_func"] ?? null;
if ($mapFunc !== null) {
@@ -140,16 +146,16 @@ class Cursor implements Iterator {
/** un générateur de lignes */
private ?Traversable $rowsGenerator;
- /** une fonction de signature function(Cursor):?iterable
*/
+ /** une fonction de signature function(Cursor): ?iterable
*/
private ?func $rowsFunc;
- /** une fonction de signature function(Cursor):?array
*/
+ /** une fonction de signature function(Cursor): ?array
*/
private ?func $colsFunc;
- /** une fonction de signature function(Cursor):?array
*/
+ /** une fonction de signature function(Cursor): ?array
*/
private ?func $mapFunc;
- /** une fonction de signature function(Cursor):bool
*/
+ /** une fonction de signature function(Cursor): bool
*/
private ?func $filterFunc;
protected ?iterable $rows;
@@ -173,6 +179,10 @@ class Cursor implements Iterator {
return null;
}
+ protected function cols(): ?array {
+ return $this->row !== null? array_keys($this->row): null;
+ }
+
protected function filter(): bool {
return false;
}
@@ -185,20 +195,24 @@ class Cursor implements Iterator {
# Iterator
function rewind() {
+ $this->cols = null;
$this->index = 0;
$this->origIndex = 0;
$this->key = null;
$this->raw = null;
$this->row = null;
if ($this->rowsGenerator !== null) {
- $this->rows = $this->rowsGenerator;
- $this->rows->rewind();
+ $rows = $this->rowsGenerator;
+ if ($rows instanceof IteratorAggregate) $rows = $rows->getIterator();
+ $rows->rewind();
+ $this->rows = $rows;
} else {
$this->rows = $this->rowsFunc->invoke();
}
}
- function valid() {
+ function valid(): bool {
+ $cols = $this->colsFunc;
$filter = $this->filterFunc;
$map = $this->mapFunc;
while ($valid = iter::valid($this->rows)) {
@@ -210,6 +224,10 @@ class Cursor implements Iterator {
if (!$filtered) {
if ($map === null) $this->row = $this->map();
else $this->row = $map->invoke([$this]);
+ if ($this->cols === null) {
+ if ($cols === null) $this->cols = $this->cols();
+ else $this->cols = $cols->invoke([$this]);
+ }
break;
} else {
iter::next($this->rows);
@@ -219,6 +237,7 @@ class Cursor implements Iterator {
if (!$valid) {
iter::close($this->rows);
$this->rows = null;
+ $this->cols = null;
$this->index = -1;
$this->origIndex = -1;
$this->key = null;
@@ -228,7 +247,7 @@ class Cursor implements Iterator {
return $valid;
}
- function current() {
+ function current(): ?array {
return $this->row;
}
diff --git a/tests/wip/php/coll/CursorTest.php b/tests/wip/php/coll/CursorTest.php
index ec820d8..f28bc95 100644
--- a/tests/wip/php/coll/CursorTest.php
+++ b/tests/wip/php/coll/CursorTest.php
@@ -13,6 +13,43 @@ class CursorTest extends TestCase {
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];
function generator() {
@@ -41,6 +78,15 @@ class CursorTest extends TestCase {
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, [
"rows_func" => function() {
return self::SCALARS;