305 lines
9.9 KiB
PHP
305 lines
9.9 KiB
PHP
<?php
|
|
namespace nur\v\base;
|
|
|
|
use Countable;
|
|
use nur\A;
|
|
use nur\b\ExceptionShadow;
|
|
use nur\b\params\Parametrable;
|
|
use nur\b\params\Tparametrable;
|
|
use nur\b\ui\IMessenger;
|
|
use nur\b\ValueException;
|
|
use nur\msg;
|
|
use nur\session;
|
|
use nur\v\page;
|
|
use Throwable;
|
|
|
|
class Alerter extends Parametrable implements Countable {
|
|
use Tparametrable;
|
|
|
|
const SESSION_KEY = "__alerter";
|
|
|
|
private static function get_session_key(?string $session_key): string {
|
|
if ($session_key !== null) return self::SESSION_KEY.":$session_key";
|
|
else return self::SESSION_KEY;
|
|
}
|
|
|
|
# Types de messages
|
|
const TYPE_ERROR = 6, TYPE_WARNING = 5, TYPE_FAILURE = 4, TYPE_SUCCESS = 3, TYPE_NOTE = 2, TYPE_INFO = 1, TYPE_DEBUG = 0;
|
|
|
|
const KEY_SESSION_KEY = "session_key";
|
|
const KEY_REDIRECT = "redirect";
|
|
const KEY_DISMISSIBLE = "dismissible";
|
|
const KEY_AUTO_SESSION = "auto_session";
|
|
|
|
const PARAMETRABLE_PARAMS_SCHEMA = [
|
|
"session_key" => ["?string", "", "clé de session pour enregistrer les messages"],
|
|
"redirect" => ["?string", null, "url vers laquelle rediriger s'il faut afficher les messages en différé"],
|
|
"dismissible" => ["bool", false, "les messages doivent-ils pouvoir être fermés par l'utilisateur?"],
|
|
"auto_session" => ["bool", false, "faut-il enregistrer et/ou restaurer automatiquement la session?"],
|
|
];
|
|
|
|
function __construct(?array $params=null) {
|
|
parent::__construct($params);
|
|
$this->reset(false);
|
|
if ($this->ppAutoSession) $this->restoreSession();
|
|
}
|
|
|
|
/** @var string */
|
|
protected $sessionKey;
|
|
|
|
function pp_setSessionKey(?string $sessionKey): void {
|
|
$this->sessionKey = self::get_session_key($sessionKey);
|
|
}
|
|
|
|
/** @var ?string url vers laquelle rediriger */
|
|
protected $ppRedirect;
|
|
|
|
/** @var bool */
|
|
protected $ppDismissible;
|
|
|
|
/** @var bool */
|
|
protected $ppAutoSession;
|
|
|
|
/**
|
|
* modifier uniquement les paramètres spécifiés
|
|
*
|
|
* - $redirect n'est modifié que s'il est différente de false
|
|
* - $dismissible n'est modifié que s'il est non null
|
|
*/
|
|
function setRedirect($redirect=false, ?bool $dismissible=null): Alerter {
|
|
if ($redirect !== false) $this->ppRedirect = $redirect;
|
|
if ($dismissible !== null) $this->ppDismissible = $dismissible;
|
|
return $this;
|
|
}
|
|
|
|
/** @var array */
|
|
private $messages;
|
|
|
|
/**
|
|
* @var int type d'alerte à afficher. il s'agit de l'alerte la plus grave qui
|
|
* a été ajoutée jusqu'ici
|
|
*/
|
|
private $type;
|
|
|
|
/** @var int type de section pour les messages à afficher */
|
|
private $msgType, $msgLevel;
|
|
|
|
/**
|
|
* @var bool une erreur a-t-elle été ajoutée? c'est le cas à partir du type
|
|
* {@link TYPE_FAILURE}
|
|
*/
|
|
private $error;
|
|
|
|
/** @var bool valeur par défaut de 'dismissible' */
|
|
private $dismissible;
|
|
|
|
/** enregistrer les messages en attente dans la session */
|
|
function saveSession(): void {
|
|
session::set($this->sessionKey, [
|
|
"messages" => $this->messages,
|
|
"atype" => $this->type,
|
|
"mtype" => $this->msgType,
|
|
"mlevel" => $this->msgLevel,
|
|
"error" => $this->error,
|
|
self::KEY_DISMISSIBLE => $this->dismissible,
|
|
]);
|
|
}
|
|
|
|
/** restaurer les messages en attente depuis la session. */
|
|
function restoreSession(?string $sessionKey=null, bool $clear=true): void {
|
|
if ($sessionKey === null) $sessionKey = $this->sessionKey;
|
|
else $sessionKey = self::get_session_key($sessionKey);
|
|
if (session::has($sessionKey)) {
|
|
[
|
|
"messages" => $this->messages,
|
|
"atype" => $this->type,
|
|
"mtype" => $this->msgType,
|
|
"mlevel" => $this->msgLevel,
|
|
"error" => $this->error,
|
|
self::KEY_DISMISSIBLE => $this->dismissible,
|
|
] = session::get($sessionKey);
|
|
if ($clear) session::del($sessionKey);
|
|
}
|
|
}
|
|
|
|
function reset(?bool $autoSession=null): void {
|
|
$this->messages = [];
|
|
$this->type = -1;
|
|
$this->msgType = -1;
|
|
$this->msgLevel = -1;
|
|
$this->error = false;
|
|
$this->dismissible = $this->ppDismissible;
|
|
if ($autoSession === null) $autoSession = $this->ppAutoSession;
|
|
if ($autoSession) $this->saveSession();
|
|
}
|
|
|
|
const MESSAGE_KEYS = [
|
|
IMessenger::KEY_USER,
|
|
IMessenger::KEY_TECH,
|
|
IMessenger::KEY_EXCEPTION,
|
|
];
|
|
|
|
/**
|
|
* ajouter un message de type $type. les messages ne sont pas affichés de
|
|
* suite: il faut appeler {@link print()} pour cela
|
|
*
|
|
* @param array|string|Throwable $message le message à afficher, conforme à
|
|
* {@link IMessenger::MESSAGE_SCHEMA}
|
|
* @param int $type le type de message
|
|
* @return bool true si l'objet n'est pas dans un état d'erreur
|
|
*/
|
|
function add($message, int $type, ?bool $dismissible=null): bool {
|
|
if ($message === null) return true;
|
|
|
|
msg::get()->ensureMessage($message);
|
|
foreach (self::MESSAGE_KEYS as $key) {
|
|
# remplacer les exceptions par des instances de ExceptionShadow, afin
|
|
# qu'elles puissent être sérialisées
|
|
if ($message[$key] instanceof Throwable) {
|
|
$message[$key] = new ExceptionShadow($message[$key]);
|
|
}
|
|
}
|
|
|
|
if ($dismissible === null) $dismissible = A::get($message, self::KEY_DISMISSIBLE);
|
|
if ($dismissible !== null) $this->dismissible = $dismissible;
|
|
$message[self::KEY_DISMISSIBLE] = $dismissible;
|
|
|
|
switch ($type) {
|
|
case self::TYPE_DEBUG:
|
|
$msgType = msg::DEBUG;
|
|
$msgLevel = msg::NORMAL;
|
|
if ($type > $this->type) {
|
|
$this->type = $type;
|
|
[$this->msgType, $this->msgLevel] = [msg::DEBUG, msg::NORMAL];
|
|
}
|
|
break;
|
|
case self::TYPE_INFO:
|
|
$msgType = msg::INFO;
|
|
$msgLevel = msg::NORMAL;
|
|
if ($type > $this->type) {
|
|
$this->type = $type;
|
|
[$this->msgType, $this->msgLevel] = [msg::INFO, msg::NORMAL];
|
|
}
|
|
break;
|
|
case self::TYPE_NOTE:
|
|
$msgType = msg::INFO;
|
|
$msgLevel = msg::MAJOR;
|
|
if ($type > $this->type) {
|
|
$this->type = $type;
|
|
[$this->msgType, $this->msgLevel] = [msg::INFO, msg::NORMAL];
|
|
}
|
|
break;
|
|
case self::TYPE_SUCCESS:
|
|
$msgType = msg::INFO + msg::SUCCESS;
|
|
$msgLevel = msg::MAJOR;
|
|
if ($type > $this->type) {
|
|
$this->type = $type;
|
|
[$this->msgType, $this->msgLevel] = [msg::INFO, msg::NORMAL];
|
|
}
|
|
break;
|
|
case self::TYPE_FAILURE:
|
|
$msgType = msg::INFO + msg::FAILURE;
|
|
$msgLevel = msg::MAJOR;
|
|
if ($type > $this->type) {
|
|
$this->type = $type;
|
|
[$this->msgType, $this->msgLevel] = [msg::INFO, msg::NORMAL];
|
|
$this->error = true;
|
|
}
|
|
break;
|
|
case self::TYPE_WARNING:
|
|
$msgType = msg::WARNING;
|
|
$msgLevel = msg::MAJOR;
|
|
if ($type > $this->type) {
|
|
$this->type = $type;
|
|
[$this->msgType, $this->msgLevel] = [msg::WARNING, msg::NORMAL];
|
|
$this->error = true;
|
|
}
|
|
break;
|
|
case self::TYPE_ERROR:
|
|
$msgType = msg::ERROR;
|
|
$msgLevel = msg::MAJOR;
|
|
if ($type > $this->type) {
|
|
$this->type = $type;
|
|
[$this->msgType, $this->msgLevel] = [msg::ERROR, msg::NORMAL];
|
|
$this->error = true;
|
|
}
|
|
break;
|
|
default:
|
|
throw ValueException::invalid_value($type, "type");
|
|
}
|
|
|
|
$this->messages[] = [$message, $msgType, $msgLevel];
|
|
if ($this->ppAutoSession) $this->saveSession();
|
|
return !$this->error;
|
|
}
|
|
|
|
/** retourner le nombre de messages ajoutés */
|
|
function count(): int {
|
|
return count($this->messages);
|
|
}
|
|
|
|
/** tester si cet objet est dans un état d'erreur suite à un message ajouté */
|
|
function isError(): bool {
|
|
return $this->error;
|
|
}
|
|
|
|
protected function printNoReset(): bool {
|
|
if (!$this->messages) return false;
|
|
$dismissible = $this->dismissible;
|
|
$msgType = $this->msgType;
|
|
if ($msgType >= msg::ERROR) $title = "Erreur";
|
|
elseif ($msgType >= msg::WARNING) $title = "Avertissement";
|
|
elseif ($msgType >= msg::INFO) $title = "Information";
|
|
else $title = null;
|
|
$msg = msg::get();
|
|
$msg->startSection($title, $this->msgType, $this->msgLevel);
|
|
foreach ($this->messages as [$message, $type, $level]) {
|
|
A::replace_z($message, self::KEY_DISMISSIBLE, $dismissible);
|
|
$msg->addMessage($message, $type, $level);
|
|
}
|
|
$msg->endSection();
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* afficher les messages qui sont en attente puis retourner $result qui vaut
|
|
* par défaut !isError()
|
|
*/
|
|
function print($result=null) {
|
|
if ($result === null) $result = !$this->error;
|
|
if ($this->printNoReset()) $this->reset();
|
|
return $result;
|
|
}
|
|
|
|
/**
|
|
* rediriger vers l'url spécifiée qui affichera les messages mis en attente
|
|
* après les avoir chargés depuis la session
|
|
*
|
|
* si $redirect===false, utiliser la valeur par défaut spécifiée dans les
|
|
* paramètres
|
|
*/
|
|
function redirect($redirect=false): void {
|
|
if ($redirect === false) $redirect = $this->ppRedirect;
|
|
page::redirect($redirect);
|
|
}
|
|
|
|
#############################################################################
|
|
# Méthodes de convenance
|
|
|
|
function error($message): Alerter { $this->add($message, self::TYPE_ERROR); return $this; }
|
|
function warning($message): Alerter { $this->add($message, self::TYPE_WARNING); return $this; }
|
|
function note($message): Alerter { $this->add($message, self::TYPE_NOTE); return $this; }
|
|
function success($message): Alerter { $this->add($message, self::TYPE_SUCCESS); return $this; }
|
|
function failure($message): Alerter { $this->add($message, self::TYPE_FAILURE); return $this; }
|
|
function info($message): Alerter { $this->add($message, self::TYPE_INFO); return $this; }
|
|
function debug($message): Alerter { $this->add($message, self::TYPE_DEBUG); return $this; }
|
|
|
|
function perror($message): void { $this->error($message); $this->print(); }
|
|
function pwarning($message): void { $this->warning($message); $this->print(); }
|
|
function pnote($message): void { $this->note($message); $this->print(); }
|
|
function psuccess($message): void { $this->success($message); $this->print(); }
|
|
function pfailure($message): void { $this->failure($message); $this->print(); }
|
|
function pinfo($message): void { $this->info($message); $this->print(); }
|
|
function pdebug($message): void { $this->debug($message); $this->print(); }
|
|
}
|