View source
<?php
namespace Drupal\simple_sitemap;
use Drupal\Core\Database\Connection;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Lock\LockBackendInterface;
use Drupal\simple_sitemap\Queue\QueueWorker;
use Drupal\Core\Path\PathValidator;
use Drupal\Core\Config\ConfigFactory;
use Drupal\Core\Datetime\DateFormatter;
use Drupal\Component\Datetime\Time;
use Drupal\simple_sitemap\Plugin\simple_sitemap\SitemapGenerator\SitemapGeneratorBase;
class Simplesitemap {
protected $entityHelper;
protected $settings;
protected $manager;
protected $configFactory;
protected $db;
protected $entityTypeManager;
protected $pathValidator;
protected $dateFormatter;
protected $time;
protected $queueWorker;
protected $variants;
protected $lock;
protected $logger;
protected static $allowedLinkSettings = [
'entity' => [
'index',
'priority',
'changefreq',
'include_images',
],
'custom' => [
'priority',
'changefreq',
],
];
protected static $linkSettingDefaults = [
'index' => FALSE,
'priority' => '0.5',
'changefreq' => '',
'include_images' => FALSE,
];
public function __construct(EntityHelper $entity_helper, SimplesitemapSettings $settings, SimplesitemapManager $manager, ConfigFactory $config_factory, Connection $database, EntityTypeManagerInterface $entity_type_manager, PathValidator $path_validator, DateFormatter $date_formatter, Time $time, QueueWorker $queue_worker, LockBackendInterface $lock = NULL, Logger $logger = NULL) {
$this->entityHelper = $entity_helper;
$this->settings = $settings;
$this->manager = $manager;
$this->configFactory = $config_factory;
$this->db = $database;
$this->entityTypeManager = $entity_type_manager;
$this->pathValidator = $path_validator;
$this->dateFormatter = $date_formatter;
$this->time = $time;
$this->queueWorker = $queue_worker;
if ($lock === NULL) {
@trigger_error('Calling Simplesitemap::__construct() without the $lock argument is deprecated in simple_sitemap:3.9. The $lock argument will be required in simple_sitemap:3.10.', E_USER_DEPRECATED);
$lock = \Drupal::service('lock');
}
$this->lock = $lock;
if ($logger === NULL) {
@trigger_error('Calling Simplesitemap::__construct() without the $logger argument is deprecated in simple_sitemap:3.9. The $logger argument will be required in simple_sitemap:3.10.', E_USER_DEPRECATED);
$logger = \Drupal::service('simple_sitemap.logger');
}
$this->logger = $logger;
}
public function getSetting($name, $default = FALSE) {
return $this->settings
->getSetting($name, $default);
}
public function saveSetting($name, $setting) {
$this->settings
->saveSetting($name, $setting);
return $this;
}
public function getQueueWorker() {
return $this->queueWorker;
}
public function getSitemapManager() {
return $this->manager;
}
public function setVariants($variants = NULL) {
if (NULL === $variants) {
$this->variants = !empty($default_variant = $this
->getSetting('default_variant', '')) ? [
$default_variant,
] : [];
}
elseif ($variants === TRUE) {
$this->variants = array_keys($this->manager
->getSitemapVariants(NULL, FALSE));
}
else {
$this->variants = (array) $variants;
}
return $this;
}
protected function getVariants($default_get_all = TRUE) {
if (NULL === $this->variants) {
$this
->setVariants($default_get_all ? TRUE : NULL);
}
return $this->variants;
}
public function getSitemap($delta = NULL) {
$chunk_info = $this
->fetchSitemapVariantInfo();
if (empty($delta) || !isset($chunk_info[$delta])) {
if (isset($chunk_info[SitemapGeneratorBase::INDEX_DELTA])) {
return $this
->fetchSitemapChunk($chunk_info[SitemapGeneratorBase::INDEX_DELTA]->id)->sitemap_string;
}
return isset($chunk_info[SitemapGeneratorBase::FIRST_CHUNK_DELTA]) ? $this
->fetchSitemapChunk($chunk_info[SitemapGeneratorBase::FIRST_CHUNK_DELTA]->id)->sitemap_string : FALSE;
}
return $this
->fetchSitemapChunk($chunk_info[$delta]->id)->sitemap_string;
}
protected function fetchSitemapVariantInfo() {
if (!empty($this
->getVariants())) {
$result = $this->db
->select('simple_sitemap', 's')
->fields('s', [
'id',
'delta',
'sitemap_created',
'type',
])
->condition('s.status', 1)
->condition('s.type', $this
->getVariants(), 'IN')
->execute();
return count($this
->getVariants()) > 1 ? $result
->fetchAllAssoc('type') : $result
->fetchAllAssoc('delta');
}
return [];
}
protected function fetchSitemapChunk($id) {
return $this->db
->query('SELECT * FROM {simple_sitemap} WHERE id = :id', [
':id' => $id,
])
->fetchObject();
}
public function removeSitemap() {
$this->manager
->removeSitemap($this
->getVariants(FALSE));
return $this;
}
public function generateSitemap($from = QueueWorker::GENERATE_TYPE_FORM) {
if (!$this->lock
->lockMayBeAvailable(QueueWorker::LOCK_ID)) {
$this->logger
->m('Unable to acquire a lock for sitemap generation.')
->log('error')
->display('error');
return $this;
}
switch ($from) {
case QueueWorker::GENERATE_TYPE_FORM:
case QueueWorker::GENERATE_TYPE_DRUSH:
$this->queueWorker
->batchGenerateSitemap($from);
break;
case QueueWorker::GENERATE_TYPE_CRON:
case QueueWorker::GENERATE_TYPE_BACKEND:
$this->queueWorker
->generateSitemap($from);
break;
}
return $this;
}
public function queue() {
$this->queueWorker
->queue($this
->getVariants());
return $this;
}
public function rebuildQueue() {
if (!$this->lock
->lockMayBeAvailable(QueueWorker::LOCK_ID)) {
$this->logger
->m('Unable to acquire a lock for sitemap generation.')
->log('error')
->display('error');
return $this;
}
$this->queueWorker
->rebuildQueue($this
->getVariants());
return $this;
}
public function enableEntityType($entity_type_id) {
$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);
}
return $this;
}
public function disableEntityType($entity_type_id) {
$enabled_entity_types = $this
->getSetting('enabled_entity_types');
if (FALSE !== ($key = array_search($entity_type_id, $enabled_entity_types))) {
unset($enabled_entity_types[$key]);
$this
->saveSetting('enabled_entity_types', array_values($enabled_entity_types));
}
$config_names = $this->configFactory
->listAll('simple_sitemap.bundle_settings.');
foreach ($config_names as $config_name) {
$config_name_parts = explode('.', $config_name);
if ($config_name_parts[3] === $entity_type_id) {
$this->configFactory
->getEditable($config_name)
->delete();
}
}
$this
->setVariants(TRUE)
->removeEntityInstanceSettings($entity_type_id);
return $this;
}
public function setBundleSettings($entity_type_id, $bundle_name = NULL, $settings = [
'index' => TRUE,
]) {
if (empty($variants = $this
->getVariants(FALSE))) {
return $this;
}
$bundle_name = NULL !== $bundle_name ? $bundle_name : $entity_type_id;
if (!empty($old_settings = $this
->getBundleSettings($entity_type_id, $bundle_name))) {
$settings = array_merge($old_settings, $settings);
}
self::supplementDefaultSettings('entity', $settings);
if ($settings != $old_settings) {
$bundle_settings = $this->configFactory
->getEditable("simple_sitemap.bundle_settings.{$variants[0]}.{$entity_type_id}.{$bundle_name}");
foreach ($settings as $setting_key => $setting) {
$bundle_settings
->set($setting_key, $setting);
}
$bundle_settings
->save();
if (empty($entity_ids = $this->entityHelper
->getEntityInstanceIds($entity_type_id, $bundle_name))) {
return $this;
}
if (empty($settings['index'])) {
$this
->removeEntityInstanceSettings($entity_type_id, $entity_ids);
return $this;
}
$query = $this->db
->select('simple_sitemap_entity_overrides', 'o')
->fields('o', [
'id',
'inclusion_settings',
])
->condition('o.entity_type', $entity_type_id)
->condition('o.type', $variants[0]);
if (!empty($entity_ids)) {
$query
->condition('o.entity_id', $entity_ids, 'IN');
}
$delete_instances = [];
foreach ($query
->execute()
->fetchAll() as $result) {
$delete = TRUE;
$instance_settings = unserialize($result->inclusion_settings);
foreach ($instance_settings as $setting_key => $instance_setting) {
if ($instance_setting != $settings[$setting_key]) {
$delete = FALSE;
break;
}
}
if ($delete) {
$delete_instances[] = $result->id;
}
}
if (!empty($delete_instances)) {
$this->db
->delete('simple_sitemap_entity_overrides')
->condition('id', $delete_instances, 'IN')
->execute();
}
}
return $this;
}
public function getBundleSettings($entity_type_id = NULL, $bundle_name = NULL, $supplement_defaults = TRUE, $multiple_variants = FALSE) {
$bundle_name = NULL !== $bundle_name ? $bundle_name : $entity_type_id;
$all_bundle_settings = [];
foreach ($variants = $this
->getVariants(FALSE) as $variant) {
if (NULL !== $entity_type_id) {
$bundle_settings = $this->configFactory
->get("simple_sitemap.bundle_settings.{$variant}.{$entity_type_id}.{$bundle_name}")
->get();
if (empty($bundle_settings) && $supplement_defaults) {
self::supplementDefaultSettings('entity', $bundle_settings);
}
}
else {
$config_names = $this->configFactory
->listAll("simple_sitemap.bundle_settings.{$variant}.");
$bundle_settings = [];
foreach ($config_names as $config_name) {
$config_name_parts = explode('.', $config_name);
$bundle_settings[$config_name_parts[3]][$config_name_parts[4]] = $this->configFactory
->get($config_name)
->get();
}
if ($supplement_defaults) {
foreach ($this->entityHelper
->getSupportedEntityTypes() as $type_id => $type_definition) {
foreach ($this->entityHelper
->getBundleInfo($type_id) as $bundle => $bundle_definition) {
if (!isset($bundle_settings[$type_id][$bundle])) {
self::supplementDefaultSettings('entity', $bundle_settings[$type_id][$bundle]);
}
}
}
}
}
if ($multiple_variants) {
$all_bundle_settings[$variant] = $bundle_settings;
}
else {
return $bundle_settings;
}
}
return $all_bundle_settings;
}
public function removeBundleSettings($entity_type_id = NULL, $bundle_name = NULL) {
if (empty($variants = $this
->getVariants(FALSE))) {
return $this;
}
if (NULL !== $entity_type_id) {
$bundle_name = NULL !== $bundle_name ? $bundle_name : $entity_type_id;
foreach ($variants as $variant) {
$this->configFactory
->getEditable("simple_sitemap.bundle_settings.{$variant}.{$entity_type_id}.{$bundle_name}")
->delete();
}
if (!empty($entity_ids = $this->entityHelper
->getEntityInstanceIds($entity_type_id, $bundle_name))) {
$this
->removeEntityInstanceSettings($entity_type_id, $entity_ids);
}
}
else {
foreach ($variants as $variant) {
$config_names = $this->configFactory
->listAll("simple_sitemap.bundle_settings.{$variant}.");
foreach ($config_names as $config_name) {
$this->configFactory
->getEditable($config_name)
->delete();
}
}
$this
->removeEntityInstanceSettings();
}
return $this;
}
public static function supplementDefaultSettings($type, &$settings, $overrides = []) {
foreach (self::$allowedLinkSettings[$type] as $allowed_link_setting) {
if (!isset($settings[$allowed_link_setting]) && isset(self::$linkSettingDefaults[$allowed_link_setting])) {
$settings[$allowed_link_setting] = isset($overrides[$allowed_link_setting]) ? $overrides[$allowed_link_setting] : self::$linkSettingDefaults[$allowed_link_setting];
}
}
}
public function setEntityInstanceSettings($entity_type_id, $id, $settings) {
if (empty($variants = $this
->getVariants(FALSE))) {
return $this;
}
if (empty($entity = $this->entityTypeManager
->getStorage($entity_type_id)
->load($id))) {
return $this;
}
$all_bundle_settings = $this
->getBundleSettings($entity_type_id, $this->entityHelper
->getEntityInstanceBundleName($entity), TRUE, TRUE);
foreach ($all_bundle_settings as $variant => $bundle_settings) {
if (!empty($bundle_settings)) {
$override = FALSE;
foreach ($settings as $key => $setting) {
if (!isset($bundle_settings[$key]) || $setting != $bundle_settings[$key]) {
$override = TRUE;
break;
}
}
if ($override) {
$this->db
->merge('simple_sitemap_entity_overrides')
->keys([
'type' => $variant,
'entity_type' => $entity_type_id,
'entity_id' => $id,
])
->fields([
'type' => $variant,
'entity_type' => $entity_type_id,
'entity_id' => $id,
'inclusion_settings' => serialize(array_merge($bundle_settings, $settings)),
])
->execute();
}
else {
$this
->removeEntityInstanceSettings($entity_type_id, $id);
}
}
}
return $this;
}
public function getEntityInstanceSettings($entity_type_id, $id) {
if (empty($variants = $this
->getVariants(FALSE))) {
return FALSE;
}
$results = $this->db
->select('simple_sitemap_entity_overrides', 'o')
->fields('o', [
'inclusion_settings',
])
->condition('o.type', $variants[0])
->condition('o.entity_type', $entity_type_id)
->condition('o.entity_id', $id)
->execute()
->fetchField();
if (!empty($results)) {
return unserialize($results);
}
if (empty($entity = $this->entityTypeManager
->getStorage($entity_type_id)
->load($id))) {
return FALSE;
}
return $this
->getBundleSettings($entity_type_id, $this->entityHelper
->getEntityInstanceBundleName($entity));
}
public function removeEntityInstanceSettings($entity_type_id = NULL, $entity_ids = NULL) {
if (empty($variants = $this
->getVariants(FALSE))) {
return $this;
}
$query = $this->db
->delete('simple_sitemap_entity_overrides')
->condition('type', $variants, 'IN');
if (NULL !== $entity_type_id) {
$query
->condition('entity_type', $entity_type_id);
if (NULL !== $entity_ids) {
$query
->condition('entity_id', (array) $entity_ids, 'IN');
}
}
$query
->execute();
return $this;
}
public function bundleIsIndexed($entity_type_id, $bundle_name = NULL) {
foreach ($this
->getBundleSettings($entity_type_id, $bundle_name, FALSE, TRUE) as $settings) {
if (!empty($settings['index'])) {
return TRUE;
}
}
return FALSE;
}
public function entityTypeIsEnabled($entity_type_id) {
return in_array($entity_type_id, $this
->getSetting('enabled_entity_types', []));
}
public function addCustomLink($path, $settings = []) {
if (empty($variants = $this
->getVariants(FALSE))) {
return $this;
}
if (!(bool) $this->pathValidator
->getUrlIfValidWithoutAccessCheck($path)) {
return $this;
}
if ($path[0] !== '/') {
return $this;
}
$variant_links = $this
->getCustomLinks(NULL, FALSE, TRUE);
foreach ($variants as $variant) {
$links = [];
$link_key = 0;
if (isset($variant_links[$variant])) {
$links = $variant_links[$variant];
$link_key = count($links);
foreach ($links as $key => $link) {
if ($link['path'] === $path) {
$link_key = $key;
break;
}
}
}
$links[$link_key] = [
'path' => $path,
] + $settings;
$this->configFactory
->getEditable("simple_sitemap.custom_links.{$variant}")
->set('links', $links)
->save();
}
return $this;
}
public function getCustomLinks($path = NULL, $supplement_defaults = TRUE, $multiple_variants = FALSE) {
$all_custom_links = [];
foreach ($variants = $this
->getVariants(FALSE) as $variant) {
$custom_links = $this->configFactory
->get("simple_sitemap.custom_links.{$variant}")
->get('links');
$custom_links = !empty($custom_links) ? $custom_links : [];
if (!empty($custom_links) && $path !== NULL) {
foreach ($custom_links as $key => $link) {
if ($link['path'] !== $path) {
unset($custom_links[$key]);
}
}
}
if (!empty($custom_links) && $supplement_defaults) {
foreach ($custom_links as $i => $link_settings) {
self::supplementDefaultSettings('custom', $link_settings);
$custom_links[$i] = $link_settings;
}
}
$custom_links = $path !== NULL && !empty($custom_links) ? array_values($custom_links)[0] : array_values($custom_links);
if (!empty($custom_links)) {
if ($multiple_variants) {
$all_custom_links[$variant] = $custom_links;
}
else {
return $custom_links;
}
}
}
return $all_custom_links;
}
public function removeCustomLinks($paths = NULL) {
if (empty($variants = $this
->getVariants(FALSE))) {
return $this;
}
if (NULL === $paths) {
foreach ($variants as $variant) {
$this->configFactory
->getEditable("simple_sitemap.custom_links.{$variant}")
->delete();
}
}
else {
$variant_links = $this
->getCustomLinks(NULL, FALSE, TRUE);
foreach ($variant_links as $variant => $links) {
$custom_links = $links;
$save = FALSE;
foreach ((array) $paths as $path) {
foreach ($custom_links as $key => $link) {
if ($link['path'] === $path) {
unset($custom_links[$key]);
$save = TRUE;
break 2;
}
}
}
if ($save) {
$this->configFactory
->getEditable("simple_sitemap.custom_links.{$variant}")
->set('links', array_values($custom_links))
->save();
}
}
}
return $this;
}
}