You are here

abstract class SitemapGeneratorBase in Simple XML sitemap 8.3

Same name and namespace in other branches
  1. 4.x src/Plugin/simple_sitemap/SitemapGenerator/SitemapGeneratorBase.php \Drupal\simple_sitemap\Plugin\simple_sitemap\SitemapGenerator\SitemapGeneratorBase

Class SitemapGeneratorBase @package Drupal\simple_sitemap\Plugin\simple_sitemap\UrlGenerator

Hierarchy

Expanded class hierarchy of SitemapGeneratorBase

4 files declare their use of SitemapGeneratorBase
EntityUrlGeneratorBase.php in src/Plugin/simple_sitemap/UrlGenerator/EntityUrlGeneratorBase.php
QueueWorker.php in src/Queue/QueueWorker.php
Simplesitemap.php in src/Simplesitemap.php
SimplesitemapManager.php in src/SimplesitemapManager.php

File

src/Plugin/simple_sitemap/SitemapGenerator/SitemapGeneratorBase.php, line 18

Namespace

Drupal\simple_sitemap\Plugin\simple_sitemap\SitemapGenerator
View source
abstract class SitemapGeneratorBase extends SimplesitemapPluginBase implements SitemapGeneratorInterface {
  const FIRST_CHUNK_DELTA = 1;
  const INDEX_DELTA = 0;
  const XMLNS = 'http://www.sitemaps.org/schemas/sitemap/0.9';

  /**
   * @var \Drupal\Core\Database\Connection
   */
  protected $db;

  /**
   * @var \Drupal\Core\Language\LanguageManagerInterface
   */
  protected $languageManager;

  /**
   * @var \Drupal\Core\Extension\ModuleHandler
   */
  protected $moduleHandler;

  /**
   * @var \Drupal\Component\Datetime\Time
   */
  protected $time;

  /**
   * @var array
   */
  protected $settings;

  /**
   * @var \Drupal\simple_sitemap\Plugin\simple_sitemap\SitemapGenerator\SitemapWriter
   */
  protected $writer;

  /**
   * @var string
   */
  protected $sitemapVariant;

  /**
   * @var array
   */
  protected $sitemapUrlSettings;

  /**
   * @var array
   */
  protected static $indexAttributes = [
    'xmlns' => self::XMLNS,
  ];

  /**
   * SitemapGeneratorBase constructor.
   * @param array $configuration
   * @param string $plugin_id
   * @param mixed $plugin_definition
   * @param \Drupal\Core\Database\Connection $database
   * @param \Drupal\Core\Extension\ModuleHandler $module_handler
   * @param \Drupal\Core\Language\LanguageManagerInterface $language_manager
   * @param \Drupal\Component\Datetime\Time $time
   * @param \Drupal\simple_sitemap\Plugin\simple_sitemap\SitemapGenerator\SitemapWriter $sitemap_writer
   */
  public function __construct(array $configuration, $plugin_id, $plugin_definition, Connection $database, ModuleHandler $module_handler, LanguageManagerInterface $language_manager, Time $time, SitemapWriter $sitemap_writer) {
    parent::__construct($configuration, $plugin_id, $plugin_definition);
    $this->db = $database;
    $this->moduleHandler = $module_handler;
    $this->languageManager = $language_manager;
    $this->time = $time;
    $this->writer = $sitemap_writer;
  }
  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
    return new static($configuration, $plugin_id, $plugin_definition, $container
      ->get('database'), $container
      ->get('module_handler'), $container
      ->get('language_manager'), $container
      ->get('datetime.time'), $container
      ->get('simple_sitemap.sitemap_writer'));
  }

  /**
   * @param string $sitemap_variant
   * @return $this
   */
  public function setSitemapVariant($sitemap_variant) {
    $this->sitemapVariant = $sitemap_variant;
    return $this;
  }

  /**
   * @return bool
   */
  protected function isDefaultVariant() {
    return $this->sitemapVariant === $this->settings['default_variant'];
  }

  /**
   * @param array $links
   * @return string
   */
  protected abstract function getXml(array $links);
  protected function getChunkInfo() {
    return $this->db
      ->select('simple_sitemap', 's')
      ->fields('s', [
      'delta',
      'sitemap_created',
      'type',
    ])
      ->condition('s.type', $this->sitemapVariant)
      ->condition('s.delta', self::INDEX_DELTA, '<>')
      ->condition('s.status', 0)
      ->execute()
      ->fetchAllAssoc('delta');
  }

  /**
   * @param array $chunk_info
   * @return string
   */
  protected function getIndexXml(array $chunk_info) {
    $this->writer
      ->openMemory();
    $this->writer
      ->setIndent(TRUE);
    $this->writer
      ->startSitemapDocument();

    // Add the XML stylesheet to document if enabled.
    if ($this->settings['xsl']) {
      $this->writer
        ->writeXsl();
    }
    $this->writer
      ->writeGeneratedBy();
    $this->writer
      ->startElement('sitemapindex');

    // Add attributes to document.
    $attributes = self::$indexAttributes;
    $sitemap_variant = $this->sitemapVariant;
    $this->moduleHandler
      ->alter('simple_sitemap_index_attributes', $attributes, $sitemap_variant);
    foreach ($attributes as $name => $value) {
      $this->writer
        ->writeAttribute($name, $value);
    }

    // Add sitemap chunk locations to document.
    foreach ($chunk_info as $chunk_data) {
      $this->writer
        ->startElement('sitemap');
      $this->writer
        ->writeElement('loc', $this
        ->getSitemapUrl($chunk_data->delta));
      $this->writer
        ->writeElement('lastmod', date('c', $chunk_data->sitemap_created));
      $this->writer
        ->endElement();
    }
    $this->writer
      ->endElement();
    $this->writer
      ->endDocument();
    return $this->writer
      ->outputMemory();
  }

  /**
   * @param string $mode
   * @return $this
   */
  public function remove($mode = 'all') {
    self::purgeSitemapVariants($this->sitemapVariant, $mode);
    return $this;
  }
  public static function purgeSitemapVariants($variants = NULL, $mode = 'all') {
    if (NULL === $variants || !empty((array) $variants)) {
      $delete_query = \Drupal::database()
        ->delete('simple_sitemap');
      switch ($mode) {
        case 'published':
          $delete_query
            ->condition('status', 1);
          break;
        case 'unpublished':
          $delete_query
            ->condition('status', 0);
          break;
        case 'all':
          break;
        default:
      }
      if (NULL !== $variants) {
        $delete_query
          ->condition('type', (array) $variants, 'IN');
      }
      $delete_query
        ->execute();
    }
  }

  /**
   * @param array $links
   * @return $this
   * @throws \Exception
   */
  public function generate(array $links) {
    $highest_id = $this->db
      ->query('SELECT MAX(id) FROM {simple_sitemap}')
      ->fetchField();
    $highest_delta = $this->db
      ->query('SELECT MAX(delta) FROM {simple_sitemap} WHERE type = :type AND status = :status', [
      ':type' => $this->sitemapVariant,
      ':status' => 0,
    ])
      ->fetchField();
    $this->db
      ->insert('simple_sitemap')
      ->fields([
      'id' => NULL === $highest_id ? 0 : $highest_id + 1,
      'delta' => NULL === $highest_delta ? self::FIRST_CHUNK_DELTA : $highest_delta + 1,
      'type' => $this->sitemapVariant,
      'sitemap_string' => $this
        ->getXml($links),
      'sitemap_created' => $this->time
        ->getRequestTime(),
      'status' => 0,
      'link_count' => count($links),
    ])
      ->execute();
    return $this;
  }

  /**
   * @return $this
   * @throws \Exception
   */
  public function generateIndex() {
    if (!empty($chunk_info = $this
      ->getChunkInfo()) && count($chunk_info) > 1) {
      $index_xml = $this
        ->getIndexXml($chunk_info);
      $highest_id = $this->db
        ->query('SELECT MAX(id) FROM {simple_sitemap}')
        ->fetchField();
      $this->db
        ->merge('simple_sitemap')
        ->keys([
        'delta' => self::INDEX_DELTA,
        'type' => $this->sitemapVariant,
        'status' => 0,
      ])
        ->insertFields([
        'id' => NULL === $highest_id ? 0 : $highest_id + 1,
        'delta' => self::INDEX_DELTA,
        'type' => $this->sitemapVariant,
        'sitemap_string' => $index_xml,
        'sitemap_created' => $this->time
          ->getRequestTime(),
        'status' => 0,
      ])
        ->updateFields([
        'sitemap_string' => $index_xml,
        'sitemap_created' => $this->time
          ->getRequestTime(),
      ])
        ->execute();
    }
    return $this;
  }

  /**
   * @return $this
   */
  public function publish() {
    $unpublished_chunk = $this->db
      ->query('SELECT MAX(id) FROM {simple_sitemap} WHERE type = :type AND status = :status', [
      ':type' => $this->sitemapVariant,
      ':status' => 0,
    ])
      ->fetchField();

    // Only allow publishing a sitemap variant if there is an unpublished
    // sitemap variant, as publishing involves deleting the currently published
    // variant.
    if (FALSE !== $unpublished_chunk) {
      $this
        ->remove('published');
      $this->db
        ->query('UPDATE {simple_sitemap} SET status = :status WHERE type = :type', [
        ':type' => $this->sitemapVariant,
        ':status' => 1,
      ]);
    }
    return $this;
  }

  /**
   * @param array $settings
   * @return $this
   */
  public function setSettings(array $settings) {
    $this->settings = $settings;
    return $this;
  }

  /**
   * @return string
   */
  protected function getCustomBaseUrl() {
    $customBaseUrl = $this->settings['base_url'];
    return !empty($customBaseUrl) ? $customBaseUrl : $GLOBALS['base_url'];
  }
  protected function getSitemapUrlSettings() {
    if (NULL === $this->sitemapUrlSettings) {
      $this->sitemapUrlSettings = [
        'absolute' => TRUE,
        'base_url' => $this
          ->getCustomBaseUrl(),
        'language' => $this->languageManager
          ->getLanguage(LanguageInterface::LANGCODE_NOT_APPLICABLE),
      ];
    }
    return $this->sitemapUrlSettings;
  }

  /**
   * @param null $delta
   * @return \Drupal\Core\GeneratedUrl|string
   */
  public function getSitemapUrl($delta = NULL) {
    $parameters = NULL !== $delta ? [
      'page' => $delta,
    ] : [];
    $url = $this
      ->isDefaultVariant() ? Url::fromRoute('simple_sitemap.sitemap_default', $parameters, $this
      ->getSitemapUrlSettings()) : Url::fromRoute('simple_sitemap.sitemap_variant', $parameters + [
      'variant' => $this->sitemapVariant,
    ], $this
      ->getSitemapUrlSettings());
    return $url
      ->toString();
  }

  /**
   * Determines if the sitemap is to be a multilingual sitemap based on several
   * factors.
   *
   * A hreflang/multilingual sitemap is only wanted if there are indexable
   * languages available and if there is a language negotiation method enabled
   * that is based on URL discovery. Any other language negotiation methods
   * should be irrelevant, as a sitemap can only use URLs to guide to the
   * correct language.
   *
   * @see https://www.drupal.org/project/simple_sitemap/issues/3154570#comment-13730522
   *
   * @return bool
   */
  public static function isMultilingualSitemap() {
    if (!\Drupal::moduleHandler()
      ->moduleExists('language')) {
      return FALSE;
    }

    /** @var \Drupal\language\LanguageNegotiatorInterface $language_negotiator */
    $language_negotiator = \Drupal::service('language_negotiator');
    $url_negotiation_method_enabled = FALSE;
    foreach ($language_negotiator
      ->getNegotiationMethods(LanguageInterface::TYPE_URL) as $method) {
      if ($language_negotiator
        ->isNegotiationMethodEnabled($method['id'])) {
        $url_negotiation_method_enabled = TRUE;
        break;
      }
    }
    $has_multiple_indexable_languages = count(array_diff_key(\Drupal::languageManager()
      ->getLanguages(), \Drupal::service('simple_sitemap.generator')
      ->getSetting('excluded_languages', []))) > 1;
    return $url_negotiation_method_enabled && $has_multiple_indexable_languages;
  }

}

Members

Namesort descending Modifiers Type Description Overrides
DependencySerializationTrait::$_entityStorages protected property An array of entity type IDs keyed by the property name of their storages.
DependencySerializationTrait::$_serviceIds protected property An array of service IDs keyed by property name used for serialization.
DependencySerializationTrait::__sleep public function 1
DependencySerializationTrait::__wakeup public function 2
MessengerTrait::$messenger protected property The messenger. 29
MessengerTrait::messenger public function Gets the messenger. 29
MessengerTrait::setMessenger public function Sets the messenger.
PluginBase::$configuration protected property Configuration information passed into the plugin. 1
PluginBase::$pluginDefinition protected property The plugin implementation definition. 1
PluginBase::$pluginId protected property The plugin_id.
PluginBase::DERIVATIVE_SEPARATOR constant A string which is used to separate base plugin IDs from the derivative ID.
PluginBase::getBaseId public function Gets the base_plugin_id of the plugin instance. Overrides DerivativeInspectionInterface::getBaseId
PluginBase::getDerivativeId public function Gets the derivative_id of the plugin instance. Overrides DerivativeInspectionInterface::getDerivativeId
PluginBase::getPluginDefinition public function Gets the definition of the plugin implementation. Overrides PluginInspectionInterface::getPluginDefinition 3
PluginBase::getPluginId public function Gets the plugin_id of the plugin instance. Overrides PluginInspectionInterface::getPluginId
PluginBase::isConfigurable public function Determines if the plugin is configurable.
SitemapGeneratorBase::$db protected property
SitemapGeneratorBase::$indexAttributes protected static property
SitemapGeneratorBase::$languageManager protected property
SitemapGeneratorBase::$moduleHandler protected property
SitemapGeneratorBase::$settings protected property
SitemapGeneratorBase::$sitemapUrlSettings protected property
SitemapGeneratorBase::$sitemapVariant protected property
SitemapGeneratorBase::$time protected property
SitemapGeneratorBase::$writer protected property
SitemapGeneratorBase::create public static function Creates an instance of the plugin. Overrides SimplesitemapPluginBase::create
SitemapGeneratorBase::FIRST_CHUNK_DELTA constant
SitemapGeneratorBase::generate public function Overrides SitemapGeneratorInterface::generate
SitemapGeneratorBase::generateIndex public function Overrides SitemapGeneratorInterface::generateIndex
SitemapGeneratorBase::getChunkInfo protected function
SitemapGeneratorBase::getCustomBaseUrl protected function
SitemapGeneratorBase::getIndexXml protected function
SitemapGeneratorBase::getSitemapUrl public function Overrides SitemapGeneratorInterface::getSitemapUrl
SitemapGeneratorBase::getSitemapUrlSettings protected function
SitemapGeneratorBase::getXml abstract protected function 1
SitemapGeneratorBase::INDEX_DELTA constant
SitemapGeneratorBase::isDefaultVariant protected function
SitemapGeneratorBase::isMultilingualSitemap public static function Determines if the sitemap is to be a multilingual sitemap based on several factors.
SitemapGeneratorBase::publish public function Overrides SitemapGeneratorInterface::publish
SitemapGeneratorBase::purgeSitemapVariants public static function
SitemapGeneratorBase::remove public function Overrides SitemapGeneratorInterface::remove
SitemapGeneratorBase::setSettings public function Overrides SitemapGeneratorInterface::setSettings
SitemapGeneratorBase::setSitemapVariant public function Overrides SitemapGeneratorInterface::setSitemapVariant
SitemapGeneratorBase::XMLNS constant
SitemapGeneratorBase::__construct public function SitemapGeneratorBase constructor. Overrides SimplesitemapPluginBase::__construct
StringTranslationTrait::$stringTranslation protected property The string translation service. 1
StringTranslationTrait::formatPlural protected function Formats a string containing a count of items.
StringTranslationTrait::getNumberOfPlurals protected function Returns the number of plurals supported by a given language.
StringTranslationTrait::getStringTranslation protected function Gets the string translation service.
StringTranslationTrait::setStringTranslation public function Sets the string translation service to use. 2
StringTranslationTrait::t protected function Translates a string to the current language or to a given language.