612 lines
		
	
	
		
			19 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
			
		
		
	
	
			612 lines
		
	
	
		
			19 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
<?php
 | 
						|
namespace nur\b\ui;
 | 
						|
 | 
						|
use Exception;
 | 
						|
use nur\A;
 | 
						|
use nur\b\ExceptionShadow;
 | 
						|
use nur\b\io\IWriter;
 | 
						|
use nur\b\params\Parametrable;
 | 
						|
use nur\b\params\Tparametrable;
 | 
						|
use nur\b\UserException;
 | 
						|
use nur\c;
 | 
						|
use nur\config;
 | 
						|
use nur\data\types\md_utils;
 | 
						|
use nur\data\types\Metadata;
 | 
						|
use nur\func;
 | 
						|
use nur\SL;
 | 
						|
use nur\writer;
 | 
						|
use Throwable;
 | 
						|
 | 
						|
abstract class AbstractMessenger extends Parametrable implements IMessenger {
 | 
						|
  use Tparametrable;
 | 
						|
 | 
						|
  const PRINT_LEVELS = [
 | 
						|
    self::KEY_USER => [
 | 
						|
      self::LEVEL_NORMAL,
 | 
						|
      config::DEVEL => self::LEVEL_MINOR,
 | 
						|
    ],
 | 
						|
    self::KEY_TECH => [
 | 
						|
      self::LEVEL_NORMAL,
 | 
						|
      config::DEVEL => self::LEVEL_MINOR,
 | 
						|
    ],
 | 
						|
    self::KEY_EXCEPTION => [
 | 
						|
      self::LEVEL_NEVER,
 | 
						|
      config::DEVEL => self::LEVEL_MINOR,
 | 
						|
    ],
 | 
						|
  ];
 | 
						|
 | 
						|
  const LOG_LEVELS = [
 | 
						|
    self::KEY_USER => [
 | 
						|
      self::LEVEL_NORMAL,
 | 
						|
      config::DEVEL => self::LEVEL_MINOR,
 | 
						|
    ],
 | 
						|
    self::KEY_TECH => [
 | 
						|
      self::LEVEL_NORMAL,
 | 
						|
      config::DEVEL => self::LEVEL_MINOR,
 | 
						|
    ],
 | 
						|
    self::KEY_EXCEPTION => [
 | 
						|
      self::LEVEL_NORMAL,
 | 
						|
      config::DEVEL => self::LEVEL_MINOR,
 | 
						|
    ],
 | 
						|
  ];
 | 
						|
 | 
						|
  const TYPE_LEVELS = [
 | 
						|
    IMessenger::TYPE_INFO,
 | 
						|
    config::DEVEL => IMessenger::TYPE_DEBUG,
 | 
						|
  ];
 | 
						|
 | 
						|
  const DATE_FORMAT = 'Y-m-d\TH:i:s.u';
 | 
						|
 | 
						|
  function __construct(?array $params=null) {
 | 
						|
    self::set_parametrable_params_defaults($params, [
 | 
						|
      "print_levels" => static::PRINT_LEVELS,
 | 
						|
      "log_levels" => static::LOG_LEVELS,
 | 
						|
      "type_levels" => static::TYPE_LEVELS,
 | 
						|
      "date_format" => static::DATE_FORMAT,
 | 
						|
    ]);
 | 
						|
    parent::__construct($params);
 | 
						|
  }
 | 
						|
 | 
						|
  const PARAMETRABLE_PARAMS_SCHEMA = [
 | 
						|
    "print_levels" => ["array", null, "niveaux par défaut pour chaque catégorie de message"],
 | 
						|
    "log_levels" => ["array", null, "niveaux par défaut pour chaque catégorie de message"],
 | 
						|
    "type_levels" => ["array", null, "niveaux par défaut des types de message"],
 | 
						|
    "log_output" => [null, null, "destination des messages de logs"],
 | 
						|
    "display_log" => ["bool", false, "faut-il afficher les logs?"],
 | 
						|
    "add_date" => ["?bool", null, "faut-il dater les messages?"],
 | 
						|
    "date_format" => ["string", null, "format de la date"]
 | 
						|
  ];
 | 
						|
 | 
						|
  /** @var array */
 | 
						|
  protected $ppPrintLevels;
 | 
						|
 | 
						|
  function pp_setPrintLevels(array $levels): void {
 | 
						|
    A::merge_nn($this->ppPrintLevels, $levels);
 | 
						|
  }
 | 
						|
 | 
						|
  /** @var array */
 | 
						|
  protected $ppLogLevels;
 | 
						|
 | 
						|
  function pp_setLogLevels(array $levels): void {
 | 
						|
    A::merge_nn($this->ppLogLevels, $levels);
 | 
						|
  }
 | 
						|
 | 
						|
  /** @var array */
 | 
						|
  protected $ppTypeLevels;
 | 
						|
 | 
						|
  /** @var IWriter */
 | 
						|
  protected $ppLogOutput;
 | 
						|
 | 
						|
  /** @var bool */
 | 
						|
  protected $ppDisplayLog;
 | 
						|
 | 
						|
  /** @var bool */
 | 
						|
  protected $ppAddDate;
 | 
						|
 | 
						|
  /** @var ?string */
 | 
						|
  protected $ppDateFormat;
 | 
						|
 | 
						|
  /** @var IWriter */
 | 
						|
  protected $logOutput;
 | 
						|
 | 
						|
  protected function afterSetParametrableParams(array $modifiedKeys, ?Metadata $md=null): void {
 | 
						|
    if (self::was_parametrable_param_modified($modifiedKeys, "log_output")) {
 | 
						|
      $this->logOutput = $this->ppLogOutput !== null? writer::with($this->ppLogOutput): null;
 | 
						|
      if (!self::was_parametrable_param_modified($modifiedKeys, "add_date")) {
 | 
						|
        $this->ppAddDate = $this->logOutput !== null;
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  function setLevels(?array $printLevels, ?array $logLevels=null, $typeLevels=null): IMessenger {
 | 
						|
    $this->setParametrableParams(SL::filter_z([
 | 
						|
      "print_levels" => $printLevels,
 | 
						|
      "log_levels" => $logLevels,
 | 
						|
      "type_levels" => $typeLevels,
 | 
						|
    ]));
 | 
						|
    return $this;
 | 
						|
  }
 | 
						|
 | 
						|
  protected function _getLevel(string $key, array $levels): int {
 | 
						|
    $level = A::get($levels, $key, self::LEVEL_NORMAL);
 | 
						|
    if (is_int($level)) return $level;
 | 
						|
 | 
						|
    $levels = A::with($level);
 | 
						|
    $level = A::get($levels, config::get_profile());
 | 
						|
    if ($level === null) $level = A::get($levels, 0);
 | 
						|
    if ($level === null) return self::LEVEL_NORMAL;
 | 
						|
 | 
						|
    return $level;
 | 
						|
  }
 | 
						|
 | 
						|
  function getPrintLevel(string $key): int {
 | 
						|
    return $this->_getLevel($key, $this->ppPrintLevels);
 | 
						|
  }
 | 
						|
 | 
						|
  function getLogLevel(string $key): int {
 | 
						|
    return $this->_getLevel($key, $this->ppLogLevels);
 | 
						|
  }
 | 
						|
 | 
						|
  function getTypeLevel(): int {
 | 
						|
    $levels = $this->ppTypeLevels;
 | 
						|
    $level = A::get($levels, config::get_profile());
 | 
						|
    if ($level === null) $level = A::get($levels, 0);
 | 
						|
    if ($level === null) return IMessenger::TYPE_INFO;
 | 
						|
 | 
						|
    return $level;
 | 
						|
  }
 | 
						|
 | 
						|
  function isLogMessage(?string $msg, int $level, string $msgKey): bool {
 | 
						|
    return $msg !== null && $level >= $this->getLogLevel($msgKey);
 | 
						|
  }
 | 
						|
 | 
						|
  function isPrintMessage(?string $msg, int $level, string $msgKey): bool {
 | 
						|
    return $msg !== null && $level >= $this->getPrintLevel($msgKey);
 | 
						|
  }
 | 
						|
 | 
						|
  protected function date() {
 | 
						|
    return date_create()->format($this->ppDateFormat);
 | 
						|
  }
 | 
						|
 | 
						|
  protected function getString($text): string {
 | 
						|
    return c::string(c::nq($text));
 | 
						|
  }
 | 
						|
  protected function filterTags(string $text): string {
 | 
						|
    return preg_replace('/<[^>]*>/', "", $text);
 | 
						|
  }
 | 
						|
  protected function filterColors(string $text): string {
 | 
						|
    return $text;
 | 
						|
  }
 | 
						|
  protected function wnl(IWriter $writer, ?bool $color, string $sep, ...$values): void {
 | 
						|
    $values = c::flatten($values);
 | 
						|
    foreach ($values as &$value) {
 | 
						|
      $value = $this->getString($value);
 | 
						|
      if (!$value) $value = false;
 | 
						|
    }; unset($value);
 | 
						|
    $text = $this->filterTags($writer->toString($sep, $values));
 | 
						|
    if ($color === null) $color = $writer->isatty();
 | 
						|
    if (!$color) $text = $this->filterColors($text);
 | 
						|
    $writer->wnl($text);
 | 
						|
  }
 | 
						|
 | 
						|
  protected function fixDest(?int &$type): void {
 | 
						|
    if ($type === null) $type = 0;
 | 
						|
    if (($type & self::DEST_MASK) === 0) $type += self::DEST_ALL;
 | 
						|
  }
 | 
						|
 | 
						|
  protected function shouldLog(?int $type): bool {
 | 
						|
    if ($this->logOutput === null) return false;
 | 
						|
    $this->fixDest($type);
 | 
						|
    return ($type & self::DEST_LOG) != 0;
 | 
						|
  }
 | 
						|
 | 
						|
  protected function shouldPrint(?int $type): bool {
 | 
						|
    $this->fixDest($type);
 | 
						|
    return ($type & self::DEST_DISPLAY) != 0 || $this->ppDisplayLog;
 | 
						|
  }
 | 
						|
 | 
						|
  #############################################################################
 | 
						|
  # Sections
 | 
						|
 | 
						|
  protected function logStartSection($title): void {
 | 
						|
    $datetime = $this->ppAddDate? $this->date()." ": "\n";
 | 
						|
    $title = "$datetime>>>> $title <<<<";
 | 
						|
    $this->wnl($this->logOutput, false, "", $title);
 | 
						|
  }
 | 
						|
 | 
						|
  protected function logEndSection(): void {
 | 
						|
  }
 | 
						|
 | 
						|
  protected abstract function printStartSection($title, ?int $msgType, ?int $msgLevel): void;
 | 
						|
  protected abstract function printEndSection(): void;
 | 
						|
 | 
						|
  /** @var bool */
 | 
						|
  private $inSection;
 | 
						|
 | 
						|
  function isInSection(): bool {
 | 
						|
    return $this->inSection;
 | 
						|
  }
 | 
						|
 | 
						|
  function startSection($title, ?int $msgType=null, ?int $msgLevel=null): IMessenger {
 | 
						|
    if ($this->inSection) $this->endSection();
 | 
						|
    $allowLog = $msgLevel === null || $msgLevel >= $this->getLogLevel(self::KEY_USER);
 | 
						|
    $allowPrint = $msgLevel === null || $msgLevel >= $this->getPrintLevel(self::KEY_USER);
 | 
						|
    if ($allowLog || $allowPrint) {
 | 
						|
      if ($allowLog && $this->shouldLog($msgType)) $this->logStartSection($title);
 | 
						|
      if ($allowPrint && $this->shouldPrint($msgType)) $this->printStartSection($title, $msgType, $msgLevel);
 | 
						|
      $this->inSection = true;
 | 
						|
    }
 | 
						|
    return $this;
 | 
						|
  }
 | 
						|
 | 
						|
  function endSection(): IMessenger {
 | 
						|
    if ($this->inSection) {
 | 
						|
      $this->printEndSection();
 | 
						|
      $this->inSection = false;
 | 
						|
    }
 | 
						|
    return $this;
 | 
						|
  }
 | 
						|
 | 
						|
  #############################################################################
 | 
						|
  # Groupes
 | 
						|
 | 
						|
  protected function getGroupCount(?array $group): int {
 | 
						|
    if ($group === null ) return 0;
 | 
						|
    $count = $group["count"];
 | 
						|
    return $count !== null? $count: 2;
 | 
						|
  }
 | 
						|
 | 
						|
  protected function getGroupIndent(?array $group, ?int $indent=null, int $maxCount=1): string {
 | 
						|
    if ($group === null) return "";
 | 
						|
    if ($indent === null) {
 | 
						|
      $indent = $group["indent"];
 | 
						|
      $count = $this->getGroupCount($group);
 | 
						|
      if ($count <= $maxCount) $indent--;
 | 
						|
    }
 | 
						|
    return str_repeat("  ", $indent);
 | 
						|
  }
 | 
						|
 | 
						|
  protected function getGroupPrefix(?array $group, int $maxCount=1): string {
 | 
						|
    if ($group === null) return "";
 | 
						|
    $count = $this->getGroupCount($group);
 | 
						|
    if ($count > $maxCount) return "";
 | 
						|
    return $group["prefix"]." :";
 | 
						|
  }
 | 
						|
 | 
						|
  protected function logStartGroup(array $group): void {
 | 
						|
    if ($this->getGroupCount($group) > 1) {
 | 
						|
      $groupIndent = $this->getGroupIndent($group, $group["indent"] - 1);
 | 
						|
      if ($this->ppAddDate) $groupIndent = self::date()." $groupIndent";
 | 
						|
      $this->wnl($this->logOutput, false, " ", $groupIndent.">", $group["prefix"]);
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  protected function logEndGroup(array $group): void {
 | 
						|
  }
 | 
						|
 | 
						|
  protected abstract function printStartGroup(array $group, ?array $groups): void;
 | 
						|
  protected abstract function printEndGroup(array $group): void;
 | 
						|
 | 
						|
  private $groups;
 | 
						|
 | 
						|
  public function isInGroup(): bool {
 | 
						|
    return $this->groups !== null;
 | 
						|
  }
 | 
						|
 | 
						|
  function startGroup($prefix, int $count=null, ?int $msgType=null, ?int $msgLevel=null): IMessenger {
 | 
						|
    $allowLog = $msgLevel === null || $msgLevel >= $this->getLogLevel(self::KEY_USER);
 | 
						|
    $allowPrint = $msgLevel === null || $msgLevel >= $this->getPrintLevel(self::KEY_USER);
 | 
						|
    if ($allowLog || $allowPrint) {
 | 
						|
      $indent = 1;
 | 
						|
      if ($this->groups !== null) {
 | 
						|
        foreach ($this->groups as $group) {
 | 
						|
          if ($group !== null) $indent++;
 | 
						|
        }
 | 
						|
      }
 | 
						|
      $group = [
 | 
						|
        "indent" => $indent,
 | 
						|
        "prefix" => $prefix,
 | 
						|
        "count" => $count,
 | 
						|
        "type" => $msgType,
 | 
						|
        "level" => $msgLevel,
 | 
						|
      ];
 | 
						|
      if ($allowLog && $this->shouldLog($msgType)) $this->logStartGroup($group);
 | 
						|
      if ($allowPrint && $this->shouldPrint($msgType)) $this->printStartGroup($group, $this->groups);
 | 
						|
    } else {
 | 
						|
      $group = false;
 | 
						|
    }
 | 
						|
    $this->groups[] = $group;
 | 
						|
    return $this;
 | 
						|
  }
 | 
						|
 | 
						|
  function endGroup(): IMessenger {
 | 
						|
    $group = array_pop($this->groups);
 | 
						|
    if ($group) {
 | 
						|
      $type = $group["type"];
 | 
						|
      if ($this->shouldLog($type)) $this->logEndGroup($group);
 | 
						|
      if ($this->shouldPrint($type)) $this->printEndGroup($group);
 | 
						|
    }
 | 
						|
    if (!$this->groups) $this->groups = null;
 | 
						|
    return $this;
 | 
						|
  }
 | 
						|
 | 
						|
  function end(bool $all=false): IMessenger {
 | 
						|
    if ($all) {
 | 
						|
      while ($this->groups) $this->endGroup();
 | 
						|
      $this->endSection();
 | 
						|
    } elseif ($this->groups) $this->endGroup();
 | 
						|
    else $this->endSection();
 | 
						|
    return $this;
 | 
						|
  }
 | 
						|
 | 
						|
  #############################################################################
 | 
						|
  # Messages
 | 
						|
 | 
						|
  const TYPE_PREFIXES = [
 | 
						|
    # les clés doivent être ordonnées de la plus grande à la plus petite
 | 
						|
    # la 2ème valeur indique s'il faut garder le préfixe s'il y a un result
 | 
						|
    self::LEVEL_CRITICAL => [
 | 
						|
      self::TYPE_ERROR => ["CRITICAL!", true],
 | 
						|
      self::TYPE_WARNING => ["ATTENTION!", true],
 | 
						|
      self::TYPE_DEBUG => ["IMPORTANT!", true],
 | 
						|
    ],
 | 
						|
    self::LEVEL_MAJOR => [
 | 
						|
      self::TYPE_ERROR => ["ERROR:", true],
 | 
						|
      self::TYPE_WARNING => ["WARN:", true],
 | 
						|
      self::TYPE_INFO => ["INFO:", false],
 | 
						|
      self::TYPE_DEBUG => ["DEBUG:", true],
 | 
						|
    ],
 | 
						|
    self::LEVEL_NORMAL => [
 | 
						|
      self::TYPE_ERROR => ["E", true],
 | 
						|
      self::TYPE_WARNING => ["W", true],
 | 
						|
      self::TYPE_INFO => ["", false],
 | 
						|
      self::TYPE_DEBUG => ["D", true],
 | 
						|
    ],
 | 
						|
    self::LEVEL_MINOR => [
 | 
						|
      self::TYPE_ERROR => ["e", true],
 | 
						|
      self::TYPE_WARNING => ["w", true],
 | 
						|
      self::TYPE_INFO => ["i", false],
 | 
						|
      self::TYPE_DEBUG => ["d", true],
 | 
						|
    ],
 | 
						|
  ];
 | 
						|
  const RESULT_PREFIXES = [
 | 
						|
    self::RESULT_FAILURE => "(FAILURE)",
 | 
						|
    self::RESULT_SUCCESS => "(SUCCESS)",
 | 
						|
    self::RESULT_NEUTRAL => "*",
 | 
						|
    self::RESULT_NONE => null,
 | 
						|
  ];
 | 
						|
 | 
						|
  protected function getResultPrefix(int $result, bool $color): ?string {
 | 
						|
    return self::RESULT_PREFIXES[$result];
 | 
						|
  }
 | 
						|
 | 
						|
  protected function getTypePrefixSuffix(int $type, int $level, bool $color, bool $haveResultPrefix): array {
 | 
						|
    $typePrefixSuffix = false;
 | 
						|
    foreach (self::TYPE_PREFIXES as $prefixLevel => $prefixes) {
 | 
						|
      if ($level >= $prefixLevel) {
 | 
						|
        foreach ($prefixes as $prefixType => $prefixValue) {
 | 
						|
          if ($type >= $prefixType) {
 | 
						|
            $typePrefixSuffix = $prefixValue;
 | 
						|
            break;
 | 
						|
          }
 | 
						|
        }
 | 
						|
      }
 | 
						|
      if ($typePrefixSuffix !== false) break;
 | 
						|
    }
 | 
						|
    if ($typePrefixSuffix === false) return [null, null];
 | 
						|
    elseif ($haveResultPrefix && !$typePrefixSuffix[1]) return [null, null];
 | 
						|
    $prefix = $typePrefixSuffix[0];
 | 
						|
    $suffix = "";
 | 
						|
    return [$prefix, $suffix];
 | 
						|
  }
 | 
						|
 | 
						|
  /** @var Metadata */
 | 
						|
  private static $message_md;
 | 
						|
 | 
						|
  protected static function message_md(): Metadata {
 | 
						|
    return md_utils::ensure_md(self::$message_md
 | 
						|
      , array_merge(self::MESSAGE_SCHEMA, self::MESSAGE_OPTIONS_SCHEMA));
 | 
						|
  }
 | 
						|
 | 
						|
  protected function logMsg(
 | 
						|
    ?array $groups,
 | 
						|
    bool $logUser, $userMsg,
 | 
						|
    bool $logTech, $techMsg,
 | 
						|
    bool $logException, $exceptionMsg,
 | 
						|
    int $type, int $level
 | 
						|
  ): void {
 | 
						|
    $group = A::last($groups);
 | 
						|
    if ($group === false) {
 | 
						|
      # groupe neutralisé
 | 
						|
      return;
 | 
						|
    }
 | 
						|
    $groupIndent = $this->getGroupIndent($group);
 | 
						|
    $groupPrefix = $this->getGroupPrefix($group);
 | 
						|
    if ($this->ppAddDate) $groupIndent = self::date()." $groupIndent";
 | 
						|
 | 
						|
    $color = false;
 | 
						|
    $result = $type & self::RESULT_MASK;
 | 
						|
    $type = $type & self::TYPE_MASK;
 | 
						|
    $resultPrefix = $this->getResultPrefix($result, $color);
 | 
						|
    [$typePrefix, $typeSuffix] = $this->getTypePrefixSuffix($type, $level, $color, $resultPrefix !== null);
 | 
						|
    $prefix = $groupIndent.$typePrefix.$resultPrefix;
 | 
						|
 | 
						|
    $logOutput = $this->logOutput;
 | 
						|
    if ($logUser) $this->wnl($logOutput, $color, " ", $prefix, $groupPrefix, $userMsg, $typeSuffix);
 | 
						|
    if ($logTech) $this->wnl($logOutput, $color, " ", $prefix, "TECH:", $techMsg, $typeSuffix);
 | 
						|
    if ($logException) {
 | 
						|
      [$summary, $traceback] = $exceptionMsg;
 | 
						|
      $this->wnl($logOutput, $color, " ", $prefix, "TRACEBACK:", $summary, $typeSuffix);
 | 
						|
      $this->wnl($logOutput, false, "", $traceback);
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  protected abstract function getUserMsg($msg): array;
 | 
						|
  protected abstract function getTechMsg($msg): array;
 | 
						|
  protected abstract function getExceptionMsg($exception, $user, $tech, bool $haveTechMsgOrSummary): array;
 | 
						|
  protected abstract function printMsg(
 | 
						|
    ?array $groups
 | 
						|
    , bool $printUser, $userMsg
 | 
						|
    , bool $printTech, $techMsg
 | 
						|
    , bool $printException, $exceptionMsg
 | 
						|
    , int  $type, int $level, array $options
 | 
						|
  ): void;
 | 
						|
 | 
						|
  protected function processMsgOptions(array $options): void {
 | 
						|
  }
 | 
						|
 | 
						|
  function ensureMessage(&$message): void {
 | 
						|
    static::message_md()->ensureSchema($message);
 | 
						|
 | 
						|
    $user =& $message[self::KEY_USER];
 | 
						|
    $tech =& $message[self::KEY_TECH];
 | 
						|
    $exception =& $message[self::KEY_EXCEPTION];
 | 
						|
    if ($exception === null) {
 | 
						|
      if ($tech instanceof Throwable || $tech instanceof ExceptionShadow) $exception = $tech;
 | 
						|
      elseif ($user instanceof Throwable || $user instanceof ExceptionShadow) $exception = $user;
 | 
						|
    }
 | 
						|
    if ($tech === null) {
 | 
						|
      if ($user instanceof Throwable || $user instanceof ExceptionShadow) $tech = $user;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  function addMessage($message, int $type, int $level): IMessenger {
 | 
						|
    $allowType = ($type & self::TYPE_MASK) >= $this->getTypeLevel();
 | 
						|
    if (!$allowType) return $this;
 | 
						|
 | 
						|
    $this->fixDest($type);
 | 
						|
    $this->ensureMessage($message);
 | 
						|
 | 
						|
    $user = $message[self::KEY_USER];
 | 
						|
    $logUser = $level >= $this->getLogLevel(self::KEY_USER);
 | 
						|
    $printUser = $level >= $this->getPrintLevel(self::KEY_USER);
 | 
						|
    $userMsg = false;
 | 
						|
    if ($user !== null) {
 | 
						|
      if ($user instanceof UserException) $msg = $user->getUserMessage();
 | 
						|
      elseif ($user instanceof Throwable || $user instanceof ExceptionShadow) $msg = $user->getMessage();
 | 
						|
      else $msg = $user;
 | 
						|
      if (!$msg) $printUser = false;
 | 
						|
      else $userMsg = $this->getUserMsg($msg);
 | 
						|
    }
 | 
						|
    $logUser &= $userMsg !== false;
 | 
						|
    $printUser &= $userMsg !== false;
 | 
						|
 | 
						|
    $tech = $message[self::KEY_TECH];
 | 
						|
    $logTech = $level >= $this->getLogLevel(self::KEY_TECH);
 | 
						|
    $printTech = $level >= $this->getPrintLevel(self::KEY_TECH);
 | 
						|
    $techMsg = false;
 | 
						|
    $techSummary = false;
 | 
						|
    $exception = $message[self::KEY_EXCEPTION];
 | 
						|
    $logException = $exception !== null && $level >= $this->getLogLevel(self::KEY_EXCEPTION);;
 | 
						|
    $printException = $exception !== null && $level >= $this->getPrintLevel(self::KEY_EXCEPTION);;
 | 
						|
    $exceptionMsg = false;
 | 
						|
    if ($tech !== null) {
 | 
						|
      if ($tech instanceof UserException) {
 | 
						|
        $msg = $tech->getTechMessage();
 | 
						|
      } elseif (($tech instanceof Throwable || $tech instanceof ExceptionShadow) && !$printException) {
 | 
						|
        $techSummary = true;
 | 
						|
        $msg = UserException::get_summary($tech);
 | 
						|
      } else {
 | 
						|
        $msg = $tech;
 | 
						|
      }
 | 
						|
      if (!$msg) $printTech = false;
 | 
						|
      else $techMsg = $this->getTechMsg($msg);
 | 
						|
    }
 | 
						|
    $logTech &= $techMsg !== false;
 | 
						|
    $printTech &= $techMsg !== false;
 | 
						|
 | 
						|
    if ($exception !== null) {
 | 
						|
      $exceptionMsg = $this->getExceptionMsg($exception, $user, $tech, $techMsg || $techSummary);
 | 
						|
    }
 | 
						|
    $logException &= $exceptionMsg !== false;
 | 
						|
    $printException &= $exceptionMsg !== false;
 | 
						|
 | 
						|
    $options = $message;
 | 
						|
    if ($this->shouldLog($type)) {
 | 
						|
      $this->logMsg(
 | 
						|
        $this->groups,
 | 
						|
        $logUser, $userMsg,
 | 
						|
        $logTech, $techMsg,
 | 
						|
        $logException, $exceptionMsg,
 | 
						|
        $type, $level);
 | 
						|
    }
 | 
						|
    if ($this->shouldPrint($type)) {
 | 
						|
      $this->printMsg(
 | 
						|
        $this->groups,
 | 
						|
        $printUser, $userMsg,
 | 
						|
        $printTech, $techMsg,
 | 
						|
        $printException, $exceptionMsg,
 | 
						|
        $type, $level, $options);
 | 
						|
    }
 | 
						|
    $this->processMsgOptions($options);
 | 
						|
    return $this;
 | 
						|
  }
 | 
						|
 | 
						|
  function aresult($result, ?array $args=null, $message=null, ?int $type=null): IMessenger {
 | 
						|
    if ($message !== null) static::message_md()->ensureSchema($message);
 | 
						|
    if (is_callable($result)) {
 | 
						|
      if ($args === null) $args = [];
 | 
						|
      try {
 | 
						|
        $result = func::call($result, ...$args);
 | 
						|
        if ($result === null) {
 | 
						|
          # cas des fonctions void
 | 
						|
          $result = true;
 | 
						|
        }
 | 
						|
      } catch (Exception $e) {
 | 
						|
        $result = $e;
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    $type = ($type?: 0) & self::DEST_MASK;
 | 
						|
    $level = self::LEVEL_MAJOR;
 | 
						|
    if ($result instanceof Exception) {
 | 
						|
      $type += self::TYPE_INFO + self::RESULT_FAILURE;
 | 
						|
      $message[self::KEY_USER] = $result;
 | 
						|
    } elseif (is_string($result)) {
 | 
						|
      $type += self::TYPE_INFO + self::RESULT_SUCCESS;
 | 
						|
      $message[self::KEY_USER] = $result;
 | 
						|
    } elseif ($result === null) {
 | 
						|
      $type += self::TYPE_INFO + self::RESULT_NEUTRAL;
 | 
						|
      A::replace_z($message, self::KEY_USER, "en cours");
 | 
						|
    } elseif ($result) {
 | 
						|
      $type += self::TYPE_INFO + self::RESULT_SUCCESS;
 | 
						|
      A::replace_z($message, self::KEY_USER, "succès");
 | 
						|
    } else {
 | 
						|
      $type += self::TYPE_INFO + self::RESULT_FAILURE;
 | 
						|
      A::replace_z($message, self::KEY_USER, "échec");
 | 
						|
    }
 | 
						|
    $this->addMessage($message, $type, $level);
 | 
						|
    if ($this->isInGroup()) $this->endGroup();
 | 
						|
    return $this;
 | 
						|
  }
 | 
						|
 | 
						|
  function astep($message=null, ?int $type=null): IMessenger {
 | 
						|
    $this->aresult(null, null, $message, $type);
 | 
						|
    return $this;
 | 
						|
  }
 | 
						|
 | 
						|
  function asuccess($message=null, ?int $type=null): IMessenger {
 | 
						|
    $this->aresult(true, null, $message, $type);
 | 
						|
    return $this;
 | 
						|
  }
 | 
						|
 | 
						|
  function afailure($message=null, ?Throwable $e=null, ?int $type=null): IMessenger {
 | 
						|
    static::message_md()->ensureSchema($message);
 | 
						|
    if ($message === null) {
 | 
						|
      $message = $e;
 | 
						|
    } elseif ($message[self::KEY_USER] === null) {
 | 
						|
      $message[self::KEY_USER] = $e;
 | 
						|
    } else {
 | 
						|
      A::replace_z($message, self::KEY_EXCEPTION, $e);
 | 
						|
    }
 | 
						|
    $this->aresult(false, null, $message, $type);
 | 
						|
    return $this;
 | 
						|
  }
 | 
						|
 | 
						|
  function action($message, $result=null, ?array $args=null, ?int $type=null, ?int $level=null): IMessenger {
 | 
						|
    $this->startGroup($message, 1, $type, $level);
 | 
						|
    if ($result !== null) $this->aresult($result, $args, null, $type);
 | 
						|
    return $this;
 | 
						|
  }
 | 
						|
}
 |