<?php
// Built per request, so it is current the moment a report is published. robots.txt points here.
// Runs as PHP only via the vhost's <Files "sitemap.xml"> handler; without it Apache serves this source.
require_once __DIR__ . '/inc/config.inc';

if ($dbconn === null) {
    http_response_code(503);
    exit;
}

// Most important first. send_app.html, app_sent.html and the dashboard are left out on purpose.
$pages = [
    ['/',                   '1.0', 'monthly'],
    ['/field_reports.html', '0.9', 'weekly'],
    ['/gallery.html',       '0.8', 'weekly'],
    ['/about.html',         '0.7', 'yearly'],
    ['/application.html',   '0.7', 'yearly'],
    ['/app_checklist.html', '0.5', 'yearly'],
    ['/app_form.html',      '0.5', 'yearly'],
    ['/recent_reports.html','0.5', 'weekly'],
];

$x = fn($s) => htmlspecialchars($s, ENT_XML1 | ENT_QUOTES, 'UTF-8');

$xml  = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
$xml .= "<urlset xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\">\n";
foreach ($pages as [$path, $priority, $freq]) {
    $xml .= "  <url>\n    <loc>" . $x($canonical_base . $path) . "</loc>\n"
          . "    <changefreq>$freq</changefreq>\n    <priority>$priority</priority>\n  </url>\n";
}

// The same "has a summary" test as field_reports.html, so it never lists a report the site won't link to.
$rows = fetchAll("
    select slug, year, month from articles
    where length(summary) > 0 and slug is not null and slug <> ''
    order by year desc, month desc, id desc
");
foreach ($rows as $row) {
    $xml .= "  <url>\n    <loc>" . $x($canonical_base . '/article/' . $row['slug']) . "</loc>\n";
    // Reports carry no edit date, so lastmod is the trip's month, left out when unusable.
    $y = (int)$row['year'];
    $m = (int)$row['month'];
    if ($y >= 1998 && $m >= 1 && $m <= 12) {
        $xml .= sprintf("    <lastmod>%04d-%02d-01</lastmod>\n", $y, $m);
    }
    $xml .= "    <changefreq>yearly</changefreq>\n    <priority>0.6</priority>\n  </url>\n";
}
$xml .= "</urlset>\n";

header('Content-Type: application/xml; charset=utf-8');
$etag = '"' . md5($xml) . '"';
header("ETag: $etag");
// mod_deflate appends -gzip to the ETag it sends, and the client returns it that way.
if (str_replace('-gzip"', '"', trim($_SERVER['HTTP_IF_NONE_MATCH'] ?? '')) === $etag) {
    http_response_code(304);
    exit;
}
echo $xml;
