'ae','Æ'=>'ae','ø'=>'o','Ø'=>'o','å'=>'aa','Å'=>'aa', 'ä'=>'ae','Ä'=>'ae','ö'=>'oe','Ö'=>'oe','ü'=>'ue','Ü'=>'ue','ß'=>'ss','ẞ'=>'ss', 'č'=>'c','Č'=>'c','ć'=>'c','Ć'=>'c','ž'=>'z','Ž'=>'z','š'=>'s','Š'=>'s','đ'=>'d','Đ'=>'d', ]); if (function_exists('iconv')) { $ascii = @iconv('UTF-8', 'ASCII//TRANSLIT//IGNORE', $slug); if ($ascii !== false) $slug = $ascii; } $slug = strtolower($slug); $slug = preg_replace('/[^a-z0-9]+/', '-', $slug) ?? ''; $slug = trim($slug, '-'); return $slug !== '' ? $slug : $fallback; } function sitemap_title_from_data_file(string $dir): string { $file = rtrim($dir, '/') . '/data.txt'; if (is_file($file)) { foreach (file($file, FILE_IGNORE_NEW_LINES) ?: [] as $line) { if (!str_contains($line, ':')) continue; [$key, $value] = array_map('trim', explode(':', $line, 2)); if (in_array(strtolower($key), ['title','name'], true) && $value !== '') return $value; } } return basename($dir); } 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); } } $articleEntries = []; $articleDirs = glob(rtrim($uploadsDir, '/') . '/*', GLOB_ONLYDIR) ?: []; sort($articleDirs, SORT_STRING); foreach ($articleDirs 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); } $articleEntries[] = [ 'id' => $articleId, 'base_slug' => sitemap_slug_from_title(sitemap_title_from_data_file($dir), $articleId), 'lastmod' => sitemap_lastmod_from_ts($lastmodCandidates ? max($lastmodCandidates) : (int)filemtime($dir)), ]; } $usedSlugs = []; foreach ($articleEntries as $entry) { $slug = $entry['base_slug']; if (isset($usedSlugs[$slug])) $slug = $entry['base_slug'] . '-' . substr($entry['id'], -6); $n = 2; while (isset($usedSlugs[$slug])) { $slug = $entry['base_slug'] . '-' . substr($entry['id'], -6) . '-' . $n; $n++; } $usedSlugs[$slug] = true; sitemap_add_url( $urls, 'https://bubulescu.org/post/' . rawurlencode($slug), $entry['lastmod'], '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 '' . "\n"; echo '' . "\n"; foreach ($urls as $url) { echo " \n"; echo ' ' . sitemap_xml_escape($url['loc']) . "\n"; echo ' ' . sitemap_xml_escape($url['lastmod']) . "\n"; echo ' ' . sitemap_xml_escape($url['changefreq']) . "\n"; echo ' ' . sitemap_xml_escape($url['priority']) . "\n"; echo " \n"; } echo "\n";