includes/modules/update.php
<?php
declare(strict_types=1);
/*
|--------------------------------------------------------------------------
| Update manifest
|--------------------------------------------------------------------------
|
| Checks whether a newer Brivacia release is available by fetching a small
| JSON manifest from the project's own site. Only handles the "is an update
| available, and what does it look like" question — actually downloading,
| verifying and installing an update is handled by api/update.php.
|
*/
const BRIVACIA_UPDATE_JSON = 'https://breat.fr/static/json/brivacia-version.json';
function brivaciaUpdateManifest(): array {
static $memo = null;
if ($memo !== null) return $memo;
$cacheFile = updateDir() . '/update-check.json';
$cached = is_file($cacheFile) ? json_decode((string)file_get_contents($cacheFile), true) : null;
if (is_array($cached) && ($cached['checked_at'] ?? 0) > time() - 3600) {
return $memo = $cached['manifest'] ?? [];
}
$json = @file_get_contents(
BRIVACIA_UPDATE_JSON . '?t=' . time(),
false,
stream_context_create([
'http' => [
'timeout' => 3,
'ignore_errors' => true,
'header' => "Cache-Control: no-cache\r\nPragma: no-cache\r\n",
],
])
);
$manifest = is_string($json) && $json !== '' ? (json_decode($json, true) ?: []) : ($cached['manifest'] ?? []);
file_put_contents($cacheFile, json_encode(['checked_at' => time(), 'manifest' => $manifest]), LOCK_EX);
return $memo = $manifest;
}
function brivaciaCurrentVersion(): string {
return function_exists('brivacia_version') ? brivacia_version() : '0.0.0';
}
// Lets an admin force the "update available" UI/flow to appear locally
// (for testing the update process itself) by dropping a file named
// update/test-update — no manifest fetch needed to exercise that path.
function brivaciaTestUpdate(): bool
{
return is_file(brivacia_root_path('update/test-update'));
}
function brivaciaUpdateAvailable(): bool {
if (brivaciaTestUpdate()) {
return true;
}
$manifest = brivaciaUpdateManifest();
if (empty($manifest['version'])) {
return false;
}
return version_compare((string)$manifest['version'], brivaciaCurrentVersion(), '>');
}
function brivaciaUpdateInfo(): array {
$manifest = brivaciaUpdateManifest();
return [
'available' => brivaciaTestUpdate() || (!empty($manifest['version']) && version_compare((string)$manifest['version'], brivaciaCurrentVersion(), '>')),
'current' => brivaciaCurrentVersion(),
'latest' => (string)($manifest['version'] ?? ''),
'download' => (string)($manifest['download'] ?? ''),
'changelog' => (string)($manifest['changelog'] ?? ''),
'minimum_php' => (string)($manifest['minimum_php'] ?? ''),
// Expected SHA-256 of the downloadable zip, lowercase hex, published
// alongside the version/download fields in the same JSON manifest.
// Checked against the actual downloaded bytes in api/update.php
// before anything gets extracted or installed.
'sha256' => strtolower(trim((string)($manifest['sha256'] ?? ''))),
];
}
function brivaciaLatestVersion(): string
{
return brivaciaUpdateInfo()['latest'] ?? brivacia_version();
}