Simplesitemap.php 18.5 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;
10

11
/**
Pawel G's avatar
Pawel G committed
12 13
 * Class Simplesitemap.
 *
Pawel G's avatar
Pawel G committed
14
 * @package Drupal\simple_sitemap
15 16 17
 */
class Simplesitemap {

18
  private $sitemapGenerator;
19 20
  private $configFactory;
  private $db;
21
  private $entityQuery;
22
  private $entityTypeManager;
23
  private $pathValidator;
24 25
  private static $allowed_link_settings = [
    'entity' => ['index', 'priority'],
Pawel G's avatar
Pawel G committed
26
    'custom' => ['priority'],
27
  ];
28

29 30
  /**
   * Simplesitemap constructor.
Pawel G's avatar
Pawel G committed
31
   *
32
   * @param $sitemapGenerator
33
   * @param $configFactoryInterface
34
   * @param $database
35
   * @param $entityQuery
36
   * @param $entityTypeManager
37 38
   * @param $pathValidator
   * @param $dateFormatter
39
   */
40
  public function __construct(
Pawel G's avatar
Pawel G committed
41
    SitemapGenerator $sitemapGenerator,
42
    $configFactoryInterface,
Pawel G's avatar
Pawel G committed
43
    Connection $database,
44
    $entityQuery,
Pawel G's avatar
Pawel G committed
45 46
    EntityTypeManagerInterface $entityTypeManager,
    PathValidator $pathValidator,
47
    $dateFormatter
48 49
  ) {
    $this->sitemapGenerator = $sitemapGenerator;
50 51
    $this->configFactory = $configFactoryInterface;
    $this->db = $database;
52
    $this->entityQuery = $entityQuery;
53
    $this->entityTypeManager = $entityTypeManager;
54
    $this->pathValidator = $pathValidator;
55
    $this->dateFormatter = $dateFormatter;
56 57
  }

58
  /**
59
   * Fetches all sitemap chunks indexed by chunk ID.
Pawel G's avatar
Pawel G committed
60
   *
61
   * @return string
Pawel G's avatar
Pawel G committed
62
   */
Pawel G's avatar
Pawel G committed
63
  private function fetchSitemapChunks() {
64
    return $this->db
65 66 67 68
      ->query("SELECT * FROM {simple_sitemap}")
      ->fetchAllAssoc('id');
  }

69 70
  /**
   * Enables sitemap support for an entity type. Enabled entity types show
71 72
   * sitemap settings on their bundle setting forms. If an enabled entity type
   * features bundles (e.g. 'node'), it needs to be set up with
73 74 75
   * setBundleSettings() as well.
   *
   * @param string $entity_type_id
Pawel G's avatar
Pawel G committed
76
   *   Entity type id like 'node'.
77
   *
Pawel G's avatar
Pawel G committed
78
   * @return $this
79 80
   */
  public function enableEntityType($entity_type_id) {
81 82 83 84
    $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);
85
    }
Pawel G's avatar
Pawel G committed
86
    return $this;
87 88 89 90 91 92 93 94
  }

  /**
   * 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
95
   *  Entity type id like 'node'.
96
   *
Pawel G's avatar
Pawel G committed
97
   * @return $this
98 99
   */
  public function disableEntityType($entity_type_id) {
100 101 102 103 104

    // 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]);
105
      $this->saveSetting('enabled_entity_types', array_values($enabled_entity_types));
106 107 108 109 110 111
    }

    // 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();
112
    }
113 114 115

    // Deleting entity overrides.
    $this->removeEntityInstanceSettings($entity_type_id);
Pawel G's avatar
Pawel G committed
116
    return $this;
117 118 119
  }

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

135
    $bundle_name = empty($bundle_name) ? $entity_type_id : $bundle_name;
136

137 138 139 140 141 142 143 144 145 146
    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()?
147 148

    // Delete entity overrides which are identical to new bundle setting.
149 150 151 152 153 154 155 156 157
    $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);
158
      }
159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186
      $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();
        }
187 188
      }
    }
189 190 191
    else {
      //todo: log error
    }
Pawel G's avatar
Pawel G committed
192
    return $this;
193 194
  }

195
  /**
196 197
   * Gets sitemap settings for an entity bundle, a non-bundle entity type or for
   * all entity types and their bundles.
198
   *
199 200 201
   * @param string|null $entity_type_id
   *  If set to null, sitemap settings for all entity types and their bundles
   *  are fetched.
202 203 204
   * @param string|null $bundle_name
   *
   * @return array|false
205 206
   *  Array of sitemap settings or array of entity types with their settings.
   *  False if entity type does not exist.
207
   */
208 209 210 211 212 213 214
  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;
215
    }
216 217 218 219 220 221 222 223 224 225
    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;
226 227
  }

Pawel G's avatar
Pawel G committed
228 229 230
  /**
   * Overrides entity bundle/entity type sitemap settings for a single entity.
   *
Pawel G's avatar
Pawel G committed
231 232 233
   * @param string $entity_type_id
   * @param int $id
   * @param array $settings
Pawel G's avatar
Pawel G committed
234
   *
Pawel G's avatar
Pawel G committed
235 236
   * @return $this
   */
237
  public function setEntityInstanceSettings($entity_type_id, $id, $settings) {
238

239 240
    $entity = $this->entityTypeManager->getStorage($entity_type_id)->load($id);
    $bundle_name = $this->getEntityInstanceBundleName($entity);
241 242 243 244 245
    $bundle_settings = $this->configFactory
      ->get("simple_sitemap.bundle_settings.$entity_type_id.$bundle_name")
      ->get();

    if (!empty($bundle_settings)) {
246 247 248 249

      // Check if overrides are different from bundle setting before saving.
      $override = FALSE;
      foreach ($settings as $key => $setting) {
250
        if ($setting != $bundle_settings[$key]) {
251 252 253 254
          $override = TRUE;
          break;
        }
      }
Pawel G's avatar
Pawel G committed
255 256
      // Save overrides for this entity if something is different.
      if ($override) {
257 258 259 260 261 262 263 264 265 266
        $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();
267
      }
Pawel G's avatar
Pawel G committed
268 269
      // Else unset override.
      else {
270
        $this->removeEntityInstanceSettings($entity_type_id, $id);
271
      }
272 273 274
    }
    else {
      //todo: log error
275
    }
Pawel G's avatar
Pawel G committed
276
    return $this;
277 278
  }

Pawel G's avatar
Pawel G committed
279
  /**
280 281
   * Gets sitemap settings for an entity instance which overrides the sitemap
   * settings of its bundle.
Pawel G's avatar
Pawel G committed
282
   *
Pawel G's avatar
Pawel G committed
283
   * @param string $entity_type_id
284
   * @param int $id
Pawel G's avatar
Pawel G committed
285
   *
286
   * @return array
Pawel G's avatar
Pawel G committed
287
   */
288 289 290 291 292 293 294 295 296 297 298 299 300 301 302
  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);
303 304 305
    }
  }

306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325
  /**
   * 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
326 327 328 329
  /**
   * Checks if an entity bundle (or a non-bundle entity type) is set to be
   * indexed in the sitemap settings.
   *
330 331
   * @param string $entity_type_id
   * @param string|null $bundle_name
Pawel G's avatar
Pawel G committed
332
   *
Pawel G's avatar
Pawel G committed
333 334
   * @return bool
   */
335
  public function bundleIsIndexed($entity_type_id, $bundle_name = NULL) {
336 337 338 339
    $settings = $this->getBundleSettings($entity_type_id, $bundle_name);
    return !empty($settings['index']);
  }

Pawel G's avatar
Pawel G committed
340 341 342
  /**
   * Checks if an entity type is enabled in the sitemap settings.
   *
343
   * @param string $entity_type_id
Pawel G's avatar
Pawel G committed
344
   *
Pawel G's avatar
Pawel G committed
345 346
   * @return bool
   */
347
  public function entityTypeIsEnabled($entity_type_id) {
348
    return in_array($entity_type_id, $this->getSetting('enabled_entity_types', []));
349 350
  }

Pawel G's avatar
Pawel G committed
351
  /**
352
   * Stores a custom path along with its sitemap settings to configuration.
Pawel G's avatar
Pawel G committed
353
   *
Pawel G's avatar
Pawel G committed
354 355
   * @param string $path
   * @param array $settings
Pawel G's avatar
Pawel G committed
356
   *
Pawel G's avatar
Pawel G committed
357
   * @return $this
Pawel G's avatar
Pawel G committed
358
   */
359
  public function addCustomLink($path, $settings) {
Pawel G's avatar
Pawel G committed
360 361 362 363 364 365 366 367
    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
368

369
    $custom_links = $this->getCustomLinks();
Pawel G's avatar
Pawel G committed
370
    foreach ($custom_links as $key => $link) {
371 372 373 374 375 376 377
      if ($link['path'] == $path) {
        $link_key = $key;
        break;
      }
    }
    $link_key = isset($link_key) ? $link_key : count($custom_links);
    $custom_links[$link_key]['path'] = $path;
378 379 380
    $this->addLinkSettings('custom', $settings, $custom_links[$link_key]); //todo: dirty
    $this->configFactory->getEditable("simple_sitemap.custom")
      ->setData($custom_links)->save();
Pawel G's avatar
Pawel G committed
381
    return $this;
382 383
  }

384 385 386 387 388 389 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
  /**
   *
   */
  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')
      ->get();
    unset($custom_links['_core']);
    return $custom_links;
  }

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

Pawel G's avatar
Pawel G committed
434 435 436
  /**
   * Removes a custom path from the sitemap settings.
   *
Pawel G's avatar
Pawel G committed
437
   * @param string $path
Pawel G's avatar
Pawel G committed
438
   *
Pawel G's avatar
Pawel G committed
439 440
   * @return $this
   */
441
  public function removeCustomLink($path) {
442
    $custom_links = $this->getCustomLinks();
Pawel G's avatar
Pawel G committed
443
    foreach ($custom_links as $key => $link) {
444 445 446
      if ($link['path'] == $path) {
        unset($custom_links[$key]);
        $custom_links = array_values($custom_links);
447 448 449
        $this->configFactory->getEditable("simple_sitemap.custom")
          ->setData($custom_links)->save();
        break;
450 451
      }
    }
Pawel G's avatar
Pawel G committed
452
    return $this;
453 454
  }

Pawel G's avatar
Pawel G committed
455 456
  /**
   * Removes all custom paths from the sitemap settings.
Pawel G's avatar
Pawel G committed
457 458
   *
   * @return $this
Pawel G's avatar
Pawel G committed
459
   */
460
  public function removeCustomLinks() {
461 462
    $this->configFactory->getEditable("simple_sitemap.custom")
      ->setData([])->save();
Pawel G's avatar
Pawel G committed
463
    return $this;
464 465
  }

Pawel G's avatar
Pawel G committed
466
  /**
467
   * Gets an entity's bundle name.
Pawel G's avatar
Pawel G committed
468
   *
469 470
   * @param string $entity
   * @return string
Pawel G's avatar
Pawel G committed
471
   */
Pawel G's avatar
Pawel G committed
472 473
  public function getEntityInstanceBundleName($entity) {
    return $entity->getEntityTypeId() == 'menu_link_content'
Pawel G's avatar
Pawel G committed
474 475
    // Menu fix.
      ? $entity->getMenuName() : $entity->bundle();
Pawel G's avatar
Pawel G committed
476 477
  }

Pawel G's avatar
Pawel G committed
478
  /**
479 480 481
   * Gets the entity type id for a bundle.
   *
   * @param string $entity
Pawel G's avatar
Pawel G committed
482 483
   * @return string
   */
Pawel G's avatar
Pawel G committed
484 485
  public function getBundleEntityTypeId($entity) {
    return $entity->getEntityTypeId() == 'menu'
Pawel G's avatar
Pawel G committed
486 487
    // Menu fix.
      ? 'menu_link_content' : $entity->getEntityType()->getBundleOf();
Pawel G's avatar
Pawel G committed
488 489
  }

490 491 492 493
  /**
   * Returns the whole sitemap, a requested sitemap chunk,
   * or the sitemap index file.
   *
Pawel G's avatar
Pawel G committed
494
   * @param int $chunk_id
495
   *
Pawel G's avatar
Pawel G committed
496
   * @return string|false
Pawel G's avatar
Pawel G committed
497 498 499 500
   *   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.
501
   */
Pawel G's avatar
Pawel G committed
502 503 504
  public function getSitemap($chunk_id = NULL) {
    $chunks = $this->fetchSitemapChunks();
    if (is_null($chunk_id) || !isset($chunks[$chunk_id])) {
505 506

      // Return sitemap index, if there are multiple sitemap chunks.
Pawel G's avatar
Pawel G committed
507 508
      if (count($chunks) > 1) {
        return $this->getSitemapIndex($chunks);
509
      }
Pawel G's avatar
Pawel G committed
510 511
      // Return sitemap if there is only one chunk.
      else {
Pawel G's avatar
Pawel G committed
512 513
        if (isset($chunks[1])) {
          return $chunks[1]->sitemap_string;
514 515
        }
        return FALSE;
516 517
      }
    }
Pawel G's avatar
Pawel G committed
518 519
    // Return specific sitemap chunk.
    else {
Pawel G's avatar
Pawel G committed
520
      return $chunks[$chunk_id]->sitemap_string;
521
    }
522 523
  }

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

538
  /**
539 540
   * Generates and returns the sitemap index as string.
   *
Pawel G's avatar
Pawel G committed
541
   * @param array $chunks
Pawel G's avatar
Pawel G committed
542
   *   Sitemap chunks which to generate the index from.
543
   *
544
   * @return string
Pawel G's avatar
Pawel G committed
545
   *   The sitemap index.
546
   */
Pawel G's avatar
Pawel G committed
547
  private function getSitemapIndex($chunks) {
548 549
    return $this->sitemapGenerator
      ->setGenerator($this)
Pawel G's avatar
Pawel G committed
550
      ->generateSitemapIndex($chunks);
Pawel G's avatar
Pawel G committed
551 552
  }

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

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

Pawel G's avatar
Pawel G committed
589 590
  /**
   * Returns a 'time ago' string of last timestamp generation.
591
   *
Pawel G's avatar
Pawel G committed
592
   * @return string|false
Pawel G's avatar
Pawel G committed
593
   *   Formatted timestamp of last sitemap generation, otherwise FALSE.
Pawel G's avatar
Pawel G committed
594
   */
595
  public function getGeneratedAgo() {
596
    $chunks = $this->fetchSitemapChunks();
Pawel G's avatar
Pawel G committed
597
    if (isset($chunks[1]->sitemap_created)) {
598
      return $this->dateFormatter
Pawel G's avatar
Pawel G committed
599
        ->formatInterval(REQUEST_TIME - $chunks[1]->sitemap_created);
600 601 602
    }
    return FALSE;
  }
Pawel G's avatar
Pawel G committed
603

604
  /**
605
   * Returns objects of entity types that can be indexed.
606 607
   *
   * @return array
Pawel G's avatar
Pawel G committed
608
   *   Objects of entity types that can be indexed by the sitemap.
609
   */
610 611
  public function getSitemapEntityTypes() {
    $entity_types = $this->entityTypeManager->getDefinitions();
612 613

    foreach ($entity_types as $entity_type_id => $entity_type) {
614 615 616
      if (!$entity_type instanceof ContentEntityTypeInterface
        || !method_exists($entity_type, 'getBundleEntityType')
        || !$entity_type->hasLinkTemplate('canonical')) {
617 618 619 620 621
        unset($entity_types[$entity_type_id]);
      }
    }
    return $entity_types;
  }
622

Pawel G's avatar
Pawel G committed
623
  /**
624 625 626
   * Checks whether an entity type does not provide bundles.
   *
   * @param string $entity_type_id
Pawel G's avatar
Pawel G committed
627 628
   * @return bool
   */
629
  public function entityTypeIsAtomic($entity_type_id) {
Pawel G's avatar
Pawel G committed
630 631
    // Menu fix.
    if ($entity_type_id == 'menu_link_content') {
632
      return FALSE;
Pawel G's avatar
Pawel G committed
633
    }
634

635
    $sitemap_entity_types = $this->getSitemapEntityTypes();
636 637 638 639 640 641
    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
642 643
    // todo: throw exception.
    return FALSE;
644
  }
Pawel G's avatar
Pawel G committed
645

646
}