139 lines
		
	
	
		
			3.9 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
			
		
		
	
	
			139 lines
		
	
	
		
			3.9 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
<?php
 | 
						|
namespace nur\b;
 | 
						|
 | 
						|
use Exception;
 | 
						|
use nur\md;
 | 
						|
use Throwable;
 | 
						|
 | 
						|
/**
 | 
						|
 * Class UserException: une exception qui peut contenir deux messages: un
 | 
						|
 * message utilisateur, et un message technique, destiné à l'exploitant
 | 
						|
 */
 | 
						|
class UserException extends Exception {
 | 
						|
  /** @param Throwable|ExceptionShadow $e */
 | 
						|
  static function get_user_message($e): ?string {
 | 
						|
    if ($e instanceof self) return $e->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;
 | 
						|
  }
 | 
						|
}
 |