Files
scoutiq/app/Core/Session.php

149 lines
3.4 KiB
PHP

<?php
namespace App\Core;
class Session
{
private const FLASH_KEY = 'flash_messages';
public function __construct()
{
if (session_status() === PHP_SESSION_NONE) {
// Set secure session parameters
session_start([
'cookie_httponly' => true,
'cookie_secure' => false, // Set to true if HTTPS is enforced (e.g. on production)
'cookie_samesite' => 'Lax',
]);
}
// Mark existing flash messages to be deleted next request
$this->ageFlashMessages();
}
/**
* Set a session value.
*/
public function set(string $key, mixed $value): void
{
$_SESSION[$key] = $value;
}
/**
* Get a session value.
*/
public function get(string $key, mixed $default = null): mixed
{
return $_SESSION[$key] ?? $default;
}
/**
* Remove a session value.
*/
public function remove(string $key): void
{
unset($_SESSION[$key]);
}
/**
* Check if a session key exists.
*/
public function has(string $key): bool
{
return isset($_SESSION[$key]);
}
/**
* Set a flash message (available only for the next request).
*/
public function setFlash(string $key, string $message): void
{
$_SESSION[self::FLASH_KEY][$key] = [
'value' => $message,
'remove' => false
];
}
/**
* Get a flash message.
*/
public function getFlash(string $key, ?string $default = null): ?string
{
return $_SESSION[self::FLASH_KEY][$key]['value'] ?? $default;
}
/**
* Get all flash messages.
*/
public function getFlashes(): array
{
$flashes = [];
foreach ($_SESSION[self::FLASH_KEY] ?? [] as $key => $flash) {
$flashes[$key] = $flash['value'];
}
return $flashes;
}
/**
* Age flash messages at start of request.
*/
private function ageFlashMessages(): void
{
$flashMessages = $_SESSION[self::FLASH_KEY] ?? [];
foreach ($flashMessages as $key => &$flash) {
if ($flash['remove']) {
unset($flashMessages[$key]);
} else {
$flash['remove'] = true;
}
}
$_SESSION[self::FLASH_KEY] = $flashMessages;
}
/**
* Generate or fetch CSRF token.
*/
public function getCsrfToken(): string
{
$token = $this->get('csrf_token');
if (!$token) {
$token = bin2hex(random_bytes(32));
$this->set('csrf_token', $token);
}
return $token;
}
/**
* Validate CSRF token.
*/
public function validateCsrfToken(?string $token): bool
{
if (!$token) {
return false;
}
$storedToken = $this->get('csrf_token');
return hash_equals($storedToken, $token);
}
/**
* Destroy the session.
*/
public function destroy(): void
{
$_SESSION = [];
if (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();
}
}