dataDir = $dataDir; $this->baseDir = $baseDir; } /** Retourne la liste des alertes à afficher aux administrateurs. */ public function adminNotices(): array { $notices = []; if ($this->hasPendingContentMigrations()) { $notices[] = [ 'type' => 'warning', 'message' => 'Des migrations de contenu sont en attente.', ]; } $update = $this->checkRemoteVersion(); if ($update !== null) { $notices[] = [ 'type' => 'info', 'message' => 'Une nouvelle version de Folio est disponible : v' . htmlspecialchars($update) . '.', ]; } return $notices; } // ─── Migrations de contenu en attente ──────────────────────────────────── private function hasPendingContentMigrations(): bool { $trackFile = $this->dataDir . '/.content_migrations.json'; $applied = []; if (file_exists($trackFile)) { $applied = json_decode((string) file_get_contents($trackFile), true) ?? []; } foreach (glob($this->baseDir . '/scripts/content/migration_*.php') ?: [] as $f) { if (!isset($applied[basename($f)])) { return true; } } return false; } // ─── Vérification version distante (Gitea) ─────────────────────────────── /** * Retourne le numéro de la version disponible si elle est supérieure * à la version déployée, null sinon. */ private function checkRemoteVersion(): ?string { $repoUrl = folioRepoUrl(); if ($repoUrl === '') { return null; } $deployedFile = $this->baseDir . '/public/version.txt'; if (!file_exists($deployedFile)) { return null; } $deployedVer = trim((string) file_get_contents($deployedFile)); if ($deployedVer === '' || !preg_match('/^\d+\.\d+\.\d+/', $deployedVer)) { return null; } $remoteVer = $this->fetchRemoteVersion($repoUrl); if ($remoteVer === null) { return null; } return version_compare($remoteVer, $deployedVer, '>') ? $remoteVer : null; } public function getBranch(): string { return folioUpdateBranch(); } public function getLastChecked(): ?int { $cacheFile = $this->dataDir . '/.version_check_cache.json'; if (!file_exists($cacheFile)) { return null; } $cache = json_decode((string) file_get_contents($cacheFile), true) ?? []; return isset($cache['fetched_at']) ? (int) $cache['fetched_at'] : null; } public function clearCache(): void { $cacheFile = $this->dataDir . '/.version_check_cache.json'; if (file_exists($cacheFile)) { unlink($cacheFile); } } public function getLastUpgradeLog(): ?string { $logFile = $this->dataDir . '/.upgrade-log'; if (!file_exists($logFile)) { return null; } return (string) file_get_contents($logFile); } /** * Récupère `public/version.txt` depuis le dépôt Gitea. * Résultat mis en cache 1 h dans `data/.version_check_cache.json`. */ private function fetchRemoteVersion(string $repoUrl): ?string { $cacheFile = $this->dataDir . '/.version_check_cache.json'; $ttl = 3600; if (file_exists($cacheFile)) { $cache = json_decode((string) file_get_contents($cacheFile), true) ?? []; if (isset($cache['fetched_at'], $cache['version']) && (time() - (int) $cache['fetched_at']) < $ttl ) { return (string) $cache['version']; } } $branch = $this->getBranch(); // URL du fichier brut : {repo}/raw/branch/{branch}/public/version.txt $rawUrl = $repoUrl . '/raw/branch/' . $branch . '/public/version.txt'; $token = (string) ($_ENV['GITEA_TOKEN'] ?? getenv('GITEA_TOKEN') ?: ''); $opts = [ 'http' => [ 'timeout' => 5, 'header' => $token !== '' ? "Authorization: token $token" : '', ], ]; $body = @file_get_contents($rawUrl, false, stream_context_create($opts)); if ($body === false) { return null; } $version = trim($body); if (!preg_match('/^\d+\.\d+\.\d+/', $version)) { return null; } file_put_contents( $cacheFile, json_encode(['fetched_at' => time(), 'version' => $version]) . "\n" ); return $version; } }