modifs.mineures sans commentaires
This commit is contained in:
parent
c1ce91ec81
commit
c4e1496b82
|
@ -0,0 +1,39 @@
|
||||||
|
<?php
|
||||||
|
namespace nur\sery;
|
||||||
|
|
||||||
|
use Traversable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class A: gestion de tableaux ou d'instances de {@link IArrayWrapper}
|
||||||
|
*
|
||||||
|
* contrairement à {@link cl}, les méthodes de cette classes sont plutôt conçues
|
||||||
|
* pour modifier le tableau en place
|
||||||
|
*/
|
||||||
|
class A {
|
||||||
|
/**
|
||||||
|
* s'assurer que $array est un array non null. retourner true si $array n'a
|
||||||
|
* pas été modifié (s'il était déjà un array), false sinon.
|
||||||
|
*/
|
||||||
|
static final function ensure_array(&$array): bool {
|
||||||
|
if (is_array($array)) return true;
|
||||||
|
if ($array instanceof IArrayWrapper) $array = $array->wrappedArray();
|
||||||
|
if ($array === null || $array === false) $array = [];
|
||||||
|
elseif ($array instanceof Traversable) $array = iterator_to_array($array);
|
||||||
|
else $array = [$array];
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* s'assurer que $array est un array s'il est non null. retourner true si
|
||||||
|
* $array n'a pas été modifié (s'il était déjà un array ou s'il valait null).
|
||||||
|
*/
|
||||||
|
static final function ensure_narray(&$array): bool {
|
||||||
|
if ($array === null || is_array($array)) return true;
|
||||||
|
if ($array instanceof IArrayWrapper) $array = $array->wrappedArray();
|
||||||
|
if ($array === false) $array = [];
|
||||||
|
elseif ($array instanceof Traversable) $array = iterator_to_array($array);
|
||||||
|
else $array = [$array];
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
<?php
|
||||||
|
namespace nur\sery;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface IArrayWrapper: un objet qui encapsule un array auquel on peut
|
||||||
|
* accéder
|
||||||
|
*/
|
||||||
|
interface IArrayWrapper {
|
||||||
|
/** retourne une référence sur l'array encapsulé */
|
||||||
|
function &wrappedArray(): ?array;
|
||||||
|
}
|
46
src/cl.php
46
src/cl.php
|
@ -5,7 +5,11 @@ use ArrayAccess;
|
||||||
use Traversable;
|
use Traversable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class cl: gestion de tableau de valeurs scalaires
|
* Class cl: gestion de tableaux ou d'instances de {@link ArrayAccess} le cas
|
||||||
|
* échéant
|
||||||
|
*
|
||||||
|
* contrairement à {@link A}, les méthodes de cette classes sont plutôt conçues
|
||||||
|
* pour retourner un nouveau tableau
|
||||||
*/
|
*/
|
||||||
class cl {
|
class cl {
|
||||||
/** retourner un array non null à partir de $array */
|
/** retourner un array non null à partir de $array */
|
||||||
|
@ -24,30 +28,6 @@ class cl {
|
||||||
else return [$array];
|
else return [$array];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* s'assurer que $array est un array non null. retourner true si $array n'a
|
|
||||||
* pas été modifié (s'il était déjà un array), false sinon.
|
|
||||||
*/
|
|
||||||
static final function ensure_array(&$array): bool {
|
|
||||||
if (is_array($array)) return true;
|
|
||||||
elseif ($array === null || $array === false) $array = [];
|
|
||||||
elseif ($array instanceof Traversable) $array = iterator_to_array($array);
|
|
||||||
else $array = [$array];
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* s'assurer que $array est un array s'il est non null. retourner true si
|
|
||||||
* $array n'a pas été modifié (s'il était déjà un array ou s'il valait null).
|
|
||||||
*/
|
|
||||||
static final function ensure_narray(&$array): bool {
|
|
||||||
if ($array === null || is_array($array)) return true;
|
|
||||||
elseif ($array === false) $array = [];
|
|
||||||
elseif ($array instanceof Traversable) $array = iterator_to_array($array);
|
|
||||||
else $array = [$array];
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** tester si $array a au moins une clé numérique */
|
/** tester si $array a au moins une clé numérique */
|
||||||
static final function have_num_keys(?array $array): bool {
|
static final function have_num_keys(?array $array): bool {
|
||||||
if ($array === null) return false;
|
if ($array === null) return false;
|
||||||
|
@ -159,7 +139,7 @@ class cl {
|
||||||
static final function merge(...$arrays): ?array {
|
static final function merge(...$arrays): ?array {
|
||||||
$merges = [];
|
$merges = [];
|
||||||
foreach ($arrays as $array) {
|
foreach ($arrays as $array) {
|
||||||
self::ensure_narray($array);
|
A::ensure_narray($array);
|
||||||
if ($array !== null) $merges[] = $array;
|
if ($array !== null) $merges[] = $array;
|
||||||
}
|
}
|
||||||
return $merges? array_merge(...$merges): null;
|
return $merges? array_merge(...$merges): null;
|
||||||
|
@ -170,7 +150,7 @@ class cl {
|
||||||
/**
|
/**
|
||||||
* vérifier que le chemin $keys existe dans le tableau $array
|
* vérifier que le chemin $keys existe dans le tableau $array
|
||||||
*
|
*
|
||||||
* si $keys est vide ou null, retourner true
|
* si $pkey est vide ou null, retourner true
|
||||||
*/
|
*/
|
||||||
static final function phas($array, $pkey): bool {
|
static final function phas($array, $pkey): bool {
|
||||||
# optimisations
|
# optimisations
|
||||||
|
@ -214,7 +194,7 @@ class cl {
|
||||||
/**
|
/**
|
||||||
* obtenir la valeur correspondant au chemin $keys dans $array
|
* obtenir la valeur correspondant au chemin $keys dans $array
|
||||||
*
|
*
|
||||||
* si $keys est vide ou null, retourner $default
|
* si $pkey est vide ou null, retourner $default
|
||||||
*/
|
*/
|
||||||
static final function pget($array, $pkey, $default=null) {
|
static final function pget($array, $pkey, $default=null) {
|
||||||
# optimisations
|
# optimisations
|
||||||
|
@ -264,7 +244,7 @@ class cl {
|
||||||
* - pset($array, ["a", "b", ""], $value) est équivalent à $array["a"]["b"][] = $value
|
* - pset($array, ["a", "b", ""], $value) est équivalent à $array["a"]["b"][] = $value
|
||||||
* la clé "" n'a pas de propriété particulière quand elle n'est pas en dernière position
|
* la clé "" n'a pas de propriété particulière quand elle n'est pas en dernière position
|
||||||
*
|
*
|
||||||
* si $keys est vide ou null, $array est remplacé par $value
|
* si $pkey est vide ou null, $array est remplacé par $value
|
||||||
*/
|
*/
|
||||||
static final function pset(&$array, $pkey, $value): void {
|
static final function pset(&$array, $pkey, $value): void {
|
||||||
# optimisations
|
# optimisations
|
||||||
|
@ -281,7 +261,7 @@ class cl {
|
||||||
$pkey = explode(".", strval($pkey));
|
$pkey = explode(".", strval($pkey));
|
||||||
}
|
}
|
||||||
# pset
|
# pset
|
||||||
self::ensure_array($array);
|
A::ensure_array($array);
|
||||||
$current =& $array;
|
$current =& $array;
|
||||||
$key = null;
|
$key = null;
|
||||||
$last = count($pkey) - 1;
|
$last = count($pkey) - 1;
|
||||||
|
@ -297,7 +277,7 @@ class cl {
|
||||||
$current = [$current];
|
$current = [$current];
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
self::ensure_array($current[$key]);
|
A::ensure_array($current[$key]);
|
||||||
$current =& $current[$key];
|
$current =& $current[$key];
|
||||||
}
|
}
|
||||||
$i++;
|
$i++;
|
||||||
|
@ -318,7 +298,7 @@ class cl {
|
||||||
* supprimer la valeur au chemin de clé $keys dans $array
|
* supprimer la valeur au chemin de clé $keys dans $array
|
||||||
*
|
*
|
||||||
* si $array vaut null ou false, sa valeur est inchangée.
|
* si $array vaut null ou false, sa valeur est inchangée.
|
||||||
* si $keys est vide ou null, $array devient null
|
* si $pkey est vide ou null, $array devient null
|
||||||
*/
|
*/
|
||||||
static final function pdel(&$array, $pkey): void {
|
static final function pdel(&$array, $pkey): void {
|
||||||
# optimisations
|
# optimisations
|
||||||
|
@ -334,7 +314,7 @@ class cl {
|
||||||
$pkey = explode(".", strval($pkey));
|
$pkey = explode(".", strval($pkey));
|
||||||
}
|
}
|
||||||
# pdel
|
# pdel
|
||||||
self::ensure_array($array);
|
A::ensure_array($array);
|
||||||
$current =& $array;
|
$current =& $array;
|
||||||
$key = null;
|
$key = null;
|
||||||
$last = count($pkey) - 1;
|
$last = count($pkey) - 1;
|
||||||
|
|
|
@ -112,15 +112,18 @@ class Sqlite {
|
||||||
return SqliteException::check($this->db, $result);
|
return SqliteException::check($this->db, $result);
|
||||||
}
|
}
|
||||||
|
|
||||||
function _exec(string $query): bool {
|
protected function db(): SQLite3 {
|
||||||
$this->open();
|
$this->open();
|
||||||
return $this->db->exec($query);
|
return $this->db;
|
||||||
|
}
|
||||||
|
|
||||||
|
function _exec(string $query): bool {
|
||||||
|
return $this->db()->exec($query);
|
||||||
}
|
}
|
||||||
|
|
||||||
function exec($query, ?array $params=null): bool {
|
function exec($query, ?array $params=null): bool {
|
||||||
$this->open();
|
$db = $this->db();
|
||||||
$query = new _query($query, $params);
|
$query = new _query($query, $params);
|
||||||
$db = $this->db;
|
|
||||||
if ($query->useStmt($db, $stmt, $sql)) {
|
if ($query->useStmt($db, $stmt, $sql)) {
|
||||||
try {
|
try {
|
||||||
return $stmt->execute()->finalize();
|
return $stmt->execute()->finalize();
|
||||||
|
@ -132,15 +135,25 @@ class Sqlite {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function beginTransaction(): void {
|
||||||
|
$this->db()->exec("begin");
|
||||||
|
}
|
||||||
|
|
||||||
|
function commit(): void {
|
||||||
|
$this->db()->exec("commit");
|
||||||
|
}
|
||||||
|
|
||||||
|
function rollback(): void {
|
||||||
|
$this->db()->exec("commit");
|
||||||
|
}
|
||||||
|
|
||||||
function _get(string $query, bool $entireRow=false) {
|
function _get(string $query, bool $entireRow=false) {
|
||||||
$this->open();
|
return $this->db()->querySingle($query, $entireRow);
|
||||||
return $this->db->querySingle($query, $entireRow);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function get($query, ?array $params=null, bool $entireRow=false) {
|
function get($query, ?array $params=null, bool $entireRow=false) {
|
||||||
$this->open();
|
$db = $this->db();
|
||||||
$query = new _query($query, $params);
|
$query = new _query($query, $params);
|
||||||
$db = $this->db;
|
|
||||||
if ($query->useStmt($db, $stmt, $sql)) {
|
if ($query->useStmt($db, $stmt, $sql)) {
|
||||||
try {
|
try {
|
||||||
$result = $this->checkResult($stmt->execute());
|
$result = $this->checkResult($stmt->execute());
|
||||||
|
@ -164,27 +177,23 @@ class Sqlite {
|
||||||
return $this->get($query, $params, true);
|
return $this->get($query, $params, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function _fetchResult(SQLite3Result $result): Generator {
|
protected function _fetchResult(SQLite3Result $result, ?SQLite3Stmt $stmt=null): Generator {
|
||||||
try {
|
try {
|
||||||
while (($row = $result->fetchArray(SQLITE3_ASSOC)) !== false) {
|
while (($row = $result->fetchArray(SQLITE3_ASSOC)) !== false) {
|
||||||
yield $row;
|
yield $row;
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
$result->finalize();
|
$result->finalize();
|
||||||
|
if ($stmt !== null) $stmt->close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function all($query, ?array $params=null): iterable {
|
function all($query, ?array $params=null): iterable {
|
||||||
$this->open();
|
$db = $this->db();
|
||||||
$query = new _query($query, $params);
|
$query = new _query($query, $params);
|
||||||
$db = $this->db;
|
|
||||||
if ($query->useStmt($db, $stmt, $sql)) {
|
if ($query->useStmt($db, $stmt, $sql)) {
|
||||||
try {
|
|
||||||
$result = $this->checkResult($stmt->execute());
|
$result = $this->checkResult($stmt->execute());
|
||||||
return $this->_fetchResult($result);
|
return $this->_fetchResult($result, $stmt);
|
||||||
} finally {
|
|
||||||
$stmt->close();
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
$result = $this->checkResult($db->query($sql));
|
$result = $this->checkResult($db->query($sql));
|
||||||
return $this->_fetchResult($result);
|
return $this->_fetchResult($result);
|
||||||
|
|
|
@ -17,6 +17,10 @@ class SqliteCapacitor {
|
||||||
/** @var Sqlite */
|
/** @var Sqlite */
|
||||||
protected $sqlite;
|
protected $sqlite;
|
||||||
|
|
||||||
|
function sqlite(): Sqlite {
|
||||||
|
return $this->sqlite;
|
||||||
|
}
|
||||||
|
|
||||||
protected function getTableName(?string $channel): string {
|
protected function getTableName(?string $channel): string {
|
||||||
return ($channel ?? "default")."_channel";
|
return ($channel ?? "default")."_channel";
|
||||||
}
|
}
|
||||||
|
@ -30,7 +34,7 @@ class SqliteCapacitor {
|
||||||
function reset(?string $channel=null) {
|
function reset(?string $channel=null) {
|
||||||
$tableName = $this->getTableName($channel);
|
$tableName = $this->getTableName($channel);
|
||||||
$this->sqlite->exec("drop table if exists $tableName");
|
$this->sqlite->exec("drop table if exists $tableName");
|
||||||
#XXX maj de la tables channels
|
#XXX maj de la tables channels dans une transaction
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @var array */
|
/** @var array */
|
||||||
|
@ -68,7 +72,7 @@ class SqliteCapacitor {
|
||||||
]);
|
]);
|
||||||
#XXX^^^ migrer vers la syntaxe tableau de create
|
#XXX^^^ migrer vers la syntaxe tableau de create
|
||||||
$this->sqlite->exec($query);
|
$this->sqlite->exec($query);
|
||||||
#XXX maj de la tables channels
|
#XXX maj de la tables channels dans une transaction
|
||||||
$this->created[$channel] = true;
|
$this->created[$channel] = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -85,10 +89,13 @@ class SqliteCapacitor {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** décharger les données du canal spécifié */
|
/** décharger les données du canal spécifié */
|
||||||
function discharge(?string $channel=null, bool $reset=true): iterable {
|
function discharge($keys=null, ?string $channel=null, ?bool $reset=null): iterable {
|
||||||
|
if ($keys !== null && !is_array($keys)) $keys = ["_id" => $keys];
|
||||||
|
if ($reset === null) $reset = $keys === null;
|
||||||
$rows = $this->sqlite->all([
|
$rows = $this->sqlite->all([
|
||||||
"select _item",
|
"select _item",
|
||||||
"from" => $this->getTableName($channel),
|
"from" => $this->getTableName($channel),
|
||||||
|
"where" => $keys,
|
||||||
]);
|
]);
|
||||||
foreach ($rows as $row) {
|
foreach ($rows as $row) {
|
||||||
$item = unserialize($row['_item']);
|
$item = unserialize($row['_item']);
|
||||||
|
@ -97,22 +104,6 @@ class SqliteCapacitor {
|
||||||
if ($reset) $this->reset($channel);
|
if ($reset) $this->reset($channel);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* appeler une fonction pour chaque élément du canal spécifié.
|
|
||||||
*
|
|
||||||
* $keys permet de filtrer parmi les élements chargés
|
|
||||||
*
|
|
||||||
* si $func retourne un tableau, il est utilisé pour mettre à jour
|
|
||||||
* l'enregistrement.
|
|
||||||
*/
|
|
||||||
function each(callable $func, ?array $keys, ?string $channel=null): void {
|
|
||||||
$context = func::_prepare($func);
|
|
||||||
foreach ($this->discharge($channel, false) as $item) {
|
|
||||||
$result = func::_call($context, [$item]);
|
|
||||||
#XXX
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* obtenir l'élément identifié par les clés spécifiées sur le canal spécifié
|
* obtenir l'élément identifié par les clés spécifiées sur le canal spécifié
|
||||||
*
|
*
|
||||||
|
@ -121,34 +112,56 @@ class SqliteCapacitor {
|
||||||
function get($keys, ?string $channel=null) {
|
function get($keys, ?string $channel=null) {
|
||||||
if ($keys === null) throw ValueException::null("keys");
|
if ($keys === null) throw ValueException::null("keys");
|
||||||
if (!is_array($keys)) $keys = ["_id" => $keys];
|
if (!is_array($keys)) $keys = ["_id" => $keys];
|
||||||
#XXX
|
$row = $this->sqlite->one([
|
||||||
|
"select _item",
|
||||||
|
"from" => $this->getTableName($channel),
|
||||||
|
"where" => $keys,
|
||||||
|
]);
|
||||||
|
if ($row === null) return null;
|
||||||
|
else return unserialize($row["_item"]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* appeler une fonction pour chaque élément du canal spécifié.
|
||||||
|
*
|
||||||
|
* $keys permet de filtrer parmi les élements chargés
|
||||||
|
*
|
||||||
|
* si $func retourne un tableau, il est utilisé pour mettre à jour
|
||||||
|
* l'enregistrement.
|
||||||
|
*/
|
||||||
|
function each($keys, callable $func, ?array $args=null, ?string $channel=null): void {
|
||||||
|
if ($keys !== null && !is_array($keys)) $keys = ["_id" => $keys];
|
||||||
|
$context = func::_prepare($func);
|
||||||
|
$sqlite = $this->sqlite;
|
||||||
|
$tableName = $this->getTableName($channel);
|
||||||
|
$rows = $sqlite->all([
|
||||||
|
"select",
|
||||||
|
"from" => $tableName,
|
||||||
|
"where" => $keys,
|
||||||
|
]);
|
||||||
|
$args ??= [];
|
||||||
|
foreach ($rows as $row) {
|
||||||
|
$item = unserialize($row['_item']);
|
||||||
|
$updates = func::_call($context, [$item, $row, ...$args]);
|
||||||
|
if (is_array($updates)) {
|
||||||
|
if (array_key_exists("_item", $updates)) {
|
||||||
|
$updates["_item"] = serialize($updates["_item"]);
|
||||||
|
}
|
||||||
|
#XXXvvv migrer vers la syntaxe tableau de update
|
||||||
|
$params = null;
|
||||||
|
$sql = ["update", $tableName, "set"];
|
||||||
|
_query::parse_set_values($updates, $setsql, $params);
|
||||||
|
$sql[] = implode(", ", $setsql);
|
||||||
|
$sql[] = "where";
|
||||||
|
_query::parse_conds(["_id" => $row["_id"]], $wheresql, $params);
|
||||||
|
$sql[] = implode(" and ", $wheresql);
|
||||||
|
$sqlite->exec(implode(" ", $sql), $params);
|
||||||
|
#XXX^^^ migrer vers la syntaxe tableau de update
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function close(): void {
|
function close(): void {
|
||||||
$this->sqlite->close();
|
$this->sqlite->close();
|
||||||
}
|
}
|
||||||
|
|
||||||
function sqlite__exec(string $query): bool {
|
|
||||||
return $this->sqlite->_exec($query);
|
|
||||||
}
|
|
||||||
|
|
||||||
function sqlite_exec($query, ?array $params=null): bool {
|
|
||||||
return $this->sqlite->exec($query, $params);
|
|
||||||
}
|
|
||||||
|
|
||||||
function sqlite__get(string $query, bool $entireRow=false) {
|
|
||||||
return $this->sqlite->_get($query, $entireRow);
|
|
||||||
}
|
|
||||||
|
|
||||||
function sqlite_get($query, ?array $params=null, bool $entireRow=false) {
|
|
||||||
return $this->sqlite->get($query, $params, $entireRow);
|
|
||||||
}
|
|
||||||
|
|
||||||
function sqlite_one($query, ?array $params=null): ?array {
|
|
||||||
return $this->sqlite->one($query, $params);
|
|
||||||
}
|
|
||||||
|
|
||||||
function sqlite_all($query, ?array $params=null): iterable {
|
|
||||||
return $this->sqlite->all($query, $params);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -91,6 +91,8 @@ class _query {
|
||||||
}
|
}
|
||||||
# value ou [operator, value]
|
# value ou [operator, value]
|
||||||
if (is_array($cond)) {
|
if (is_array($cond)) {
|
||||||
|
#XXX implémenter le support de ["between", lower, upper]
|
||||||
|
# et aussi ["in", values]
|
||||||
$op = null;
|
$op = null;
|
||||||
$value = null;
|
$value = null;
|
||||||
$condkeys = array_keys($cond);
|
$condkeys = array_keys($cond);
|
||||||
|
|
|
@ -5,12 +5,13 @@ use ArrayAccess;
|
||||||
use Countable;
|
use Countable;
|
||||||
use Iterator;
|
use Iterator;
|
||||||
use nur\sery\cl;
|
use nur\sery\cl;
|
||||||
|
use nur\sery\IArrayWrapper;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class BaseArray: implémentation de base d'un objet array-like, qui peut aussi
|
* Class BaseArray: implémentation de base d'un objet array-like, qui peut aussi
|
||||||
* servir comme front-end pour un array
|
* servir comme front-end pour un array
|
||||||
*/
|
*/
|
||||||
class BaseArray implements ArrayAccess, Countable, Iterator {
|
class BaseArray implements ArrayAccess, Countable, Iterator, IArrayWrapper {
|
||||||
function __construct(?array &$data=null) {
|
function __construct(?array &$data=null) {
|
||||||
$this->reset($data);
|
$this->reset($data);
|
||||||
}
|
}
|
||||||
|
@ -18,10 +19,11 @@ class BaseArray implements ArrayAccess, Countable, Iterator {
|
||||||
/** @var array */
|
/** @var array */
|
||||||
protected $data;
|
protected $data;
|
||||||
|
|
||||||
|
function &wrappedArray(): ?array { return $this->data; }
|
||||||
|
|
||||||
function __toString(): string { return var_export($this->data, true); }
|
function __toString(): string { return var_export($this->data, true); }
|
||||||
#function __debugInfo() { return $this->data; }
|
#function __debugInfo() { return $this->data; }
|
||||||
function reset(?array &$data): void { $this->data =& $data; }
|
function reset(?array &$data): void { $this->data =& $data; }
|
||||||
function &array(): ?array { return $this->data; }
|
|
||||||
function count(): int { return $this->data !== null? count($this->data): 0; }
|
function count(): int { return $this->data !== null? count($this->data): 0; }
|
||||||
function keys(): array { return $this->data !== null? array_keys($this->data): []; }
|
function keys(): array { return $this->data !== null? array_keys($this->data): []; }
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,7 @@ class SqliteCapacitorTest extends TestCase {
|
||||||
$capacitor->charge("first", $channel);
|
$capacitor->charge("first", $channel);
|
||||||
$capacitor->charge("second", $channel);
|
$capacitor->charge("second", $channel);
|
||||||
$capacitor->charge("third", $channel);
|
$capacitor->charge("third", $channel);
|
||||||
$items = iterator_to_array($capacitor->discharge($channel, false));
|
$items = iterator_to_array($capacitor->discharge(null, $channel, false));
|
||||||
self::assertSame(["first", "second", "third"], $items);
|
self::assertSame(["first", "second", "third"], $items);
|
||||||
}
|
}
|
||||||
function _testChargeArrays(SqliteCapacitor $capacitor, ?string $channel) {
|
function _testChargeArrays(SqliteCapacitor $capacitor, ?string $channel) {
|
||||||
|
@ -45,4 +45,42 @@ class SqliteCapacitorTest extends TestCase {
|
||||||
$this->_testChargeArrays($capacitor, "arrays");
|
$this->_testChargeArrays($capacitor, "arrays");
|
||||||
$capacitor->close();
|
$capacitor->close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function testEach() {
|
||||||
|
$capacitor = new class(__DIR__.'/capacitor.db') extends SqliteCapacitor {
|
||||||
|
protected function getKeyDefinitions(?string $channel): ?array {
|
||||||
|
return [
|
||||||
|
"age" => "integer",
|
||||||
|
"done" => "integer default 0",
|
||||||
|
];
|
||||||
|
}
|
||||||
|
protected function getKeyValues($item, ?string $channel): ?array {
|
||||||
|
return [
|
||||||
|
"age" => $item["age"],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
$channel = "each";
|
||||||
|
$capacitor->reset($channel);
|
||||||
|
$capacitor->charge(["name" => "first", "age" => 5], $channel);
|
||||||
|
$capacitor->charge(["name" => "second", "age" => 10], $channel);
|
||||||
|
$capacitor->charge(["name" => "third", "age" => 15], $channel);
|
||||||
|
$capacitor->charge(["name" => "fourth", "age" => 20], $channel);
|
||||||
|
|
||||||
|
$setDone = function ($item, $row, $suffix=null) {
|
||||||
|
$updates = ["done" => 1];
|
||||||
|
if ($suffix !== null) {
|
||||||
|
$item["name"] .= $suffix;
|
||||||
|
$updates["_item"] = $item;
|
||||||
|
}
|
||||||
|
return $updates;
|
||||||
|
};
|
||||||
|
$capacitor->each(["age" => [">", 10]], $setDone, ["++"], $channel);
|
||||||
|
$capacitor->each(["done" => 0], $setDone, null, $channel);
|
||||||
|
Txx(iterator_to_array($capacitor->discharge(null, $channel, false)));
|
||||||
|
|
||||||
|
$capacitor->close();
|
||||||
|
self::assertTrue(true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue