<?php
// +-------------------------------------------------+
// | 2002-2007 PMB Services / www.sigb.net pmb@sigb.net et contributeurs (voir www.sigb.net)
// +-------------------------------------------------+
// $Id: SitemapBuilder.php,v 1.3.2.2 2026/01/09 15:16:00 rtigero Exp $
namespace Pmb\SEO\Library;

use encoding_normalize;
use Pmb\SEO\Orm\SEOSitemapEntryOrm;

class SitemapBuilder
{
    protected $sitemapPath = "";

    protected $file = "";

    protected $entries = array();

    /**
     * Construction du fichier de sitemap
     *
     * @return void
     */
    public function buildSitemap(): void
    {
        $this->initSitemapPath();
        $this->file = fopen($this->sitemapPath, "w+");
        $this->fetchData();
        $this->buildHeader();
        $this->buildEntries($this->entries);
        $this->buildFooter();
        fclose($this->file);
    }

    /**
     * Construction de l'en-tête du fichier sitemap
     * @return void
     */
    protected function buildHeader(): void
    {
        $this->writeFile("<?xml version='1.0' encoding='UTF-8'?>\n<urlset xmlns='http://www.sitemaps.org/schemas/sitemap/0.9'>\n\t");
    }

    /**
     * Construction de la fin du fichier sitemap
     * @return void
     */
    protected function buildFooter(): void
    {
        $this->writeFile("</urlset>");
    }

    /**
     * Construction des entrées du fichier sitemap
     *
     * @param array $entries Les entrées à traiter
     * @return void
     */
    protected function buildEntries($entries = array()): void
    {
        foreach ($entries as $entry) {
            $url = $entry->getEntryURL();
            if (! empty($url) && $entry->inSitemap) {
                $this->writeFile("<url>\n\t\t");
                $this->writeFile("<loc>" . htmlentities($url, ENT_QUOTES, 'UTF-8') . "</loc>\n\t\t");
                if (! empty($entry->frequencyUpdate)) {
                    $this->writeFile("<changefreq>" . $entry->frequencyUpdate . "</changefreq>\n\t\t");
                }
                if (! empty($entry->priority)) {
                    $this->writeFile("<priority>" . $entry->priority . "</priority>\n\t");
                }
                $lastMod = $entry->getLastMod();
                if (! empty($lastMod)) {
                    $this->writeFile("<lastmod>" . $lastMod . "</lastmod>\n\t\t");
                }

                $this->writeFile("</url>\n\t");
            }
            $this->buildEntries($entry->childs);
        }
    }

    /**
     * Récupération des données pour pouvoir générer le sitemap
     *
     * @return void
     */
    protected function fetchData()
    {
        $topEntries = SEOSitemapEntryOrm::find("num_parent", 0, "sitemap_order");
        foreach ($topEntries as $entry) {
            $modelNamespace = "Pmb\\SEO\\Models\\Entries\\SEOSitemapEntry" . ucfirst($entry->type);
            if (class_exists($modelNamespace)) {
                $model = new $modelNamespace($entry->{SEOSitemapEntryOrm::$idTableName});
                $model->fetchChildren(true);
                $this->entries[] = $model;
            }
        }
    }

    /**
     * Ecriture dans le fichier sitemap
     *
     * @param string $content Le contenu à écrire
     * @return void
     */
    protected function writeFile(string $content): void
    {
        fwrite($this->file, encoding_normalize::utf8_normalize($content));
    }

    /**
     * Initialisation du chemin du fichier sitemap
     * @return void
     */
    protected function initSitemapPath(): void
    {
        global $base_path;
        $this->sitemapPath = $base_path . "/sitemap.xml";
    }

    public function getSitemapPath(): string
    {
        if (empty($this->sitemapPath)) {
            $this->initSitemapPath();
        }
        return $this->sitemapPath;
    }
}
