From 9387949937342c0270ddafb0d2a668a86e69913c Mon Sep 17 00:00:00 2001 From: Jephte Clain Date: Fri, 30 May 2025 23:39:53 +0400 Subject: [PATCH 01/11] Init changelog & version 0.6.0p82 --- CHANGES.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGES.md b/CHANGES.md index f3b7c5a..3779907 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,3 +1,5 @@ +## Release 0.6.0p82 du 30/05/2025-23:39 + ## Release 0.6.0p74 du 30/05/2025-23:35 migrer de nulib/php à nulib/base From 9fc0464c3d9ceef750abcff286d7e50132a5f164 Mon Sep 17 00:00:00 2001 From: Jephte Clain Date: Mon, 2 Jun 2025 07:46:36 +0400 Subject: [PATCH 02/11] modifs.mineures sans commentaires --- .idea/php.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/.idea/php.xml b/.idea/php.xml index 3c96682..8f998bb 100644 --- a/.idea/php.xml +++ b/.idea/php.xml @@ -70,6 +70,7 @@ + From afaa816effac909cb0284ad9b0853cd0a9813c9d Mon Sep 17 00:00:00 2001 From: Jephte Clain Date: Thu, 5 Jun 2025 14:56:01 +0400 Subject: [PATCH 03/11] =?UTF-8?q?d=C3=A9placer=20certains=20fichiers=20dan?= =?UTF-8?q?s=20nur-ture?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bin/csv2xlsx.php | 2 +- bin/dumpser.php | 2 +- bin/json2yml.php | 2 +- bin/nucache.php | 2 +- .../steam-train.php => bin/storage.mysql.php | 4 +- bin/storage.sqlite.php | 7 + bin/yml2json.php | 2 +- composer.json | 7 +- src/cli/BgLauncherApp.php | 124 ++++++++++++++++++ src/{tools => cli}/Csv2xlsxApp.php | 2 +- src/{tools => cli}/DumpserApp.php | 2 +- src/{tools => cli}/Json2yamlApp.php | 2 +- src/{tools => cli}/NucacheApp.php | 4 +- src/cli/SteamTrainApp.php | 53 ++++++++ .../cli/StorageMysqlApp.php | 11 +- .../cli/StorageSqliteApp.php | 13 +- src/{tools => cli}/Yaml2jsonApp.php | 2 +- 17 files changed, 212 insertions(+), 29 deletions(-) rename nur_bin/steam-train.php => bin/storage.mysql.php (63%) create mode 100755 bin/storage.sqlite.php create mode 100644 src/cli/BgLauncherApp.php rename src/{tools => cli}/Csv2xlsxApp.php (96%) rename src/{tools => cli}/DumpserApp.php (96%) rename src/{tools => cli}/Json2yamlApp.php (94%) rename src/{tools => cli}/NucacheApp.php (99%) create mode 100644 src/cli/SteamTrainApp.php rename nur_bin/storage.mysql.php => src/cli/StorageMysqlApp.php (95%) mode change 100755 => 100644 rename nur_bin/storage.sqlite.php => src/cli/StorageSqliteApp.php (95%) mode change 100755 => 100644 rename src/{tools => cli}/Yaml2jsonApp.php (94%) diff --git a/bin/csv2xlsx.php b/bin/csv2xlsx.php index 0f0bb32..5fb7464 100755 --- a/bin/csv2xlsx.php +++ b/bin/csv2xlsx.php @@ -2,6 +2,6 @@ "lancer un script en tâche de fond", + "usage" => "ApplicationClass args...", + + "sections" => [ + parent::VERBOSITY_SECTION, + ], + + ["-i", "--infos", "name" => "action", "value" => self::ACTION_INFOS, + "help" => "Afficher des informations sur la tâche", + ], + ["-s", "--start", "name" => "action", "value" => self::ACTION_START, + "help" => "Démarrer la tâche", + ], + ["-k", "--stop", "name" => "action", "value" => self::ACTION_STOP, + "help" => "Arrêter la tâche", + ], + ]; + + protected int $action = self::ACTION_START; + + protected ?array $args = null; + + static function show_infos(RunFile $runfile, ?int $level=null): void { + msg::print($runfile->getDesc(), $level); + msg::print(yaml::with(["data" => $runfile->read()]), ($level ?? 0) - 1); + } + + function main() { + $args = $this->args; + + $appClass = $args[0] ?? null; + if ($appClass === null) { + self::die("Vous devez spécifier la classe de l'application"); + } + $appClass = $args[0] = str_replace("/", "\\", $appClass); + if (!class_exists($appClass)) { + self::die("$appClass: classe non trouvée"); + } + + $useRunfile = constant("$appClass::USE_RUNFILE"); + if (!$useRunfile) { + self::die("Cette application ne supporte le lancement en tâche de fond"); + } + + $runfile = app::with($appClass)->getRunfile(); + switch ($this->action) { + case self::ACTION_START: + $argc = count($args); + $appClass::_manage_runfile($argc, $args, $runfile); + if ($runfile->warnIfLocked()) self::exit(app::EC_LOCKED); + array_splice($args, 0, 0, [ + PHP_BINARY, + path::abspath(NULIB_APP_app_launcher), + ]); + app::params_putenv(); + self::_start($args, $runfile); + break; + case self::ACTION_STOP: + self::_stop($runfile); + self::show_infos($runfile, -1); + break; + case self::ACTION_INFOS: + self::show_infos($runfile); + break; + } + } + + public static function _start(array $args, Runfile $runfile): void { + $pid = pcntl_fork(); + if ($pid == -1) { + # parent, impossible de forker + throw new ExitError(app::EC_FORK_PARENT, "Unable to fork"); + } elseif (!$pid) { + # child, fork ok + $runfile->wfPrepare($pid); + $outfile = $runfile->getOutfile() ?? "/tmp/NULIB_APP_app_console.out"; + $exitcode = app::EC_FORK_CHILD; + try { + # rediriger STDIN, STDOUT et STDERR + fclose(fopen($outfile, "wb")); // vider le fichier + fclose(STDIN); $in = fopen("/dev/null", "rb"); + fclose(STDOUT); $out = fopen($outfile, "ab"); + fclose(STDERR); $err = fopen($outfile, "ab"); + # puis lancer la commande + $cmd = new Cmd($args); + $cmd->addSource("/g/init.env"); + $cmd->addRedir("both", $outfile, true); + $cmd->fork_exec($exitcode, false); + sh::_waitpid(-$pid, $exitcode); + } finally { + $runfile->wfReaped($exitcode); + } + } + } + + public static function _stop(Runfile $runfile): bool { + $data = $runfile->read(); + $pid = $runfile->_getCid($data); + msg::action("stop $pid"); + if ($runfile->wfKill($reason)) { + msg::asuccess(); + return true; + } else { + msg::afailure($reason); + return false; + } + } +} diff --git a/src/tools/Csv2xlsxApp.php b/src/cli/Csv2xlsxApp.php similarity index 96% rename from src/tools/Csv2xlsxApp.php rename to src/cli/Csv2xlsxApp.php index 7ac9a59..c38a149 100644 --- a/src/tools/Csv2xlsxApp.php +++ b/src/cli/Csv2xlsxApp.php @@ -1,5 +1,5 @@ self::TITLE, + "description" => << 1, + "help" => "spécifier le nombre d'étapes", + ], + ["-f", "--force-enabled", "value" => true, + "help" => "lancer la commande même si les tâches planifiées sont désactivées", + ], + ["-n", "--no-install-signal-handler", "value" => false, + "help" => "ne pas installer le gestionnaire de signaux", + ], + ]; + + protected $count = 100; + + protected bool $forceEnabled = false; + + protected bool $installSignalHandler = true; + + function main() { + app::check_bgapplication_enabled($this->forceEnabled); + if ($this->installSignalHandler) app::install_signal_handler(); + $count = intval($this->count); + msg::info("Starting train for ".words::q($count, "step#s")); + app::action("Running train...", $count); + for ($i = 1; $i <= $count; $i++) { + msg::print("Tchou-tchou! x $i"); + app::step(); + sleep(1); + } + msg::info("Stopping train at ".new DateTime()); + } +} diff --git a/nur_bin/storage.mysql.php b/src/cli/StorageMysqlApp.php old mode 100755 new mode 100644 similarity index 95% rename from nur_bin/storage.mysql.php rename to src/cli/StorageMysqlApp.php index 6e84c51..18cd551 --- a/nur_bin/storage.mysql.php +++ b/src/cli/StorageMysqlApp.php @@ -1,16 +1,15 @@ -#!/usr/bin/php Date: Thu, 5 Jun 2025 15:38:21 +0400 Subject: [PATCH 04/11] factoriser --- src/cli/AbstractStorageApp.php | 111 ++++++++++++++++++++++++++++++ src/cli/StorageMysqlApp.php | 97 +++------------------------ src/cli/StorageSqliteApp.php | 119 +++------------------------------ 3 files changed, 131 insertions(+), 196 deletions(-) create mode 100644 src/cli/AbstractStorageApp.php diff --git a/src/cli/AbstractStorageApp.php b/src/cli/AbstractStorageApp.php new file mode 100644 index 0000000..41cea65 --- /dev/null +++ b/src/cli/AbstractStorageApp.php @@ -0,0 +1,111 @@ +|<|>|<=|>=|(?:is\s+)?null|(?:is\s+)?not\s+null)\s*(.*)$/', $arg, $ms); + } + + protected function storageCtl(CapacitorStorage $storage): void { + $args = $this->args; + + $channelClass = $this->channelClass; + $tableName = $this->tableName; + if ($channelClass === null && $tableName === null) { + $name = A::shift($args); + if ($name !== null) { + if (!$storage->channelExists($name, $row)) { + self::die("$name: nom de canal de données introuvable"); + } + if ($row["class_name"] !== "class@anonymous") $channelClass = $row["class_name"]; + else $tableName = $row["table_name"]; + } + } + if ($channelClass !== null) { + $channelClass = str_replace("/", "\\", $channelClass); + $channel = new $channelClass; + } elseif ($tableName !== null) { + $channel = new class($tableName) extends CapacitorChannel { + function __construct(?string $name=null) { + parent::__construct($name); + $this->tableName = $name; + } + }; + } else { + $found = false; + foreach ($storage->getChannels() as $row) { + msg::print($row["name"]); + $found = true; + } + if ($found) self::exit(); + self::die("Vous devez spécifier le canal de données"); + } + $capacitor = new Capacitor($storage, $channel); + + switch ($this->action) { + case self::ACTION_RESET: + $capacitor->reset(true); + break; + case self::ACTION_QUERY: + if (!$args) { + # lister les id + $out = new Stream(STDOUT); + $primaryKeys = $storage->getPrimaryKeys($channel); + $rows = $storage->db()->all([ + "select", + "cols" => $primaryKeys, + "from" => $channel->getTableName(), + ]); + $out->fputcsv($primaryKeys); + foreach ($rows as $row) { + $rowIds = $storage->getRowIds($channel, $row); + $out->fputcsv($rowIds); + } + } else { + # afficher les lignes correspondantes + if (count($args) == 1 && !self::isa_cond($args[0])) { + $filter = $args[0]; + } else { + $filter = []; + $ms = null; + foreach ($args as $arg) { + if (self::isa_cond($arg, $ms)) { + $filter[$ms[1]] = [$ms[2], $ms[3]]; + } else { + $filter[$arg] = ["not null"]; + } + } + } + $first = true; + $capacitor->each($filter, function ($item, $row) use (&$first) { + if ($first) $first = false; + else echo "---\n"; + yaml::dump($row); + }); + } + break; + case self::ACTION_SQL: + echo $capacitor->getCreateSql()."\n"; + break; + } + } +} diff --git a/src/cli/StorageMysqlApp.php b/src/cli/StorageMysqlApp.php index 18cd551..42fea8e 100644 --- a/src/cli/StorageMysqlApp.php +++ b/src/cli/StorageMysqlApp.php @@ -1,26 +1,23 @@ parent::ARGS, "purpose" => "gestion d'un capacitor mysql", "usage" => [ - "-d DBCONN -c CHANNEL [--query] key=value...", - "-d DBCONN -c CHANNEL --sql-create", - ], - ["-d", "--dbconn", "args" => 1, - "help" => "nom de la connexion à la base de données", + "DBCONN [CHANNEL_NAME | -t TABLE | -c CHANNEL_CLASS] [--query] key=value...", + "DBCONN [CHANNEL_NAME | -t TABLE | -c CHANNEL_CLASS] --sql-create", ], ["-t", "--table-name", "args" => 1, "help" => "nom de la table porteuse du canal de données", @@ -28,6 +25,9 @@ class StorageMysqlApp extends Application { ["-c", "--channel-class", "args" => 1, "help" => "nom de la classe dérivée de CapacitorChannel", ], + ["-z", "--reset", "name" => "action", "value" => self::ACTION_RESET, + "help" => "réinitialiser le canal", + ], ["--query", "name" => "action", "value" => self::ACTION_QUERY, "help" => "lister les lignes correspondant aux valeurs spécifiées. c'est l'action par défaut", ], @@ -35,88 +35,13 @@ class StorageMysqlApp extends Application { "help" => "afficher la requête pour créer la table", ], ]; - - protected ?string $dbconn = null; - - protected ?string $tableName = null; - - protected ?string $channelClass = null; - - protected int $action = self::ACTION_QUERY; - - protected ?array $args = null; - - protected static function isa_cond(string $arg, ?array &$ms=null): bool { - return preg_match('/^(.+?)\s*(=|<>|<|>|<=|>=|(?:is\s+)?null|(?:is\s+)?not\s+null)\s*(.*)$/', $arg, $ms); - } - function main() { - $dbconn = $this->dbconn; + $dbconn = A::shift($this->args); if ($dbconn === null) self::die("Vous devez spécifier la base de données"); $tmp = config::db($dbconn); if ($tmp === null) self::die("$dbconn: base de données invalide"); - $dbconn = $tmp; + $storage = new MysqlStorage($tmp); - if ($this->channelClass !== null) { - $channelClass = str_replace("/", "\\", $this->channelClass); - $channel = new $channelClass; - } elseif ($this->tableName !== null) { - $channel = new class($this->tableName) extends CapacitorChannel { - function __construct(?string $name=null) { - parent::__construct($name); - $this->tableName = $name; - } - }; - } else { - self::die("Vous devez spécifier le canal de données"); - } - - $storage = new MysqlStorage($dbconn); - $capacitor = new Capacitor($storage, $channel); - - switch ($this->action) { - case self::ACTION_QUERY: - $args = $this->args; - if (!$args) { - # lister les id - $out = new Stream(STDOUT); - $primaryKeys = $storage->getPrimaryKeys($channel); - $rows = $storage->db()->all([ - "select", - "cols" => $primaryKeys, - "from" => $channel->getTableName(), - ]); - $out->fputcsv($primaryKeys); - foreach ($rows as $row) { - $rowIds = $storage->getRowIds($channel, $row); - $out->fputcsv($rowIds); - } - } else { - # afficher les lignes correspondantes - if (count($args) == 1 && !self::isa_cond($args[0])) { - $filter = $args[0]; - } else { - $filter = []; - $ms = null; - foreach ($args as $arg) { - if (self::isa_cond($arg, $ms)) { - $filter[$ms[1]] = [$ms[2], $ms[3]]; - } else { - $filter[$arg] = ["not null"]; - } - } - } - $first = true; - $capacitor->each($filter, function ($item, $row) use (&$first) { - if ($first) $first = false; - else echo "---\n"; - yaml::dump($row); - }); - } - break; - case self::ACTION_SQL: - echo $capacitor->getCreateSql()."\n"; - break; - } + $this->storageCtl($storage); } } diff --git a/src/cli/StorageSqliteApp.php b/src/cli/StorageSqliteApp.php index a0880cf..cacdba0 100644 --- a/src/cli/StorageSqliteApp.php +++ b/src/cli/StorageSqliteApp.php @@ -1,29 +1,16 @@ parent::ARGS, "purpose" => "gestion d'un capacitor sqlite", "usage" => [ - "-f DBFILE -n CHANNEL [--query] key=value...", - "-f DBFILE -n CHANNEL --sql-create", - ], - ["-f", "--dbfile", "args" => 1, - "help" => "chemin vers la base de données", - ], - ["-n", "--name", "args" => 1, - "help" => "nom du canal de données. table-name et channel-class sont chargés depuis la base de données", + "DBFILE [CHANNEL_NAME | -t TABLE | -c CHANNEL_CLASS] [--query] key=value...", + "DBFILE [CHANNEL_NAME | -t TABLE | -c CHANNEL_CLASS] --sql-create", ], ["-t", "--table-name", "args" => 1, "help" => "nom de la table porteuse du canal de données", @@ -31,6 +18,9 @@ class StorageSqliteApp extends Application { ["-c", "--channel-class", "args" => 1, "help" => "nom de la classe dérivée de CapacitorChannel", ], + ["-z", "--reset", "name" => "action", "value" => self::ACTION_RESET, + "help" => "réinitialiser le canal", + ], ["--query", "name" => "action", "value" => self::ACTION_QUERY, "help" => "lister les lignes correspondant aux valeurs spécifiées. c'est l'action par défaut", ], @@ -39,103 +29,12 @@ class StorageSqliteApp extends Application { ], ]; - protected ?string $dbfile = null; - - protected ?string $name = null; - - protected ?string $tableName = null; - - protected ?string $channelClass = null; - - protected int $action = self::ACTION_QUERY; - - protected ?array $args = null; - - protected static function isa_cond(string $arg, ?array &$ms=null): bool { - return preg_match('/^(.+?)\s*(=|<>|<|>|<=|>=|(?:is\s+)?null|(?:is\s+)?not\s+null)\s*(.*)$/', $arg, $ms); - } - function main() { - $dbfile = $this->dbfile; + $dbfile = A::shift($this->args); if ($dbfile === null) self::die("Vous devez spécifier la base de données"); if (!file_exists($dbfile)) self::die("$dbfile: fichier introuvable"); $storage = new SqliteStorage($dbfile); - $db = $storage->db(); - $name = $this->name; - $channelClass = $this->channelClass; - $tableName = $this->tableName; - if ($name !== null) { - if (!$storage->channelExists($name, $row)) { - self::die("$name: nom de canal de données introuvable"); - } - if ($row["class_name"] !== "class@anonymous") $channelClass = $row["class_name"]; - else $tableName = $row["table_name"]; - } - if ($channelClass !== null) { - $channelClass = str_replace("/", "\\", $channelClass); - $channel = new $channelClass; - } elseif ($tableName !== null) { - $channel = new class($tableName) extends CapacitorChannel { - function __construct(?string $name=null) { - parent::__construct($name); - $this->tableName = $name; - } - }; - } else { - $found = false; - foreach ($storage->getChannels() as $row) { - msg::print($row["name"]); - $found = true; - } - if ($found) self::exit(); - self::die("Vous devez spécifier le canal de données"); - } - $capacitor = new Capacitor($storage, $channel); - - switch ($this->action) { - case self::ACTION_QUERY: - $args = $this->args; - if (!$args) { - # lister les id - $out = new Stream(STDOUT); - $primaryKeys = $storage->getPrimaryKeys($channel); - $rows = $db->all([ - "select", - "cols" => $primaryKeys, - "from" => $channel->getTableName(), - ]); - $out->fputcsv($primaryKeys); - foreach ($rows as $row) { - $rowIds = $storage->getRowIds($channel, $row); - $out->fputcsv($rowIds); - } - } else { - # afficher les lignes correspondantes - if (count($args) == 1 && !self::isa_cond($args[0])) { - $filter = $args[0]; - } else { - $filter = []; - $ms = null; - foreach ($args as $arg) { - if (self::isa_cond($arg, $ms)) { - $filter[$ms[1]] = [$ms[2], $ms[3]]; - } else { - $filter[$arg] = ["not null"]; - } - } - } - $first = true; - $capacitor->each($filter, function ($item, $row) use (&$first) { - if ($first) $first = false; - else echo "---\n"; - yaml::dump($row); - }); - } - break; - case self::ACTION_SQL: - echo $capacitor->getCreateSql()."\n"; - break; - } + $this->storageCtl($storage); } } From aaa99825f0ebaacc5d9311bcb09ae12050530fb7 Mon Sep 17 00:00:00 2001 From: Jephte Clain Date: Thu, 5 Jun 2025 15:40:18 +0400 Subject: [PATCH 05/11] ajout storage.pgsql --- bin/storage.pgsql.php | 7 +++++++ composer.json | 1 + src/cli/StoragePgsqlApp.php | 41 +++++++++++++++++++++++++++++++++++++ 3 files changed, 49 insertions(+) create mode 100755 bin/storage.pgsql.php create mode 100644 src/cli/StoragePgsqlApp.php diff --git a/bin/storage.pgsql.php b/bin/storage.pgsql.php new file mode 100755 index 0000000..296a6c6 --- /dev/null +++ b/bin/storage.pgsql.php @@ -0,0 +1,7 @@ +#!/usr/bin/php + parent::ARGS, + "purpose" => "gestion d'un capacitor pgsql", + "usage" => [ + "DBCONN [CHANNEL_NAME | -t TABLE | -c CHANNEL_CLASS] [--query] key=value...", + "DBCONN [CHANNEL_NAME | -t TABLE | -c CHANNEL_CLASS] --sql-create", + ], + ["-t", "--table-name", "args" => 1, + "help" => "nom de la table porteuse du canal de données", + ], + ["-c", "--channel-class", "args" => 1, + "help" => "nom de la classe dérivée de CapacitorChannel", + ], + ["-z", "--reset", "name" => "action", "value" => self::ACTION_RESET, + "help" => "réinitialiser le canal", + ], + ["--query", "name" => "action", "value" => self::ACTION_QUERY, + "help" => "lister les lignes correspondant aux valeurs spécifiées. c'est l'action par défaut", + ], + ["-s", "--sql-create", "name" => "action", "value" => self::ACTION_SQL, + "help" => "afficher la requête pour créer la table", + ], + ]; + function main() { + $dbconn = A::shift($this->args); + if ($dbconn === null) self::die("Vous devez spécifier la base de données"); + $tmp = config::db($dbconn); + if ($tmp === null) self::die("$dbconn: base de données invalide"); + $storage = new PgsqlStorage($tmp); + + $this->storageCtl($storage); + } +} From e221300ba47f6d1177349b55834c8b2adc30dc8b Mon Sep 17 00:00:00 2001 From: Jephte Clain Date: Tue, 10 Jun 2025 17:55:28 +0400 Subject: [PATCH 06/11] support du retour direct depuis setup() --- nur_src/v/base/AbstractPageContainer.php | 56 +++++++-- nur_src/v/base/TComponent.php | 2 +- nur_src/v/html5/Html5BasicPageContainer.php | 42 ++++--- .../v/html5/Html5NavigablePageContainer.php | 114 +++++++++--------- nur_src/v/html5/Html5VanillaPageContainer.php | 8 +- nur_src/v/model/IComponent.php | 2 +- nur_src/v/vp/AppCasauthPage.php | 2 +- nur_src/v/vp/AppDevauthPage.php | 2 +- nur_src/v/vp/AppExtauthPage.php | 2 +- nur_src/v/vp/AppLogoutPage.php | 2 +- 10 files changed, 137 insertions(+), 95 deletions(-) diff --git a/nur_src/v/base/AbstractPageContainer.php b/nur_src/v/base/AbstractPageContainer.php index 6c027da..260e607 100644 --- a/nur_src/v/base/AbstractPageContainer.php +++ b/nur_src/v/base/AbstractPageContainer.php @@ -8,6 +8,7 @@ use nur\b\ExitError; use nur\co; use nur\config; use nur\func; +use nur\json; use nur\v\html5\Html5BasicErrorPage; use nur\v\model\IChildComponent; use nur\v\model\IComponent; @@ -19,6 +20,7 @@ use nur\v\page; use nur\v\prefix; use nur\v\vo; use Throwable; +use Traversable; abstract class AbstractPageContainer implements IPageContainer { protected static function ensure_preparec(IComponent $c, bool $afterPrepare=false): bool { @@ -41,10 +43,10 @@ abstract class AbstractPageContainer implements IPageContainer { return false; } - protected static function ensure_setupc(IComponent $c, bool $afterSetup=false): bool { + protected static function ensure_setupc(IComponent $c, bool $afterSetup=false, &$output=null): bool { if (!$c->didSetup()) { $c->beforeSetup(); - $c->setup(); + $output = $c->setup(); if ($afterSetup) $c->afterSetup(); return true; } @@ -248,6 +250,7 @@ abstract class AbstractPageContainer implements IPageContainer { function print(): void { $page = $this->page; page::set_current_page($page); + $output = null; try { $this->phase = self::PREPARE_PHASE; @@ -265,14 +268,43 @@ abstract class AbstractPageContainer implements IPageContainer { config::configure($this->config["configure_options"]); $this->phase = self::SETUP_PHASE; - if (self::ensure_setupc($page)) { + if (self::ensure_setupc($page, false, $output)) { $this->overrideSetup($page); $page->afterSetup(); } $this->phase = self::PRINT_PHASE; - $this->overridePrint($page); - + if ($output instanceof IComponent) { + self::ensure_phasec($output); + if ($this->beforePrint($output)) { + $this->haveOutput = true; + co::_print([$output]); + } + } elseif (is_callable($output)) { + if ($this->beforePrint(null)) { + $this->haveOutput = true; + $output(); + } + } elseif ($output !== null) { + if ($this->beforePrint(null)) { + $this->haveOutput = true; + if (is_iterable($output)) { + header("Content-Type: application/json"); + echo "["; + $sep = ""; + foreach ($output as $data) { + $line = json::encode($data); + echo "$sep$line\n"; + $sep = ","; + } + echo "]"; + } else { + co::_print([strval($output)]); + } + } + } else { + $this->overridePrint($page); + } } catch (Throwable $e) { if ($e instanceof ExitError && !$e->isError()) { # NOP @@ -293,6 +325,9 @@ abstract class AbstractPageContainer implements IPageContainer { } if ($page->didSetup()) { $this->phase = self::TEARDOWN_PHASE; + if ($output instanceof IComponent) { + self::ensure_teardownc($output); + } if (self::ensure_teardownc($page)) { $this->overrideTeardown($page); $page->afterTeardown(); @@ -310,11 +345,14 @@ abstract class AbstractPageContainer implements IPageContainer { protected function overrideSetup(IPage $page): void { } + protected function beforePrint(?IComponent $component): bool { + return $component === null || $component->haveContent(); + } + protected function overridePrint(IPage $page): void { - if ($page->haveContent()) { - $this->haveOutput = true; - co::_print([$page]); - } + if (!$this->beforePrint($page)) return; + $this->haveOutput = true; + co::_print([$page]); } protected function overrideTeardown(IPage $page): void { diff --git a/nur_src/v/base/TComponent.php b/nur_src/v/base/TComponent.php index 8d0035d..61dcd46 100644 --- a/nur_src/v/base/TComponent.php +++ b/nur_src/v/base/TComponent.php @@ -55,7 +55,7 @@ trait TComponent { protected $setupDone = false; function beforeSetup(): void {} - function setup(): void {} + function setup() {} function afterSetup(): void { $this->setupDone = true; } function didSetup(): bool { return $this->setupDone; } diff --git a/nur_src/v/html5/Html5BasicPageContainer.php b/nur_src/v/html5/Html5BasicPageContainer.php index ddcd6fd..4ba485b 100644 --- a/nur_src/v/html5/Html5BasicPageContainer.php +++ b/nur_src/v/html5/Html5BasicPageContainer.php @@ -6,6 +6,7 @@ use nur\co; use nur\session; use nur\v\ly; use nur\v\model\IBasicPage; +use nur\v\model\IComponent; use nur\v\model\IPage; class Html5BasicPageContainer extends Html5VanillaPageContainer { @@ -23,30 +24,31 @@ class Html5BasicPageContainer extends Html5VanillaPageContainer { function isAutocloseSession(): bool { return $this->config["autoclose_session"]; } - protected function overridePrint(IPage $page): void { + protected function beforePrint(?IComponent $component): bool { if ($this->isAutocloseSession()) session::close(); + return parent::beforePrint($component); + } + + protected function overridePrint(IPage $page): void { + if (!$this->beforePrint($page)) return; if ($page instanceof IBasicPage) { - if ($page->haveContent()) { - $this->doResolveConfig(); - $this->haveOutput = true; - $this->printStartHtml(); - $this->printStartHead(); - $this->printCss(); - $this->printJs(); - $this->printScript(); - $this->printHeadTitle(); - $this->printEndHead(); - $this->printStartBody(); - $this->printContent(); - $this->printEndBody(); - $this->printEndHtml(); - } + $this->doResolveConfig(); + $this->haveOutput = true; + $this->printStartHtml(); + $this->printStartHead(); + $this->printCss(); + $this->printJs(); + $this->printScript(); + $this->printHeadTitle(); + $this->printEndHead(); + $this->printStartBody(); + $this->printContent(); + $this->printEndBody(); + $this->printEndHtml(); } else { # si ce n'est pas une instance de IBasicPage, l'imprimer tel quel - if ($page->haveContent()) { - $this->haveOutput = true; - co::_write([$this->page]); - } + $this->haveOutput = true; + co::_write([$page]); } } diff --git a/nur_src/v/html5/Html5NavigablePageContainer.php b/nur_src/v/html5/Html5NavigablePageContainer.php index ab02ef1..ccc80b7 100644 --- a/nur_src/v/html5/Html5NavigablePageContainer.php +++ b/nur_src/v/html5/Html5NavigablePageContainer.php @@ -12,69 +12,65 @@ use nur\v\v; class Html5NavigablePageContainer extends Html5BasicPageContainer { protected function overridePrint(IPage $page): void { - if ($this->isAutocloseSession()) session::close(); + if (!$this->beforePrint($page)) return; if ($page instanceof IBasicPage) { - if ($page->haveContent()) { - $this->doResolveConfig(); - $this->haveOutput = true; - $this->printStartHtml(); - $this->printStartHead(); - $this->printCss(); - $this->printJs(); - $this->printScript(); - $this->printHeadTitle(); - $this->printEndHead(); - $this->printStartBody(); - if ($page instanceof INavigablePage) { - $showNavigation = $page->navigationShowNavigation(); - $implementsOwnLayout = $page->navigationImplementsOwnLayout(); - $containerOptions = $page->CONTAINER_OPTIONS(); - } else { - $showNavigation = false; - $containerOptions = null; - } - if ($showNavigation) { - $page->beforePrintStartNavigation(); - if ($implementsOwnLayout) $page->printStartNavigation(); - else $this->printStartNavigation($page->NAVBAR_OPTIONS()); - $page->afterPrintStartNavigation(); - - $page->beforePrintNavigation(); - $page->printNavigation(); - $page->afterPrintNavigation(); - - $page->beforePrintEndNavigation(); - if ($implementsOwnLayout) $page->printEndNavigation(); - else $this->printEndNavigation(); - $page->afterPrintEndNavigation(); - - $page->beforePrintStartContainer(); - if ($implementsOwnLayout) $page->printStartContainer(); - else $this->printStartContainer($containerOptions); - $page->afterPrintStartContainer(); - } else { - $this->printStartContainer($containerOptions); - } - $this->printContent(); - # s'assurer que le layout est correctement fermé - ly::end(); - if ($showNavigation) { - $page->beforePrintEndContainer(); - if ($implementsOwnLayout) $page->printEndContainer(); - else $this->printEndContainer(); - $page->afterPrintEndContainer(); - } else { - $this->printEndContainer(); - } - $this->printEndBody(); - $this->printEndHtml(); + $this->doResolveConfig(); + $this->haveOutput = true; + $this->printStartHtml(); + $this->printStartHead(); + $this->printCss(); + $this->printJs(); + $this->printScript(); + $this->printHeadTitle(); + $this->printEndHead(); + $this->printStartBody(); + if ($page instanceof INavigablePage) { + $showNavigation = $page->navigationShowNavigation(); + $implementsOwnLayout = $page->navigationImplementsOwnLayout(); + $containerOptions = $page->CONTAINER_OPTIONS(); + } else { + $showNavigation = false; + $containerOptions = null; } + if ($showNavigation) { + $page->beforePrintStartNavigation(); + if ($implementsOwnLayout) $page->printStartNavigation(); + else $this->printStartNavigation($page->NAVBAR_OPTIONS()); + $page->afterPrintStartNavigation(); + + $page->beforePrintNavigation(); + $page->printNavigation(); + $page->afterPrintNavigation(); + + $page->beforePrintEndNavigation(); + if ($implementsOwnLayout) $page->printEndNavigation(); + else $this->printEndNavigation(); + $page->afterPrintEndNavigation(); + + $page->beforePrintStartContainer(); + if ($implementsOwnLayout) $page->printStartContainer(); + else $this->printStartContainer($containerOptions); + $page->afterPrintStartContainer(); + } else { + $this->printStartContainer($containerOptions); + } + $this->printContent(); + # s'assurer que le layout est correctement fermé + ly::end(); + if ($showNavigation) { + $page->beforePrintEndContainer(); + if ($implementsOwnLayout) $page->printEndContainer(); + else $this->printEndContainer(); + $page->afterPrintEndContainer(); + } else { + $this->printEndContainer(); + } + $this->printEndBody(); + $this->printEndHtml(); } else { # si ce n'est pas une instance de IBasicPage, l'imprimer tel quel - if ($page->haveContent()) { - $this->haveOutput = true; - co::_write([$this->page]); - } + $this->haveOutput = true; + co::_write([$this->page]); } } diff --git a/nur_src/v/html5/Html5VanillaPageContainer.php b/nur_src/v/html5/Html5VanillaPageContainer.php index bad67ac..47a1fbe 100644 --- a/nur_src/v/html5/Html5VanillaPageContainer.php +++ b/nur_src/v/html5/Html5VanillaPageContainer.php @@ -12,6 +12,7 @@ use nur\v\base\AbstractPageContainer; use nur\v\base\MenuManager; use nur\v\fo; use nur\v\ly; +use nur\v\model\IBasicPage; use nur\v\model\IComponent; use nur\v\model\IPage; use nur\v\model\IPlugin; @@ -46,7 +47,8 @@ class Html5VanillaPageContainer extends AbstractPageContainer { } protected function overridePrint(IPage $page): void { - if ($page->haveContent()) { + if (!$this->beforePrint($page)) return; + if ($page instanceof IPage) { $this->doResolveConfig(); $this->haveOutput = true; $this->printStartHtml(); @@ -62,6 +64,10 @@ class Html5VanillaPageContainer extends AbstractPageContainer { $this->printContent(); $this->printEndBody(); $this->printEndHtml(); + } else { + # si ce n'est pas une instance de IPage, l'imprimer tel quel + $this->haveOutput = true; + co::_write([$page]); } } diff --git a/nur_src/v/model/IComponent.php b/nur_src/v/model/IComponent.php index 30ab379..8b2bd2d 100644 --- a/nur_src/v/model/IComponent.php +++ b/nur_src/v/model/IComponent.php @@ -43,7 +43,7 @@ interface IComponent extends IPlugin { function beforeSetup(): void; /** initialiser le composant */ - function setup(): void; + function setup(); /** marquer le composant comme initialisé */ function afterSetup(): void; diff --git a/nur_src/v/vp/AppCasauthPage.php b/nur_src/v/vp/AppCasauthPage.php index 43da853..b9158df 100644 --- a/nur_src/v/vp/AppCasauthPage.php +++ b/nur_src/v/vp/AppCasauthPage.php @@ -23,7 +23,7 @@ class AppCasauthPage extends AbstractPage { /** @var string nom de l'utilisateur connecté */ private $user; - function setup(): void { + function setup() { $destUrl = $retUrl = null; $user = false; if ($user === false) $user = A::get($_SERVER, "REMOTE_USER", false); diff --git a/nur_src/v/vp/AppDevauthPage.php b/nur_src/v/vp/AppDevauthPage.php index 398f220..7b0c698 100644 --- a/nur_src/v/vp/AppDevauthPage.php +++ b/nur_src/v/vp/AppDevauthPage.php @@ -9,7 +9,7 @@ class AppDevauthPage extends AInitPage { /** @var string nom de l'utilisateur connecté */ private $user; - function setup(): void { + function setup() { if (!$this->isDevauthAllowed()) { page::redirect($this->getLoginUrl()); } diff --git a/nur_src/v/vp/AppExtauthPage.php b/nur_src/v/vp/AppExtauthPage.php index 75a4653..1cebcc2 100644 --- a/nur_src/v/vp/AppExtauthPage.php +++ b/nur_src/v/vp/AppExtauthPage.php @@ -23,7 +23,7 @@ class AppExtauthPage extends AbstractPage { /** @var string nom de l'utilisateur connecté */ private $user; - function setup(): void { + function setup() { $destUrl = null; $user = false; if ($user === false) $user = A::get($_SERVER, "REMOTE_USER", false); diff --git a/nur_src/v/vp/AppLogoutPage.php b/nur_src/v/vp/AppLogoutPage.php index 27b765d..e6afc6c 100644 --- a/nur_src/v/vp/AppLogoutPage.php +++ b/nur_src/v/vp/AppLogoutPage.php @@ -16,7 +16,7 @@ class AppLogoutPage extends AInitPage { return static::DEBUG || F::get("d"); } - function setup(): void { + function setup() { cookie::set("MOD_AUTH_CAS", false); cookie::set("MOD_AUTH_CAS_S", false); authz::manager()->resetSession(authz::DISCONNECTED); From 1c7961d356b951a4fd8f49f5c4d044cebf7f20c0 Mon Sep 17 00:00:00 2001 From: Jephte Clain Date: Wed, 11 Jun 2025 16:03:28 +0400 Subject: [PATCH 07/11] modifs.mineures sans commentaires --- src/schema/TODO.md | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/schema/TODO.md b/src/schema/TODO.md index ab891c4..1f5cda4 100644 --- a/src/schema/TODO.md +++ b/src/schema/TODO.md @@ -3,20 +3,23 @@ * rajouter l'attribut "size" pour spécifier la taille maximale des valeurs * cela pourrait servir pour générer automatiquement des tables SQL * ou pour modéliser un schéma FSV +* support `max_size`, qui diffère de `size` en ce qu'on ne spécifie qu'une + taille maximum. sinon, faire `size` à la place de `max_size` et `fixed_size` + à la plage de `size` -* support allowed_values +* support `allowed_values` * valeurs composite/computed * analyse / vérification de la valeur complète après calcul du résultat, si tous les résultats sont bons * calcul des valeurs composites/computed par une fonction avant/après l'analyse globale si résultat ok - * fonction getter_func, setter_func, deleter_func pour les propriétés de type + * fonction `getter_func`, `setter_func`, `deleter_func` pour les propriétés de type computed * tdate et tdatetime. qu'en est-il des autres classes (delay, etc.) - * parse_format pour spécifier le format d'analyse au lieu de l'auto-détecter + * `parse_format` pour spécifier le format d'analyse au lieu de l'auto-détecter -* ScalarSchema::from_property() +* `ScalarSchema::from_property()` * l'argument $format de AssocWrapper::format() est un tableau associatif `[$key => $format]` @@ -68,7 +71,7 @@ la définition de ces "circonstances" est encore à faire: soit un paramètre lors de la définition du schéma, soit un truc magique du genre "toutes les valeurs séquentielles sont des clés du schéma", soit un mode automatique - activé par un paramètre où une valeur "val" devient "val"=>true si la clé + activé par un paramètre où une valeur `"val"` devient `"val"=>true` si la clé "val" existe dans le schéma -*- coding: utf-8 mode: markdown -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8:noeol:binary \ No newline at end of file From cb8e0f1ec08b954832ae9e9c9cb02aca4afe9070 Mon Sep 17 00:00:00 2001 From: Jephte Clain Date: Mon, 16 Jun 2025 12:15:26 +0400 Subject: [PATCH 08/11] ajout de l'icone pending --- TODO.md | 14 +++++ nur_src/v/bs3/Bs3IconManager.php | 3 ++ nur_src/v/icon.php | 93 ++++++++++++++++---------------- 3 files changed, 64 insertions(+), 46 deletions(-) diff --git a/TODO.md b/TODO.md index 6a61f80..19e0c06 100644 --- a/TODO.md +++ b/TODO.md @@ -7,5 +7,19 @@ ## Vrac * classe de base `profile_manager` qui permet de gérer des profils +* class Tool permettant d'appliquer un traitement à une valeur scalaire + * ArrayTool permet d'appliquer les traitement à tous les éléments du tableau + * les traitements sont une suite d'opérations à faire, ou de filtres à + appliquer, qui ne sont appliqués que lors du parcours effectif de la liste + * exemple + ```php + $result = ArrayTool::with($source) + ->filterKey("key") + ->filter("value") + ->add("value", "key") + ->addAll($iterable) + ->all(); + ``` + déterminer le genre de traitements que l'on peut offrir -*- coding: utf-8 mode: markdown -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8:noeol:binary \ No newline at end of file diff --git a/nur_src/v/bs3/Bs3IconManager.php b/nur_src/v/bs3/Bs3IconManager.php index 32746ab..f429424 100644 --- a/nur_src/v/bs3/Bs3IconManager.php +++ b/nur_src/v/bs3/Bs3IconManager.php @@ -11,6 +11,7 @@ class Bs3IconManager implements IIconManager { "warning" => "exclamation-sign", "error" => "remove-sign", + "pending" => "hourglass", "refresh", "config" => "cog", "save" => "floppy-disk", @@ -83,6 +84,7 @@ EOT; 'success' => 'ok-sign', 'warning' => 'exclamation-sign', 'error' => 'remove-sign', + 'pending' => 'hourglass', 'refresh' => 'refresh', 'config' => 'cog', 'save' => 'floppy-disk', @@ -139,6 +141,7 @@ EOT; '', ]; const ERROR = /*autogen*/['']; + const PENDING = /*autogen*/['']; const REFRESH = /*autogen*/['']; const CONFIG = /*autogen*/['']; const SAVE = /*autogen*/['']; diff --git a/nur_src/v/icon.php b/nur_src/v/icon.php index 7308669..1d20ac1 100644 --- a/nur_src/v/icon.php +++ b/nur_src/v/icon.php @@ -47,57 +47,58 @@ class icon { ############################################################################# - static final function info(?string $suffix=null, ?string $alt="INFO: "): array { return self::manager()->getIcon("info", $suffix, $alt); } - static final function success(?string $suffix=null, ?string $alt="SUCCESS: "): array { return self::manager()->getIcon("success", $suffix, $alt); } - static final function warning(?string $suffix=null, ?string $alt="WARNING: "): array { return self::manager()->getIcon("warning", $suffix, $alt); } - static final function error(?string $suffix=null, ?string $alt="ERROR: "): array { return self::manager()->getIcon("error", $suffix, $alt); } + static final function info($suffix=null, ?string $alt="INFO: "): array { return self::manager()->getIcon("info", $suffix, $alt); } + static final function success($suffix=null, ?string $alt="SUCCESS: "): array { return self::manager()->getIcon("success", $suffix, $alt); } + static final function warning($suffix=null, ?string $alt="WARNING: "): array { return self::manager()->getIcon("warning", $suffix, $alt); } + static final function error($suffix=null, ?string $alt="ERROR: "): array { return self::manager()->getIcon("error", $suffix, $alt); } - static final function refresh(?string $suffix=null, ?string $alt=null): array { return self::manager()->getIcon("refresh", $suffix, $alt); } - static final function config(?string $suffix=null, ?string $alt=null): array { return self::manager()->getIcon("config", $suffix, $alt); } - static final function save(?string $suffix=null, ?string $alt=null): array { return self::manager()->getIcon("save", $suffix, $alt); } - static final function download(?string $suffix=null, ?string $alt=null): array { return self::manager()->getIcon("download", $suffix, $alt); } - static final function upload(?string $suffix=null, ?string $alt=null): array { return self::manager()->getIcon("upload", $suffix, $alt); } - static final function bin(?string $suffix=null, ?string $alt=null): array { return self::manager()->getIcon("bin", $suffix, $alt); } - static final function mail(?string $suffix=null, ?string $alt=null): array { return self::manager()->getIcon("mail", $suffix, $alt); } - static final function search(?string $suffix=null, ?string $alt=null): array { return self::manager()->getIcon("search", $suffix, $alt); } - static final function user(?string $suffix=null, ?string $alt=null): array { return self::manager()->getIcon("user", $suffix, $alt); } - static final function login(?string $suffix=null, ?string $alt=null): array { return self::manager()->getIcon("login", $suffix, $alt); } - static final function logout(?string $suffix=null, ?string $alt=null): array { return self::manager()->getIcon("logout", $suffix, $alt); } - static final function new_window(?string $suffix=null, ?string $alt=null): array { return self::manager()->getIcon("new_window", $suffix, $alt); } + static final function pending($suffix=null, ?string $alt=null): array { return self::manager()->getIcon("hourglass", $suffix, $alt); } + static final function refresh($suffix=null, ?string $alt=null): array { return self::manager()->getIcon("refresh", $suffix, $alt); } + static final function config($suffix=null, ?string $alt=null): array { return self::manager()->getIcon("config", $suffix, $alt); } + static final function save($suffix=null, ?string $alt=null): array { return self::manager()->getIcon("save", $suffix, $alt); } + static final function download($suffix=null, ?string $alt=null): array { return self::manager()->getIcon("download", $suffix, $alt); } + static final function upload($suffix=null, ?string $alt=null): array { return self::manager()->getIcon("upload", $suffix, $alt); } + static final function bin($suffix=null, ?string $alt=null): array { return self::manager()->getIcon("bin", $suffix, $alt); } + static final function mail($suffix=null, ?string $alt=null): array { return self::manager()->getIcon("mail", $suffix, $alt); } + static final function search($suffix=null, ?string $alt=null): array { return self::manager()->getIcon("search", $suffix, $alt); } + static final function user($suffix=null, ?string $alt=null): array { return self::manager()->getIcon("user", $suffix, $alt); } + static final function login($suffix=null, ?string $alt=null): array { return self::manager()->getIcon("login", $suffix, $alt); } + static final function logout($suffix=null, ?string $alt=null): array { return self::manager()->getIcon("logout", $suffix, $alt); } + static final function new_window($suffix=null, ?string $alt=null): array { return self::manager()->getIcon("new_window", $suffix, $alt); } - static final function ignore(?string $suffix=null, ?string $alt=null): array { return self::manager()->getIcon("fast-forward", $suffix, $alt); } - static final function replace(?string $suffix=null, ?string $alt=null): array { return self::manager()->getIcon("erase", $suffix, $alt); } - static final function delete(?string $suffix=null, ?string $alt=null): array { return self::manager()->getIcon("remove", $suffix, $alt); } + static final function ignore($suffix=null, ?string $alt=null): array { return self::manager()->getIcon("fast-forward", $suffix, $alt); } + static final function replace($suffix=null, ?string $alt=null): array { return self::manager()->getIcon("erase", $suffix, $alt); } + static final function delete($suffix=null, ?string $alt=null): array { return self::manager()->getIcon("remove", $suffix, $alt); } - static final function arrow_up(?string $suffix=null, ?string $alt=null): array { return self::manager()->getIcon("arrow_up", $suffix, $alt); } - static final function arrow_down(?string $suffix=null, ?string $alt=null): array { return self::manager()->getIcon("arrow_down", $suffix, $alt); } - static final function arrow_left(?string $suffix=null, ?string $alt=null): array { return self::manager()->getIcon("arrow_left", $suffix, $alt); } - static final function arrow_right(?string $suffix=null, ?string $alt=null): array { return self::manager()->getIcon("arrow_right", $suffix, $alt); } - static final function chevron_up(?string $suffix=null, ?string $alt=null): array { return self::manager()->getIcon("chevron_up", $suffix, $alt); } - static final function chevron_down(?string $suffix=null, ?string $alt=null): array { return self::manager()->getIcon("chevron_down", $suffix, $alt); } - static final function chevron_left(?string $suffix=null, ?string $alt=null): array { return self::manager()->getIcon("chevron_left", $suffix, $alt); } - static final function chevron_right(?string $suffix=null, ?string $alt=null): array { return self::manager()->getIcon("chevron_right", $suffix, $alt); } - static final function hand_up(?string $suffix=null, ?string $alt=null): array { return self::manager()->getIcon("hand_up", $suffix, $alt); } - static final function hand_down(?string $suffix=null, ?string $alt=null): array { return self::manager()->getIcon("hand_down", $suffix, $alt); } - static final function hand_left(?string $suffix=null, ?string $alt=null): array { return self::manager()->getIcon("hand_left", $suffix, $alt); } - static final function hand_right(?string $suffix=null, ?string $alt=null): array { return self::manager()->getIcon("hand_right", $suffix, $alt); } - static final function menu_up(?string $suffix=null, ?string $alt=null): array { return self::manager()->getIcon("menu_up", $suffix, $alt); } - static final function menu_down(?string $suffix=null, ?string $alt=null): array { return self::manager()->getIcon("menu_down", $suffix, $alt); } - static final function menu_left(?string $suffix=null, ?string $alt=null): array { return self::manager()->getIcon("menu_left", $suffix, $alt); } - static final function menu_right(?string $suffix=null, ?string $alt=null): array { return self::manager()->getIcon("menu_right", $suffix, $alt); } - static final function triangle_up(?string $suffix=null, ?string $alt=null): array { return self::manager()->getIcon("triangle_up", $suffix, $alt); } - static final function triangle_down(?string $suffix=null, ?string $alt=null): array { return self::manager()->getIcon("triangle_down", $suffix, $alt); } - static final function triangle_left(?string $suffix=null, ?string $alt=null): array { return self::manager()->getIcon("triangle_left", $suffix, $alt); } - static final function triangle_right(?string $suffix=null, ?string $alt=null): array { return self::manager()->getIcon("triangle_right", $suffix, $alt); } + static final function arrow_up($suffix=null, ?string $alt=null): array { return self::manager()->getIcon("arrow_up", $suffix, $alt); } + static final function arrow_down($suffix=null, ?string $alt=null): array { return self::manager()->getIcon("arrow_down", $suffix, $alt); } + static final function arrow_left($suffix=null, ?string $alt=null): array { return self::manager()->getIcon("arrow_left", $suffix, $alt); } + static final function arrow_right($suffix=null, ?string $alt=null): array { return self::manager()->getIcon("arrow_right", $suffix, $alt); } + static final function chevron_up($suffix=null, ?string $alt=null): array { return self::manager()->getIcon("chevron_up", $suffix, $alt); } + static final function chevron_down($suffix=null, ?string $alt=null): array { return self::manager()->getIcon("chevron_down", $suffix, $alt); } + static final function chevron_left($suffix=null, ?string $alt=null): array { return self::manager()->getIcon("chevron_left", $suffix, $alt); } + static final function chevron_right($suffix=null, ?string $alt=null): array { return self::manager()->getIcon("chevron_right", $suffix, $alt); } + static final function hand_up($suffix=null, ?string $alt=null): array { return self::manager()->getIcon("hand_up", $suffix, $alt); } + static final function hand_down($suffix=null, ?string $alt=null): array { return self::manager()->getIcon("hand_down", $suffix, $alt); } + static final function hand_left($suffix=null, ?string $alt=null): array { return self::manager()->getIcon("hand_left", $suffix, $alt); } + static final function hand_right($suffix=null, ?string $alt=null): array { return self::manager()->getIcon("hand_right", $suffix, $alt); } + static final function menu_up($suffix=null, ?string $alt=null): array { return self::manager()->getIcon("menu_up", $suffix, $alt); } + static final function menu_down($suffix=null, ?string $alt=null): array { return self::manager()->getIcon("menu_down", $suffix, $alt); } + static final function menu_left($suffix=null, ?string $alt=null): array { return self::manager()->getIcon("menu_left", $suffix, $alt); } + static final function menu_right($suffix=null, ?string $alt=null): array { return self::manager()->getIcon("menu_right", $suffix, $alt); } + static final function triangle_up($suffix=null, ?string $alt=null): array { return self::manager()->getIcon("triangle_up", $suffix, $alt); } + static final function triangle_down($suffix=null, ?string $alt=null): array { return self::manager()->getIcon("triangle_down", $suffix, $alt); } + static final function triangle_left($suffix=null, ?string $alt=null): array { return self::manager()->getIcon("triangle_left", $suffix, $alt); } + static final function triangle_right($suffix=null, ?string $alt=null): array { return self::manager()->getIcon("triangle_right", $suffix, $alt); } - static final function star(?string $suffix=null, ?string $alt=null): array { return self::manager()->getIcon("star", $suffix, $alt); } - static final function star_empty(?string $suffix=null, ?string $alt=null): array { return self::manager()->getIcon("star_empty", $suffix, $alt); } - static final function heart(?string $suffix=null, ?string $alt=null): array { return self::manager()->getIcon("heart", $suffix, $alt); } - static final function heart_empty(?string $suffix=null, ?string $alt=null): array { return self::manager()->getIcon("heart_empty", $suffix, $alt); } + static final function star($suffix=null, ?string $alt=null): array { return self::manager()->getIcon("star", $suffix, $alt); } + static final function star_empty($suffix=null, ?string $alt=null): array { return self::manager()->getIcon("star_empty", $suffix, $alt); } + static final function heart($suffix=null, ?string $alt=null): array { return self::manager()->getIcon("heart", $suffix, $alt); } + static final function heart_empty($suffix=null, ?string $alt=null): array { return self::manager()->getIcon("heart_empty", $suffix, $alt); } - static final function plus(?string $suffix=null, ?string $alt=null): array { return self::manager()->getIcon("plus", $suffix, $alt); } - static final function minus(?string $suffix=null, ?string $alt=null): array { return self::manager()->getIcon("minus", $suffix, $alt); } + static final function plus($suffix=null, ?string $alt=null): array { return self::manager()->getIcon("plus", $suffix, $alt); } + static final function minus($suffix=null, ?string $alt=null): array { return self::manager()->getIcon("minus", $suffix, $alt); } # template: - #static final function xxx(?string $suffix=null, ?string $alt=null): array { return self::manager()->getIcon("xxx", $suffix, $alt); } + #static final function xxx($suffix=null, ?string $alt=null): array { return self::manager()->getIcon("xxx", $suffix, $alt); } } From 5e01a695722e6b1275d45803f1c13e8941cce5ba Mon Sep 17 00:00:00 2001 From: Jephte Clain Date: Mon, 16 Jun 2025 17:56:44 +0400 Subject: [PATCH 09/11] =?UTF-8?q?option=20pour=20ne=20pas=20recr=C3=A9er?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app.php | 2 +- src/cli/AbstractStorageApp.php | 4 +++- src/cli/StorageMysqlApp.php | 10 ++++------ src/cli/StoragePgsqlApp.php | 4 ++++ src/cli/StorageSqliteApp.php | 3 +++ 5 files changed, 15 insertions(+), 8 deletions(-) diff --git a/src/app.php b/src/app.php index 97802b9..fa64b05 100644 --- a/src/app.php +++ b/src/app.php @@ -459,7 +459,7 @@ class app { function getRunfile(): RunFile { $name = $this->name; $runfile = $this->getWorkfile($name); - $logfile = $this->getLogfile("$name.out", false); + $logfile = $this->getLogfile("$name.log", false); return $this->runfile ??= new RunFile($name, $runfile, $logfile); } diff --git a/src/cli/AbstractStorageApp.php b/src/cli/AbstractStorageApp.php index 41cea65..9526d74 100644 --- a/src/cli/AbstractStorageApp.php +++ b/src/cli/AbstractStorageApp.php @@ -19,6 +19,8 @@ abstract class AbstractStorageApp extends Application { protected int $action = self::ACTION_QUERY; + protected bool $recreate = true; + protected ?array $args = null; protected static function isa_cond(string $arg, ?array &$ms=null): bool { @@ -63,7 +65,7 @@ abstract class AbstractStorageApp extends Application { switch ($this->action) { case self::ACTION_RESET: - $capacitor->reset(true); + $capacitor->reset($this->recreate); break; case self::ACTION_QUERY: if (!$args) { diff --git a/src/cli/StorageMysqlApp.php b/src/cli/StorageMysqlApp.php index 42fea8e..300493a 100644 --- a/src/cli/StorageMysqlApp.php +++ b/src/cli/StorageMysqlApp.php @@ -2,13 +2,7 @@ namespace nulib\cli; use nulib\A; -use nulib\app\cli\Application; -use nulib\db\Capacitor; -use nulib\db\CapacitorChannel; use nulib\db\mysql\MysqlStorage; -use nulib\ext\yaml; -use nulib\file\Stream; -use nulib\output\msg; use nur\config; class StorageMysqlApp extends AbstractStorageApp { @@ -28,6 +22,9 @@ class StorageMysqlApp extends AbstractStorageApp { ["-z", "--reset", "name" => "action", "value" => self::ACTION_RESET, "help" => "réinitialiser le canal", ], + ["-n", "--no-recreate", "name" => "recreate", "value" => false, + "help" => "ne pas recréer la table correspondant au canal" + ], ["--query", "name" => "action", "value" => self::ACTION_QUERY, "help" => "lister les lignes correspondant aux valeurs spécifiées. c'est l'action par défaut", ], @@ -35,6 +32,7 @@ class StorageMysqlApp extends AbstractStorageApp { "help" => "afficher la requête pour créer la table", ], ]; + function main() { $dbconn = A::shift($this->args); if ($dbconn === null) self::die("Vous devez spécifier la base de données"); diff --git a/src/cli/StoragePgsqlApp.php b/src/cli/StoragePgsqlApp.php index fc63c65..48def90 100644 --- a/src/cli/StoragePgsqlApp.php +++ b/src/cli/StoragePgsqlApp.php @@ -22,6 +22,9 @@ class StoragePgsqlApp extends AbstractStorageApp { ["-z", "--reset", "name" => "action", "value" => self::ACTION_RESET, "help" => "réinitialiser le canal", ], + ["-n", "--no-recreate", "name" => "recreate", "value" => false, + "help" => "ne pas recréer la table correspondant au canal" + ], ["--query", "name" => "action", "value" => self::ACTION_QUERY, "help" => "lister les lignes correspondant aux valeurs spécifiées. c'est l'action par défaut", ], @@ -29,6 +32,7 @@ class StoragePgsqlApp extends AbstractStorageApp { "help" => "afficher la requête pour créer la table", ], ]; + function main() { $dbconn = A::shift($this->args); if ($dbconn === null) self::die("Vous devez spécifier la base de données"); diff --git a/src/cli/StorageSqliteApp.php b/src/cli/StorageSqliteApp.php index cacdba0..1724a0d 100644 --- a/src/cli/StorageSqliteApp.php +++ b/src/cli/StorageSqliteApp.php @@ -21,6 +21,9 @@ class StorageSqliteApp extends AbstractStorageApp { ["-z", "--reset", "name" => "action", "value" => self::ACTION_RESET, "help" => "réinitialiser le canal", ], + ["-n", "--no-recreate", "name" => "recreate", "value" => false, + "help" => "ne pas recréer la table correspondant au canal" + ], ["--query", "name" => "action", "value" => self::ACTION_QUERY, "help" => "lister les lignes correspondant aux valeurs spécifiées. c'est l'action par défaut", ], From 0b8c39a35c9533c6ae98152da2723c395b369d85 Mon Sep 17 00:00:00 2001 From: Jephte Clain Date: Tue, 17 Jun 2025 12:57:15 +0400 Subject: [PATCH 10/11] renommer scripts --- bin/{storage.mysql.php => mysql.storage.php} | 4 ++-- bin/{storage.pgsql.php => pgsql.storage.php} | 4 ++-- bin/{storage.sqlite.php => sqlite.storage.php} | 4 ++-- composer.json | 6 +++--- src/app.php | 2 +- src/cli/{StorageMysqlApp.php => MysqlStorageApp.php} | 2 +- src/cli/{StoragePgsqlApp.php => PgsqlStorageApp.php} | 2 +- src/cli/{StorageSqliteApp.php => SqliteStorageApp.php} | 2 +- 8 files changed, 13 insertions(+), 13 deletions(-) rename bin/{storage.mysql.php => mysql.storage.php} (63%) rename bin/{storage.pgsql.php => pgsql.storage.php} (63%) rename bin/{storage.sqlite.php => sqlite.storage.php} (62%) rename src/cli/{StorageMysqlApp.php => MysqlStorageApp.php} (96%) rename src/cli/{StoragePgsqlApp.php => PgsqlStorageApp.php} (96%) rename src/cli/{StorageSqliteApp.php => SqliteStorageApp.php} (96%) diff --git a/bin/storage.mysql.php b/bin/mysql.storage.php similarity index 63% rename from bin/storage.mysql.php rename to bin/mysql.storage.php index 3804828..69f8833 100755 --- a/bin/storage.mysql.php +++ b/bin/mysql.storage.php @@ -2,6 +2,6 @@ name; $runfile = $this->getWorkfile($name); - $logfile = $this->getLogfile("$name.log", false); + $logfile = $this->getLogfile("$name.out", false); return $this->runfile ??= new RunFile($name, $runfile, $logfile); } diff --git a/src/cli/StorageMysqlApp.php b/src/cli/MysqlStorageApp.php similarity index 96% rename from src/cli/StorageMysqlApp.php rename to src/cli/MysqlStorageApp.php index 300493a..6f28225 100644 --- a/src/cli/StorageMysqlApp.php +++ b/src/cli/MysqlStorageApp.php @@ -5,7 +5,7 @@ use nulib\A; use nulib\db\mysql\MysqlStorage; use nur\config; -class StorageMysqlApp extends AbstractStorageApp { +class MysqlStorageApp extends AbstractStorageApp { const ARGS = [ "merge" => parent::ARGS, "purpose" => "gestion d'un capacitor mysql", diff --git a/src/cli/StoragePgsqlApp.php b/src/cli/PgsqlStorageApp.php similarity index 96% rename from src/cli/StoragePgsqlApp.php rename to src/cli/PgsqlStorageApp.php index 48def90..c10bfde 100644 --- a/src/cli/StoragePgsqlApp.php +++ b/src/cli/PgsqlStorageApp.php @@ -5,7 +5,7 @@ use nulib\A; use nulib\db\pgsql\PgsqlStorage; use nur\config; -class StoragePgsqlApp extends AbstractStorageApp { +class PgsqlStorageApp extends AbstractStorageApp { const ARGS = [ "merge" => parent::ARGS, "purpose" => "gestion d'un capacitor pgsql", diff --git a/src/cli/StorageSqliteApp.php b/src/cli/SqliteStorageApp.php similarity index 96% rename from src/cli/StorageSqliteApp.php rename to src/cli/SqliteStorageApp.php index 1724a0d..357099d 100644 --- a/src/cli/StorageSqliteApp.php +++ b/src/cli/SqliteStorageApp.php @@ -4,7 +4,7 @@ namespace nulib\cli; use nulib\A; use nulib\db\sqlite\SqliteStorage; -class StorageSqliteApp extends AbstractStorageApp { +class SqliteStorageApp extends AbstractStorageApp { const ARGS = [ "merge" => parent::ARGS, "purpose" => "gestion d'un capacitor sqlite", From 990533a906f566bdfccffd208c44eaa8e3301172 Mon Sep 17 00:00:00 2001 From: Jephte Clain Date: Tue, 17 Jun 2025 16:11:21 +0400 Subject: [PATCH 11/11] modifs.mineures sans commentaires --- src/cache/CacheChannel.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/cache/CacheChannel.php b/src/cache/CacheChannel.php index f222b09..4272a99 100644 --- a/src/cache/CacheChannel.php +++ b/src/cache/CacheChannel.php @@ -63,7 +63,7 @@ class CacheChannel extends CapacitorChannel { ]); } - function onCreate($item, array $values, ?array $alwaysNull, ?string $duration=null): ?array { + function onCreate($item, array $row, ?array $alwaysNull, ?string $duration=null): ?array { $now = new DateTime(); $duration ??= $this->duration; return [ @@ -72,7 +72,7 @@ class CacheChannel extends CapacitorChannel { ]; } - function onUpdate($item, array $values, array $pvalues, ?string $duration=null): ?array { + function onUpdate($item, array $row, array $prow, ?string $duration=null): ?array { $now = new DateTime(); $duration ??= $this->duration; return [ @@ -97,9 +97,9 @@ class CacheChannel extends CapacitorChannel { $found = false; $expired = false; $this->each($cacheIds, - function($item, $values) use (&$found, &$expired) { + function($row) use (&$found, &$expired) { $found = true; - $expired = $values["duration"]->isElapsed(); + $expired = $row["duration"]->isElapsed(); }); return !$found || $expired; }