nulib-base/php/src/cache/CursorChannel.php

128 lines
3.1 KiB
PHP

<?php
namespace nulib\cache;
use IteratorAggregate;
use nulib\cl;
use nulib\db\CapacitorChannel;
use nulib\db\CapacitorStorage;
use nulib\php\func;
use Traversable;
class CursorChannel extends CapacitorChannel implements IteratorAggregate {
static function with($cursorId=null, ?iterable $rows=null, ?CapacitorStorage $storage=null): self {
$storage ??= cache::storage();
$channel = (new static($cursorId))->initStorage($storage);
if ($rows !== null) $channel->rechargeAll($rows);
return $channel;
}
const NAME = "cursor";
const TABLE_NAME = "cursor";
const COLUMN_DEFINITIONS = [
"group_id_" => "varchar(32) not null", // groupe de curseur
"id_" => "varchar(128) not null", // nom du curseur
"key_index_" => "integer not null",
"key_" => "varchar(128) not null",
"search_" => "varchar(255)",
"primary key (group_id_, id_, key_index_)",
];
const ADD_COLUMNS = null;
protected function COLUMN_DEFINITIONS(): ?array {
return cl::merge(self::COLUMN_DEFINITIONS, static::ADD_COLUMNS);
}
/**
* @param array|string $cursorId
*/
function __construct($cursorId) {
parent::__construct();
cache::verifix_id($cursorId);
[
"group_id" => $this->groupId,
"id" => $this->id,
] = $cursorId;
}
protected string $groupId;
protected string $id;
function getCursorId(): array {
return [
"group_id" => $this->groupId,
"id" => $this->id,
];
}
function getBaseFilter(): ?array {
return [
"group_id_" => $this->groupId,
"id_" => $this->id,
];
}
protected int $index = 0;
protected function getSearch($item): ?string {
$search = cl::filter_n(cl::with($item));
$search = implode(" ", $search);
return substr($search, 0, 255);
}
function getItemValues($item, $key=null): ?array {
$index = $this->index++;
$key = $key ?? $index;
$key = substr(strval($key), 0, 128);
$addColumns = static::ADD_COLUMNS ?? [];
$addColumns = cl::select($item,
array_filter(array_keys($addColumns), function ($key) {
return is_string($key);
}));
return cl::merge($addColumns, [
"group_id_" => $this->groupId,
"id_" => $this->id,
"key_index_" => $index,
"key_" => $key,
"search_" => $this->getSearch($item),
]);
}
function reset(bool $recreate=false): void {
$this->index = 0;
parent::reset($recreate);
}
function chargeAll(?iterable $items, $func=null, ?array $args=null): int {
if ($items === null) return 0;
$count = 0;
if ($func !== null) $func = func::with($func, $args)->bind($this);
foreach ($items as $key => $item) {
$count += $this->charge($item, $func, [$key]);
}
return $count;
}
function rechargeAll(?iterable $items): self {
$this->delete(null);
$this->index = 0;
$this->chargeAll($items);
return $this;
}
function getIterator(): Traversable {
$rows = $this->dbAll([
"cols" => ["key_", "item__"],
"where" => $this->getBaseFilter(),
]);
foreach ($rows as $row) {
$key = $row["key_"];
$item = $this->unserialize($row["item__"]);
yield $key => $item;
}
}
}