Simplesitemap.php 19 KB
Newer Older
1 2
<?php

Pawel G's avatar
Pawel G committed
3
namespace Drupal\simple_sitemap;
4

5
use Drupal\Core\Entity\ContentEntityTypeInterface;
6
use Drupal\simple_sitemap\Form\FormHelper;
Pawel G's avatar
Pawel G committed
7 8 9
use Drupal\Core\Database\Connection;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Path\PathValidator;
Pawel G's avatar
Pawel G committed
10 11 12
use Drupal\Core\Entity\Query\QueryFactory;
use Drupal\Core\Config\ConfigFactory;
use Drupal\Core\Datetime\DateFormatter;
Pawel G's avatar
Pawel G committed
13
use Drupal\Component\Datetime\Time;
14

15
/**
Pawel G's avatar
Pawel G committed
16 17
 * Class Simplesitemap.
 *
Pawel G's avatar
Pawel G committed
18
 * @package Drupal\simple_sitemap
19 20 21
 */
class Simplesitemap {

22
  private $sitemapGenerator;
23 24
  private $configFactory;
  private $db;
25
  private $entityQuery;
26
  private $entityTypeManager;
27
  private $pathValidator;
Pawel G's avatar
Pawel G committed
28
  private $time;
29 30
  private static $allowed_link_settings = [
    'entity' => ['index', 'priority'],
Pawel G's avatar
Pawel G committed
31
    'custom' => ['priority'],
32
  ];
33

34 35
  /**
   * Simplesitemap constructor.
Pawel G's avatar
Pawel G committed
36
   *
Pawel G's avatar
Pawel G committed
37 38 39 40 41 42 43 44
   * @param \Drupal\simple_sitemap\SitemapGenerator $sitemapGenerator
   * @param \Drupal\Core\Config\ConfigFactory $configFactory
   * @param \Drupal\Core\Database\Connection $database
   * @param \Drupal\Core\Entity\Query\QueryFactory $entityQuery
   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entityTypeManager
   * @param \Drupal\Core\Path\PathValidator $pathValidator
   * @param \Drupal\Core\Datetime\DateFormatter $dateFormatter
   * @param \Drupal\Component\Datetime\Time $time
45
   */
46
  public function __construct(
Pawel G's avatar
Pawel G committed
47
    SitemapGenerator $sitemapGenerator,
Pawel G's avatar
Pawel G committed
48
    ConfigFactory $configFactory,
Pawel G's avatar
Pawel G committed
49
    Connection $database,
Pawel G's avatar
Pawel G committed
50
    QueryFactory $entityQuery,
Pawel G's avatar
Pawel G committed
51 52
    EntityTypeManagerInterface $entityTypeManager,
    PathValidator $pathValidator,
Pawel G's avatar
Pawel G committed
53 54
    DateFormatter $dateFormatter,
    Time $time
55 56
  ) {
    $this->sitemapGenerator = $sitemapGenerator;
Pawel G's avatar
Pawel G committed
57
    $this->configFactory = $configFactory;
58
    $this->db = $database;
59
    $this->entityQuery = $entityQuery;
60
    $this->entityTypeManager = $entityTypeManager;
61
    $this->pathValidator = $pathValidator;
62
    $this->dateFormatter = $dateFormatter;
Pawel G's avatar
Pawel G committed
63
    $this->time = $time;
64 65
  }

66
  /**
67
   * Fetches all sitemap chunks indexed by chunk ID.
Pawel G's avatar
Pawel G committed
68
   *
69
   * @return string
Pawel G's avatar
Pawel G committed
70
   */
Pawel G's avatar
Pawel G committed
71
  private function fetchSitemapChunks() {
72
    return $this->db
73 74 75 76
      ->query("SELECT * FROM {simple_sitemap}")
      ->fetchAllAssoc('id');
  }

77 78
  /**
   * Enables sitemap support for an entity type. Enabled entity types show
79 80
   * sitemap settings on their bundle setting forms. If an enabled entity type
   * features bundles (e.g. 'node'), it needs to be set up with
81 82 83
   * setBundleSettings() as well.
   *
   * @param string $entity_type_id
Pawel G's avatar
Pawel G committed
84
   *   Entity type id like 'node'.
85
   *
Pawel G's avatar
Pawel G committed
86
   * @return $this
87 88
   */
  public function enableEntityType($entity_type_id) {
89 90 91 92
    $enabled_entity_types = $this->getSetting('enabled_entity_types');
    if (!in_array($entity_type_id, $enabled_entity_types)) {
      $enabled_entity_types[] = $entity_type_id;
      $this->saveSetting('enabled_entity_types', $enabled_entity_types);
93
    }
Pawel G's avatar
Pawel G committed
94
    return $this;
95 96 97 98 99 100 101 102
  }

  /**
   * Disables sitemap support for an entity type. Disabling support for an
   * entity type deletes its sitemap settings permanently and removes sitemap
   * settings from entity forms.
   *
   * @param string $entity_type_id
103
   *  Entity type id like 'node'.
104
   *
Pawel G's avatar
Pawel G committed
105
   * @return $this
106 107
   */
  public function disableEntityType($entity_type_id) {
108 109 110 111 112

    // Updating settings.
    $enabled_entity_types = $this->getSetting('enabled_entity_types');
    if (($key = array_search($entity_type_id, $enabled_entity_types)) !== FALSE) {
      unset ($enabled_entity_types[$key]);
113
      $this->saveSetting('enabled_entity_types', array_values($enabled_entity_types));
114 115 116 117 118 119
    }

    // Deleting inclusion settings.
    $config_names = $this->configFactory->listAll("simple_sitemap.bundle_settings.$entity_type_id");
    foreach($config_names as $config_name) {
      $this->configFactory->getEditable($config_name)->delete();
120
    }
121 122 123

    // Deleting entity overrides.
    $this->removeEntityInstanceSettings($entity_type_id);
Pawel G's avatar
Pawel G committed
124
    return $this;
125 126 127
  }

  /**
Pawel G's avatar
Pawel G committed
128
   * Sets sitemap settings for a non-bundle entity type (e.g. user) or a bundle
129 130 131
   * of an entity type (e.g. page).
   *
   * @param string $entity_type_id
Pawel G's avatar
Pawel G committed
132
   *   Entity type id like 'node' the bundle belongs to.
133
   * @param string $bundle_name
Pawel G's avatar
Pawel G committed
134
   *   Name of the bundle. NULL if entity type has no bundles.
135
   * @param array $settings
Pawel G's avatar
Pawel G committed
136 137
   *   An array of sitemap settings for this bundle/entity type.
   *   Example: ['index' => TRUE, 'priority' => 0.5].
Pawel G's avatar
Pawel G committed
138 139
   *
   * @return $this
140 141
   */
  public function setBundleSettings($entity_type_id, $bundle_name = NULL, $settings) {
142

143
    $bundle_name = empty($bundle_name) ? $entity_type_id : $bundle_name;
144

145 146 147 148 149 150 151 152 153 154
    foreach($settings as $setting_key => $setting) {
      if ($setting_key == 'index') {
        $setting = intval($setting);
      }
      $this->configFactory
        ->getEditable("simple_sitemap.bundle_settings.$entity_type_id.$bundle_name")
        ->set($setting_key, $setting)
        ->save();
    }
    //todo: Use addLinkSettings()?
155 156

    // Delete entity overrides which are identical to new bundle setting.
157 158 159 160 161 162 163 164 165
    $sitemap_entity_types = $this->getSitemapEntityTypes();
    if (isset($sitemap_entity_types[$entity_type_id])) {
      $entity_type = $sitemap_entity_types[$entity_type_id];
      $keys = $entity_type->getKeys();
      $keys['bundle'] = $entity_type_id == 'menu_link_content' ? 'menu_name' : $keys['bundle'];

      $query = $this->entityQuery->get($entity_type_id);
      if (!$this->entityTypeIsAtomic($entity_type_id)) {
        $query->condition($keys['bundle'], $bundle_name);
166
      }
167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194
      $entity_ids = $query->execute();

      $bundle_settings = $this->configFactory
        ->get("simple_sitemap.bundle_settings.$entity_type_id.$bundle_name");

      $query = $this->db->select('simple_sitemap_entity_overrides', 'o')
        ->fields('o', ['id', 'inclusion_settings'])
        ->condition('o.entity_type', $entity_type_id);
      if (!empty($entity_ids)) {
        $query->condition('o.entity_id', $entity_ids, 'IN');
      }
      $results = $query->execute()
        ->fetchAll();

      foreach($results as $result) {
        $delete = TRUE;
        $instance_settings = unserialize($result->inclusion_settings);
        foreach ($instance_settings as $setting_key => $instance_setting) {
          if ($instance_setting != $bundle_settings->get($setting_key)) {
            $delete = FALSE;
            break;
          }
        }
        if ($delete) {
          $this->db->delete('simple_sitemap_entity_overrides')
            ->condition('id', $result->id)
            ->execute();
        }
195 196
      }
    }
197 198 199
    else {
      //todo: log error
    }
Pawel G's avatar
Pawel G committed
200
    return $this;
201 202
  }

203
  /**
204 205
   * Gets sitemap settings for an entity bundle, a non-bundle entity type or for
   * all entity types and their bundles.
206
   *
207 208 209
   * @param string|null $entity_type_id
   *  If set to null, sitemap settings for all entity types and their bundles
   *  are fetched.
210 211 212
   * @param string|null $bundle_name
   *
   * @return array|false
213 214
   *  Array of sitemap settings or array of entity types with their settings.
   *  False if entity type does not exist.
215
   */
216 217 218 219 220 221 222
  public function getBundleSettings($entity_type_id = NULL, $bundle_name = NULL) {
    if (!is_null($entity_type_id)) {
      $bundle_name = empty($bundle_name) ? $entity_type_id : $bundle_name;
      $settings = $this->configFactory
        ->get("simple_sitemap.bundle_settings.$entity_type_id.$bundle_name")
        ->get();
      $bundle_settings = !empty($settings) ? $settings : FALSE;
223
    }
224 225 226 227 228 229 230 231 232 233
    else {
      $config_names = $this->configFactory->listAll("simple_sitemap.bundle_settings");
      $bundle_settings = [];
      foreach($config_names as $config_name) {
        $config_name_parts = explode('.', $config_name);
        $bundle_settings[$config_name_parts[2]][$config_name_parts[3]]
          = $this->configFactory->get($config_name)->get();
      }
    }
    return $bundle_settings;
234 235
  }

Pawel G's avatar
Pawel G committed
236 237 238
  /**
   * Overrides entity bundle/entity type sitemap settings for a single entity.
   *
Pawel G's avatar
Pawel G committed
239 240 241
   * @param string $entity_type_id
   * @param int $id
   * @param array $settings
Pawel G's avatar
Pawel G committed
242
   *
Pawel G's avatar
Pawel G committed
243 244
   * @return $this
   */
245
  public function setEntityInstanceSettings($entity_type_id, $id, $settings) {
246

247 248
    $entity = $this->entityTypeManager->getStorage($entity_type_id)->load($id);
    $bundle_name = $this->getEntityInstanceBundleName($entity);
249 250 251 252 253
    $bundle_settings = $this->configFactory
      ->get("simple_sitemap.bundle_settings.$entity_type_id.$bundle_name")
      ->get();

    if (!empty($bundle_settings)) {
254 255 256 257

      // Check if overrides are different from bundle setting before saving.
      $override = FALSE;
      foreach ($settings as $key => $setting) {
258
        if ($setting != $bundle_settings[$key]) {
259 260 261 262
          $override = TRUE;
          break;
        }
      }
Pawel G's avatar
Pawel G committed
263 264
      // Save overrides for this entity if something is different.
      if ($override) {
265 266 267 268 269 270 271 272 273 274
        $this->db->merge('simple_sitemap_entity_overrides')
          ->key([
            'entity_type' => $entity_type_id,
            'entity_id' => $id])
          ->fields([
            'entity_type' => $entity_type_id,
            'entity_id' => $id,
            'inclusion_settings' => serialize($settings),
          ])
          ->execute();
275
      }
Pawel G's avatar
Pawel G committed
276 277
      // Else unset override.
      else {
278
        $this->removeEntityInstanceSettings($entity_type_id, $id);
279
      }
280 281 282
    }
    else {
      //todo: log error
283
    }
Pawel G's avatar
Pawel G committed
284
    return $this;
285 286
  }

Pawel G's avatar
Pawel G committed
287
  /**
288 289
   * Gets sitemap settings for an entity instance which overrides the sitemap
   * settings of its bundle.
Pawel G's avatar
Pawel G committed
290
   *
Pawel G's avatar
Pawel G committed
291
   * @param string $entity_type_id
292
   * @param int $id
Pawel G's avatar
Pawel G committed
293
   *
294
   * @return array
Pawel G's avatar
Pawel G committed
295
   */
296 297 298 299 300 301 302 303 304 305 306 307 308 309 310
  public function getEntityInstanceSettings($entity_type_id, $id) {
    $results = $this->db->select('simple_sitemap_entity_overrides', 'o')
      ->fields('o', ['inclusion_settings'])
      ->condition('o.entity_type', $entity_type_id)
      ->condition('o.entity_id', $id)
      ->execute()
      ->fetchField();

    if (!empty($results)) {
      return unserialize($results);
    }
    else {
      $entity = $this->entityTypeManager->getStorage($entity_type_id)->load($id);
      $bundle_name = $this->getEntityInstanceBundleName($entity);
      return $this->getBundleSettings($entity_type_id, $bundle_name);
311 312 313
    }
  }

314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333
  /**
   * Removes sitemap settings for an entity that overrides the sitemap settings
   * of its bundle.
   *
   * @param string $entity_type_id
   * @param string|null $entity_ids
   *
   * @return $this
   */
  public function removeEntityInstanceSettings($entity_type_id, $entity_ids = NULL) {
    $query = $this->db->delete('simple_sitemap_entity_overrides')
      ->condition('entity_type', $entity_type_id);
    if (!is_null($entity_ids)) {
      $entity_ids = !is_array($entity_ids) ? [$entity_ids] : $entity_ids;
      $query->condition('entity_id', $entity_ids, 'IN');
    }
    $query->execute();
    return $this;
  }

Pawel G's avatar
Pawel G committed
334 335 336 337
  /**
   * Checks if an entity bundle (or a non-bundle entity type) is set to be
   * indexed in the sitemap settings.
   *
338 339
   * @param string $entity_type_id
   * @param string|null $bundle_name
Pawel G's avatar
Pawel G committed
340
   *
Pawel G's avatar
Pawel G committed
341 342
   * @return bool
   */
343
  public function bundleIsIndexed($entity_type_id, $bundle_name = NULL) {
344 345 346 347
    $settings = $this->getBundleSettings($entity_type_id, $bundle_name);
    return !empty($settings['index']);
  }

Pawel G's avatar
Pawel G committed
348 349 350
  /**
   * Checks if an entity type is enabled in the sitemap settings.
   *
351
   * @param string $entity_type_id
Pawel G's avatar
Pawel G committed
352
   *
Pawel G's avatar
Pawel G committed
353 354
   * @return bool
   */
355
  public function entityTypeIsEnabled($entity_type_id) {
356
    return in_array($entity_type_id, $this->getSetting('enabled_entity_types', []));
357 358
  }

Pawel G's avatar
Pawel G committed
359
  /**
360
   * Stores a custom path along with its sitemap settings to configuration.
Pawel G's avatar
Pawel G committed
361
   *
Pawel G's avatar
Pawel G committed
362 363
   * @param string $path
   * @param array $settings
Pawel G's avatar
Pawel G committed
364
   *
Pawel G's avatar
Pawel G committed
365
   * @return $this
Pawel G's avatar
Pawel G committed
366
   */
367
  public function addCustomLink($path, $settings) {
Pawel G's avatar
Pawel G committed
368 369 370 371 372 373 374 375
    if (!$this->pathValidator->isValid($path)) {
      // todo: log error.
      return $this;
    }
    if ($path[0] != '/') {
      // todo: log error.
      return $this;
    }
Pawel G's avatar
Pawel G committed
376

377
    $custom_links = $this->getCustomLinks();
Pawel G's avatar
Pawel G committed
378
    foreach ($custom_links as $key => $link) {
379 380 381 382 383 384 385
      if ($link['path'] == $path) {
        $link_key = $key;
        break;
      }
    }
    $link_key = isset($link_key) ? $link_key : count($custom_links);
    $custom_links[$link_key]['path'] = $path;
386 387
    $this->addLinkSettings('custom', $settings, $custom_links[$link_key]); //todo: dirty
    $this->configFactory->getEditable("simple_sitemap.custom")
388
      ->set('links', $custom_links)->save();
Pawel G's avatar
Pawel G committed
389
    return $this;
390 391
  }

392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420
  /**
   *
   */
  private function addLinkSettings($type, $settings, &$target) {
    foreach ($settings as $setting_key => $setting) {
      if (in_array($setting_key, self::$allowed_link_settings[$type])) {
        switch ($setting_key) {
          case 'priority':
            if (!FormHelper::isValidPriority($setting)) {
              // todo: log error.
              continue;
            }
            break;

          // todo: add index check.
        }
        $target[$setting_key] = $setting;
      }
    }
  }

  /**
   * Returns an array of custom paths and their sitemap settings.
   *
   * @return array
   */
  public function getCustomLinks() {
    $custom_links = $this->configFactory
      ->get('simple_sitemap.custom')
421
      ->get('links');
422 423 424
    return $custom_links;
  }

Pawel G's avatar
Pawel G committed
425 426 427
  /**
   * Returns settings for a custom path added to the sitemap settings.
   *
Pawel G's avatar
Pawel G committed
428
   * @param string $path
Pawel G's avatar
Pawel G committed
429
   *
Pawel G's avatar
Pawel G committed
430
   * @return array|false
Pawel G's avatar
Pawel G committed
431
   */
432
  public function getCustomLink($path) {
433
    foreach ($this->getCustomLinks() as $key => $link) {
434
      if ($link['path'] == $path) {
435
        return $link;
436 437 438 439 440
      }
    }
    return FALSE;
  }

Pawel G's avatar
Pawel G committed
441 442 443
  /**
   * Removes a custom path from the sitemap settings.
   *
Pawel G's avatar
Pawel G committed
444
   * @param string $path
Pawel G's avatar
Pawel G committed
445
   *
Pawel G's avatar
Pawel G committed
446 447
   * @return $this
   */
448
  public function removeCustomLink($path) {
449
    $custom_links = $this->getCustomLinks();
Pawel G's avatar
Pawel G committed
450
    foreach ($custom_links as $key => $link) {
451 452 453
      if ($link['path'] == $path) {
        unset($custom_links[$key]);
        $custom_links = array_values($custom_links);
454
        $this->configFactory->getEditable("simple_sitemap.custom")
455
          ->set('links', $custom_links)->save();
456
        break;
457 458
      }
    }
Pawel G's avatar
Pawel G committed
459
    return $this;
460 461
  }

Pawel G's avatar
Pawel G committed
462 463
  /**
   * Removes all custom paths from the sitemap settings.
Pawel G's avatar
Pawel G committed
464 465
   *
   * @return $this
Pawel G's avatar
Pawel G committed
466
   */
467
  public function removeCustomLinks() {
468
    $this->configFactory->getEditable("simple_sitemap.custom")
469
      ->set('links', [])->save();
Pawel G's avatar
Pawel G committed
470
    return $this;
471 472
  }

Pawel G's avatar
Pawel G committed
473
  /**
474
   * Gets an entity's bundle name.
Pawel G's avatar
Pawel G committed
475
   *
476 477
   * @param string $entity
   * @return string
Pawel G's avatar
Pawel G committed
478
   */
Pawel G's avatar
Pawel G committed
479 480
  public function getEntityInstanceBundleName($entity) {
    return $entity->getEntityTypeId() == 'menu_link_content'
Pawel G's avatar
Pawel G committed
481 482
    // Menu fix.
      ? $entity->getMenuName() : $entity->bundle();
Pawel G's avatar
Pawel G committed
483 484
  }

Pawel G's avatar
Pawel G committed
485
  /**
486 487 488
   * Gets the entity type id for a bundle.
   *
   * @param string $entity
Pawel G's avatar
Pawel G committed
489 490
   * @return string
   */
Pawel G's avatar
Pawel G committed
491 492
  public function getBundleEntityTypeId($entity) {
    return $entity->getEntityTypeId() == 'menu'
Pawel G's avatar
Pawel G committed
493 494
    // Menu fix.
      ? 'menu_link_content' : $entity->getEntityType()->getBundleOf();
Pawel G's avatar
Pawel G committed
495 496
  }

497 498 499 500
  /**
   * Returns the whole sitemap, a requested sitemap chunk,
   * or the sitemap index file.
   *
Pawel G's avatar
Pawel G committed
501
   * @param int $chunk_id
502
   *
Pawel G's avatar
Pawel G committed
503
   * @return string|false
Pawel G's avatar
Pawel G committed
504 505 506 507
   *   If no sitemap id provided, either a sitemap index is returned, or the
   *   whole sitemap, if the amount of links does not exceed the max links
   *   setting. If a sitemap id is provided, a sitemap chunk is returned. False
   *   if sitemap is not retrievable from the database.
508
   */
Pawel G's avatar
Pawel G committed
509 510
  public function getSitemap($chunk_id = NULL) {
    $chunks = $this->fetchSitemapChunks();
Pawel G's avatar
Pawel G committed
511
    if (null === $chunk_id || !isset($chunks[$chunk_id])) {
512 513

      // Return sitemap index, if there are multiple sitemap chunks.
Pawel G's avatar
Pawel G committed
514 515
      if (count($chunks) > 1) {
        return $this->getSitemapIndex($chunks);
516
      }
Pawel G's avatar
Pawel G committed
517 518
      // Return sitemap if there is only one chunk.
      else {
Pawel G's avatar
Pawel G committed
519 520
        if (isset($chunks[1])) {
          return $chunks[1]->sitemap_string;
521 522
        }
        return FALSE;
523 524
      }
    }
Pawel G's avatar
Pawel G committed
525 526
    // Return specific sitemap chunk.
    else {
Pawel G's avatar
Pawel G committed
527
      return $chunks[$chunk_id]->sitemap_string;
528
    }
529 530
  }

531 532
  /**
   * Generates the sitemap for all languages and saves it to the db.
533 534
   *
   * @param string $from
Pawel G's avatar
Pawel G committed
535 536
   *   Can be 'form', 'cron', 'drush' or 'nobatch'.
   *   This decides how the batch process is to be run.
537
   */
538
  public function generateSitemap($from = 'form') {
539 540 541 542
    $this->sitemapGenerator
      ->setGenerator($this)
      ->setGenerateFrom($from)
      ->startGeneration();
543 544
  }

545
  /**
546 547
   * Generates and returns the sitemap index as string.
   *
Pawel G's avatar
Pawel G committed
548
   * @param array $chunks
Pawel G's avatar
Pawel G committed
549
   *   Sitemap chunks which to generate the index from.
550
   *
551
   * @return string
Pawel G's avatar
Pawel G committed
552
   *   The sitemap index.
553
   */
Pawel G's avatar
Pawel G committed
554
  private function getSitemapIndex($chunks) {
555 556
    return $this->sitemapGenerator
      ->setGenerator($this)
Pawel G's avatar
Pawel G committed
557
      ->generateSitemapIndex($chunks);
Pawel G's avatar
Pawel G committed
558 559
  }

560
  /**
561 562
   * Returns a specific sitemap setting or a default value if setting does not
   * exist.
563 564
   *
   * @param string $name
Pawel G's avatar
Pawel G committed
565
   *   Name of the setting, like 'max_links'.
566
   *
567
   * @param mixed $default
Pawel G's avatar
Pawel G committed
568
   *   Value to be returned if the setting does not exist in the configuration.
569
   *
570
   * @return mixed
571
   *   The current setting from configuration or a default value.
572
   */
573
  public function getSetting($name, $default = FALSE) {
574 575 576 577
    $setting = $this->configFactory
      ->get('simple_sitemap.settings')
      ->get($name);
    return !is_null($setting) ? $setting : $default;
578
  }
579

580
  /**
581
   * Stores a specific sitemap setting in configuration.
582
   *
Pawel G's avatar
Pawel G committed
583
   * @param string $name
Pawel G's avatar
Pawel G committed
584
   *   Setting name, like 'max_links'.
Pawel G's avatar
Pawel G committed
585
   * @param mixed $setting
Pawel G's avatar
Pawel G committed
586
   *   The setting to be saved.
Pawel G's avatar
Pawel G committed
587 588
   *
   * @return $this
589
   */
590
  public function saveSetting($name, $setting) {
591 592
    $this->configFactory->getEditable("simple_sitemap.settings")
      ->set($name, $setting)->save();
Pawel G's avatar
Pawel G committed
593
    return $this;
594
  }
595

Pawel G's avatar
Pawel G committed
596 597
  /**
   * Returns a 'time ago' string of last timestamp generation.
598
   *
Pawel G's avatar
Pawel G committed
599
   * @return string|false
Pawel G's avatar
Pawel G committed
600
   *   Formatted timestamp of last sitemap generation, otherwise FALSE.
Pawel G's avatar
Pawel G committed
601
   */
602
  public function getGeneratedAgo() {
603
    $chunks = $this->fetchSitemapChunks();
Pawel G's avatar
Pawel G committed
604
    if (isset($chunks[1]->sitemap_created)) {
605
      return $this->dateFormatter
Pawel G's avatar
Pawel G committed
606
        ->formatInterval($this->time->getRequestTime() - $chunks[1]->sitemap_created);
607 608 609
    }
    return FALSE;
  }
Pawel G's avatar
Pawel G committed
610

611
  /**
612
   * Returns objects of entity types that can be indexed.
613 614
   *
   * @return array
Pawel G's avatar
Pawel G committed
615
   *   Objects of entity types that can be indexed by the sitemap.
616
   */
617 618
  public function getSitemapEntityTypes() {
    $entity_types = $this->entityTypeManager->getDefinitions();
619 620

    foreach ($entity_types as $entity_type_id => $entity_type) {
621 622 623
      if (!$entity_type instanceof ContentEntityTypeInterface
        || !method_exists($entity_type, 'getBundleEntityType')
        || !$entity_type->hasLinkTemplate('canonical')) {
624 625 626 627 628
        unset($entity_types[$entity_type_id]);
      }
    }
    return $entity_types;
  }
629

Pawel G's avatar
Pawel G committed
630
  /**
631 632 633
   * Checks whether an entity type does not provide bundles.
   *
   * @param string $entity_type_id
Pawel G's avatar
Pawel G committed
634 635
   * @return bool
   */
636
  public function entityTypeIsAtomic($entity_type_id) {
Pawel G's avatar
Pawel G committed
637 638
    // Menu fix.
    if ($entity_type_id == 'menu_link_content') {
639
      return FALSE;
Pawel G's avatar
Pawel G committed
640
    }
641

642
    $sitemap_entity_types = $this->getSitemapEntityTypes();
643 644 645 646 647 648
    if (isset($sitemap_entity_types[$entity_type_id])) {
      $entity_type = $sitemap_entity_types[$entity_type_id];
      if (empty($entity_type->getBundleEntityType())) {
        return TRUE;
      }
    }
Pawel G's avatar
Pawel G committed
649 650
    // todo: throw exception.
    return FALSE;
651
  }
Pawel G's avatar
Pawel G committed
652

653
}