namespace Drupal\simple_sitemap;
-use Drupal\simple_sitemap\Form\FormHelper;
use Drupal\Core\Database\Connection;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Path\PathValidator;
-use Drupal\Core\Entity\Query\QueryFactory;
use Drupal\Core\Config\ConfigFactory;
use Drupal\Core\Datetime\DateFormatter;
+use Drupal\Component\Datetime\Time;
+use Drupal\simple_sitemap\Plugin\simple_sitemap\UrlGenerator\UrlGeneratorManager;
/**
* Class Simplesitemap
*/
protected $db;
- /**
- * @var \Drupal\Core\Entity\Query\QueryFactory
- */
- protected $entityQuery;
-
/**
* @var \Drupal\Core\Entity\EntityTypeManagerInterface
*/
*/
protected $pathValidator;
+ /**
+ * @var \Drupal\Core\Datetime\DateFormatter
+ */
+ protected $dateFormatter;
+
+ /**
+ * @var \Drupal\Component\Datetime\Time
+ */
+ protected $time;
+
+ /**
+ * @var \Drupal\simple_sitemap\Batch
+ */
+ protected $batch;
+
+ /**
+ * @var \Drupal\Core\Extension\ModuleHandler
+ */
+ protected $moduleHandler;
+
+ /**
+ * @var \Drupal\simple_sitemap\Plugin\simple_sitemap\UrlGenerator\UrlGeneratorManager
+ */
+ protected $urlGeneratorManager;
+
/**
* @var array
*/
- protected static $allowed_link_settings = [
- 'entity' => ['index', 'priority'],
- 'custom' => ['priority'],
+ protected static $allowedLinkSettings = [
+ 'entity' => ['index', 'priority', 'changefreq', 'include_images'],
+ 'custom' => ['priority', 'changefreq'],
+ ];
+
+ /**
+ * @var array
+ */
+ protected static $linkSettingDefaults = [
+ 'index' => 1,
+ 'priority' => 0.5,
+ 'changefreq' => '',
+ 'include_images' => 0,
];
/**
* @param \Drupal\simple_sitemap\EntityHelper $entityHelper
* @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
+ * @param \Drupal\simple_sitemap\Batch $batch
+ * @param \Drupal\simple_sitemap\Plugin\simple_sitemap\UrlGenerator\UrlGeneratorManager $urlGeneratorManager
*/
public function __construct(
SitemapGenerator $sitemapGenerator,
EntityHelper $entityHelper,
ConfigFactory $configFactory,
Connection $database,
- QueryFactory $entityQuery,
EntityTypeManagerInterface $entityTypeManager,
PathValidator $pathValidator,
- DateFormatter $dateFormatter
+ DateFormatter $dateFormatter,
+ Time $time,
+ Batch $batch,
+ UrlGeneratorManager $urlGeneratorManager
) {
$this->sitemapGenerator = $sitemapGenerator;
$this->entityHelper = $entityHelper;
$this->configFactory = $configFactory;
$this->db = $database;
- $this->entityQuery = $entityQuery;
$this->entityTypeManager = $entityTypeManager;
$this->pathValidator = $pathValidator;
$this->dateFormatter = $dateFormatter;
+ $this->time = $time;
+ $this->batch = $batch;
+ $this->urlGeneratorManager = $urlGeneratorManager;
}
/**
* @return $this
*/
public function saveSetting($name, $setting) {
- $this->configFactory->getEditable("simple_sitemap.settings")
+ $this->configFactory->getEditable('simple_sitemap.settings')
->set($name, $setting)->save();
return $this;
}
*/
protected function fetchSitemapChunkInfo() {
return $this->db
- ->query("SELECT id, sitemap_created FROM {simple_sitemap}")
+ ->query('SELECT id, sitemap_created FROM {simple_sitemap}')
->fetchAllAssoc('id');
}
* @return object
* A sitemap chunk object.
*/
- private function fetchSitemapChunk($id) {
+ protected function fetchSitemapChunk($id) {
return $this->db->query('SELECT * FROM {simple_sitemap} WHERE id = :id',
[':id' => $id])->fetchObject();
}
/**
- * Generates the sitemap for all languages and saves it to the db.
+ * Generates the XML sitemap and saves it to the db.
*
* @param string $from
- * Can be 'form', 'cron', 'drush' or 'nobatch'.
+ * Can be 'form', 'backend', 'drush' or 'nobatch'.
* This decides how the batch process is to be run.
+ *
+ * @return bool|\Drupal\simple_sitemap\Simplesitemap
*/
public function generateSitemap($from = 'form') {
- $this->sitemapGenerator
- ->setGenerator($this)
- ->setGenerateFrom($from)
- ->startGeneration();
+
+ $this->batch->setBatchSettings([
+ '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,
+ ]);
+
+ $plugins = $this->urlGeneratorManager->getDefinitions();
+
+ usort($plugins, function($a, $b) {
+ return $a['weight'] - $b['weight'];
+ });
+
+ foreach ($plugins as $plugin) {
+ 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']);
+ }
+ }
+ }
+
+ $success = $this->batch->start();
+ return $from === 'nobatch' ? $this : $success;
}
/**
*
* @return string
* The sitemap index.
+ *
+ * @todo Need to make sure response is cached.
*/
protected function getSitemapIndex($chunk_info) {
return $this->sitemapGenerator
- ->setGenerator($this)
+ ->setSettings(['base_url' => $this->getSetting('base_url', '')])
->generateSitemapIndex($chunk_info);
}
$chunks = $this->fetchSitemapChunkInfo();
if (isset($chunks[SitemapGenerator::FIRST_CHUNK_INDEX]->sitemap_created)) {
return $this->dateFormatter
- ->formatInterval(REQUEST_TIME - $chunks[SitemapGenerator::FIRST_CHUNK_INDEX]
+ ->formatInterval($this->time->getRequestTime() - $chunks[SitemapGenerator::FIRST_CHUNK_INDEX]
->sitemap_created);
}
return FALSE;
* setBundleSettings() as well.
*
* @param string $entity_type_id
- * Entity type id like 'node'.
+ * Entity type id like 'node'.
*
* @return $this
*/
}
// Deleting inclusion settings.
- $config_names = $this->configFactory->listAll("simple_sitemap.bundle_settings.$entity_type_id");
- foreach($config_names as $config_name) {
+ $config_names = $this->configFactory->listAll("simple_sitemap.bundle_settings.$entity_type_id.");
+ foreach ($config_names as $config_name) {
$this->configFactory->getEditable($config_name)->delete();
}
* of an entity type (e.g. page).
*
* @param string $entity_type_id
- * Entity type id like 'node' the bundle belongs to.
+ * Entity type id like 'node' the bundle belongs to.
* @param string $bundle_name
- * Name of the bundle. NULL if entity type has no bundles.
+ * Name of the bundle. NULL if entity type has no bundles.
* @param array $settings
- * An array of sitemap settings for this bundle/entity type.
- * Example: ['index' => TRUE, 'priority' => 0.5].
+ * An array of sitemap settings for this bundle/entity type.
+ * Example: ['index' => TRUE, 'priority' => 0.5, 'changefreq' => 'never', 'include_images' => FALSE].
*
* @return $this
+ *
+ * @todo: enableEntityType automatically
*/
- public function setBundleSettings($entity_type_id, $bundle_name = NULL, $settings) {
-
+ public function setBundleSettings($entity_type_id, $bundle_name = NULL, $settings = []) {
$bundle_name = empty($bundle_name) ? $entity_type_id : $bundle_name;
- foreach($settings as $setting_key => $setting) {
- if ($setting_key == 'index') {
+ if (!empty($old_settings = $this->getBundleSettings($entity_type_id, $bundle_name))) {
+ $settings = array_merge($old_settings, $settings);
+ }
+ else {
+ self::supplementDefaultSettings('entity', $settings);
+ }
+
+ $bundle_settings = $this->configFactory
+ ->getEditable("simple_sitemap.bundle_settings.$entity_type_id.$bundle_name");
+ 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();
+ $bundle_settings->set($setting_key, $setting);
}
- //todo: Use addLinkSettings()?
+ $bundle_settings->save();
// Delete entity overrides which are identical to new bundle setting.
- $sitemap_entity_types = $this->entityHelper->getSitemapEntityTypes();
+ $sitemap_entity_types = $this->entityHelper->getSupportedEntityTypes();
if (isset($sitemap_entity_types[$entity_type_id])) {
$entity_type = $sitemap_entity_types[$entity_type_id];
$keys = $entity_type->getKeys();
// Menu fix.
- $keys['bundle'] = $entity_type_id == 'menu_link_content' ? 'menu_name' : $keys['bundle'];
+ $keys['bundle'] = $entity_type_id === 'menu_link_content' ? 'menu_name' : $keys['bundle'];
- $query = $this->entityQuery->get($entity_type_id);
+ $query = $this->entityTypeManager->getStorage($entity_type_id)->getQuery();
if (!$this->entityHelper->entityTypeIsAtomic($entity_type_id)) {
$query->condition($keys['bundle'], $bundle_name);
}
$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);
$query->condition('o.entity_id', $entity_ids, 'IN');
}
- foreach($query->execute()->fetchAll() as $result) {
+ $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 != $bundle_settings->get($setting_key)) {
+ if ($instance_setting != $settings[$setting_key]) {
$delete = FALSE;
break;
}
}
if ($delete) {
- $this->db->delete('simple_sitemap_entity_overrides')
- ->condition('id', $result->id)
- ->execute();
+ $delete_instances[] = $result->id;
}
}
+ if (!empty($delete_instances)) {
+ $this->db->delete('simple_sitemap_entity_overrides')
+ ->condition('id', $delete_instances, 'IN')
+ ->execute();
+ }
}
else {
//todo: log error
public function getBundleSettings($entity_type_id = NULL, $bundle_name = NULL) {
if (NULL !== $entity_type_id) {
$bundle_name = empty($bundle_name) ? $entity_type_id : $bundle_name;
- $settings = $this->configFactory
+ $bundle_settings = $this->configFactory
->get("simple_sitemap.bundle_settings.$entity_type_id.$bundle_name")
->get();
- $bundle_settings = !empty($settings) ? $settings : FALSE;
+ return !empty($bundle_settings) ? $bundle_settings : FALSE;
}
else {
- $config_names = $this->configFactory->listAll("simple_sitemap.bundle_settings");
- $bundle_settings = [];
- foreach($config_names as $config_name) {
+ $config_names = $this->configFactory->listAll('simple_sitemap.bundle_settings.');
+ $all_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();
+ $all_settings[$config_name_parts[2]][$config_name_parts[3]] = $this->configFactory->get($config_name)->get();
+ }
+ return $all_settings;
+ }
+ }
+
+ /**
+ * Supplements all missing link setting with default values.
+ *
+ * @param string $type
+ * 'entity'|'custom'
+ * @param array &$settings
+ * @param array $overrides
+ */
+ 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];
}
}
- return $bundle_settings;
}
/**
* @return $this
*/
public function setEntityInstanceSettings($entity_type_id, $id, $settings) {
-
$entity = $this->entityTypeManager->getStorage($entity_type_id)->load($id);
- $bundle_name = $this->entityHelper->getEntityInstanceBundleName($entity);
- $bundle_settings = $this->configFactory
- ->get("simple_sitemap.bundle_settings.$entity_type_id.$bundle_name")
- ->get();
-
+ $bundle_settings = $this->getBundleSettings(
+ $entity_type_id, $this->entityHelper->getEntityInstanceBundleName($entity)
+ );
if (!empty($bundle_settings)) {
// Check if overrides are different from bundle setting before saving.
$override = FALSE;
foreach ($settings as $key => $setting) {
- if ($setting != $bundle_settings[$key]) {
+ if (!isset($bundle_settings[$key]) || $setting != $bundle_settings[$key]) {
$override = TRUE;
break;
}
->fields([
'entity_type' => $entity_type_id,
'entity_id' => $id,
- 'inclusion_settings' => serialize($settings),
- ])
+ 'inclusion_settings' => serialize(array_merge($bundle_settings, $settings)),])
->execute();
}
// Else unset override.
* @param array $settings
*
* @return $this
+ *
+ * @todo Validate $settings and throw exceptions
*/
- public function addCustomLink($path, $settings) {
+ public function addCustomLink($path, $settings = []) {
if (!$this->pathValidator->isValid($path)) {
// todo: log error.
return $this;
}
- if ($path[0] != '/') {
+ if ($path[0] !== '/') {
// todo: log error.
return $this;
}
- $custom_links = $this->getCustomLinks();
+ $custom_links = $this->getCustomLinks(FALSE);
foreach ($custom_links as $key => $link) {
- if ($link['path'] == $path) {
+ if ($link['path'] === $path) {
$link_key = $key;
break;
}
}
$link_key = isset($link_key) ? $link_key : count($custom_links);
- $custom_links[$link_key]['path'] = $path;
- $this->addLinkSettings('custom', $settings, $custom_links[$link_key]); //todo: dirty
- $this->configFactory->getEditable("simple_sitemap.custom")
+ $custom_links[$link_key] = ['path' => $path] + $settings;
+ $this->configFactory->getEditable('simple_sitemap.custom')
->set('links', $custom_links)->save();
return $this;
}
- /**
- *
- */
- protected 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.
*
+ * @param bool $supplement_default_settings
* @return array
*/
- public function getCustomLinks() {
+ public function getCustomLinks($supplement_default_settings = TRUE) {
$custom_links = $this->configFactory
->get('simple_sitemap.custom')
->get('links');
+
+ if ($supplement_default_settings) {
+ foreach ($custom_links as $i => $link_settings) {
+ self::supplementDefaultSettings('custom', $link_settings);
+ $custom_links[$i] = $link_settings;
+ }
+ }
+
return $custom_links !== NULL ? $custom_links : [];
}
*/
public function getCustomLink($path) {
foreach ($this->getCustomLinks() as $key => $link) {
- if ($link['path'] == $path) {
+ if ($link['path'] === $path) {
return $link;
}
}
* @return $this
*/
public function removeCustomLink($path) {
- $custom_links = $this->getCustomLinks();
+ $custom_links = $this->getCustomLinks(FALSE);
foreach ($custom_links as $key => $link) {
- if ($link['path'] == $path) {
+ if ($link['path'] === $path) {
unset($custom_links[$key]);
$custom_links = array_values($custom_links);
- $this->configFactory->getEditable("simple_sitemap.custom")
+ $this->configFactory->getEditable('simple_sitemap.custom')
->set('links', $custom_links)->save();
break;
}
* @return $this
*/
public function removeCustomLinks() {
- $this->configFactory->getEditable("simple_sitemap.custom")
+ $this->configFactory->getEditable('simple_sitemap.custom')
->set('links', [])->save();
return $this;
}