nur-sery/nur_src/session.php

257 lines
7.8 KiB
PHP

<?php
namespace nur;
/**
* Class session: gestion des sessions
*/
class session {
/** durée de session par défaut: 24 minutes */
const DURATION = 1440;
/** @var int */
protected static $duration;
/** obtenir la durée d'une session en secondes. */
static final function get_duration(): int {
$duration = self::$duration;
if ($duration === null) $duration = static::DURATION;
return $duration;
}
/**
* spécifier la durée d'une session en secondes.
* cette méthode doit être appelée avant start()
*/
static final function set_duration(int $duration): void {
self::$duration = $duration;
}
/** vérifier si la session a été démarrée. */
static final function started(): bool {
return session_status() == PHP_SESSION_ACTIVE;
}
private static $started_once = false;
/** vérifier si la session a été démarrée au moins une fois */
static final function started_once(): bool {
return self::$started_once;
}
/** nom de la variable de session qui indique quand elle a été créée. */
const SESSION_CREATION_TIME = "nur\\session_creation_time";
/**
* démarrer la session si nécessaire. étendre la durée du cookie de session
* de la valeur get_duration()
*
* la page est automatiquement configurée par PHP pour ne pas être mise en
* cache, il est donc inutile d'utiliser {@link http::no_cache()}
*
* retourner true si la session vient d'être créée, false si elle a été
* chargée depuis le disque
*/
static final function start(): bool {
if (!self::started()) {
$duration = self::get_duration();
$can_set_cookies = !headers_sent();
if ($can_set_cookies) {
# durée initiale du cookie
session_set_cookie_params($duration);
}
session_start([
"gc_maxlifetime" => $duration,
]);
self::$started_once = true;
$creation_time = self::get(self::SESSION_CREATION_TIME, false);
if (!$creation_time) {
# création initiale
self::set(self::SESSION_CREATION_TIME, time());
return true;
} elseif ($can_set_cookies) {
# étendre la durée du cookie
$params = session_get_cookie_params();
setcookie(session_name(), session_id(), time() + $duration, $params["path"], $params["domain"], $params["secure"], $params["httponly"]);
}
}
return false;
}
/**
* enregistrer la session, la fermer et libérer son verrou.
*
* cette fonction peut être appelée avant une opération longue si on n'a plus
* besoin de la session.
*
* retourn true si la session a été fermée, false sinon.
*/
static final function close(): bool {
if (self::started()) {
session_write_close();
return true;
}
return false;
}
/**
* vider la session de toutes ses variables ($unset_only==true) ou la détruire
* ($unset_only==false). en cas de destruction de la session, supprimer aussi
* le cookie de session
*
* si $unset_only==true, refaire la variable SESSION_CREATION_TIME
*/
static final function destroy(bool $unset_only=false, bool $clear_cookie=true): void {
self::start();
if ($unset_only) {
session_unset();
self::set(self::SESSION_CREATION_TIME, time());
} else {
$can_set_cookies = !headers_sent();
if ($clear_cookie && $can_set_cookies && ini_get("session.use_cookies")) {
$params = session_get_cookie_params();
setcookie(session_name(), '', time() - 42000, $params["path"], $params["domain"], $params["secure"], $params["httponly"]);
}
session_destroy();
}
}
/**
* Vider la session de toutes les clés spécifiées dans $keys qui ne sont pas
* mentionnées dans $keeps
*
* Si $keys vaut null, toutes les clés sont supprimées comme avec destroy(true)
* notamment, cela signifie que la variable SESSION_CREATION_TIME est refaite
*/
static final function unset_keys(?array $keys, ?array $keeps=null): void {
$update_session_creation_time = false;
if ($keys === null) {
$keys = array_keys($_SESSION);
$update_session_creation_time = true;
}
if ($keeps !== null) $keys = array_diff($keys, $keeps);
foreach ($keys as $key) {
unset($_SESSION[$key]);
}
if ($update_session_creation_time) {
self::set(self::SESSION_CREATION_TIME, time());
}
}
/** Vider la session de toutes les clés spécifiées. */
static final function unset_key(...$keys): void {
self::unset_keys($keys);
}
/**
* Dans la session, ne garder que les clés spécifiées.
*
* Refaire la variable SESSION_CREATION_TIME
*/
static final function keep_key(...$keeps): void {
self::unset_keys(null, $keeps);
}
/** vérifier si la session est démarrée et si la clé spécifiée existe. */
static final function has($key): bool {
if ($key === null || $key === false) return false;
return isset($_SESSION) && array_key_exists($key, $_SESSION);
}
/** obtenir la valeur associée à la clé spécifiée si la session est démarrée. */
static final function get(string $key, $default=null) {
if (!isset($_SESSION)) return $default;
return A::get($_SESSION, $key, $default);
}
/**
* mettre à jour la valeur d'une variable de session.
*
* ne pas chercher à savoir si la session est démarrée ou non
*/
static final function set(string $key, $value): void {
$_SESSION[$key] = $value;
}
/**
* comme {@link set()} mais rouvrir automatiquement la session si nécessaire,
* à condition qu'elle aie déjà été ouverte une fois
*/
static final function setx(string $key, $value): void {
$close = !self::started() && self::started_once();
if ($close) self::start();
self::set($key, $value);
if ($close) self::close();
}
/**
* supprimer une variable de session.
*
* ne pas chercher à savoir si la session est démarrée ou non
*/
static final function del(string $key): void {
unset($_SESSION[$key]);
}
/**
* comme {@link del()} mais rouvrir automatiquement la session si nécessaire,
* à condition qu'elle aie déjà été ouverte une fois
*/
static final function delx(string $key): void {
$close = !self::started() && self::started_once();
if ($close) self::start();
self::del($key);
if ($close) self::close();
}
/** vérifier si chemin de clé spécifié existe dans la session. */
static final function phas($pkey): bool {
return isset($_SESSION) && A::phas($_SESSION, $pkey);
}
/** obtenir la valeur associée au chemin de clé spécifié si la session est démarrée. */
static final function pget($pkey, $default=null) {
return isset($_SESSION) && A::pget($_SESSION, $pkey, $default);
}
/**
* mettre à jour la valeur correspondant au chemin de clé spécifié.
*
* ne pas chercher à savoir si la session est démarrée ou non
*/
static final function pset($pkey, $value): void {
A::pset($_SESSION, $pkey, $value);
}
/**
* comme {@link pset()} mais rouvrir automatiquement la session si nécessaire,
* à condition qu'elle aie déjà été ouverte une fois
*/
static final function psetx(string $key, $value): void {
$close = !self::started() && self::started_once();
if ($close) self::start();
self::pset($key, $value);
if ($close) self::close();
}
/**
* supprimer la variable au chemin de clé spécifié.
*
* ne pas chercher à savoir si la session est démarrée ou non
*/
static final function pdel($pkey): void {
A::pdel($_SESSION, $pkey);
}
/**
* comme {@link pdel()} mais rouvrir automatiquement la session si nécessaire,
* à condition qu'elle aie déjà été ouverte une fois
*/
static final function pdelx(string $key): void {
$close = !self::started() && self::started_once();
if ($close) self::start();
self::pdel($key);
if ($close) self::close();
}
}