diff --git a/src/output/IMessenger.php b/src/output/IMessenger.php
index aeceae9..3110317 100644
--- a/src/output/IMessenger.php
+++ b/src/output/IMessenger.php
@@ -5,8 +5,8 @@ namespace nur\sery\output;
* Interface IMessenger: un objet pouvant afficher des messages de l'application
*/
interface IMessenger {
- const LEVEL_DEBUG = -1, LEVEL_NORMAL = 0, LEVEL_MAJOR = 1, LEVEL_NONE = 2;
- const MIN_LEVEL = self::LEVEL_DEBUG, MAX_LEVEL = self::LEVEL_MAJOR;
+ const DEBUG = -1, NORMAL = 0, MAJOR = 1, NONE = 2;
+ const MIN_LEVEL = self::DEBUG, MAX_LEVEL = self::MAJOR;
/** réinitialiser les paramètres de l'objet */
function resetParams(?array $params=null): void;
@@ -22,7 +22,7 @@ interface IMessenger {
* flush tous les messages en cours. ne peut être imbriqué. on peut considérer
* que c'est une sorte de "reset" de l'objet
*/
- function section($content, ?int $level=null): void;
+ function section($content, ?callable $func=null, ?int $level=null): void;
/**
* commencer un chapitre.
@@ -30,7 +30,7 @@ interface IMessenger {
* peut être imbriqué dans un autre chapitre. terminer automatiquement
* l'action en cours avec un résultat neutre
*/
- function title($content, ?int $level=null): void;
+ function title($content, ?callable $func=null, ?int $level=null): void;
/** ajouter une description au chapitre courant. */
function desc($content, ?int $level=null): void;
@@ -40,7 +40,7 @@ interface IMessenger {
*
* peut être imbriqué dans une autre action.
*/
- function action($content, ?int $level=null): void;
+ function action($content, ?callable $func=null, ?int $level=null): void;
/**
* ajouter une étape à l'action courante.
diff --git a/src/output/TODO.md b/src/output/TODO.md
index 059a71d..59913e2 100644
--- a/src/output/TODO.md
+++ b/src/output/TODO.md
@@ -1,127 +1,8 @@
-# IMessenger
+# TOOD
-## TOOD
-
-* [ ] section(), title() et action() acceptent une fonction qui fait le travail
- avec en premier argument l'instance de messenger, et qui termine l'objet
- l'objet ensuite
* [ ] possibilité de paramétrer le nom du fichier destination pour faire une
rotation des logs
-* [ ] support quiet (uniquement major), very-quiet (aucun message n'est affiché)
* [ ] support verbose? cela suppose rajouter un niveau supplémentaire `LEVEL_MINOR`
entre `LEVEL_DEBUG` et `LEVEL_NORMAL`
-## Principe
-
-* 3 niveaux: DEBUG, NORMAL, MAJOR
-* plusieurs types de messages:
- * section: flush tous les messages en cours, ne peut pas être imbriqué
- * title: début d'une action de haut niveau, peut être imbriqué
- * desc: description longue de l'action de haut niveau qui vient de démarrer
- * print: donnée non structurée
- * action: début d'une action, peut être imbriqué
- * step: étape d'une action
- * success: résultat: action réussie
- * failure: résultat: action ratée
- * info: événement: pour information
- * note: événement: information importante
- * warn: événement: avertissement
- * error: événement: erreur
- * end: fin de action ou title
-* section, title et desc ne sont affichés que si une action ou un événement est affiché en-dessous
-* quand on "rajoute" une desc, décider s'il faut remplacer la description en cours pas encore affichée, ou s'il faut simplement le rajouter à la suite
-
-
-visuellement:
-* debug
- ~~~
- >> section <<
- t title
- > desc
- print
- . action:
- . step
- v action success
- . action:
- . step
- x action failure
- v action success
- x action failure
- . action0:
- . action1:
- ? action2 result
- ? action1 result
- ? action0 result
- i info
- w warn
- e error
- t title0
- t title1
- print under title1
- print under title0
- ~~~
- result est soit success, soit failure..
-* normal
- ~~~
-
- >>> section <<<
- >>> ------- <<<
- T title
- > desc
- print
- . action:
- . step
- V action success
- . action:
- . step
- X action failure
- V action success
- X action failure
- . action0:
- . action1:
- ? action2 result
- ? action1 result
- ? action0 result
- I info
- W warn
- E error
- T title0
- T title1
- print under title1
- print under title0
- ~~~
-* major
- ~~~
-
- ===========
- = section =
- ===========
- title
- -------
- > desc
- print
- . action:
- . step
- V action success
- . action:
- . step
- X action failure
- V action success
- X action failure
- . action0:
- . action1:
- ? action2 result
- ? action1 result
- ? action0 result
- NOTE: info
- ATTENTION: warn
- CRITICAL: error
- title0
- --------
- title1
- --------
- print under title1
- print under title0
- ~~~
-
-*- 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/src/output/_messenger.php b/src/output/_messenger.php
index 44520b1..4cd24ab 100644
--- a/src/output/_messenger.php
+++ b/src/output/_messenger.php
@@ -65,16 +65,16 @@ abstract class _messenger {
#############################################################################
- const DEBUG = IMessenger::LEVEL_DEBUG;
- const NORMAL = IMessenger::LEVEL_NORMAL;
- const MAJOR = IMessenger::LEVEL_MAJOR;
- const NONE = IMessenger::LEVEL_NONE;
+ const DEBUG = IMessenger::DEBUG;
+ const NORMAL = IMessenger::NORMAL;
+ const MAJOR = IMessenger::MAJOR;
+ const NONE = IMessenger::NONE;
static function reset_params(?array $params=null): void { static::get()->resetParams($params); }
- static function section($content, ?int $level=null): void { static::get()->section($content, $level); }
- static function title($content, ?int $level=null): void { static::get()->title($content, $level); }
+ static function section($content, ?callable $func=null, ?int $level=null): void { static::get()->section($content, $func, $level); }
+ static function title($content, ?callable $func=null, ?int $level=null): void { static::get()->title($content, $func, $level); }
static function desc($content, ?int $level=null): void { static::get()->desc($content, $level); }
- static function action($content, ?int $level=null): void { static::get()->action($content, $level); }
+ static function action($content, ?callable $func=null, ?int $level=null): void { static::get()->action($content, $func, $level); }
static function step($content, ?int $level=null): void { static::get()->step($content, $level); }
static function asuccess($content=null): void { static::get()->asuccess($content); }
static function afailure($content=null): void { static::get()->afailure($content); }
diff --git a/src/output/std/ProxyMessenger.php b/src/output/std/ProxyMessenger.php
index cddf2c6..2950a06 100644
--- a/src/output/std/ProxyMessenger.php
+++ b/src/output/std/ProxyMessenger.php
@@ -25,10 +25,10 @@ class ProxyMessenger implements IMessenger {
}; unset($msg);
return $clone;
}
- function section($content, ?int $level=null): void { foreach ($this->msgs as $msg) { $msg->section($content, $level); } }
- function title($content, ?int $level=null): void { foreach ($this->msgs as $msg) { $msg->title($content, $level); } }
+ function section($content, ?callable $func=null, ?int $level=null): void { foreach ($this->msgs as $msg) { $msg->section($content, $func, $level); } }
+ function title($content, ?callable $func=null, ?int $level=null): void { foreach ($this->msgs as $msg) { $msg->title($content, $func, $level); } }
function desc($content, ?int $level=null): void { foreach ($this->msgs as $msg) { $msg->desc($content, $level); } }
- function action($content, ?int $level=null): void { foreach ($this->msgs as $msg) { $msg->action($content, $level); } }
+ function action($content, ?callable $func=null, ?int $level=null): void { foreach ($this->msgs as $msg) { $msg->action($content, $func, $level); } }
function step($content, ?int $level=null): void { foreach ($this->msgs as $msg) { $msg->step($content, $level); } }
function asuccess($content=null): void { foreach ($this->msgs as $msg) { $msg->asuccess($content); } }
function afailure($content=null): void { foreach ($this->msgs as $msg) { $msg->afailure($content); } }
diff --git a/src/output/std/StdMessenger.php b/src/output/std/StdMessenger.php
index 3bf925b..cd577c9 100644
--- a/src/output/std/StdMessenger.php
+++ b/src/output/std/StdMessenger.php
@@ -13,16 +13,16 @@ class StdMessenger implements IMessenger {
const DATE_FORMAT = 'Y-m-d\TH:i:s.u';
const VALID_LEVELS = [
- self::LEVEL_DEBUG,
- self::LEVEL_NORMAL,
- self::LEVEL_MAJOR,
- self::LEVEL_NONE,
+ self::DEBUG,
+ self::NORMAL,
+ self::MAJOR,
+ self::NONE,
];
const LEVEL_MAP = [
- "debug" => self::LEVEL_DEBUG, "verbose" => self::LEVEL_DEBUG,
- "normal" => self::LEVEL_NORMAL,
- "major" => self::LEVEL_MAJOR, "quiet" => self::LEVEL_MAJOR,
- "none" => self::LEVEL_NONE, "silent" => self::LEVEL_NONE,
+ "debug" => self::DEBUG, "verbose" => self::DEBUG,
+ "normal" => self::NORMAL,
+ "major" => self::MAJOR, "quiet" => self::MAJOR,
+ "none" => self::NONE, "silent" => self::NONE,
];
protected static function decr_level(int $level): int {
@@ -44,7 +44,7 @@ class StdMessenger implements IMessenger {
}
const GENERIC_PREFIXES = [
- self::LEVEL_MAJOR => [
+ self::MAJOR => [
"section" => [true, "SECTION!", "===", "=", "=", "==="],
"title" => [false, "TITLE!", null, "T", "", "==="],
"desc" => ["DESC!", ">", ""],
@@ -55,7 +55,7 @@ class StdMessenger implements IMessenger {
"step" => ["*", ".", ""],
"print" => [null, null, null],
],
- self::LEVEL_NORMAL => [
+ self::NORMAL => [
"section" => [true, "SECTION:", "---", "-", "-", "---"],
"title" => [false, "TITLE:", null, "T", "", "---"],
"desc" => ["DESC:", ">", ""],
@@ -66,7 +66,7 @@ class StdMessenger implements IMessenger {
"step" => ["*", ".", ""],
"print" => [null, null, null],
],
- self::LEVEL_DEBUG => [
+ self::DEBUG => [
"section" => [true, "section", null, ">>", "<<", null],
"title" => [false, "title", null, "t", "", null],
"desc" => ["desc", ">", ""],
@@ -91,15 +91,15 @@ class StdMessenger implements IMessenger {
$indent = cl::get($params, "indent", static::INDENT);
$defaultLevel = cl::get($params, "default_level");
- if ($defaultLevel === null) $defaultLevel = self::LEVEL_NORMAL;
+ if ($defaultLevel === null) $defaultLevel = self::NORMAL;
$defaultLevel = self::verifix_level($defaultLevel);
$debug = boolval(cl::get($params, "debug"));
$minLevel = cl::get($params, "min_level");
- if ($minLevel === null && $debug) $minLevel = self::LEVEL_DEBUG;
+ if ($minLevel === null && $debug) $minLevel = self::DEBUG;
if ($minLevel === null) $minLevel = cl::get($params, "verbosity"); # alias
- if ($minLevel === null) $minLevel = self::LEVEL_NORMAL;
- $minLevel = self::verifix_level($minLevel, self::LEVEL_NONE);
+ if ($minLevel === null) $minLevel = self::NORMAL;
+ $minLevel = self::verifix_level($minLevel, self::NONE);
$addDate = boolval(cl::get($params, "add_date"));
$dateFormat = cl::get($params, "date_format", static::DATE_FORMAT);
@@ -135,9 +135,9 @@ class StdMessenger implements IMessenger {
$debug = cl::get($params, "debug");
$minLevel = cl::get($params, "min_level");
- if ($minLevel === null && $debug !== null) $minLevel = $debug? self::LEVEL_DEBUG: self::LEVEL_NORMAL;
+ if ($minLevel === null && $debug !== null) $minLevel = $debug? self::DEBUG: self::NORMAL;
if ($minLevel === null) $minLevel = cl::get($params, "verbosity"); # alias
- if ($minLevel !== null) $minLevel = self::verifix_level($minLevel, self::LEVEL_NONE);
+ if ($minLevel !== null) $minLevel = self::verifix_level($minLevel, self::NONE);
$addDate = cl::get($params, "add_date");
$dateFormat = cl::get($params, "date_format");
@@ -424,7 +424,7 @@ class StdMessenger implements IMessenger {
/** @var array section qui est en attente d'affichage */
protected $section;
- function section($content, ?int $level=null): void {
+ function section($content, ?callable $func=null, ?int $level=null): void {
$this->endSection();
$this->inSection = true;
if (!$this->checkLevel($level)) return;
@@ -434,6 +434,13 @@ class StdMessenger implements IMessenger {
"content" => $content,
"print_content" => true,
];
+ if ($func !== null) {
+ try {
+ $func($this);
+ } finally {
+ $this->endSection();
+ }
+ }
}
protected function printSection() {
@@ -458,8 +465,9 @@ class StdMessenger implements IMessenger {
/** @var array */
protected $title;
- function title($content, ?int $level=null): void {
+ function title($content, ?callable $func=null, ?int $level=null): void {
if (!$this->checkLevel($level)) return;
+ $until = count($this->titles);
$this->titles[] = [
"line_prefix" => $this->getLinePrefix(),
"level" => $level,
@@ -469,6 +477,13 @@ class StdMessenger implements IMessenger {
"print_descs" => false,
];
$this->title =& $this->titles[count($this->titles) - 1];
+ if ($func !== null) {
+ try {
+ $func($this);
+ } finally {
+ $this->endTitle($until);
+ }
+ }
}
function desc($content, ?int $level=null): void {
@@ -508,8 +523,11 @@ class StdMessenger implements IMessenger {
}; unset($title);
}
- protected function endTitle(): void {
- array_pop($this->titles);
+ protected function endTitle(?int $until=null): void {
+ if ($until === null) $until = count($this->titles) - 1;
+ while (count($this->titles) > $until) {
+ array_pop($this->titles);
+ }
if ($this->titles) {
$this->title =& $this->titles[count($this->titles) - 1];
} else {
@@ -524,8 +542,9 @@ class StdMessenger implements IMessenger {
/** @var array */
protected $action;
- function action($content, ?int $level=null): void {
+ function action($content, ?callable $func=null, ?int $level=null): void {
$this->checkLevel($level);
+ $until = count($this->actions);
$this->actions[] = [
"line_prefix" => $this->getLinePrefix(),
"level" => $level,
@@ -535,6 +554,18 @@ class StdMessenger implements IMessenger {
"result_content" => null,
];
$this->action =& $this->actions[count($this->actions) - 1];
+ if ($func !== null) {
+ try {
+ $result = $func($this);
+ if ($result !== null) {
+ if ($result === true) $this->asuccess();
+ elseif ($result === false) $this->afailure();
+ else $this->adone($result);
+ }
+ } finally {
+ $this->endAction($until);
+ }
+ }
}
function printActions(bool $willEnd=false): void {
@@ -597,8 +628,11 @@ class StdMessenger implements IMessenger {
$this->endAction();
}
- protected function endAction(): void {
- array_pop($this->actions);
+ protected function endAction(?int $until=null): void {
+ if ($until === null) $until = count($this->actions) - 1;
+ while (count($this->actions) > $until) {
+ array_pop($this->actions);
+ }
if ($this->actions) {
$this->action =& $this->actions[count($this->actions) - 1];
} else {
diff --git a/tbin/test-console.php b/tbin/test-console.php
index 248f4b2..8a522d6 100755
--- a/tbin/test-console.php
+++ b/tbin/test-console.php
@@ -44,116 +44,246 @@ for ($i = 1; $i <= $count; $i++) {
break;
}
}
-$c = new StdMessenger($params);
+$msg = new StdMessenger($params);
-$c->section("section");
+$msg->title("title0");
+$msg->title("title1");
+$msg->print("print under title1");
+$msg->end();
+$msg->print("print under title0");
+$msg->end();
-$c->title("title");
-$c->desc("desc");
-$c->print("print");
+$msg->desc("action avec step");
+$msg->action("action avec step");
+$msg->step("step");
+$msg->asuccess("action success");
-$c->action("action");
-$c->step("step");
-$c->asuccess("action success");
+$msg->action("action avec step");
+$msg->step("step");
+$msg->afailure("action failure");
-$c->action("action");
-$c->step("step");
-$c->afailure("action failure");
+$msg->action("action avec step");
+$msg->step("step");
+$msg->adone("action neutral");
-$c->action("action");
-$c->step("step");
-$c->adone("action neutral");
+$msg->desc("actions sans step");
+$msg->action("action sans step");
+$msg->asuccess("action success");
-$c->action("action");
-$c->asuccess("action success");
+$msg->action("action sans step");
+$msg->afailure("action failure");
-$c->action("action");
-$c->afailure("action failure");
+$msg->action("action sans step");
+$msg->adone("action neutral");
-$c->action("action");
-$c->adone("action neutral");
+$msg->desc("actions imbriquées");
+$msg->action("action0");
+$msg->action("action1");
+$msg->action("action2");
+$msg->asuccess("action2 success");
+$msg->asuccess("action1 success");
+$msg->asuccess("action0 success");
-$c->action("action0");
-$c->action("action1");
-$c->action("action2");
-$c->asuccess("action2 success");
-$c->asuccess("action1 success");
-$c->asuccess("action0 success");
+$msg->desc("action avec step, sans messages");
+$msg->action("action avec step, sans messages, success");
+$msg->step("step");
+$msg->asuccess();
-$c->action("action");
-$c->step("step");
-$c->asuccess();
+$msg->action("action avec step, sans messages, failure");
+$msg->step("step");
+$msg->afailure();
-$c->action("action");
-$c->step("step");
-$c->afailure();
+$msg->action("action avec step, sans messages, done");
+$msg->step("step");
+$msg->adone();
-$c->action("action");
-$c->step("step");
-$c->adone();
+$msg->desc("action sans step, sans messages");
+$msg->action("action sans step, sans messages, success");
+$msg->asuccess();
-$c->action("action");
-$c->asuccess();
+$msg->action("action sans step, sans messages, failure");
+$msg->afailure();
-$c->action("action");
-$c->afailure();
+$msg->action("action sans step, sans messages, done");
+$msg->adone();
-$c->action("action");
-$c->adone();
+$msg->desc("actions imbriquées, sans messages");
+$msg->action("action0");
+$msg->action("action1");
+$msg->action("action2");
+$msg->asuccess();
+$msg->asuccess();
+$msg->asuccess();
-$c->action("action0");
-$c->action("action1");
-$c->action("action2");
-$c->asuccess();
-$c->asuccess();
-$c->asuccess();
+$msg->info("info");
+$msg->note("note");
+$msg->warn("warn");
+$msg->error("error");
-$c->info("info");
-$c->note("note");
-$c->warn("warn");
-$c->error("error");
+$msg->section("section", function ($msg) {
+ $msg->title("title", function ($msg) {
+ $msg->desc("desc");
+ $msg->print("print");
-$c->end();
+ $msg->desc("action avec step");
+ $msg->action("action avec step", function ($msg) {
+ $msg->step("step");
+ $msg->asuccess("action success");
+ });
-$c->title("title0");
-$c->title("title1");
-$c->print("print under title1");
-$c->end();
-$c->print("print under title0");
-$c->end();
+ $msg->action("action avec step", function ($msg) {
+ $msg->step("step");
+ $msg->afailure("action failure");
+ });
-$c->end(true);
+ $msg->action("action avec step", function ($msg) {
+ $msg->step("step");
+ $msg->adone("action done");
+ });
-$c->section("multi-line\nsection");
-$c->title("multi-line\ntitle");
-$c->title("another\ntitle");
-$c->print("multi-line\nprint");
-$c->info("multi-line\ninfo");
-$c->action("multi-line\naction");
-$c->asuccess();
-$c->action("multi-line\naction");
-$c->step("multi-line\nstep");
-$c->afailure();
-$c->action("multi-line\naction");
-$c->step("multi-line\nstep");
-$c->asuccess("multi-line\nsuccess");
-$c->action("multi-line\naction");
-$c->step("multi-line\nstep");
-$c->adone("multi-line\ndone");
-$c->end(true);
+ $msg->desc("actions sans step");
+ $msg->action("action sans step", function ($msg) {
+ $msg->asuccess("action success");
+ });
-$exception = new Exception("message");
-$userException1 = new UserException("userMessage");
-$userException2 = new UserException("userMessage", "techMessage");
-$c->section("Exceptions");
-$c->title("avec message");
-$c->info(["exception", $exception]);
-$c->info(["userException1", $userException1]);
-$c->info(["userException2", $userException2]);
-$c->end();
+ $msg->action("action sans step", function ($msg) {
+ $msg->afailure("action failure");
+ });
+
+ $msg->action("action sans step", function ($msg) {
+ $msg->adone("action done");
+ });
+
+ $msg->desc("actions imbriquées");
+ $msg->action("action0", function ($msg) {
+ $msg->action("action1", function ($msg) {
+ $msg->action("action2", function ($msg) {
+ $msg->asuccess("action2 success");
+ });
+ $msg->asuccess("action1 success");
+ });
+ $msg->asuccess("action0 success");
+ });
+
+ $msg->desc("action avec step, sans messages");
+ $msg->action("action avec step, sans messages, success", function ($msg) {
+ $msg->step("step");
+ $msg->asuccess();
+ });
+
+ $msg->action("action avec step, sans messages, failure", function ($msg) {
+ $msg->step("step");
+ $msg->afailure();
+ });
+
+ $msg->action("action avec step, sans messages, done", function ($msg) {
+ $msg->step("step");
+ $msg->adone();
+ });
+
+ $msg->desc("action sans step, sans messages");
+ $msg->action("action sans step, sans messages, success", function ($msg) {
+ $msg->asuccess();
+ });
+
+ $msg->action("action sans step, sans messages, failure", function ($msg) {
+ $msg->afailure();
+ });
+
+ $msg->action("action sans step, sans messages, done", function ($msg) {
+ $msg->adone();
+ });
+
+ $msg->desc("actions imbriquées, sans messages");
+ $msg->action("action0", function ($msg) {
+ $msg->action("action1", function ($msg) {
+ $msg->action("action2", function ($msg) {
+ $msg->asuccess();
+ });
+ $msg->asuccess();
+ });
+ $msg->asuccess();
+ });
+
+ $msg->desc("action avec step, avec code de retour");
+ $msg->action("action avec step, avec code de retour true", function ($msg) {
+ $msg->step("step");
+ return true;
+ });
+
+ $msg->action("action avec step, avec code de retour false", function ($msg) {
+ $msg->step("step");
+ return false;
+ });
+
+ $msg->action("action avec step, avec code de retour autre", function ($msg) {
+ $msg->step("step");
+ return "autre";
+ });
+
+ $msg->action("action avec step, avec code de retour null", function ($msg) {
+ $msg->step("step");
+ });
+
+ $msg->desc("action sans step, avec code de retour");
+ $msg->action("action sans step, avec code de retour true", function ($msg) {
+ return true;
+ });
+
+ $msg->action("action sans step, avec code de retour false", function ($msg) {
+ return false;
+ });
+
+ $msg->action("action sans step, avec code de retour autre", function ($msg) {
+ return "autre";
+ });
+
+ # ici, il n'y aura pas de message du tout
+ $msg->action("action sans step, avec code de retour null", function ($msg) {
+ });
+
+ $msg->info("info");
+ $msg->note("note");
+ $msg->warn("warn");
+ $msg->error("error");
+ });
+});
+
+$msg->section("multi-line\nsection", function ($msg) {
+ $msg->title("multi-line\ntitle");
+ $msg->title("another\ntitle");
+
+ $msg->print("multi-line\nprint");
+ $msg->info("multi-line\ninfo");
+ $msg->action("multi-line\naction");
+ $msg->asuccess();
+ $msg->action("multi-line\naction");
+ $msg->step("multi-line\nstep");
+ $msg->afailure();
+ $msg->action("multi-line\naction");
+ $msg->step("multi-line\nstep");
+ $msg->asuccess("multi-line\nsuccess");
+ $msg->action("multi-line\naction");
+ $msg->step("multi-line\nstep");
+ $msg->adone("multi-line\ndone");
+
+ $msg->end();
+ $msg->end();
+});
+
+$msg->section("Exceptions", function ($msg) {
+ $e = new Exception("message");
+ $u1 = new UserException("userMessage");
+ $u2 = new UserException("userMessage", "techMessage");
+ $msg->title("avec message", function ($msg) use ($e, $u1, $u2) {
+ $msg->info(["exception", $e]);
+ $msg->info(["userException1", $u1]);
+ $msg->info(["userException2", $u2]);
+ });
+ $msg->title("sans message", function ($msg) use ($e, $u1, $u2) {
+ $msg->info($e);
+ $msg->info($u1);
+ $msg->info($u2);
+ });
+});
-$c->title("sans message");
-$c->info($exception);
-$c->info($userException1);
-$c->info($userException2);
-$c->end();