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();
 | |
|   }
 | |
| }
 |