Updated to Drupal 8.5. Core Media not yet in use.
[yaffs-website] / web / modules / contrib / simple_sitemap / src / SitemapGenerator.php
index ce1198faf773c311d357785f7f0598d1ebfa326d..aac9cb97f4633fbb08834d6e91ac2807248e408e 100644 (file)
@@ -2,11 +2,10 @@
 
 namespace Drupal\simple_sitemap;
 
-use XMLWriter;
-use Drupal\simple_sitemap\Batch\Batch;
 use Drupal\Core\Database\Connection;
 use Drupal\Core\Extension\ModuleHandler;
 use Drupal\Core\Language\LanguageManagerInterface;
+use Drupal\Component\Datetime\Time;
 
 /**
  * Class SitemapGenerator
@@ -20,11 +19,7 @@ class SitemapGenerator {
   const XMLNS_XHTML = 'http://www.w3.org/1999/xhtml';
   const GENERATED_BY = 'Generated by the Simple XML sitemap Drupal module: https://drupal.org/project/simple_sitemap.';
   const FIRST_CHUNK_INDEX = 1;
-
-  /**
-   * @var \Drupal\simple_sitemap\Batch\Batch
-   */
-  protected $batch;
+  const XMLNS_IMAGE = 'http://www.google.com/schemas/sitemap-image/1.1';
 
   /**
    * @var \Drupal\simple_sitemap\EntityHelper
@@ -36,7 +31,6 @@ class SitemapGenerator {
    */
   protected $db;
 
-
   /**
    * @var \Drupal\Core\Language\LanguageManagerInterface
    */
@@ -48,148 +42,88 @@ class SitemapGenerator {
   protected $moduleHandler;
 
   /**
-   * @var string
+   * @var bool
    */
-  protected $generateFrom = 'form';
+  protected $isHreflangSitemap;
 
   /**
-   * @var bool
+   * @var \Drupal\Component\Datetime\Time
    */
-  protected $isHreflangSitemap;
+  protected $time;
+
+  /**
+   * @var array
+   */
+  protected $settings;
+
+  /**
+   * @var \XMLWriter
+   */
+  protected $writer;
+
+  /**
+   * @var array
+   */
+  protected static $attributes = [
+    'xmlns' => self::XMLNS,
+    'xmlns:xhtml' => self::XMLNS_XHTML,
+    'xmlns:image' => self::XMLNS_IMAGE,
+  ];
 
   /**
-   * @var \Drupal\simple_sitemap\Simplesitemap
+   * @var array
    */
-  protected $generator;
+  protected static $indexAttributes = [
+    'xmlns' => self::XMLNS,
+  ];
 
   /**
    * SitemapGenerator constructor.
-   * @param \Drupal\simple_sitemap\Batch\Batch $batch
    * @param \Drupal\simple_sitemap\EntityHelper $entityHelper
    * @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\SitemapWriter $sitemapWriter
    */
   public function __construct(
-    Batch $batch,
     EntityHelper $entityHelper,
     Connection $database,
     ModuleHandler $module_handler,
-    LanguageManagerInterface $language_manager
+    LanguageManagerInterface $language_manager,
+    Time $time,
+    SitemapWriter $sitemapWriter
   ) {
-    $this->batch = $batch;
     $this->entityHelper = $entityHelper;
     $this->db = $database;
     $this->moduleHandler = $module_handler;
     $this->languageManager = $language_manager;
-    $this->setIsHreflangSitemap();
-  }
-
-  protected function setIsHreflangSitemap() {
-    $this->isHreflangSitemap = count($this->languageManager->getLanguages()) > 1;
+    $this->time = $time;
+    $this->writer = $sitemapWriter;
   }
 
   /**
    * @return bool
    */
-  public function isHreflangSitemap() {
+  protected function isHreflangSitemap() {
+    if (NULL === $this->isHreflangSitemap) {
+      $this->isHreflangSitemap = count(array_diff_key($this->languageManager->getLanguages(), $this->settings['excluded_languages'])) > 1;
+    }
     return $this->isHreflangSitemap;
   }
 
   /**
-   * @param \Drupal\simple_sitemap\Simplesitemap $generator
+   * @param array $settings
    * @return $this
    */
-  public function setGenerator(Simplesitemap $generator) {
-    $this->generator = $generator;
+  public function setSettings(array $settings) {
+    $this->settings = $settings;
     return $this;
   }
 
   /**
-   * @param string $from
-   * @return $this
-   */
-  public function setGenerateFrom($from) {
-    $this->generateFrom = $from;
-    return $this;
-  }
-
-  /**
-   * Adds all operations to the batch and starts it.
-   */
-  public function startGeneration() {
-    $this->batch->setBatchInfo([
-      'from' => $this->generateFrom,
-      'batch_process_limit' => !empty($this->generator->getSetting('batch_process_limit'))
-        ? $this->generator->getSetting('batch_process_limit') : NULL,
-      'max_links' => $this->generator->getSetting('max_links', 2000),
-      'skip_untranslated' => $this->generator->getSetting('skip_untranslated', FALSE),
-      'remove_duplicates' => $this->generator->getSetting('remove_duplicates', TRUE),
-      'entity_types' => $this->generator->getBundleSettings(),
-      'base_url' => $this->generator->getSetting('base_url', ''),
-    ]);
-    // Add custom link generating operation.
-    $this->batch->addOperation('generateCustomUrls', $this->getCustomUrlsData());
-
-    // Add entity link generating operations.
-    foreach ($this->getEntityTypeData() as $data) {
-      $this->batch->addOperation('generateBundleUrls', $data);
-    }
-    $this->batch->start();
-  }
-
-  /**
-   * Returns a batch-ready data array for custom link generation.
-   *
-   * @return array
-   *   Data to be processed.
-   */
-  protected function getCustomUrlsData() {
-    $paths = [];
-    foreach ($this->generator->getCustomLinks() as $i => $custom_path) {
-      $paths[$i]['path'] = $custom_path['path'];
-      $paths[$i]['priority'] = isset($custom_path['priority']) ? $custom_path['priority'] : NULL;
-      // todo: implement lastmod.
-      $paths[$i]['lastmod'] = NULL;
-    }
-    return $paths;
-  }
-
-  /**
-   * Collects entity metadata for entities that are set to be indexed
-   * and returns an array of batch-ready data sets for entity link generation.
-   *
-   * @return array
-   */
-  protected function getEntityTypeData() {
-    $data_sets = [];
-    $sitemap_entity_types = $this->entityHelper->getSitemapEntityTypes();
-    $entity_types = $this->generator->getBundleSettings();
-    foreach ($entity_types as $entity_type_name => $bundles) {
-      if (isset($sitemap_entity_types[$entity_type_name])) {
-        $keys = $sitemap_entity_types[$entity_type_name]->getKeys();
-
-        // Menu fix.
-        $keys['bundle'] = $entity_type_name == 'menu_link_content' ? 'menu_name' : $keys['bundle'];
-
-        foreach ($bundles as $bundle_name => $bundle_settings) {
-          if ($bundle_settings['index']) {
-            $data_sets[] = [
-              'bundle_settings' => $bundle_settings,
-              'bundle_name' => $bundle_name,
-              'entity_type_name' => $entity_type_name,
-              'keys' => $keys,
-            ];
-          }
-        }
-      }
-    }
-    return $data_sets;
-  }
-
-  /**
-   * Wrapper method which takes links along with their options, lets other
-   * modules alter the links and then generates and saves the sitemap.
+   * Wrapper method which takes links along with their options and then
+   * generates and saves the sitemap.
    *
    * @param array $links
    *   All links with their multilingual versions and settings.
@@ -197,15 +131,12 @@ class SitemapGenerator {
    *   Remove old sitemap from database before inserting the new one.
    */
   public function generateSitemap(array $links, $remove_sitemap = FALSE) {
-    // Invoke alter hook.
-    $this->moduleHandler->alter('simple_sitemap_links', $links);
-
     $values = [
       'id' => $remove_sitemap ? self::FIRST_CHUNK_INDEX
         : $this->db->query('SELECT MAX(id) FROM {simple_sitemap}')
           ->fetchField() + 1,
       'sitemap_string' => $this->generateSitemapChunk($links),
-      'sitemap_created' => REQUEST_TIME,
+      'sitemap_created' => $this->time->getRequestTime(),
     ];
     if ($remove_sitemap) {
       $this->db->truncate('simple_sitemap')->execute();
@@ -222,27 +153,37 @@ class SitemapGenerator {
    * @return string sitemap index
    */
   public function generateSitemapIndex(array $chunk_info) {
-    $writer = new XMLWriter();
-    $writer->openMemory();
-    $writer->setIndent(TRUE);
-    $writer->startDocument(self::XML_VERSION, self::ENCODING);
-    $writer->writeComment(self::GENERATED_BY);
-    $writer->startElement('sitemapindex');
-    $writer->writeAttribute('xmlns', self::XMLNS);
+    $this->writer->openMemory();
+    $this->writer->setIndent(TRUE);
+    $this->writer->startDocument(self::XML_VERSION, self::ENCODING);
+    $this->writer->writeComment(self::GENERATED_BY);
+    $this->writer->startElement('sitemapindex');
+
+    // Add attributes to document.
+    $this->moduleHandler->alter('simple_sitemap_index_attributes', self::$indexAttributes);
+    foreach (self::$indexAttributes as $name => $value) {
+      $this->writer->writeAttribute($name, $value);
+    }
 
+    // Add sitemap locations to document.
     foreach ($chunk_info as $chunk_id => $chunk_data) {
-      $writer->startElement('sitemap');
-      $writer->writeElement('loc', $this->getCustomBaseUrl() . '/sitemaps/' . $chunk_id . '/' . 'sitemap.xml');
-      $writer->writeElement('lastmod', date_iso8601($chunk_data->sitemap_created));
-      $writer->endElement();
+      $this->writer->startElement('sitemap');
+      $this->writer->writeElement('loc', $this->getCustomBaseUrl() . '/sitemaps/' . $chunk_id . '/' . 'sitemap.xml');
+      $this->writer->writeElement('lastmod', date_iso8601($chunk_data->sitemap_created));
+      $this->writer->endElement();
     }
-    $writer->endElement();
-    $writer->endDocument();
-    return $writer->outputMemory();
+
+    $this->writer->endElement();
+    $this->writer->endDocument();
+
+    return $this->writer->outputMemory();
   }
 
+  /**
+   * @return string
+   */
   public function getCustomBaseUrl() {
-    $customBaseUrl = $this->generator->getSetting('base_url', '');
+    $customBaseUrl = $this->settings['base_url'];
     return !empty($customBaseUrl) ? $customBaseUrl : $GLOBALS['base_url'];
   }
 
@@ -256,54 +197,72 @@ class SitemapGenerator {
    *   Sitemap chunk
    */
   protected function generateSitemapChunk(array $links) {
-    $writer = new XMLWriter();
-    $writer->openMemory();
-    $writer->setIndent(TRUE);
-    $writer->startDocument(self::XML_VERSION, self::ENCODING);
-    $writer->writeComment(self::GENERATED_BY);
-    $writer->startElement('urlset');
-    $writer->writeAttribute('xmlns', self::XMLNS);
-
-    if ($this->isHreflangSitemap()) {
-      $writer->writeAttribute('xmlns:xhtml', self::XMLNS_XHTML);
+    $this->writer->openMemory();
+    $this->writer->setIndent(TRUE);
+    $this->writer->startDocument(self::XML_VERSION, self::ENCODING);
+    $this->writer->writeComment(self::GENERATED_BY);
+    $this->writer->startElement('urlset');
+
+    // Add attributes to document.
+    if (!$this->isHreflangSitemap()) {
+      unset(self::$attributes['xmlns:xhtml']);
+    }
+    $this->moduleHandler->alter('simple_sitemap_attributes', self::$attributes);
+    foreach (self::$attributes as $name => $value) {
+      $this->writer->writeAttribute($name, $value);
     }
 
+    // Add URLs to document.
+    $this->moduleHandler->alter('simple_sitemap_links', $links);
     foreach ($links as $link) {
 
       // Add each translation variant URL as location to the sitemap.
-      $writer->startElement('url');
-      $writer->writeElement('loc', $link['url']);
+      $this->writer->startElement('url');
+      $this->writer->writeElement('loc', $link['url']);
 
       // If more than one language is enabled, add all translation variant URLs
       // as alternate links to this location turning the sitemap into a hreflang
       // sitemap.
-      if ($this->isHreflangSitemap()) {
+      if (isset($link['alternate_urls']) && $this->isHreflangSitemap()) {
         foreach ($link['alternate_urls'] as $language_id => $alternate_url) {
-          $writer->startElement('xhtml:link');
-          $writer->writeAttribute('rel', 'alternate');
-          $writer->writeAttribute('hreflang', $language_id);
-          $writer->writeAttribute('href', $alternate_url);
-          $writer->endElement();
+          $this->writer->startElement('xhtml:link');
+          $this->writer->writeAttribute('rel', 'alternate');
+          $this->writer->writeAttribute('hreflang', $language_id);
+          $this->writer->writeAttribute('href', $alternate_url);
+          $this->writer->endElement();
         }
       }
 
       // Add lastmod if any.
       if (isset($link['lastmod'])) {
-        $writer->writeElement('lastmod', $link['lastmod']);
+        $this->writer->writeElement('lastmod', $link['lastmod']);
       }
 
-      //todo: Implement changefreq here.
+      // Add changefreq if any.
+      if (isset($link['changefreq'])) {
+        $this->writer->writeElement('changefreq', $link['changefreq']);
+      }
 
       // Add priority if any.
       if (isset($link['priority'])) {
-        $writer->writeElement('priority', $link['priority']);
+        $this->writer->writeElement('priority', $link['priority']);
       }
 
-      $writer->endElement();
+      // Add images if any.
+      if (!empty($link['images'])) {
+        foreach ($link['images'] as $image) {
+          $this->writer->startElement('image:image');
+          $this->writer->writeElement('image:loc', $image['path']);
+          $this->writer->endElement();
+        }
+      }
+
+      $this->writer->endElement();
     }
-    $writer->endElement();
-    $writer->endDocument();
-    return $writer->outputMemory();
+    $this->writer->endElement();
+    $this->writer->endDocument();
+
+    return $this->writer->outputMemory();
   }
 
 }