<?php

namespace Drupal\simple_sitemap\Plugin\simple_sitemap\SitemapGenerator;

use Drupal\Core\Routing\RouteProviderInterface;

/**
 * Sitemap XML writer.
 */
class SitemapWriter extends \XMLWriter {

  protected const GENERATED_BY = 'Generated by the Simple XML Sitemap Drupal module: https://drupal.org/project/simple_sitemap.';
  protected const XML_VERSION = '1.0';
  protected const ENCODING = 'UTF-8';

  /**
   * The route provider.
   *
   * @var \Drupal\Core\Routing\RouteProviderInterface
   */
  protected $routeProvider;

  /**
   * SitemapWriter constructor.
   *
   * @param \Drupal\Core\Routing\RouteProviderInterface $route_provider
   *   The route provider.
   */
  public function __construct(RouteProviderInterface $route_provider) {
    $this->routeProvider = $route_provider;
  }

  /**
   * Adds the XML stylesheet to the XML page.
   */
  public function writeXsl($generator_id): void {
    // Using this instead of URL::fromRoute() to avoid creating a path with the
    // subdomain from which creation was triggered which might lead to a CORS
    // problem.
    // See https://www.drupal.org/project/simple_sitemap/issues/3131672.
    $xsl_url = $this->routeProvider
      ->getRouteByName('simple_sitemap.sitemap_xsl')
      ->getPath();

    // Now substituting path placeholder as URL::fromRoute() would do.
    $xsl_url = str_replace('{sitemap_generator}', $generator_id, $xsl_url);

    // The above workaround however generates an incorrect path when the site is
    // located in a subdirectory, which is why the following logic adds the base
    // path of the installation.
    // See https://www.drupal.org/project/simple_sitemap/issues/3154494.
    // All of this seems to be an over engineered way of writing '/sitemap_generator/{sitemap_generator}/sitemap.xsl',
    // but may be useful in cases where another module alters the routes.
    $xsl_url = base_path() . ltrim($xsl_url, '/');

    $this->writePI('xml-stylesheet', 'type="text/xsl" href="' . $xsl_url . '"');
  }

  /**
   * Writes 'generated by' comment.
   */
  public function writeGeneratedBy(): void {
    $this->writeComment(self::GENERATED_BY);
  }

  /**
   * Creates document tag.
   */
  public function startSitemapDocument(): void {
    $this->startDocument(self::XML_VERSION, self::ENCODING);
  }

}
