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

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

Pawel G's avatar
Pawel G committed
5 6 7
use Drupal\Core\Database\Connection;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Path\PathValidator;
Pawel G's avatar
Pawel G committed
8 9
use Drupal\Core\Config\ConfigFactory;
use Drupal\Core\Datetime\DateFormatter;
10
use Drupal\Component\Datetime\Time;
11
use Drupal\simple_sitemap\Plugin\simple_sitemap\UrlGenerator\UrlGeneratorManager;
12

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

Pawel G's avatar
Pawel G committed
19 20 21
  /**
   * @var \Drupal\simple_sitemap\SitemapGenerator
   */
22
  protected $sitemapGenerator;
Pawel G's avatar
Pawel G committed
23 24 25 26

  /**
   * @var \Drupal\simple_sitemap\EntityHelper
   */
27
  protected $entityHelper;
Pawel G's avatar
Pawel G committed
28 29 30 31

  /**
   * @var \Drupal\Core\Config\ConfigFactory
   */
32
  protected $configFactory;
Pawel G's avatar
Pawel G committed
33 34 35 36

  /**
   * @var \Drupal\Core\Database\Connection
   */
37
  protected $db;
Pawel G's avatar
Pawel G committed
38 39 40 41

  /**
   * @var \Drupal\Core\Entity\EntityTypeManagerInterface
   */
42
  protected $entityTypeManager;
Pawel G's avatar
Pawel G committed
43 44 45 46

  /**
   * @var \Drupal\Core\Path\PathValidator
   */
47
  protected $pathValidator;
Pawel G's avatar
Pawel G committed
48

49 50 51 52 53
  /**
   * @var \Drupal\Core\Datetime\DateFormatter
   */
  protected $dateFormatter;

54 55 56 57 58
  /**
   * @var \Drupal\Component\Datetime\Time
   */
  protected $time;

59
  /**
60
   * @var \Drupal\simple_sitemap\Batch
61 62 63 64 65 66 67 68
   */
  protected $batch;

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

69 70 71 72 73
  /**
   * @var \Drupal\simple_sitemap\Plugin\simple_sitemap\UrlGenerator\UrlGeneratorManager
   */
  protected $urlGeneratorManager;

Pawel G's avatar
Pawel G committed
74 75 76
  /**
   * @var array
   */
Pawel G's avatar
Pawel G committed
77
  protected static $allowedLinkSettings = [
78
    'entity' => ['index', 'priority', 'changefreq', 'include_images'],
79 80 81
    'custom' => ['priority', 'changefreq'],
  ];

Pawel G's avatar
Pawel G committed
82 83 84 85
  /**
   * @var array
   */
  protected static $linkSettingDefaults = [
86
    'index' => 1,
87
    'priority' => 0.5,
88
    'changefreq' => '',
89
    'include_images' => 0,
90
  ];
91

92 93
  /**
   * Simplesitemap constructor.
Pawel G's avatar
Pawel G committed
94
   * @param \Drupal\simple_sitemap\SitemapGenerator $sitemapGenerator
95
   * @param \Drupal\simple_sitemap\EntityHelper $entityHelper
Pawel G's avatar
Pawel G committed
96 97 98 99 100
   * @param \Drupal\Core\Config\ConfigFactory $configFactory
   * @param \Drupal\Core\Database\Connection $database
   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entityTypeManager
   * @param \Drupal\Core\Path\PathValidator $pathValidator
   * @param \Drupal\Core\Datetime\DateFormatter $dateFormatter
101
   * @param \Drupal\Component\Datetime\Time $time
102 103
   * @param \Drupal\simple_sitemap\Batch $batch
   * @param \Drupal\simple_sitemap\Plugin\simple_sitemap\UrlGenerator\UrlGeneratorManager $urlGeneratorManager
104
   */
105
  public function __construct(
Pawel G's avatar
Pawel G committed
106
    SitemapGenerator $sitemapGenerator,
107
    EntityHelper $entityHelper,
Pawel G's avatar
Pawel G committed
108
    ConfigFactory $configFactory,
Pawel G's avatar
Pawel G committed
109 110 111
    Connection $database,
    EntityTypeManagerInterface $entityTypeManager,
    PathValidator $pathValidator,
112
    DateFormatter $dateFormatter,
113 114
    Time $time,
    Batch $batch,
115
    UrlGeneratorManager $urlGeneratorManager
116 117
  ) {
    $this->sitemapGenerator = $sitemapGenerator;
118
    $this->entityHelper = $entityHelper;
Pawel G's avatar
Pawel G committed
119
    $this->configFactory = $configFactory;
120 121
    $this->db = $database;
    $this->entityTypeManager = $entityTypeManager;
122
    $this->pathValidator = $pathValidator;
123
    $this->dateFormatter = $dateFormatter;
124
    $this->time = $time;
125
    $this->batch = $batch;
126
    $this->urlGeneratorManager = $urlGeneratorManager;
127 128
  }

129
  /**
130 131
   * Returns a specific sitemap setting or a default value if setting does not
   * exist.
Pawel G's avatar
Pawel G committed
132
   *
133 134 135 136 137 138 139 140
   * @param string $name
   *   Name of the setting, like 'max_links'.
   *
   * @param mixed $default
   *   Value to be returned if the setting does not exist in the configuration.
   *
   * @return mixed
   *   The current setting from configuration or a default value.
Pawel G's avatar
Pawel G committed
141
   */
142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159
  public function getSetting($name, $default = FALSE) {
    $setting = $this->configFactory
      ->get('simple_sitemap.settings')
      ->get($name);
    return NULL !== $setting ? $setting : $default;
  }

  /**
   * Stores a specific sitemap setting in configuration.
   *
   * @param string $name
   *   Setting name, like 'max_links'.
   * @param mixed $setting
   *   The setting to be saved.
   *
   * @return $this
   */
  public function saveSetting($name, $setting) {
Pawel G's avatar
Pawel G committed
160
    $this->configFactory->getEditable('simple_sitemap.settings')
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 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207
      ->set($name, $setting)->save();
    return $this;
  }

  /**
   * Returns the whole sitemap, a requested sitemap chunk,
   * or the sitemap index file.
   *
   * @param int $chunk_id
   *
   * @return string|false
   *   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.
   */
  public function getSitemap($chunk_id = NULL) {
    $chunk_info = $this->fetchSitemapChunkInfo();

    if (NULL === $chunk_id || !isset($chunk_info[$chunk_id])) {

      if (count($chunk_info) > 1) {
        // Return sitemap index, if there are multiple sitemap chunks.
        return $this->getSitemapIndex($chunk_info);
      }
      else {
        // Return sitemap if there is only one chunk.
        return count($chunk_info) === 1
        && isset($chunk_info[SitemapGenerator::FIRST_CHUNK_INDEX])
          ? $this->fetchSitemapChunk(SitemapGenerator::FIRST_CHUNK_INDEX)
            ->sitemap_string
          : FALSE;
      }
    }
    else {
      // Return specific sitemap chunk.
      return $this->fetchSitemapChunk($chunk_id)->sitemap_string;
    }
  }

  /**
   * Fetches all sitemap chunk timestamps keyed by chunk ID.
   *
   * @return array
   *   An array containing chunk creation timestamps keyed by chunk ID.
   */
  protected function fetchSitemapChunkInfo() {
208
    return $this->db
Pawel G's avatar
Pawel G committed
209
      ->query('SELECT id, sitemap_created FROM {simple_sitemap}')
210 211 212
      ->fetchAllAssoc('id');
  }

213 214 215 216 217 218 219 220 221
  /**
   * Fetches a single sitemap chunk by ID.
   *
   * @param int $id
   *   The chunk ID.
   *
   * @return object
   *   A sitemap chunk object.
   */
222
  protected function fetchSitemapChunk($id) {
223 224 225 226 227
    return $this->db->query('SELECT * FROM {simple_sitemap} WHERE id = :id',
      [':id' => $id])->fetchObject();
  }

  /**
Pawel G's avatar
Pawel G committed
228
   * Generates the XML sitemap and saves it to the db.
229 230
   *
   * @param string $from
Pawel G's avatar
Pawel G committed
231
   *   Can be 'form', 'backend', 'drush' or 'nobatch'.
232
   *   This decides how the batch process is to be run.
Pawel G's avatar
Pawel G committed
233 234
   *
   * @return bool|\Drupal\simple_sitemap\Simplesitemap
235 236
   */
  public function generateSitemap($from = 'form') {
237

Pawel G's avatar
Pawel G committed
238
    $this->batch->setBatchSettings([
239 240 241 242 243 244 245 246 247
      'base_url' => $this->getSetting('base_url', ''),
      'batch_process_limit' => $this->getSetting('batch_process_limit', NULL),
      'max_links' => $this->getSetting('max_links', 2000),
      'skip_untranslated' => $this->getSetting('skip_untranslated', FALSE),
      'remove_duplicates' => $this->getSetting('remove_duplicates', TRUE),
      'excluded_languages' => $this->getSetting('excluded_languages', []),
      'from' => $from,
    ]);

Pawel G's avatar
Pawel G committed
248 249 250 251 252 253 254
    $plugins = $this->urlGeneratorManager->getDefinitions();

    usort($plugins, function($a, $b) {
      return $a['weight'] - $b['weight'];
    });

    foreach ($plugins as $plugin) {
255 256 257 258 259 260 261 262
      if ($plugin['enabled']) {
        if (!empty($plugin['settings']['instantiate_for_each_data_set'])) {
          foreach ($this->urlGeneratorManager->createInstance($plugin['id'])->getDataSets() as $data_sets) {
            $this->batch->addOperation($plugin['id'], $data_sets);
          }
        }
        else {
          $this->batch->addOperation($plugin['id']);
263 264
        }
      }
265 266
    }

Pawel G's avatar
Pawel G committed
267 268
    $success = $this->batch->start();
    return $from === 'nobatch' ? $this : $success;
269 270 271 272 273
  }

  /**
   * Generates and returns the sitemap index as string.
   *
Pawel G's avatar
Pawel G committed
274 275
   * @param array $chunk_info
   *   Array containing chunk creation timestamps keyed by chunk ID.
276 277 278
   *
   * @return string
   *   The sitemap index.
279 280
   *
   * @todo Need to make sure response is cached.
281
   */
Pawel G's avatar
Pawel G committed
282
  protected function getSitemapIndex($chunk_info) {
283
    return $this->sitemapGenerator
Pawel G's avatar
Pawel G committed
284
      ->setSettings(['base_url' => $this->getSetting('base_url', '')])
Pawel G's avatar
Pawel G committed
285
      ->generateSitemapIndex($chunk_info);
286 287 288 289 290 291 292 293 294 295 296 297
  }

  /**
   * Returns a 'time ago' string of last timestamp generation.
   *
   * @return string|false
   *   Formatted timestamp of last sitemap generation, otherwise FALSE.
   */
  public function getGeneratedAgo() {
    $chunks = $this->fetchSitemapChunkInfo();
    if (isset($chunks[SitemapGenerator::FIRST_CHUNK_INDEX]->sitemap_created)) {
      return $this->dateFormatter
298
        ->formatInterval($this->time->getRequestTime() - $chunks[SitemapGenerator::FIRST_CHUNK_INDEX]
299 300 301 302 303
            ->sitemap_created);
    }
    return FALSE;
  }

304 305
  /**
   * Enables sitemap support for an entity type. Enabled entity types show
306 307
   * sitemap settings on their bundle setting forms. If an enabled entity type
   * features bundles (e.g. 'node'), it needs to be set up with
308 309 310
   * setBundleSettings() as well.
   *
   * @param string $entity_type_id
Pawel G's avatar
Pawel G committed
311
   *  Entity type id like 'node'.
312
   *
Pawel G's avatar
Pawel G committed
313
   * @return $this
314 315
   */
  public function enableEntityType($entity_type_id) {
316 317 318 319
    $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);
320
    }
Pawel G's avatar
Pawel G committed
321
    return $this;
322 323 324 325 326 327 328 329
  }

  /**
   * 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
330
   *  Entity type id like 'node'.
331
   *
Pawel G's avatar
Pawel G committed
332
   * @return $this
333 334
   */
  public function disableEntityType($entity_type_id) {
335 336 337

    // Updating settings.
    $enabled_entity_types = $this->getSetting('enabled_entity_types');
338
    if (FALSE !== ($key = array_search($entity_type_id, $enabled_entity_types))) {
339
      unset ($enabled_entity_types[$key]);
340
      $this->saveSetting('enabled_entity_types', array_values($enabled_entity_types));
341 342 343
    }

    // Deleting inclusion settings.
344
    $config_names = $this->configFactory->listAll("simple_sitemap.bundle_settings.$entity_type_id.");
Pawel G's avatar
Pawel G committed
345
    foreach ($config_names as $config_name) {
346
      $this->configFactory->getEditable($config_name)->delete();
347
    }
348 349 350

    // Deleting entity overrides.
    $this->removeEntityInstanceSettings($entity_type_id);
Pawel G's avatar
Pawel G committed
351
    return $this;
352 353 354
  }

  /**
Pawel G's avatar
Pawel G committed
355
   * Sets sitemap settings for a non-bundle entity type (e.g. user) or a bundle
356 357 358
   * of an entity type (e.g. page).
   *
   * @param string $entity_type_id
Pawel G's avatar
Pawel G committed
359
   *  Entity type id like 'node' the bundle belongs to.
360
   * @param string $bundle_name
Pawel G's avatar
Pawel G committed
361
   *  Name of the bundle. NULL if entity type has no bundles.
362
   * @param array $settings
Pawel G's avatar
Pawel G committed
363 364
   *  An array of sitemap settings for this bundle/entity type.
   *  Example: ['index' => TRUE, 'priority' => 0.5, 'changefreq' => 'never', 'include_images' => FALSE].
Pawel G's avatar
Pawel G committed
365 366
   *
   * @return $this
367 368
   *
   * @todo: enableEntityType automatically
369
   */
370
  public function setBundleSettings($entity_type_id, $bundle_name = NULL, $settings = []) {
371
    $bundle_name = empty($bundle_name) ? $entity_type_id : $bundle_name;
372

Pawel G's avatar
Pawel G committed
373 374 375 376 377 378
    if (!empty($old_settings = $this->getBundleSettings($entity_type_id, $bundle_name))) {
      $settings = array_merge($old_settings, $settings);
    }
    else {
      self::supplementDefaultSettings('entity', $settings);
    }
379 380 381

    $bundle_settings = $this->configFactory
      ->getEditable("simple_sitemap.bundle_settings.$entity_type_id.$bundle_name");
Pawel G's avatar
Pawel G committed
382
    foreach ($settings as $setting_key => $setting) {
383
      if ($setting_key === 'index') {
384 385
        $setting = intval($setting);
      }
386
      $bundle_settings->set($setting_key, $setting);
387
    }
388
    $bundle_settings->save();
389 390

    // Delete entity overrides which are identical to new bundle setting.
Pawel G's avatar
Pawel G committed
391
    $sitemap_entity_types = $this->entityHelper->getSupportedEntityTypes();
392 393 394
    if (isset($sitemap_entity_types[$entity_type_id])) {
      $entity_type = $sitemap_entity_types[$entity_type_id];
      $keys = $entity_type->getKeys();
395 396

      // Menu fix.
Pawel G's avatar
Pawel G committed
397
      $keys['bundle'] = $entity_type_id === 'menu_link_content' ? 'menu_name' : $keys['bundle'];
398

399
      $query = $this->entityTypeManager->getStorage($entity_type_id)->getQuery();
400
      if (!$this->entityHelper->entityTypeIsAtomic($entity_type_id)) {
401
        $query->condition($keys['bundle'], $bundle_name);
402
      }
403 404 405 406 407 408 409 410 411
      $entity_ids = $query->execute();

      $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');
      }

412
      $delete_instances = [];
Pawel G's avatar
Pawel G committed
413
      foreach ($query->execute()->fetchAll() as $result) {
414 415 416
        $delete = TRUE;
        $instance_settings = unserialize($result->inclusion_settings);
        foreach ($instance_settings as $setting_key => $instance_setting) {
417
          if ($instance_setting != $settings[$setting_key]) {
418 419 420 421 422
            $delete = FALSE;
            break;
          }
        }
        if ($delete) {
423
          $delete_instances[] = $result->id;
424
        }
425
      }
426 427 428 429 430
      if (!empty($delete_instances)) {
        $this->db->delete('simple_sitemap_entity_overrides')
          ->condition('id', $delete_instances, 'IN')
          ->execute();
      }
431
    }
432 433 434
    else {
      //todo: log error
    }
Pawel G's avatar
Pawel G committed
435
    return $this;
436 437
  }

438
  /**
439 440
   * Gets sitemap settings for an entity bundle, a non-bundle entity type or for
   * all entity types and their bundles.
441
   *
442 443 444
   * @param string|null $entity_type_id
   *  If set to null, sitemap settings for all entity types and their bundles
   *  are fetched.
445 446 447
   * @param string|null $bundle_name
   *
   * @return array|false
Pawel G's avatar
Pawel G committed
448 449
   *  Array of sitemap settings for an entity bundle, a non-bundle entity type
   *  or for all entity types and their bundles.
450
   *  False if entity type does not exist.
451
   */
452
  public function getBundleSettings($entity_type_id = NULL, $bundle_name = NULL) {
453
    if (NULL !== $entity_type_id) {
454
      $bundle_name = empty($bundle_name) ? $entity_type_id : $bundle_name;
455
      $bundle_settings = $this->configFactory
456 457
        ->get("simple_sitemap.bundle_settings.$entity_type_id.$bundle_name")
        ->get();
458
      return !empty($bundle_settings) ? $bundle_settings : FALSE;
459
    }
460
    else {
Pawel G's avatar
Pawel G committed
461
      $config_names = $this->configFactory->listAll('simple_sitemap.bundle_settings.');
462
      $all_settings = [];
Pawel G's avatar
Pawel G committed
463
      foreach ($config_names as $config_name) {
464
        $config_name_parts = explode('.', $config_name);
465
        $all_settings[$config_name_parts[2]][$config_name_parts[3]] = $this->configFactory->get($config_name)->get();
466 467 468 469 470 471
      }
      return $all_settings;
    }
  }

  /**
472 473
   * Supplements all missing link setting with default values.
   *
474
   * @param string $type
Pawel G's avatar
Pawel G committed
475 476 477
   *  'entity'|'custom'
   * @param array &$settings
   * @param array $overrides
478
   */
Pawel G's avatar
Pawel G committed
479
  public static function supplementDefaultSettings($type, &$settings, $overrides = []) {
480
    foreach (self::$allowedLinkSettings[$type] as $allowed_link_setting) {
481
      if (!isset($settings[$allowed_link_setting])
Pawel G's avatar
Pawel G committed
482
        && isset(self::$linkSettingDefaults[$allowed_link_setting])) {
483 484 485
        $settings[$allowed_link_setting] = isset($overrides[$allowed_link_setting])
          ? $overrides[$allowed_link_setting]
          : self::$linkSettingDefaults[$allowed_link_setting];
486 487
      }
    }
488 489
  }

Pawel G's avatar
Pawel G committed
490 491 492
  /**
   * Overrides entity bundle/entity type sitemap settings for a single entity.
   *
Pawel G's avatar
Pawel G committed
493 494 495
   * @param string $entity_type_id
   * @param int $id
   * @param array $settings
Pawel G's avatar
Pawel G committed
496
   *
Pawel G's avatar
Pawel G committed
497 498
   * @return $this
   */
499
  public function setEntityInstanceSettings($entity_type_id, $id, $settings) {
500
    $entity = $this->entityTypeManager->getStorage($entity_type_id)->load($id);
501 502 503
    $bundle_settings = $this->getBundleSettings(
      $entity_type_id, $this->entityHelper->getEntityInstanceBundleName($entity)
    );
504
    if (!empty($bundle_settings)) {
505 506 507 508

      // Check if overrides are different from bundle setting before saving.
      $override = FALSE;
      foreach ($settings as $key => $setting) {
509
        if (!isset($bundle_settings[$key]) || $setting != $bundle_settings[$key]) {
510 511 512 513
          $override = TRUE;
          break;
        }
      }
Pawel G's avatar
Pawel G committed
514 515
      // Save overrides for this entity if something is different.
      if ($override) {
516 517 518 519 520 521 522
        $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,
523
            'inclusion_settings' => serialize(array_merge($bundle_settings, $settings)),])
524
          ->execute();
525
      }
Pawel G's avatar
Pawel G committed
526 527
      // Else unset override.
      else {
528
        $this->removeEntityInstanceSettings($entity_type_id, $id);
529
      }
530 531 532
    }
    else {
      //todo: log error
533
    }
Pawel G's avatar
Pawel G committed
534
    return $this;
535 536
  }

Pawel G's avatar
Pawel G committed
537
  /**
538
   * Gets sitemap settings for an entity instance which overrides the sitemap
539
   * settings of its bundle, or bundle settings, if they are not overridden.
Pawel G's avatar
Pawel G committed
540
   *
Pawel G's avatar
Pawel G committed
541
   * @param string $entity_type_id
542
   * @param int $id
Pawel G's avatar
Pawel G committed
543
   *
544
   * @return array|false
Pawel G's avatar
Pawel G committed
545
   */
546 547 548 549 550 551 552 553 554
  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)) {
555
      return unserialize($results);
556 557
    }
    else {
558 559 560 561 562 563
      $entity = $this->entityTypeManager->getStorage($entity_type_id)
        ->load($id);
      return $this->getBundleSettings(
        $entity_type_id,
        $this->entityHelper->getEntityInstanceBundleName($entity)
      );
564 565 566
    }
  }

567 568 569 570 571 572 573 574 575 576 577 578
  /**
   * 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);
579
    if (NULL !== $entity_ids) {
580 581 582 583 584 585 586
      $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
587 588 589 590
  /**
   * Checks if an entity bundle (or a non-bundle entity type) is set to be
   * indexed in the sitemap settings.
   *
591 592
   * @param string $entity_type_id
   * @param string|null $bundle_name
Pawel G's avatar
Pawel G committed
593
   *
Pawel G's avatar
Pawel G committed
594 595
   * @return bool
   */
596
  public function bundleIsIndexed($entity_type_id, $bundle_name = NULL) {
597 598 599 600
    $settings = $this->getBundleSettings($entity_type_id, $bundle_name);
    return !empty($settings['index']);
  }

Pawel G's avatar
Pawel G committed
601 602 603
  /**
   * Checks if an entity type is enabled in the sitemap settings.
   *
604
   * @param string $entity_type_id
Pawel G's avatar
Pawel G committed
605
   *
Pawel G's avatar
Pawel G committed
606 607
   * @return bool
   */
608
  public function entityTypeIsEnabled($entity_type_id) {
609
    return in_array($entity_type_id, $this->getSetting('enabled_entity_types', []));
610 611
  }

Pawel G's avatar
Pawel G committed
612
  /**
613
   * Stores a custom path along with its sitemap settings to configuration.
Pawel G's avatar
Pawel G committed
614
   *
Pawel G's avatar
Pawel G committed
615 616
   * @param string $path
   * @param array $settings
Pawel G's avatar
Pawel G committed
617
   *
Pawel G's avatar
Pawel G committed
618
   * @return $this
619 620
   *
   * @todo Validate $settings and throw exceptions
Pawel G's avatar
Pawel G committed
621
   */
622
  public function addCustomLink($path, $settings = []) {
Pawel G's avatar
Pawel G committed
623 624 625 626
    if (!$this->pathValidator->isValid($path)) {
      // todo: log error.
      return $this;
    }
Pawel G's avatar
Pawel G committed
627
    if ($path[0] !== '/') {
Pawel G's avatar
Pawel G committed
628 629 630
      // todo: log error.
      return $this;
    }
Pawel G's avatar
Pawel G committed
631

632
    $custom_links = $this->getCustomLinks(FALSE);
Pawel G's avatar
Pawel G committed
633
    foreach ($custom_links as $key => $link) {
634
      if ($link['path'] === $path) {
635 636 637 638 639
        $link_key = $key;
        break;
      }
    }
    $link_key = isset($link_key) ? $link_key : count($custom_links);
640
    $custom_links[$link_key] = ['path' => $path] + $settings;
Pawel G's avatar
Pawel G committed
641
    $this->configFactory->getEditable('simple_sitemap.custom')
642
      ->set('links', $custom_links)->save();
Pawel G's avatar
Pawel G committed
643
    return $this;
644 645
  }

646 647 648
  /**
   * Returns an array of custom paths and their sitemap settings.
   *
649
   * @param bool $supplement_default_settings
650 651
   * @return array
   */
652
  public function getCustomLinks($supplement_default_settings = TRUE) {
653 654
    $custom_links = $this->configFactory
      ->get('simple_sitemap.custom')
655
      ->get('links');
656 657 658

    if ($supplement_default_settings) {
      foreach ($custom_links as $i => $link_settings) {
Pawel G's avatar
Pawel G committed
659 660
        self::supplementDefaultSettings('custom', $link_settings);
        $custom_links[$i] = $link_settings;
661 662 663
      }
    }

664
    return $custom_links !== NULL ? $custom_links : [];
665 666
  }

Pawel G's avatar
Pawel G committed
667 668 669
  /**
   * Returns settings for a custom path added to the sitemap settings.
   *
Pawel G's avatar
Pawel G committed
670
   * @param string $path
Pawel G's avatar
Pawel G committed
671
   *
Pawel G's avatar
Pawel G committed
672
   * @return array|false
Pawel G's avatar
Pawel G committed
673
   */
674
  public function getCustomLink($path) {
675
    foreach ($this->getCustomLinks() as $key => $link) {
676
      if ($link['path'] === $path) {
677
        return $link;
678 679 680 681 682
      }
    }
    return FALSE;
  }

Pawel G's avatar
Pawel G committed
683 684 685
  /**
   * Removes a custom path from the sitemap settings.
   *
Pawel G's avatar
Pawel G committed
686
   * @param string $path
Pawel G's avatar
Pawel G committed
687
   *
Pawel G's avatar
Pawel G committed
688 689
   * @return $this
   */
690
  public function removeCustomLink($path) {
691
    $custom_links = $this->getCustomLinks(FALSE);
Pawel G's avatar
Pawel G committed
692
    foreach ($custom_links as $key => $link) {
693
      if ($link['path'] === $path) {
694 695
        unset($custom_links[$key]);
        $custom_links = array_values($custom_links);
Pawel G's avatar
Pawel G committed
696
        $this->configFactory->getEditable('simple_sitemap.custom')
697
          ->set('links', $custom_links)->save();
698
        break;
699 700
      }
    }
Pawel G's avatar
Pawel G committed
701
    return $this;
702 703
  }

Pawel G's avatar
Pawel G committed
704 705
  /**
   * Removes all custom paths from the sitemap settings.
Pawel G's avatar
Pawel G committed
706 707
   *
   * @return $this
Pawel G's avatar
Pawel G committed
708
   */
709
  public function removeCustomLinks() {
Pawel G's avatar
Pawel G committed
710
    $this->configFactory->getEditable('simple_sitemap.custom')
711
      ->set('links', [])->save();
Pawel G's avatar
Pawel G committed
712
    return $this;
713
  }
714
}