<pman>Intégration de la branche dev74

This commit is contained in:
Jephté Clain 2025-06-26 10:34:18 +04:00
commit 8a843d9a6f
6 changed files with 158 additions and 12 deletions

58
TODO.md
View File

@ -21,5 +21,63 @@
->all(); ->all();
``` ```
déterminer le genre de traitements que l'on peut offrir déterminer le genre de traitements que l'on peut offrir
* syntaxe pour CTable: définition des en-têtes et des valeurs des colonnes dans
la même expression
~~~php
new CTable($rows, [
"contents" => [
## champ
["Nom", "nom"],
["Prénom", "prenom"],
## fonction
["Age", function(Cursor $cursor) {
return (new Date())->diff($cursor->row["date_naissance"]);
}],
## Pas de contenu
["Vide", null],
## Contenu dynamique
["Contenu", [
"before",
v::span("hello"),
Cursor::dyn("name"),
"after",
Cursor::dyn(function(Cursor $cursor) {
return $cursor["surname"];
}),
]],
## colspan
["First",
function() { return "sur deux colonnes"; },
"colspan" => 2,
],
["Second", null],
## colspan dynamique
# la valeur de Element n'est évaluée que si colspan==null
["Groupe", function(Cursor $row) {
$break = $breaker->shouldBreakOn($row["code_groupe"]));
if ($break) {
$row->set("colspan", 2);
return "{$row["code_groupe"]} {$row["libelle_groupe"]}";
} else {
$row->set("colspan", null);
return null;
}
}, "colspan" => function(Cursor $row) {
return $row->get("colspan");
}],
["Element", function(Cursor $row) {
return $row["libelle_element"];
}]
],
]);
~~~
bien entendu, bien que ce ne soit pas démontré ici, le premier argument
(l'en-tête) est un contenu, pas seulement une chaine
* Cursor::dyn permet d'insérer une valeur qui sera évaluée plus tard lors de la
résolution du contenu
* pour Cursor, CTable, etc., un paramètre "params_func" permet de générer une
partie des paramètres de façon dynamique.
c'est juste du sucre, c'est strictement équivalent à construire le tableau
des paramètres avant d'instancier l'objet.
-*- coding: utf-8 mode: markdown -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8:noeol:binary -*- coding: utf-8 mode: markdown -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8:noeol:binary

View File

@ -269,23 +269,34 @@ abstract class AbstractPageContainer implements IPageContainer {
$this->phase = self::SETUP_PHASE; $this->phase = self::SETUP_PHASE;
if (self::ensure_setupc($page, false, $output)) { if (self::ensure_setupc($page, false, $output)) {
if ($output === false) {
# désactiver la gestion des actions si le retour est false (retour en
# l'état)
$page->dispatchAction(false);
}
$this->overrideSetup($page); $this->overrideSetup($page);
$page->afterSetup(); $page->afterSetup();
} }
$this->phase = self::PRINT_PHASE; $this->phase = self::PRINT_PHASE;
if ($output instanceof IComponent) { if ($output instanceof IComponent) {
# composant autonome
self::ensure_phasec($output); self::ensure_phasec($output);
if ($this->beforePrint($output)) { if ($this->beforePrint($output)) {
$this->haveOutput = true; $this->haveOutput = true;
co::_print([$output]); co::_print([$output]);
} }
} elseif (is_callable($output)) { } elseif (is_callable($output)) {
# générateur de contenu
if ($this->beforePrint(null)) { if ($this->beforePrint(null)) {
$this->haveOutput = true; $this->haveOutput = true;
$output(); $output();
} }
} elseif ($output === false) {
# retour en l'état (contenu déjà géré dans setup())
$this->haveOutput = false;
} elseif ($output !== null) { } elseif ($output !== null) {
# contenu json ou texte
if ($this->beforePrint(null)) { if ($this->beforePrint(null)) {
$this->haveOutput = true; $this->haveOutput = true;
if (is_iterable($output)) { if (is_iterable($output)) {
@ -299,10 +310,11 @@ abstract class AbstractPageContainer implements IPageContainer {
} }
echo "]"; echo "]";
} else { } else {
co::_print([strval($output)]); co::_write([strval($output)]);
} }
} }
} else { } else {
# afficher la page normalement
$this->overridePrint($page); $this->overridePrint($page);
} }
} catch (Throwable $e) { } catch (Throwable $e) {

View File

@ -49,6 +49,13 @@ class showmorePlugin extends BasePlugin {
protected ?string $onShow; protected ?string $onShow;
protected bool $initialShow = false;
function show(bool $show=true): self {
$this->initialShow = $show;
return $this;
}
function startc(): array { function startc(): array {
return v::sdiv(["class" => $this->containerClass]); return v::sdiv(["class" => $this->containerClass]);
} }
@ -56,7 +63,10 @@ class showmorePlugin extends BasePlugin {
function invite($vs=null): array { function invite($vs=null): array {
$vs ??= $this->inviteContent; $vs ??= $this->inviteContent;
return v::a([ return v::a([
"class" => $this->inviteClass, "class" => [
$this->inviteClass,
"hidden" => $this->initialShow,
],
"href" => "#", "href" => "#",
$vs, $vs,
]); ]);
@ -64,7 +74,10 @@ class showmorePlugin extends BasePlugin {
function startp(): array { function startp(): array {
return v::sdiv([ return v::sdiv([
"class" => [$this->panelClass, "hidden"], "class" => [
$this->panelClass,
"hidden" => !$this->initialShow,
],
]); ]);
} }

View File

@ -4,7 +4,7 @@ namespace nulib\cache;
use Closure; use Closure;
use IteratorAggregate; use IteratorAggregate;
use nulib\cache\CacheChannel; use nulib\cache\CacheChannel;
use nulib\cache\storage_cache; use nulib\cache\cache;
use nulib\cl; use nulib\cl;
use nulib\db\CapacitorChannel; use nulib\db\CapacitorChannel;
use Traversable; use Traversable;
@ -40,7 +40,7 @@ class CacheDataChannel extends CapacitorChannel implements IteratorAggregate {
} }
function getIterator(): Traversable { function getIterator(): Traversable {
$cm = storage_cache::get(); $cm = cache::get();
if ($cm->shouldUpdate($this->cacheIds)) { if ($cm->shouldUpdate($this->cacheIds)) {
$this->capacitor->reset(); $this->capacitor->reset();
foreach (($this->builder)() as $key => $row) { foreach (($this->builder)() as $key => $row) {

View File

@ -1,13 +1,20 @@
<?php <?php
namespace nulib\cache; namespace nulib\cache;
use nulib\app;
use nulib\cache\CacheChannel; use nulib\cache\CacheChannel;
use nulib\cache\CacheDataChannel; use nulib\cache\CacheDataChannel;
use nulib\db\Capacitor; use nulib\db\Capacitor;
use nulib\db\CapacitorStorage; use nulib\db\CapacitorStorage;
use nulib\db\sqlite\SqliteStorage; use nulib\db\sqlite\SqliteStorage;
class storage_cache { class cache {
protected static ?string $dbfile = null;
protected static function dbfile(): ?string {
return self::$dbfile ??= app::get()->getVarfile("cache.db");
}
protected static ?CapacitorStorage $storage = null; protected static ?CapacitorStorage $storage = null;
static function set_storage(CapacitorStorage $storage): CapacitorStorage { static function set_storage(CapacitorStorage $storage): CapacitorStorage {
@ -15,7 +22,7 @@ class storage_cache {
} }
protected static function get_storage(): CapacitorStorage { protected static function get_storage(): CapacitorStorage {
return self::$storage ??= new SqliteStorage(""); return self::$storage ??= new SqliteStorage(self::dbfile());
} }
protected static ?CacheChannel $channel = null; protected static ?CacheChannel $channel = null;

View File

@ -1,6 +1,7 @@
<?php <?php
namespace nulib\php\coll; namespace nulib\php\coll;
use ArrayAccess;
use Iterator; use Iterator;
use IteratorAggregate; use IteratorAggregate;
use nulib\cl; use nulib\cl;
@ -18,7 +19,7 @@ use Traversable;
* @property-read array|null $value alias pour $row * @property-read array|null $value alias pour $row
* @property-read iterable|null $rows la source des lignes * @property-read iterable|null $rows la source des lignes
*/ */
class Cursor implements Iterator { class Cursor implements Iterator, ArrayAccess {
const PARAMS_SCHEMA = [ const PARAMS_SCHEMA = [
"rows" => ["?iterable"], "rows" => ["?iterable"],
"rows_func" => ["?callable"], "rows_func" => ["?callable"],
@ -70,10 +71,14 @@ 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(mixed $rows, Cursor): ?iterable</code> */ /**
* une fonction de signature <code>function(mixed $rows, Cursor): ?iterable</code>
*/
private ?func $rowsFunc; private ?func $rowsFunc;
/** une fonction de signature <code>function(?array $row, Cursor): bool</code> */ /**
* une fonction de signature <code>function(?array $row, Cursor): bool</code>
*/
private ?func $filterFunc = null; private ?func $filterFunc = null;
function setFilter(array $filter): self { function setFilter(array $filter): self {
@ -89,7 +94,9 @@ class Cursor implements Iterator {
return $this; return $this;
} }
/** une fonction de signature <code>function(?array $row, Cursor): ?array</code> */ /**
* une fonction de signature <code>function(?array $row, Cursor): ?array</code>
*/
private ?func $mapFunc = null; private ?func $mapFunc = null;
function setMap(array $map): self { function setMap(array $map): self {
@ -105,7 +112,9 @@ class Cursor implements Iterator {
return $this; return $this;
} }
/** une fonction de signature <code>function(?array $row, Cursor): ?array</code> */ /**
* une fonction de signature <code>function(?array $row, Cursor): ?array</code>
*/
private ?func $colsFunc = null; private ?func $colsFunc = null;
function setColsFunc(?callable $func): self { function setColsFunc(?callable $func): self {
@ -151,6 +160,50 @@ class Cursor implements Iterator {
return null; return null;
} }
function offsetExists($offset): bool {
return cl::has($this->row, $offset);
}
function offsetGet($offset) {
return cl::get($this->row, $offset);
}
function offsetSet($offset, $value): void {
cl::set($this->row, $offset, $value);
}
function offsetUnset($offset): void {
cl::del($this->row, $offset);
}
/**
* données de session: cela permet de maintenir certaines informations pendant
* le parcours des données
*/
protected ?array $data;
/** @param string|int $key */
function has($key): bool {
return cl::has($this->data, $key);
}
/** @param string|int $key */
function get($key) {
return cl::get($this->data, $key);
}
/** @param string|int $key */
function set($key, $value): void {
$this->data[$key] = $value;
}
/** @param string|int $key */
function del($key) {
$orig = cl::get($this->data, $key);
unset($this->data[$key]);
return $orig;
}
protected function convertToRow($raw): ?array { protected function convertToRow($raw): ?array {
return cl::withn($raw); return cl::withn($raw);
} }
@ -177,6 +230,7 @@ class Cursor implements Iterator {
$this->key = null; $this->key = null;
$this->raw = null; $this->raw = null;
$this->row = null; $this->row = null;
$this->data = null;
if ($this->rowsGenerator !== null) { if ($this->rowsGenerator !== null) {
$rows = $this->rowsGenerator; $rows = $this->rowsGenerator;
if ($rows instanceof IteratorAggregate) $rows = $rows->getIterator(); if ($rows instanceof IteratorAggregate) $rows = $rows->getIterator();
@ -223,6 +277,8 @@ class Cursor implements Iterator {
$this->key = null; $this->key = null;
$this->raw = null; $this->raw = null;
$this->row = null; $this->row = null;
# ne pas toucher à data, l'utilisateur peut vouloir continuer à consulter
# les valeurs
} }
return $valid; return $valid;
} }