<?php
/*
|| sitemap.php -- XML sitemap for search engines.
||
|| Almost every page on the site is a deep link into index.php, so crawlers
|| only find displays by walking the paginated browse lists and will miss a
|| great many of them.  This lists every indexable URL explicitly, with the
|| last modified date we already track in display.ldate so freshness is
|| reported accurately.
||
|| Referenced from robots.txt.  Submit https://cooldisplays.net/sitemap.php in
|| Google Search Console.
*/

header('Content-Type: application/xml; charset=utf-8');

$db = "";
try {
   $db = new PDO("sqlite:data/display.db");
   $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch (PDOException $e)
{
   header("HTTP/1.1 500 Internal Server Error");
   echo("<!-- unable to open database -->");
   exit(1);
}

/*
|| Fixed, so that the URLs listed here are byte for byte the ones the pages
|| declare as canonical.  Keep in step with siteOrigin() in index.php.
*/
function origin()
{
   return "https://cooldisplays.net";
}

/*
|| ldate is stored as a unix timestamp; sitemaps want W3C datetime.
*/
function sitemapDate($ldate)
{
   if (!isset($ldate) or $ldate == 0)
      return "";

   return gmdate("Y-m-d", (int) $ldate);
}

function urlEntry($loc, $lastmod = "", $changefreq = "", $priority = "")
{
   echo("  <url>\n");
   echo("    <loc>" . htmlspecialchars($loc, ENT_XML1, "UTF-8") . "</loc>\n");
   if (strcmp($lastmod, "") != 0)
      echo("    <lastmod>$lastmod</lastmod>\n");
   if (strcmp($changefreq, "") != 0)
      echo("    <changefreq>$changefreq</changefreq>\n");
   if (strcmp($priority, "") != 0)
      echo("    <priority>$priority</priority>\n");
   echo("  </url>\n");
}

$base = origin();

echo("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
echo("<urlset xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\">\n");

/*
|| Home and the evergreen content pages.
*/
urlEntry($base . "/", "", "daily", "1.0");
foreach (array("displays", "map", "faq", "about", "terms", "tools") as $page)
   urlEntry($base . "/index.php?page=" . $page, "", "monthly", "0.5");

/*
|| One landing page per state.  These are the pages that rank for
|| "christmas lights in <state>", so they get a high priority.
*/
try {
   $sql = "select initials from tag where type = 'STATE' order by name";
   foreach ($db->query($sql) as $row)
      urlEntry($base . "/index.php?page=state&state=" . $row['initials'],
               "", "weekly", "0.8");
} catch (PDOException $e)
{
   echo("  <!-- state query failed -->\n");
}

/*
|| One page per holiday tag.
*/
try {
   $sql = "select id from tag where type = 'HOLIDAY' order by name";
   foreach ($db->query($sql) as $row)
      urlEntry($base . "/index.php?page=displays&tag=" . $row['id'],
               "", "weekly", "0.6");
} catch (PDOException $e)
{
   echo("  <!-- holiday query failed -->\n");
}

/*
|| Every active display.  Inactive displays are deliberately left out: they
|| carry noindex (see SinglePage::robotsMeta), so listing them here would only
|| ask Google to crawl pages we have told it not to index.
*/
try {
   $sql = "select displayid, ldate from display "
        . "where active = 'Y' order by ldate desc";
   foreach ($db->query($sql) as $row)
   {
      urlEntry($base . "/index.php?page=single&id=" . $row['displayid'],
               sitemapDate($row['ldate']), "monthly", "0.7");
   }
} catch (PDOException $e)
{
   echo("  <!-- display query failed -->\n");
}

echo("</urlset>\n");

?>
