<?php
declare(strict_types=1);


/*
|--------------------------------------------------------------------------
| ABDL MAP 2.10 – DYNAMISCHE SITEMAP
|--------------------------------------------------------------------------
|
| Enthält:
|
| - wichtige öffentliche statische Seiten
| - öffentliche freigegebene Community-Profile
| - öffentliche aktive zukünftige Events
|
| Enthält NICHT:
|
| - Bearbeitungsseiten
| - private Events
| - Tokens
| - Filter-/Suchseiten
| - Pagination
| - Admin-/Debug-Seiten
| - Erstellungsformulare mit noindex
|
|--------------------------------------------------------------------------
*/


require_once __DIR__ . '/includes/bootstrap.php';


/*
|--------------------------------------------------------------------------
| Header
|--------------------------------------------------------------------------
*/

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

header(
    'Cache-Control: public, max-age=3600'
);

header(
    'X-Content-Type-Options: nosniff'
);


/*
|--------------------------------------------------------------------------
| Basis-URL
|--------------------------------------------------------------------------
*/

$baseUrl =
    defined('APP_URL')
        ? rtrim((string) APP_URL, '/')
        : 'https://abdl-map.4lima.de';


/*
|--------------------------------------------------------------------------
| XML Escape
|--------------------------------------------------------------------------
*/

function sitemapXml(
    string $value
): string {

    return
        htmlspecialchars(
            $value,
            ENT_XML1
            |
            ENT_QUOTES,
            'UTF-8'
        );
}


/*
|--------------------------------------------------------------------------
| Datum formatieren
|--------------------------------------------------------------------------
*/

function sitemapDate(
    mixed $value
): ?string {

    if (
        !is_string($value)
        ||
        trim($value) === ''
    ) {
        return null;
    }


    try {

        $date =
            new DateTimeImmutable(
                $value
            );


        return
            $date->format(
                DATE_ATOM
            );


    } catch (Throwable) {

        return null;
    }
}


/*
|--------------------------------------------------------------------------
| URL-Eintrag
|--------------------------------------------------------------------------
*/

function sitemapWriteUrl(
    string $url,
    ?string $lastmod = null
): void {

    echo "  <url>\n";

    echo
        '    <loc>'
        .
        sitemapXml($url)
        .
        "</loc>\n";


    if (
        $lastmod !== null
        &&
        $lastmod !== ''
    ) {

        echo
            '    <lastmod>'
            .
            sitemapXml($lastmod)
            .
            "</lastmod>\n";
    }


    echo "  </url>\n";
}


/*
|--------------------------------------------------------------------------
| XML starten
|--------------------------------------------------------------------------
*/

echo
    '<?xml version="1.0" encoding="UTF-8"?>'
    .
    "\n";


echo
    '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">'
    .
    "\n";


/*
|--------------------------------------------------------------------------
| Statische Seiten
|--------------------------------------------------------------------------
|
| Nur Seiten, die tatsächlich indexiert werden sollen.
|
| Bewusst NICHT:
|
| - eintragen.php
| - event_eintragen.php
| - link_eintragen.php
| - feedback.php
| - edit_*.php
| - private/tokenisierte Seiten
|--------------------------------------------------------------------------
*/

$staticPages = [

    '/',

    '/karte.php',

    '/eintraege.php',

    '/neueste_eintraege.php',

    '/kategorien.php',

    '/events.php',

    '/links.php',

    '/krabbelgruppe.php',

    '/impressum.php',

    '/datenschutz.php',

    '/jugendschutz.php'
];


foreach (
    $staticPages
    as $path
) {

    sitemapWriteUrl(
        $baseUrl
        .
        $path
    );
}


/*
|--------------------------------------------------------------------------
| Öffentliche Community-Profile
|--------------------------------------------------------------------------
|
| Gleicher Public-Gate-Gedanke wie im restlichen 2.10-System.
|
| Einträge müssen:
|
| - public
| - approved
| - Standort anonymisiert
|
| sein.
|--------------------------------------------------------------------------
*/

try {

    $markerStmt =
        $pdo->query(
            "
            SELECT
                id,
                created_at

            FROM markers

            WHERE visibility = 'public'

              AND status = 'approved'

              AND location_anonymized = 1

            ORDER BY
                id ASC
            "
        );


    while (
        $marker =
            $markerStmt->fetch(
                PDO::FETCH_ASSOC
            )
    ) {

        $id =
            (int) (
                $marker['id']
                ??
                0
            );


        if ($id <= 0) {
            continue;
        }


        $lastmod =
            sitemapDate(
                $marker['created_at']
                ??
                null
            );


        sitemapWriteUrl(
            $baseUrl
            .
            '/eintrag.php?id='
            .
            $id,
            $lastmod
        );
    }


} catch (Throwable $e) {

    if (
        function_exists('appLog')
    ) {

        appLog(
            'warning',
            'Sitemap konnte Community-Profile nicht laden.',
            [
                'exception' =>
                    $e->getMessage()
            ]
        );
    }
}


/*
|--------------------------------------------------------------------------
| Öffentliche Events
|--------------------------------------------------------------------------
|
| Nur:
|
| - visibility = public
| - status = active
| - nicht vergangen
|
| Private, gelöschte und abgesagte Events werden nicht aufgenommen.
|--------------------------------------------------------------------------
*/

try {

    $eventStmt =
        $pdo->query(
            "
            SELECT
                id,
                event_date

            FROM events

            WHERE visibility = 'public'

              AND status = 'active'

              AND event_date >= CURDATE()

            ORDER BY
                event_date ASC,
                id ASC
            "
        );


    while (
        $event =
            $eventStmt->fetch(
                PDO::FETCH_ASSOC
            )
    ) {

        $id =
            (int) (
                $event['id']
                ??
                0
            );


        if ($id <= 0) {
            continue;
        }


        $lastmod =
            sitemapDate(
                $event['event_date']
                ??
                null
            );


        sitemapWriteUrl(
            $baseUrl
            .
            '/event.php?id='
            .
            $id,
            $lastmod
        );
    }


} catch (Throwable $e) {

    if (
        function_exists('appLog')
    ) {

        appLog(
            'warning',
            'Sitemap konnte Events nicht laden.',
            [
                'exception' =>
                    $e->getMessage()
            ]
        );
    }
}


/*
|--------------------------------------------------------------------------
| Ende
|--------------------------------------------------------------------------
*/

echo "</urlset>\n";