125 lines
4.5 KiB
PHP
125 lines
4.5 KiB
PHP
<?php
|
|
|
|
namespace classes;
|
|
|
|
/**
|
|
* Ensures additive system session activity storage exists.
|
|
*
|
|
* This project uses lazy runtime schema bootstraps instead of a central
|
|
* migration runner, so every change must be idempotent.
|
|
*/
|
|
class system_session_activity_schema_bootstrap
|
|
{
|
|
private static bool $initialized = false;
|
|
|
|
public static function ensureTables(): void
|
|
{
|
|
if (self::$initialized) {
|
|
return;
|
|
}
|
|
|
|
global $db;
|
|
|
|
$queries = [
|
|
"CREATE TABLE IF NOT EXISTS system_session_activity (
|
|
id INT AUTO_INCREMENT PRIMARY KEY,
|
|
session_hash CHAR(64) NOT NULL,
|
|
session_kind VARCHAR(16) NOT NULL,
|
|
principal_id INT NOT NULL,
|
|
customer_number_context INT NULL,
|
|
device_type VARCHAR(16) NOT NULL DEFAULT 'unknown',
|
|
user_agent VARCHAR(1024) NULL,
|
|
last_route VARCHAR(255) NULL,
|
|
first_seen_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
last_seen_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
updated_at TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
|
UNIQUE KEY uniq_system_session_activity_session_hash (session_hash),
|
|
INDEX idx_system_session_activity_last_seen_at (last_seen_at),
|
|
INDEX idx_system_session_activity_principal (session_kind, principal_id),
|
|
INDEX idx_system_session_activity_customer_context (customer_number_context)
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci",
|
|
];
|
|
|
|
foreach ($queries as $sql) {
|
|
$db->query($sql);
|
|
}
|
|
|
|
self::ensureColumn(
|
|
'system_session_activity',
|
|
'customer_number_context',
|
|
'ALTER TABLE system_session_activity ADD COLUMN customer_number_context INT NULL AFTER principal_id'
|
|
);
|
|
self::ensureColumn(
|
|
'system_session_activity',
|
|
'device_type',
|
|
"ALTER TABLE system_session_activity ADD COLUMN device_type VARCHAR(16) NOT NULL DEFAULT 'unknown' AFTER customer_number_context"
|
|
);
|
|
self::ensureColumn(
|
|
'system_session_activity',
|
|
'user_agent',
|
|
'ALTER TABLE system_session_activity ADD COLUMN user_agent VARCHAR(1024) NULL AFTER device_type'
|
|
);
|
|
self::ensureColumn(
|
|
'system_session_activity',
|
|
'last_route',
|
|
'ALTER TABLE system_session_activity ADD COLUMN last_route VARCHAR(255) NULL AFTER user_agent'
|
|
);
|
|
self::ensureColumn(
|
|
'system_session_activity',
|
|
'first_seen_at',
|
|
'ALTER TABLE system_session_activity ADD COLUMN first_seen_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP AFTER last_route'
|
|
);
|
|
self::ensureColumn(
|
|
'system_session_activity',
|
|
'last_seen_at',
|
|
'ALTER TABLE system_session_activity ADD COLUMN last_seen_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP AFTER first_seen_at'
|
|
);
|
|
self::ensureColumn(
|
|
'system_session_activity',
|
|
'created_at',
|
|
'ALTER TABLE system_session_activity ADD COLUMN created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP AFTER last_seen_at'
|
|
);
|
|
self::ensureColumn(
|
|
'system_session_activity',
|
|
'updated_at',
|
|
'ALTER TABLE system_session_activity ADD COLUMN updated_at TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP AFTER created_at'
|
|
);
|
|
|
|
self::$initialized = true;
|
|
}
|
|
|
|
public static function tableHasColumn(string $table, string $column): bool
|
|
{
|
|
global $db;
|
|
|
|
$table = $db->escape_string($table);
|
|
$column = $db->escape_string($column);
|
|
$database = $db->escape_string($db->getDatabase());
|
|
|
|
$sql = "SELECT COUNT(*) AS c
|
|
FROM information_schema.COLUMNS
|
|
WHERE TABLE_SCHEMA = '$database'
|
|
AND TABLE_NAME = '$table'
|
|
AND COLUMN_NAME = '$column'";
|
|
$result = $db->query($sql);
|
|
if (!$result) {
|
|
return false;
|
|
}
|
|
|
|
$row = $result->fetch_assoc();
|
|
return ((int)($row['c'] ?? 0)) > 0;
|
|
}
|
|
|
|
public static function ensureColumn(string $table, string $column, string $alterSql): void
|
|
{
|
|
global $db;
|
|
|
|
if (self::tableHasColumn($table, $column)) {
|
|
return;
|
|
}
|
|
|
|
$db->query($alterSql);
|
|
}
|
|
}
|