342 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
			
		
		
	
	
			342 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
| <?php
 | |
| namespace nur\v\html5;
 | |
| 
 | |
| use nur\A;
 | |
| use nur\b\ui\AbstractMessenger;
 | |
| use nur\b\UserException;
 | |
| use nur\data\types\md_utils;
 | |
| use nur\data\types\Metadata;
 | |
| use nur\v\v;
 | |
| use nur\v\vo;
 | |
| 
 | |
| class Html5Messenger extends AbstractMessenger {
 | |
|   const MESSAGE_OPTIONS_SCHEMA = [];
 | |
| 
 | |
|   /** @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));
 | |
|   }
 | |
| 
 | |
|   const SECTION_LEVEL_CLASSES = [
 | |
|     # les clés doivent être ordonnées de la plus grande à la plus petite
 | |
|     self::LEVEL_CRITICAL => "msg-section-critical",
 | |
|     self::LEVEL_MAJOR => "msg-section-major",
 | |
|     self::LEVEL_NORMAL => "msg-section-normal",
 | |
|     self::LEVEL_MINOR => "msg-section-minor",
 | |
|   ];
 | |
|   const SECTION_TYPE_CLASSES = [
 | |
|     # les clés doivent être ordonnées de la plus grande à la plus petite
 | |
|     self::TYPE_ERROR => "msg-section-error",
 | |
|     self::TYPE_WARNING => "msg-section-warning",
 | |
|     self::TYPE_INFO => "msg-section-info",
 | |
|     self::TYPE_DEBUG => "msg-section-debug",
 | |
|   ];
 | |
|   const SECTION_TYPE_PREFIXES = [
 | |
|     # les clés doivent être ordonnées de la plus grande à la plus petite
 | |
|     self::LEVEL_CRITICAL => [
 | |
|       self::TYPE_ERROR => "[CRITIQUE!] ",
 | |
|       self::TYPE_WARNING => "[AVERTISSEMENT!] ",
 | |
|       self::TYPE_DEBUG => "[IMPORTANT!] ",
 | |
|     ],
 | |
|     self::LEVEL_MAJOR => [
 | |
|       self::TYPE_ERROR => "[ERREUR] ",
 | |
|       self::TYPE_WARNING => "[AVERTISSEMENT] ",
 | |
|       self::TYPE_DEBUG => "[NOTE] ",
 | |
|     ],
 | |
|     self::LEVEL_NORMAL => [
 | |
|       self::TYPE_DEBUG => null,
 | |
|     ],
 | |
|     self::LEVEL_MINOR => [
 | |
|       self::TYPE_ERROR => "[erreur] ",
 | |
|       self::TYPE_WARNING => "[avertissement] ",
 | |
|       self::TYPE_DEBUG => null,
 | |
|     ],
 | |
|   ];
 | |
| 
 | |
|   const GROUP_LEVEL_CLASSES = [
 | |
|     # les clés doivent être ordonnées de la plus grande à la plus petite
 | |
|     self::LEVEL_CRITICAL => "msg-group-critical",
 | |
|     self::LEVEL_MAJOR => "msg-group-major",
 | |
|     self::LEVEL_NORMAL => "msg-group-normal",
 | |
|     self::LEVEL_MINOR => "msg-group-minor",
 | |
|   ];
 | |
|   const GROUP_TYPE_CLASSES = [
 | |
|     # les clés doivent être ordonnées de la plus grande à la plus petite
 | |
|     self::TYPE_ERROR => "msg-group-error",
 | |
|     self::TYPE_WARNING => "msg-group-warning",
 | |
|     self::TYPE_INFO => "msg-group-info",
 | |
|     self::TYPE_DEBUG => "msg-group-debug",
 | |
|   ];
 | |
|   
 | |
|   const LEVEL_CLASSES = [
 | |
|     # les clés doivent être ordonnées de la plus grande à la plus petite
 | |
|     self::LEVEL_CRITICAL => "msg-critical",
 | |
|     self::LEVEL_MAJOR => "msg-major",
 | |
|     self::LEVEL_NORMAL => "msg-normal",
 | |
|     self::LEVEL_MINOR => "msg-minor",
 | |
|   ];
 | |
|   const TYPE_CLASSES = [
 | |
|     # les clés doivent être ordonnées de la plus grande à la plus petite
 | |
|     self::TYPE_ERROR => "msg-error",
 | |
|     self::TYPE_WARNING => "msg-warning",
 | |
|     self::TYPE_INFO => "msg-info",
 | |
|     self::TYPE_DEBUG => "msg-debug",
 | |
|   ];
 | |
|   const TYPE_PREFIXES = [
 | |
|     # les clés doivent être ordonnées de la plus grande à la plus petite
 | |
|     self::LEVEL_CRITICAL => [
 | |
|       self::TYPE_ERROR => "[CRITICAL!] ",
 | |
|       self::TYPE_WARNING => "[ATTENTION!] ",
 | |
|       self::TYPE_DEBUG => "[IMPORTANT!] ",
 | |
|     ],
 | |
|     self::LEVEL_MAJOR => [
 | |
|       self::TYPE_ERROR => "[ERROR] ",
 | |
|       self::TYPE_WARNING => "[WARN] ",
 | |
|       self::TYPE_DEBUG => "[NOTE] ",
 | |
|     ],
 | |
|     self::LEVEL_NORMAL => [
 | |
|       self::TYPE_DEBUG => null,
 | |
|     ],
 | |
|     self::LEVEL_MINOR => [
 | |
|       self::TYPE_ERROR => "[error] ",
 | |
|       self::TYPE_WARNING => "[warn] ",
 | |
|       self::TYPE_INFO => null,
 | |
|       self::TYPE_DEBUG => "[debug] ",
 | |
|     ],
 | |
|   ];
 | |
|   
 | |
|   const RESULT_CLASS_PREFIXES = [
 | |
|     self::RESULT_FAILURE => ["msg-result-failure", "✘ "],
 | |
|     self::RESULT_SUCCESS => ["msg-result-success", "✔ "],
 | |
|     self::RESULT_NEUTRAL => ["msg-result-neutral", ". "],
 | |
|     self::RESULT_NONE => [null, null],
 | |
|   ];
 | |
| 
 | |
|   protected function getClassPrefix(
 | |
|     ?int $type, ?int $level
 | |
|     , array $levelClasses
 | |
|     , array $typeClasses
 | |
|     , ?array $typePrefixes=null
 | |
|   ): array {
 | |
|     $class = null;
 | |
|     $prefix = false;
 | |
|     
 | |
|     if ($type !== null) {
 | |
|       $class = [];
 | |
|       foreach ($levelClasses as $classLevel => $classValue) {
 | |
|         if ($level >= $classLevel) {
 | |
|           $class[] = $classValue;
 | |
|           break;
 | |
|         }
 | |
|       }
 | |
|       foreach ($typeClasses as $classType => $classValue) {
 | |
|         if ($type >= $classType) {
 | |
|           $class[] = $classValue;
 | |
|           break;
 | |
|         }
 | |
|       }
 | |
|   
 | |
|       if ($level !== null && $typePrefixes !== null) {
 | |
|         foreach ($typePrefixes as $prefixLevel => $prefixes) {
 | |
|           if ($level >= $prefixLevel) {
 | |
|             foreach ($prefixes as $prefixType => $prefixValue) {
 | |
|               if ($type >= $prefixType) {
 | |
|                 $prefix = $prefixValue;
 | |
|                 break;
 | |
|               }
 | |
|             }
 | |
|           }
 | |
|           if ($prefix !== false) break;
 | |
|         }
 | |
|       }
 | |
|     }
 | |
|     return [$class, $prefix];
 | |
|   }
 | |
| 
 | |
|   protected function getResultClassPrefix(int $result): array {
 | |
|     return static::RESULT_CLASS_PREFIXES[$result];
 | |
|   }
 | |
| 
 | |
|   protected $showSectionHeading = false;
 | |
| 
 | |
|   function setShowSectionHeading(bool $showSectionHeading=true): self {
 | |
|     $this->showSectionHeading = $showSectionHeading;
 | |
|     return $this;
 | |
|   }
 | |
| 
 | |
|   protected function printStartSection($title, ?int $msgType, ?int $msgLevel): void {
 | |
|     if ($msgType !== null) {
 | |
|       $result = $msgType & self::RESULT_MASK;
 | |
|       $msgType = $msgType & self::TYPE_MASK;
 | |
|     } else {
 | |
|       $result = self::RESULT_NONE;
 | |
|     }
 | |
|     [$typeClass, $typePrefix] = $this->getClassPrefix($msgType, $msgLevel
 | |
|       , static::SECTION_LEVEL_CLASSES
 | |
|       , static::SECTION_TYPE_CLASSES
 | |
|       , static::SECTION_TYPE_PREFIXES
 | |
|     );
 | |
|     [$resultClass, $resultPrefix] = $this->getResultClassPrefix($result);
 | |
|     $sectionHeading = null;
 | |
|     if ($title && $this->showSectionHeading) {
 | |
|       $sectionHeading = v::div([
 | |
|         "class" => "msg-section-heading",
 | |
|         v::h3([
 | |
|           "class" => "msg-section-title",
 | |
|           $typePrefix, $resultPrefix, q($title),
 | |
|         ]),
 | |
|       ]);
 | |
|     }
 | |
|     vo::sdiv([
 | |
|       "class" => ["msg-section", $typeClass, $resultClass],
 | |
|       $sectionHeading,
 | |
|       v::sdiv(["class" => "msg-section-body"]),
 | |
|     ]);
 | |
|   }
 | |
| 
 | |
|   protected function printEndSection(): void {
 | |
|     vo::ediv();
 | |
|     vo::ediv();
 | |
|   }
 | |
| 
 | |
|   protected function getGroupCount(?array $group): int {
 | |
|     if ($group === null ) return 0;
 | |
|     $count = $group["count"];
 | |
|     return $count !== null? $count: 2;
 | |
|   }
 | |
| 
 | |
|   protected function getGroupPrefix(?array $group, int $maxCount=1): string {
 | |
|     if ($group === null) return "";
 | |
|     return $this->getGroupCount($group) > $maxCount? "": $group["prefix"]." : ";
 | |
|   }
 | |
| 
 | |
|   protected function printStartGroup(array $group, ?array $groups): void {
 | |
|     if ($this->getGroupCount($group) > 1) {
 | |
|       $type = $group["type"];
 | |
|       $level = $group["level"];
 | |
|       $prefix = $group["prefix"];
 | |
|       if ($type !== null) $type = $type & self::TYPE_MASK;
 | |
|       [$typeClass, $typePrefix] = $this->getClassPrefix($type, $level
 | |
|         , static::GROUP_LEVEL_CLASSES
 | |
|         , static::GROUP_TYPE_CLASSES
 | |
|       );
 | |
|       vo::sdiv([
 | |
|         "class" => ["msg-group", $typeClass],
 | |
|         v::div([
 | |
|           "class" => "msg-group-heading",
 | |
|           v::h4([
 | |
|             "class" => "msg-group-title",
 | |
|             $typePrefix, q($prefix),
 | |
|           ]),
 | |
|         ]),
 | |
|         v::sdiv(["class" => "msg-group-body"]),
 | |
|       ]);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   protected function printEndGroup(array $group): void {
 | |
|     if ($this->getGroupCount($group) > 1) {
 | |
|       vo::ediv();
 | |
|       vo::ediv();
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   protected function getUserMsg($msg): array {
 | |
|     return v::span([
 | |
|       "class" => "msg-user",
 | |
|       q($msg),
 | |
|     ]);
 | |
|   }
 | |
| 
 | |
|   protected function getTechMsg($msg): array {
 | |
|     return v::div([
 | |
|       "class" => "msg-tech",
 | |
|       "style" => "margin-top: 1em;",
 | |
|       "Le message d'erreur technique est : ", q($msg),
 | |
|     ]);
 | |
|   }
 | |
| 
 | |
|   protected function getExceptionMsg($exception, $user, $tech, bool $haveTechMsgOrSummary): array {
 | |
|     $msg = [
 | |
|       v::sdiv(["class" => "msg-exception"]),
 | |
|       v::div([
 | |
|         "class" => "msg-exception-summary",
 | |
|         "style" => "margin-top: 1em;",
 | |
|         "D'autres informations techniques sont disponibles. Le service informatique sera peut-être amené à vous les demander. ",
 | |
|         v::a([
 | |
|           "href" => "",
 | |
|           "accesskey" => "d",
 | |
|           "onclick" => 'javascript: var $me = jQuery(this).closest("div.msg-exception"); $me.find("div.msg-exception-details").removeClass("hidden"); $me.find("div.msg-exception-summary").addClass("hidden"); return false;',
 | |
|           "Afficher les détails..."
 | |
|         ]),
 | |
|       ]),
 | |
|       v::sdiv(["class" => "msg-exception-details hidden"]),
 | |
|     ];
 | |
|     if (!$haveTechMsgOrSummary || ($exception !== $user && $exception !== $tech)) {
 | |
|       $msg[] = v::div([
 | |
|         "class" => "msg-exception-tech",
 | |
|         "style" => "margin-top: 1em;",
 | |
|         "Le message d'erreur technique détaillé est: ",
 | |
|         q(UserException::get_summary($exception)),
 | |
|       ]);
 | |
|     }
 | |
|     $msg[] = v::div([
 | |
|       "class" => "msg-exception-traceback",
 | |
|       "style" => "margin-top: 1em;",
 | |
|       "Traceback:",
 | |
|       v::pre([UserException::get_traceback($exception)]),
 | |
|     ]);
 | |
|     $msg[] = v::ediv();
 | |
|     $msg[] = v::ediv();
 | |
|     return $msg;
 | |
|   }
 | |
| 
 | |
|   protected function printMsg(
 | |
|     ?array $groups,
 | |
|     bool $printUser, $userMsg,
 | |
|     bool $printTech, $techMsg,
 | |
|     bool $printException, $exceptionMsg,
 | |
|     int $type, int $level, array $options
 | |
|   ): void {
 | |
|     $group = A::last($groups);
 | |
|     if ($group === false) {
 | |
|       # groupe neutralisé
 | |
|       return;
 | |
|     }
 | |
|     $groupPrefix = $this->getGroupPrefix($group);
 | |
| 
 | |
|     $result = $type & self::RESULT_MASK;
 | |
|     $type = $type & self::TYPE_MASK;
 | |
|     [$typeClass, $typePrefix] = $this->getClassPrefix($type, $level
 | |
|       , static::LEVEL_CLASSES
 | |
|       , static::TYPE_CLASSES
 | |
|       , static::TYPE_PREFIXES
 | |
|     );
 | |
|     [$resultClass, $resultPrefix] = $this->getResultClassPrefix($result);
 | |
| 
 | |
|     if ($printUser || $printTech || $printException) {
 | |
|       $lines = v::sdiv([
 | |
|         "class" => ["msg", $typeClass, $resultClass],
 | |
|         $typePrefix, $resultPrefix, $groupPrefix,
 | |
|       ]);
 | |
|       if ($printUser) $lines[] = $userMsg;
 | |
|       elseif ($userMsg) $lines[] = ["\n<!--", $userMsg, "-->"];
 | |
|       if ($printTech) $lines[] = $techMsg;
 | |
|       elseif ($techMsg) $lines[] = ["\n<!--", $techMsg, "-->"];
 | |
|       if ($printException) $lines[] = $exceptionMsg;
 | |
|       elseif ($exceptionMsg) $lines[] = ["\n<!--", $exceptionMsg, "-->"];
 | |
|       $lines[] = v::ediv();
 | |
|     } else {
 | |
|       $lines = ["\n<!--", $typePrefix, $resultPrefix];
 | |
|       if ($userMsg) $lines[] = ["\n", $userMsg];
 | |
|       if ($techMsg) $lines[] = ["\n", $techMsg];
 | |
|       if ($exceptionMsg) $lines[] = ["\n", $exceptionMsg];
 | |
|       $lines[] = "-->";
 | |
|     }
 | |
|     vo::print($lines);
 | |
|   }
 | |
| }
 |