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 @@
+
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/bin/csv2xlsx.php b/bin/csv2xlsx.php
index 0f0bb32..5fb7464 100755
--- a/bin/csv2xlsx.php
+++ b/bin/csv2xlsx.php
@@ -2,6 +2,6 @@
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",
- ],
- ["-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",
- ],
- ["--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",
- ],
- ];
-
- 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;
- 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;
-
- 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;
- }
- }
-});
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/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/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/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); }
}
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);
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;
}
diff --git a/nur_bin/storage.sqlite.php b/src/cli/AbstractStorageApp.php
old mode 100755
new mode 100644
similarity index 55%
rename from nur_bin/storage.sqlite.php
rename to src/cli/AbstractStorageApp.php
index a636ce3..9526d74
--- a/nur_bin/storage.sqlite.php
+++ b/src/cli/AbstractStorageApp.php
@@ -1,48 +1,17 @@
-#!/usr/bin/php
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",
- ],
- ["-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",
- ],
- ["--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",
- ],
- ];
-
- protected ?string $dbfile = null;
-
- protected ?string $name = null;
+abstract class AbstractStorageApp extends Application {
+ const ACTION_RESET = 0, ACTION_QUERY = 1, ACTION_SQL = 2;
protected ?string $tableName = null;
@@ -50,28 +19,28 @@ Application::run(new class 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 {
return preg_match('/^(.+?)\s*(=|<>|<|>|<=|>=|(?:is\s+)?null|(?:is\s+)?not\s+null)\s*(.*)$/', $arg, $ms);
}
- function main() {
- $dbfile = $this->dbfile;
- 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();
+ protected function storageCtl(CapacitorStorage $storage): void {
+ $args = $this->args;
- $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 ($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 ($row["class_name"] !== "class@anonymous") $channelClass = $row["class_name"];
- else $tableName = $row["table_name"];
}
if ($channelClass !== null) {
$channelClass = str_replace("/", "\\", $channelClass);
@@ -95,13 +64,15 @@ Application::run(new class extends Application {
$capacitor = new Capacitor($storage, $channel);
switch ($this->action) {
+ case self::ACTION_RESET:
+ $capacitor->reset($this->recreate);
+ break;
case self::ACTION_QUERY:
- $args = $this->args;
if (!$args) {
# lister les id
$out = new Stream(STDOUT);
$primaryKeys = $storage->getPrimaryKeys($channel);
- $rows = $db->all([
+ $rows = $storage->db()->all([
"select",
"cols" => $primaryKeys,
"from" => $channel->getTableName(),
@@ -139,4 +110,4 @@ Application::run(new class extends Application {
break;
}
}
-});
+}
diff --git a/src/cli/BgLauncherApp.php b/src/cli/BgLauncherApp.php
new file mode 100644
index 0000000..f9d789d
--- /dev/null
+++ b/src/cli/BgLauncherApp.php
@@ -0,0 +1,124 @@
+ "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 @@
parent::ARGS,
+ "purpose" => "gestion d'un capacitor mysql",
+ "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",
+ ],
+ ["-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",
+ ],
+ ["-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 MysqlStorage($tmp);
+
+ $this->storageCtl($storage);
+ }
+}
diff --git a/src/tools/NucacheApp.php b/src/cli/NucacheApp.php
similarity index 99%
rename from src/tools/NucacheApp.php
rename to src/cli/NucacheApp.php
index 583e44e..7248f47 100644
--- a/src/tools/NucacheApp.php
+++ b/src/cli/NucacheApp.php
@@ -1,10 +1,10 @@
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",
+ ],
+ ["-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",
+ ],
+ ["-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);
+ }
+}
diff --git a/src/cli/SqliteStorageApp.php b/src/cli/SqliteStorageApp.php
new file mode 100644
index 0000000..357099d
--- /dev/null
+++ b/src/cli/SqliteStorageApp.php
@@ -0,0 +1,43 @@
+ parent::ARGS,
+ "purpose" => "gestion d'un capacitor sqlite",
+ "usage" => [
+ "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",
+ ],
+ ["-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",
+ ],
+ ["-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",
+ ],
+ ["-s", "--sql-create", "name" => "action", "value" => self::ACTION_SQL,
+ "help" => "afficher la requête pour créer la table",
+ ],
+ ];
+
+ function main() {
+ $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);
+
+ $this->storageCtl($storage);
+ }
+}
diff --git a/src/cli/SteamTrainApp.php b/src/cli/SteamTrainApp.php
new file mode 100644
index 0000000..3040883
--- /dev/null
+++ b/src/cli/SteamTrainApp.php
@@ -0,0 +1,53 @@
+ 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/src/tools/Yaml2jsonApp.php b/src/cli/Yaml2jsonApp.php
similarity index 94%
rename from src/tools/Yaml2jsonApp.php
rename to src/cli/Yaml2jsonApp.php
index 9eba6ea..0cd4541 100644
--- a/src/tools/Yaml2jsonApp.php
+++ b/src/cli/Yaml2jsonApp.php
@@ -1,5 +1,5 @@
$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