movmaker-webui/sitemap.php
2026-06-20 17:05:04 +02:00

97 lines
3.5 KiB
PHP

<?php
// Dynamic XML sitemap for public MVLog pages and enabled article permalinks.
declare(strict_types=1);
date_default_timezone_set('Europe/Copenhagen');
$root = __DIR__;
$config = is_file($root . '/config.php') ? require $root . '/config.php' : [];
$uploadsDir = (string)($config['uploads_dir'] ?? ($root . '/in-dir'));
$videosDir = (string)($config['videos_dir'] ?? ($root . '/out-dir'));
function sitemap_xml_escape(string $value): string {
return htmlspecialchars($value, ENT_XML1 | ENT_COMPAT, 'UTF-8');
}
function sitemap_lastmod_from_ts(int|float $ts): string {
return gmdate('Y-m-d', (int)$ts);
}
function sitemap_article_id_is_valid(string $id): bool {
return (bool)preg_match('/^[0-9]{14}[a-f0-9]{16}$/', $id);
}
function sitemap_add_url(array &$urls, string $loc, string $lastmod, string $changefreq, string $priority): void {
$urls[$loc] = [
'loc' => $loc,
'lastmod' => $lastmod,
'changefreq' => $changefreq,
'priority' => $priority,
];
}
$urls = [];
$staticPages = [
['https://bubulescu.org/', $root . '/index.php', 'daily', '1.0'],
['https://bubulescu.org/contact.php', $root . '/contact.php', 'monthly', '0.5'],
['https://bubulescu.org/feed.php', $root . '/feed.php', 'monthly', '0.3'],
];
foreach ($staticPages as [$loc, $path, $changefreq, $priority]) {
if (is_file($path)) {
sitemap_add_url($urls, $loc, sitemap_lastmod_from_ts((int)filemtime($path)), $changefreq, $priority);
}
}
foreach (glob(rtrim($uploadsDir, '/') . '/*', GLOB_ONLYDIR) ?: [] as $dir) {
if (!is_file($dir . '/.mvlog-permalink')) continue;
$idFile = $dir . '/.mvlog-id';
$articleId = is_file($idFile) ? strtolower(trim((string)@file_get_contents($idFile))) : '';
if (!sitemap_article_id_is_valid($articleId)) continue;
$state = [];
$stateFile = $dir . '/.movmaker-state.json';
if (is_file($stateFile)) {
$decoded = json_decode((string)@file_get_contents($stateFile), true);
if (is_array($decoded)) $state = $decoded;
}
$lastmodCandidates = [];
foreach ([$dir . '/data.txt', $stateFile, $idFile, $dir . '/.mvlog-permalink'] as $candidate) {
if (is_file($candidate)) $lastmodCandidates[] = (int)filemtime($candidate);
}
$output = isset($state['output']) && is_string($state['output']) ? basename($state['output']) : '';
if ($output !== '') {
$videoPath = rtrim($videosDir, '/') . '/' . $output;
if (is_file($videoPath)) $lastmodCandidates[] = (int)filemtime($videoPath);
}
$lastmodTs = $lastmodCandidates ? max($lastmodCandidates) : (int)filemtime($dir);
sitemap_add_url(
$urls,
'https://bubulescu.org/?id=' . rawurlencode($articleId),
sitemap_lastmod_from_ts($lastmodTs),
'monthly',
'0.8'
);
}
ksort($urls, SORT_STRING);
header('Content-Type: application/xml; charset=UTF-8');
header('X-MVLog-Sitemap: dynamic');
header('Cache-Control: public, max-age=300');
echo '<?xml version="1.0" encoding="UTF-8"?>' . "\n";
echo '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">' . "\n";
foreach ($urls as $url) {
echo " <url>\n";
echo ' <loc>' . sitemap_xml_escape($url['loc']) . "</loc>\n";
echo ' <lastmod>' . sitemap_xml_escape($url['lastmod']) . "</lastmod>\n";
echo ' <changefreq>' . sitemap_xml_escape($url['changefreq']) . "</changefreq>\n";
echo ' <priority>' . sitemap_xml_escape($url['priority']) . "</priority>\n";
echo " </url>\n";
}
echo "</urlset>\n";