298 lines
10 KiB
PHP
298 lines
10 KiB
PHP
<?php
|
|
namespace nulib\output\std;
|
|
|
|
use Exception;
|
|
use nulib\A;
|
|
use nulib\cl;
|
|
use nulib\exceptions;
|
|
use nulib\ExceptionShadow;
|
|
use Throwable;
|
|
|
|
abstract class AbstractMessenger implements _IMessenger {
|
|
const ADD_DATE = false;
|
|
|
|
const SHOW_IDS = false;
|
|
|
|
protected static function verifix_level($level, int $max_level=self::MAX_LEVEL): int {
|
|
if (!in_array($level, self::VALID_LEVELS, true)) {
|
|
$level = cl::get(self::LEVEL_MAP, $level, $level);
|
|
}
|
|
if (!in_array($level, self::VALID_LEVELS, true)) {
|
|
throw new Exception("$level: invalid level");
|
|
}
|
|
if ($level > $max_level) {
|
|
throw new Exception("$level: level not allowed here");
|
|
}
|
|
return $level;
|
|
}
|
|
|
|
/** @var StdOutput la sortie standard */
|
|
protected StdOutput $out;
|
|
|
|
/** @var int level par défaut dans lequel les messages sont affichés */
|
|
protected int $defaultLevel;
|
|
|
|
/** @var int level minimum que doivent avoir les messages pour être affichés */
|
|
protected int $minLevel;
|
|
|
|
/** @var bool faut-il ajouter la date à chaque ligne? */
|
|
protected bool $addDate;
|
|
|
|
/** @var string format de la date */
|
|
protected string $dateFormat;
|
|
|
|
/** @var bool faut-il afficher les ids (p=id t=id a=id) */
|
|
protected bool $showIds;
|
|
|
|
/** @var ?string identifiant de ce messenger, à ajouter à chaque ligne */
|
|
protected ?string $id;
|
|
|
|
protected int $lastTitleId = 1;
|
|
|
|
protected abstract function title__getId(): ?int;
|
|
|
|
protected int $lastActionId = 1;
|
|
|
|
protected abstract function action__getId(): ?int;
|
|
|
|
protected function getLinePrefix(): ?string {
|
|
$linePrefix = null;
|
|
if ($this->addDate) {
|
|
$date = date_create()->format($this->dateFormat);
|
|
$linePrefix .= "$date ";
|
|
}
|
|
if ($this->showIds) {
|
|
if ($this->id !== null) $linePrefix .= "p=$this->id ";
|
|
$titleId = $this->title__getId();
|
|
if ($titleId !== null) $linePrefix .= "t=$titleId ";
|
|
$actionId = $this->action__getId();
|
|
if ($actionId !== null) $linePrefix .= "a=$actionId ";
|
|
}
|
|
return $linePrefix;
|
|
}
|
|
|
|
protected function decrLevel(int $level, int $amount=-1): int {
|
|
$level += $amount;
|
|
if ($level < self::MIN_LEVEL) $level = self::MIN_LEVEL;
|
|
return $level;
|
|
}
|
|
|
|
protected function checkLevel(?int &$level): bool {
|
|
if ($level === null) $level = $this->defaultLevel;
|
|
elseif ($level < 0) $level = $this->decrLevel($this->defaultLevel, $level);
|
|
return $level >= $this->minLevel;
|
|
}
|
|
|
|
protected function _printTitle(
|
|
int $level, string $type, ?string $linePrefix, int $indentLevel,
|
|
StdOutput $out, $content
|
|
): void {
|
|
$prefixes = self::GENERIC_PREFIXES[$level][$type];
|
|
if ($prefixes[0]) $out->print();
|
|
$content = cl::with($content);
|
|
if ($out->isColor()) {
|
|
$before = $prefixes[2];
|
|
$prefix = $prefixes[3];
|
|
$prefix2 = $prefix !== null? "$prefix ": null;
|
|
$suffix = $prefixes[4];
|
|
$suffix2 = $suffix !== null? " $suffix": null;
|
|
$after = $prefixes[5];
|
|
|
|
$lines = $out->getLines(false, ...$content);
|
|
$maxlen = 0;
|
|
foreach ($lines as &$content) {
|
|
$line = $out->filterColors($content);
|
|
$len = mb_strlen($line);
|
|
if ($len > $maxlen) $maxlen = $len;
|
|
$content = [$content, $len];
|
|
}; unset($content);
|
|
if ($before !== null) {
|
|
if ($linePrefix !== null) $out->write($linePrefix);
|
|
$out->iprint($indentLevel, $prefix, substr($before, 1), str_repeat($before[0], $maxlen), $suffix);
|
|
}
|
|
foreach ($lines as [$content, $len]) {
|
|
if ($linePrefix !== null) $out->write($linePrefix);
|
|
$padding = $len < $maxlen? str_repeat(" ", $maxlen - $len): null;
|
|
$out->iprint($indentLevel, $prefix2, $content, $padding, $suffix2);
|
|
}
|
|
if ($after !== null) {
|
|
if ($linePrefix !== null) $out->write($linePrefix);
|
|
$out->iprint($indentLevel, $prefix, substr($after, 1), str_repeat($after[0], $maxlen), $suffix);
|
|
}
|
|
} else {
|
|
$prefix = $prefixes[1];
|
|
if ($prefix !== null) $prefix .= " ";
|
|
$prefix2 = str_repeat(" ", mb_strlen($prefix));
|
|
$lines = $out->getLines(false, ...$content);
|
|
foreach ($lines as $content) {
|
|
if ($linePrefix !== null) $out->write($linePrefix);
|
|
$out->iprint($indentLevel, $prefix, $content);
|
|
$prefix = $prefix2;
|
|
}
|
|
}
|
|
}
|
|
|
|
protected abstract function action__flush(bool $endAction=false, ?int $overrideLevel=null): void;
|
|
|
|
protected function _printAction(
|
|
int $level, ?string $linePrefix, int $indentLevel,
|
|
StdOutput $out,
|
|
bool $printContent, $content,
|
|
bool $printResult, ?bool $rsuccess, $rcontent
|
|
): void {
|
|
$color = $out->isColor();
|
|
if ($rsuccess === true) $type = "success";
|
|
elseif ($rsuccess === false) $type = "failure";
|
|
else $type = "done";
|
|
$rprefixes = self::RESULT_PREFIXES[$type];
|
|
if ($color) {
|
|
$rprefix = $rprefixes[1];
|
|
$rprefix2 = null;
|
|
if ($rprefix !== null) {
|
|
$rprefix .= " ";
|
|
$rprefix2 = $out->filterColors($out->filterContent($rprefix));
|
|
$rprefix2 = str_repeat(" ", mb_strlen($rprefix2));
|
|
}
|
|
} else {
|
|
$rprefix = $rprefixes[0];
|
|
if ($rprefix !== null) $rprefix .= " ";
|
|
$rprefix2 = str_repeat(" ", mb_strlen($rprefix));
|
|
}
|
|
if ($printContent && $printResult) {
|
|
A::ensure_array($content);
|
|
if ($rcontent) {
|
|
$content[] = ": ";
|
|
$content[] = $rcontent;
|
|
}
|
|
$lines = $out->getLines(false, ...$content);
|
|
foreach ($lines as $content) {
|
|
if ($linePrefix !== null) $out->write($linePrefix);
|
|
$out->iprint($indentLevel, $rprefix, $content);
|
|
$rprefix = $rprefix2;
|
|
}
|
|
} elseif ($printContent) {
|
|
$prefixes = self::GENERIC_PREFIXES[$level]["step"];
|
|
if ($color) {
|
|
$prefix = $prefixes[1];
|
|
if ($prefix !== null) $prefix .= " ";
|
|
$prefix2 = $out->filterColors($out->filterContent($prefix));
|
|
$prefix2 = str_repeat(" ", mb_strlen($prefix2));
|
|
$suffix = $prefixes[2];
|
|
} else {
|
|
$prefix = $prefixes[0];
|
|
if ($prefix !== null) $prefix .= " ";
|
|
$prefix2 = str_repeat(" ", mb_strlen($prefix));
|
|
$suffix = null;
|
|
}
|
|
A::ensure_array($content);
|
|
$content[] = ":";
|
|
$lines = $out->getLines(false, ...$content);
|
|
foreach ($lines as $content) {
|
|
if ($linePrefix !== null) $out->write($linePrefix);
|
|
$out->iprint($indentLevel, $prefix, $content, $suffix);
|
|
$prefix = $prefix2;
|
|
}
|
|
} elseif ($printResult) {
|
|
if (!$rcontent) {
|
|
if ($type === "success") $rcontent = $color? "succès": "";
|
|
elseif ($type === "failure") $rcontent = $color? "échec": "";
|
|
elseif ($type === "done") $rcontent = "fait";
|
|
}
|
|
$rprefix = " $rprefix";
|
|
$rprefix2 = " $rprefix2";
|
|
$lines = $out->getLines(false, $rcontent);
|
|
foreach ($lines as $rcontent) {
|
|
if ($linePrefix !== null) $out->write($linePrefix);
|
|
$out->iprint($indentLevel, $rprefix, $rcontent);
|
|
$rprefix = $rprefix2;
|
|
}
|
|
}
|
|
}
|
|
|
|
protected function _printGeneric(
|
|
int $level, string $type, ?string $linePrefix, int $indentLevel,
|
|
StdOutput $out, $content
|
|
): void {
|
|
$prefixes = self::GENERIC_PREFIXES[$level][$type];
|
|
$content = cl::with($content);
|
|
if ($out->isColor()) {
|
|
$prefix = $prefixes[1];
|
|
$prefix2 = null;
|
|
if ($prefix !== null) {
|
|
$prefix .= " ";
|
|
$prefix2 = $out->filterColors($out->filterContent($prefix));
|
|
$prefix2 = str_repeat(" ", mb_strlen($prefix2));
|
|
}
|
|
$suffix = $prefixes[2];
|
|
$lines = $out->getLines(false, ...$content);
|
|
foreach ($lines as $content) {
|
|
if ($linePrefix !== null) $out->write($linePrefix);
|
|
$out->iprint($indentLevel, $prefix, $content, $suffix);
|
|
$prefix = $prefix2;
|
|
}
|
|
} else {
|
|
$prefix = $prefixes[0];
|
|
if ($prefix !== null) $prefix .= " ";
|
|
$prefix2 = str_repeat(" ", mb_strlen($prefix));
|
|
$lines = $out->getLines(false, ...$content);
|
|
foreach ($lines as $content) {
|
|
if ($linePrefix !== null) $out->write($linePrefix);
|
|
$out->iprint($indentLevel, $prefix, $content);
|
|
$prefix = $prefix2;
|
|
}
|
|
}
|
|
}
|
|
|
|
protected function _printGenericOrException(
|
|
?int $level, string $type, int $indentLevel,
|
|
StdOutput $out, $content
|
|
): void {
|
|
$linePrefix = $this->getLinePrefix();
|
|
# si $content contient des exceptions, les afficher avec un level moindre
|
|
$exceptions = null;
|
|
if (is_array($content)) {
|
|
$valueContent = null;
|
|
foreach ($content as $value) {
|
|
if ($value instanceof Throwable || $value instanceof ExceptionShadow) {
|
|
$exceptions[] = $value;
|
|
} else {
|
|
$valueContent[] = $value;
|
|
}
|
|
}
|
|
if ($valueContent === null) $content = null;
|
|
elseif (count($valueContent) == 1) $content = $valueContent[0];
|
|
else $content = $valueContent;
|
|
} elseif ($content instanceof Throwable || $content instanceof ExceptionShadow) {
|
|
$exceptions[] = $content;
|
|
$content = null;
|
|
}
|
|
|
|
$flushActions = true;
|
|
$showContent = $this->checkLevel($level);
|
|
if ($content !== null && $showContent) {
|
|
$this->action__flush(); $flushActions = false;
|
|
$this->_printGeneric($level, $type, $linePrefix, $indentLevel, $out, $content);
|
|
}
|
|
if ($exceptions !== null) {
|
|
$level1 = $this->decrLevel($level);
|
|
$showTraceback = $this->checkLevel($level1);
|
|
foreach ($exceptions as $exception) {
|
|
# tout d'abord message
|
|
$message = exceptions::get_message($exception);
|
|
if ($showContent) {
|
|
if ($flushActions) { $this->action__flush(); $flushActions = false; }
|
|
$this->_printGeneric($level, $type, $linePrefix, $indentLevel, $out, $message);
|
|
}
|
|
# puis summary et traceback
|
|
if ($showTraceback) {
|
|
if ($flushActions) { $this->action__flush(); $flushActions = false; }
|
|
$summary = exceptions::get_summary($exception, false);
|
|
$this->_printGeneric($level1, $type, $linePrefix, $indentLevel, $out, $summary);
|
|
$traceback = exceptions::get_traceback($exception);
|
|
$this->_printGeneric($level1, $type, $linePrefix, $indentLevel, $out, $traceback);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|