getUserMessage(); else return null; } /** @param Throwable|ExceptionShadow $e */ static function get_tech_message($e): ?string { if ($e instanceof self) return $e->getTechMessage(); else return $e->getMessage(); } /** @param Throwable|ExceptionShadow $e */ static function get_message($e): ?string { $message = null; if ($e instanceof self) { if ($message === null) $message = $e->getTechMessage(); if ($message === null) $message = $e->getUserMessage(); } if ($message === null) $message = $e->getMessage(); return $message; } /** @param Throwable|ExceptionShadow $e */ static final function get_user_summary($e): string { $parts = []; $first = true; while ($e !== null) { $message = self::get_user_message($e); if (!$message) $message = "(no message)"; if ($first) $first = false; else $parts[] = "caused by "; $parts[] = get_class($e) . ": " . $message; $e = $e->getPrevious(); } return implode(", ", $parts); } /** @param Throwable|ExceptionShadow $e */ static final function get_tech_summary($e): string { $parts = []; $first = true; while ($e !== null) { $message = self::get_tech_message($e); if (!$message) $message = "(no message)"; if ($first) $first = false; else $parts[] = "caused by "; $parts[] = get_class($e) . ": " . $message; $e = $e->getPrevious(); } return implode(", ", $parts); } /** @param Throwable|ExceptionShadow $e */ static final function get_summary($e): string { $parts = []; $first = true; while ($e !== null) { $message = self::get_message($e); if (!$message) $message = "(no message)"; if ($first) $first = false; else $parts[] = "caused by "; if ($e instanceof ExceptionShadow) $class = $e->getClass(); else $class = get_class($e); $parts[] = "$class: $message"; $e = $e->getPrevious(); } return implode(", ", $parts); } /** @param Throwable|ExceptionShadow $e */ static final function get_traceback($e): string { $tbs = []; $previous = false; while ($e !== null) { if (!$previous) { $efile = $e->getFile(); $eline = $e->getLine(); $tbs[] = "at $efile($eline)"; } else { $tbs[] = "~~ caused by: " . self::get_summary($e); } $tbs[] = $e->getTraceAsString(); $e = $e->getPrevious(); $previous = true; #XXX il faudrait ne pas réinclure les lignes communes aux exceptions qui # ont déjà été affichées } return implode("\n", $tbs); } const SCHEMA = [ "user" => [null, null, "message utilisateur"], "tech" => [null, null, "message technique"], ]; const USER_MESSAGE = null; const TECH_MESSAGE = null; function __construct($message, $code=0, ?Throwable $previous=null) { md::ensure_schema($message, self::SCHEMA); $user_message = $message["user"]; if ($user_message === null) $user_message = static::USER_MESSAGE; $this->userMessage = $user_message; $tech_message = $message["tech"]; if ($tech_message === null) $tech_message = static::TECH_MESSAGE; if ($tech_message === null) $tech_message = $previous; $this->techMessage = $tech_message; $message = $tech_message; if ($message === null) $message = $user_message; parent::__construct($message, $code, $previous); } protected $userMessage; function getUserMessage(): ?string { return $this->userMessage; } protected $techMessage; function getTechMessage(): ?string { return $this->techMessage; } }