Moves imgration flag to DB with fallback to file
parent
a77cf5b328
commit
49e147c5b5
|
@ -4,15 +4,40 @@ namespace App\Core;
|
|||
|
||||
class Maintenance
|
||||
{
|
||||
public const FLAG_PATH = __DIR__ . '/../../storage/maintenance.flag';
|
||||
// Keep it simple: store the flag within the app directory
|
||||
public const FLAG_PATH = __DIR__ . '/../../app/.maintenance.flag';
|
||||
|
||||
public static function isEnabled(): bool
|
||||
{
|
||||
if (getenv('JILO_MAINTENANCE') === '1') {
|
||||
return true;
|
||||
}
|
||||
// Prefer DB settings if available in the current request
|
||||
if (isset($GLOBALS['db'])) {
|
||||
try {
|
||||
require_once __DIR__ . '/Settings.php';
|
||||
$settings = new Settings($GLOBALS['db']);
|
||||
return $settings->get('maintenance_enabled', '0') === '1';
|
||||
} catch (\Throwable $e) {
|
||||
// fall back to file flag
|
||||
}
|
||||
}
|
||||
return file_exists(self::FLAG_PATH);
|
||||
}
|
||||
|
||||
public static function enable(string $message = ''): bool
|
||||
{
|
||||
if (isset($GLOBALS['db'])) {
|
||||
try {
|
||||
require_once __DIR__ . '/Settings.php';
|
||||
$settings = new Settings($GLOBALS['db']);
|
||||
$ok1 = $settings->set('maintenance_enabled', '1');
|
||||
$ok2 = $settings->set('maintenance_message', $message);
|
||||
return $ok1 && $ok2;
|
||||
} catch (\Throwable $e) {
|
||||
// fall back to file flag
|
||||
}
|
||||
}
|
||||
$dir = dirname(self::FLAG_PATH);
|
||||
if (!is_dir($dir)) {
|
||||
mkdir($dir, 0755, true);
|
||||
|
@ -23,6 +48,17 @@ class Maintenance
|
|||
|
||||
public static function disable(): bool
|
||||
{
|
||||
if (isset($GLOBALS['db'])) {
|
||||
try {
|
||||
require_once __DIR__ . '/Settings.php';
|
||||
$settings = new Settings($GLOBALS['db']);
|
||||
$ok1 = $settings->set('maintenance_enabled', '0');
|
||||
// keep last message for reference, optional to clear
|
||||
return $ok1;
|
||||
} catch (\Throwable $e) {
|
||||
// fall back to file flag
|
||||
}
|
||||
}
|
||||
if (file_exists(self::FLAG_PATH)) {
|
||||
return unlink(self::FLAG_PATH);
|
||||
}
|
||||
|
@ -34,6 +70,19 @@ class Maintenance
|
|||
if (!self::isEnabled()) {
|
||||
return '';
|
||||
}
|
||||
$envMsg = getenv('JILO_MAINTENANCE_MESSAGE');
|
||||
if ($envMsg) {
|
||||
return trim($envMsg);
|
||||
}
|
||||
if (isset($GLOBALS['db'])) {
|
||||
try {
|
||||
require_once __DIR__ . '/Settings.php';
|
||||
$settings = new Settings($GLOBALS['db']);
|
||||
return (string)$settings->get('maintenance_message', '');
|
||||
} catch (\Throwable $e) {
|
||||
// ignore and fall back to file flag
|
||||
}
|
||||
}
|
||||
$msg = @file_get_contents(self::FLAG_PATH);
|
||||
return is_string($msg) ? trim($msg) : '';
|
||||
}
|
||||
|
|
|
@ -0,0 +1,54 @@
|
|||
<?php
|
||||
|
||||
namespace App\Core;
|
||||
|
||||
use PDO;
|
||||
use Exception;
|
||||
|
||||
class Settings
|
||||
{
|
||||
private PDO $pdo;
|
||||
|
||||
public function __construct($db)
|
||||
{
|
||||
if ($db instanceof PDO) {
|
||||
$this->pdo = $db;
|
||||
} elseif (is_object($db) && method_exists($db, 'getConnection')) {
|
||||
$pdo = $db->getConnection();
|
||||
if (!$pdo instanceof PDO) {
|
||||
throw new Exception('Settings: database wrapper did not return PDO');
|
||||
}
|
||||
$this->pdo = $pdo;
|
||||
} else {
|
||||
$type = is_object($db) ? get_class($db) : gettype($db);
|
||||
throw new Exception("Settings: unsupported database type: {$type}");
|
||||
}
|
||||
$this->ensureTable();
|
||||
}
|
||||
|
||||
private function ensureTable(): void
|
||||
{
|
||||
$driver = $this->pdo->getAttribute(PDO::ATTR_DRIVER_NAME);
|
||||
if ($driver === 'sqlite') {
|
||||
$sql = "CREATE TABLE IF NOT EXISTS settings (\n `key` TEXT PRIMARY KEY,\n `value` TEXT,\n `updated_at` TEXT NOT NULL\n )";
|
||||
} else {
|
||||
$sql = "CREATE TABLE IF NOT EXISTS settings (\n `key` VARCHAR(191) NOT NULL PRIMARY KEY,\n `value` TEXT NULL,\n `updated_at` DATETIME NOT NULL\n ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4";
|
||||
}
|
||||
$this->pdo->exec($sql);
|
||||
}
|
||||
|
||||
public function get(string $key, $default = null)
|
||||
{
|
||||
$stmt = $this->pdo->prepare('SELECT `value` FROM settings WHERE `key` = :k');
|
||||
$stmt->execute([':k' => $key]);
|
||||
$val = $stmt->fetchColumn();
|
||||
if ($val === false) return $default;
|
||||
return $val;
|
||||
}
|
||||
|
||||
public function set(string $key, $value): bool
|
||||
{
|
||||
$stmt = $this->pdo->prepare('REPLACE INTO settings (`key`, `value`, `updated_at`) VALUES (:k, :v, NOW())');
|
||||
return (bool)$stmt->execute([':k' => $key, ':v' => $value]);
|
||||
}
|
||||
}
|
|
@ -12,7 +12,12 @@
|
|||
</div>
|
||||
<div class="card-body">
|
||||
<p class="lead">The site is temporarily unavailable due to maintenance.</p>
|
||||
<?php $mm = \App\Core\Maintenance::getMessage(); ?>
|
||||
<?php if ($mm): ?>
|
||||
<p class="mb-0"><em><?= htmlspecialchars($mm) ?></em></p>
|
||||
<?php else: ?>
|
||||
<p class="text-muted">Please try again later.</p>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -49,6 +49,13 @@ php scripts/maintenance.php off
|
|||
php scripts/maintenance.php status
|
||||
```
|
||||
|
||||
Notes:
|
||||
|
||||
- The maintenance flag is stored at `app/.maintenance.flag`.
|
||||
- You can also control maintenance via environment variables (useful when the filesystem is read-only):
|
||||
- `JILO_MAINTENANCE=1` enables maintenance mode
|
||||
- `JILO_MAINTENANCE_MESSAGE="Your message"` sets the banner message
|
||||
|
||||
## Authoring new migrations
|
||||
|
||||
1. Create a new SQL file in `doc/database/migrations/`, e.g.:
|
||||
|
|
Loading…
Reference in New Issue