257 lines
		
	
	
		
			7.8 KiB
		
	
	
	
		
			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();
 | 
						|
  }
 | 
						|
}
 |