Commit 3bac331a authored by Pawel G's avatar Pawel G
Browse files

Split simple_sitemap.entity_types into individual configuration objects for each bundle.

parent a4e20977
node: []
taxonomy_term: []
menu_link_content: []
......@@ -3,3 +3,7 @@ cron_generate: true
remove_duplicates: true
skip_untranslated: false
batch_process_limit: 1500
enabled_entity_types:
- 'node'
- 'taxonomy_term'
- 'menu_link_content'
......@@ -16,24 +16,25 @@ simple_sitemap.settings:
batch_process_limit:
label: 'Batch process limit'
type: integer
enabled_entity_types:
label: 'Enabled entity types'
type: sequence
sequence:
type: string
simple_sitemap.entity_types:
simple_sitemap.bundle_settings.*.*:
label: 'Entity bundle settings'
type: config_object
mapping:
type: sequence
sequence:
type: sequence
sequence:
type: mapping
mapping:
index:
label: 'Index'
type: integer
priority:
label: 'Priority'
type: string
index:
label: 'Index'
type: integer
priority:
label: 'Priority'
type: string
simple_sitemap.custom:
label: 'Custom links'
type: config_object
sequence:
type: mapping
......
......@@ -11,13 +11,10 @@
$(context).find('#edit-simple-sitemap').drupalSetSummary(function(context) {
var vals = [];
if ($(context).find('#edit-simple-sitemap-index-content-1').is(':checked')) {
// Display summary of the settings in tabs.
vals.push(Drupal.t('Included in sitemap'));
vals.push(Drupal.t('Priority') + ' ' + $('#edit-simple-sitemap-priority option:selected', context).text());
}
else {
// Display summary of the settings in tabs.
vals.push(Drupal.t('Excluded from sitemap'));
}
return vals.join('<br />');
......
......@@ -221,7 +221,7 @@ function simple_sitemap_update_8203() {
}
/**
* Remove entity type settings for entity types which do not have the canonical
* Removing entity type settings for entity types which do not have the canonical
* link template.
*/
function simple_sitemap_update_8204() {
......@@ -244,3 +244,32 @@ function simple_sitemap_update_8204() {
\Drupal::service('config.factory')->getEditable("simple_sitemap.entity_types")
->setData($entity_types)->save();
}
/**
* Splitting simple_sitemap.entity_types into individual configuration objects
* for each bundle.
*/
function simple_sitemap_update_8205() {
$entity_types = \Drupal::config('simple_sitemap.entity_types')->get();
unset($entity_types['_core']);
$enabled_entity_types = [];
foreach($entity_types as $entity_type_id => $bundles) {
$enabled_entity_types[] = $entity_type_id;
foreach($bundles as $bundle_name => $bundle_settings) {
\Drupal::service('config.factory')
->getEditable("simple_sitemap.bundle_settings.$entity_type_id.$bundle_name")
->setData($bundle_settings)->save();
}
}
// Add enabled entity type settings.
\Drupal::service('config.factory')
->getEditable('simple_sitemap.settings')
->set('enabled_entity_types', $enabled_entity_types)
->save();
// Remove old configuration object.
\Drupal::service('config.factory')
->getEditable('simple_sitemap.entity_types')
->delete();
}
......@@ -7,6 +7,7 @@
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\system\MenuInterface;
/**
* Implements hook_help.
......@@ -34,15 +35,18 @@ function simple_sitemap_form_alter(&$form, $form_state, $form_id) {
'#title' => t('Simple XML sitemap'),
'#description' => $f->entityCategory == 'instance' ? t('Settings for this entity can be overridden here.') : '',
];
// Attach some js magic to forms.
// todo: JS not working on comment entity form, hence disabling.
if ($f->entityTypeId != 'comment' || $f->entityCategory != 'instance') {
$form['#attached']['library'][] = 'simple_sitemap/form';
}
// Only attach fieldset summary js to 'additional settings' vertical tabs.
if (isset($form['additional_settings'])) {
$form['#attached']['library'][] = 'simple_sitemap/fieldsetSummaries';
}
$f->displayEntitySettings($form['simple_sitemap'])
// todo: do not show setting when creating new bundle.
->displayRegenerateNow($form['simple_sitemap']);
......@@ -107,36 +111,14 @@ function simple_sitemap_cron() {
}
}
/**
* Implements hook_entity_bundle_delete().
*
* Removes settings of the removed bundle.
*
* @todo Not working for menu bundles, as they are technically not bundles. Implement hook_menu_delete().
* @todo delete entity overrides
*/
function simple_sitemap_entity_bundle_delete($entity_type_id, $bundle) {
$generator = \Drupal::service('simple_sitemap.generator');
$entity_types = $generator->getConfig('entity_types');
if (isset($entity_types[$entity_type_id][$bundle])) {
unset($entity_types[$entity_type_id][$bundle]);
$generator->saveConfig('entity_types', $entity_types);
$message = "You may want to <a href='@url'>regenerate</a> your XML sitemap now.";
if ($generator->getSetting('cron_generate')) {
$message .= ' Otherwise the sitemap will be regenerated on the next cron run.';
}
drupal_set_message(t($message, ['@url' => $GLOBALS['base_url'] . '/admin/config/search/simplesitemap']));
}
}
/**
* Implements hook_entity_delete().
*
* Removes settings of the removed entity.
*
* @param \Drupal\Core\Entity\EntityInterface $entity
*/
function simple_sitemap_entity_delete(EntityInterface $entity) {
\Drupal::database()->delete('simple_sitemap_entity_overrides')
->condition('entity_type', $entity->getEntityTypeId())
->condition('entity_id', $entity->id())
->execute();
\Drupal::service('simple_sitemap.generator')
->removeEntityInstanceSettings($entity->getEntityTypeId(), $entity->id());
}
......@@ -6,6 +6,7 @@ services:
- '@simple_sitemap.sitemap_generator'
- '@config.factory'
- '@database'
- '@entity.query'
- '@entity_type.manager'
- '@path.validator'
- '@date.formatter'
......
......@@ -415,5 +415,4 @@ class BatchUrlGenerator {
->log('error');
}
}
}
......@@ -322,7 +322,6 @@ class FormHelper {
* @return bool
*/
public static function isValidPriority($priority) {
return !is_numeric($priority) || $priority < 0 || $priority > 1 ? FALSE : TRUE;
return is_numeric($priority) && $priority >= 0 && $priority <= 1;
}
}
......@@ -24,7 +24,7 @@ class SimplesitemapCustomLinksForm extends SimplesitemapFormBase {
public function buildForm(array $form, FormStateInterface $form_state) {
$setting_string = '';
foreach ($this->generator->getConfig('custom') as $custom_link) {
foreach ($this->generator->getCustomLinks() as $custom_link) {
$setting_string .= isset($custom_link['priority'])
? $custom_link['path'] . ' ' . $this->formHelper->formatPriority($custom_link['priority'])
: $custom_link['path'];
......
......@@ -43,12 +43,15 @@ class SimplesitemapEntitiesForm extends SimplesitemapFormBase {
$this->formHelper->processForm($form_state);
foreach ($entity_type_labels as $entity_type_id => $entity_type_label) {
$css_entity_type_id = str_replace('_', '-', $entity_type_id);
$form['simple_sitemap_entities']['entities'][$entity_type_id] = [
'#type' => 'details',
'#title' => $entity_type_label,
'#open' => $this->generator->entityTypeIsEnabled($entity_type_id),
];
$form['simple_sitemap_entities']['entities'][$entity_type_id][$entity_type_id . '_enabled'] = [
'#type' => 'checkbox',
'#title' => $this->t('Enable @entity_type_label <em>(@entity_type_id)</em> support', ['@entity_type_label' => strtolower($entity_type_label), '@entity_type_id' => $entity_type_id]),
......@@ -64,6 +67,7 @@ class SimplesitemapEntitiesForm extends SimplesitemapFormBase {
}
$form['#attached']['drupalSettings']['simple_sitemap']['all_entities'][] = $css_entity_type_id;
if ($this->generator->entityTypeIsAtomic($entity_type_id)) {
$form['simple_sitemap_entities']['entities'][$entity_type_id][$entity_type_id . '_enabled']['#description'] = $this->t('Sitemap settings for this entity type can be set below and overridden on its entity pages.');
$this->formHelper->setEntityCategory('bundle')
......@@ -73,7 +77,9 @@ class SimplesitemapEntitiesForm extends SimplesitemapFormBase {
$form['#attached']['drupalSettings']['simple_sitemap']['atomic_entities'][] = $css_entity_type_id;
}
}
$this->formHelper->displayRegenerateNow($form['simple_sitemap_entities']['entities']);
return parent::buildForm($form, $form_state);
}
......
......@@ -18,6 +18,7 @@ class Simplesitemap {
private $sitemapGenerator;
private $configFactory;
private $db;
private $entityQuery;
private $entityTypeManager;
private $pathValidator;
private static $allowed_link_settings = [
......@@ -31,6 +32,7 @@ class Simplesitemap {
* @param $sitemapGenerator
* @param $configFactoryInterface
* @param $database
* @param $entityQuery
* @param $entityTypeManager
* @param $pathValidator
* @param $dateFormatter
......@@ -39,6 +41,7 @@ class Simplesitemap {
SitemapGenerator $sitemapGenerator,
$configFactoryInterface,
Connection $database,
$entityQuery,
EntityTypeManagerInterface $entityTypeManager,
PathValidator $pathValidator,
$dateFormatter
......@@ -46,28 +49,16 @@ class Simplesitemap {
$this->sitemapGenerator = $sitemapGenerator;
$this->configFactory = $configFactoryInterface;
$this->db = $database;
$this->entityQuery = $entityQuery;
$this->entityTypeManager = $entityTypeManager;
$this->pathValidator = $pathValidator;
$this->dateFormatter = $dateFormatter;
}
/**
* Gets a specific sitemap configuration from the configuration storage.
*
* @param string $key
* Configuration key, like 'entity_types'.
*
* @return mixed
* The requested configuration.
*/
public function getConfig($key) {
$config = $this->configFactory->get("simple_sitemap.$key")->get();
unset($config['_core']);
return $config;
}
/**
* Fetches all sitemap chunks indexed by chunk ID.
*
* @return string
*/
private function fetchSitemapChunks() {
return $this->db
......@@ -75,26 +66,10 @@ class Simplesitemap {
->fetchAllAssoc('id');
}
/**
* Saves a specific sitemap configuration to db.
*
* @param string $key
* Configuration key, like 'entity_types'.
* @param mixed $value
* The configuration to be saved.
*
* @return $this
*/
public function saveConfig($key, $value) {
$this->configFactory->getEditable("simple_sitemap.$key")
->setData($value)->save();
return $this;
}
/**
* Enables sitemap support for an entity type. Enabled entity types show
* sitemap settings on their bundles. If an enabled entity type does not
* featured bundles (e.g. 'user'), it needs to be set up with
* sitemap settings on their bundle setting forms. If an enabled entity type
* features bundles (e.g. 'node'), it needs to be set up with
* setBundleSettings() as well.
*
* @param string $entity_type_id
......@@ -103,10 +78,10 @@ class Simplesitemap {
* @return $this
*/
public function enableEntityType($entity_type_id) {
$entity_types = $this->getConfig('entity_types');
if (empty($entity_types[$entity_type_id])) {
$entity_types[$entity_type_id] = [];
$this->saveConfig('entity_types', $entity_types);
$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;
}
......@@ -117,20 +92,28 @@ class Simplesitemap {
* settings from entity forms.
*
* @param string $entity_type_id
* Entity type id like 'node'.
* Entity type id like 'node'.
*
* @return $this
*/
public function disableEntityType($entity_type_id) {
$entity_types = $this->getConfig('entity_types');
if (isset($entity_types[$entity_type_id])) {
unset($entity_types[$entity_type_id]);
$this->saveConfig('entity_types', $entity_types);
// todo: test
$this->db->delete('simple_sitemap_entity_overrides')
->condition('entity_type', $entity_type_id)
->execute();
// 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]);
array_values($enabled_entity_types);
$this->saveSetting('enabled_entity_types', $enabled_entity_types);
}
// 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();
}
// Deleting entity overrides.
$this->removeEntityInstanceSettings($entity_type_id);
return $this;
}
......@@ -151,52 +134,96 @@ class Simplesitemap {
public function setBundleSettings($entity_type_id, $bundle_name = NULL, $settings) {
$bundle_name = empty($bundle_name) ? $entity_type_id : $bundle_name;
$entity_types = $this->getConfig('entity_types');
$this->addLinkSettings('entity', $settings, $entity_types[$entity_type_id][$bundle_name]);
$this->saveConfig('entity_types', $entity_types);
$results = $this->db->select('simple_sitemap_entity_overrides', 'o')
->fields('o', ['id', 'inclusion_settings'])
->condition('o.entity_type', $entity_type_id)
->execute()
->fetchAll();
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()?
// Delete entity overrides which are identical to new bundle setting.
foreach($results as $result) {
$delete = TRUE;
$instance_settings = unserialize($result->inclusion_settings);
foreach ($instance_settings as $key => $instance_setting) {
if ($instance_setting != $entity_types[$entity_type_id][$bundle_name][$key]) {
$delete = FALSE;
break;
}
$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);
}
if ($delete) {
$this->db->delete('simple_sitemap_entity_overrides')
->condition('id', $result->id)
->execute();
$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();
}
}
}
else {
//todo: log error
}
return $this;
}
/**
* Gets sitemap settings for an entity bundle or a non-bundle entity type.
* Gets sitemap settings for an entity bundle, a non-bundle entity type or for
* all entity types and their bundles.
*
* @param string $entity_type_id
* @param string|null $entity_type_id
* If set to null, sitemap settings for all entity types and their bundles
* are fetched.
* @param string|null $bundle_name
*
* @return array|false
* Array of sitemap settings or array of entity types with their settings.
* False if entity type does not exist.
*/
public function getBundleSettings($entity_type_id, $bundle_name = NULL) {
$bundle_name = empty($bundle_name) ? $entity_type_id : $bundle_name;
$entity_types = $this->getConfig('entity_types');
if (isset($entity_types[$entity_type_id][$bundle_name])) {
$settings = $entity_types[$entity_type_id][$bundle_name];
return $settings;
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;
}
return FALSE;
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;
}
/**
......@@ -209,15 +236,19 @@ class Simplesitemap {
* @return $this
*/
public function setEntityInstanceSettings($entity_type_id, $id, $settings) {
$entity_types = $this->getConfig('entity_types');
$entity = $this->entityTypeManager->getStorage($entity_type_id)->load($id);
$bundle_name = $this->getEntityInstanceBundleName($entity);
if (isset($entity_types[$entity_type_id][$bundle_name])) {
$bundle_settings = $this->configFactory
->get("simple_sitemap.bundle_settings.$entity_type_id.$bundle_name")
->get();
if (!empty($bundle_settings)) {
// Check if overrides are different from bundle setting before saving.
$override = FALSE;
foreach ($settings as $key => $setting) {
if ($setting != $entity_types[$entity_type_id][$bundle_name][$key]) {
if ($setting != $bundle_settings[$key]) {
$override = TRUE;
break;
}
......@@ -237,10 +268,7 @@ class Simplesitemap {
}
// Else unset override.
else {
$this->db->delete('simple_sitemap_entity_overrides')
->condition('entity_type', $entity_type_id)
->condition('entity_id', $id)
->execute();
$this->removeEntityInstanceSettings($entity_type_id, $id);
}
}
else {
......@@ -250,8 +278,8 @@ class Simplesitemap {
}
/**
* Gets sitemap settings for an entity instance which overrides bundle
* settings.
* Gets sitemap settings for an entity instance which overrides the sitemap
* settings of its bundle.
*
* @param string $entity_type_id
* @param int $id
......@@ -276,12 +304,32 @@ class Simplesitemap {
}
}
/**
* 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;
}
/**
* Checks if an entity bundle (or a non-bundle entity type) is set to be
* indexed in the sitemap settings.
*
* @param $entity_type_id
* @param null $bundle_name
* @param string $entity_type_id
* @param string|null $bundle_name
*
* @return bool
*/
......@@ -293,17 +341,16 @@ class Simplesitemap {
/**
* Checks if an entity type is enabled in the sitemap settings.
*
* @param $entity_type_id
* @param string $entity_type_id
*
* @return bool
*/
public function entityTypeIsEnabled($entity_type_id) {
$entity_types = $this->getConfig('entity_types');
return isset($entity_types[$entity_type_id]);
return in_array($entity_type_id, $this->getSetting('enabled_entity_types', []));
}
/**
* Adds a custom path to the sitemap settings.
* Stores a custom path along with its sitemap settings to configuration.
*
* @param string $path
* @param array $settings
......@@ -320,7 +367,7 @@ class Simplesitemap {
return $this;
}
$custom_links = $this->getConfig('custom');
$custom_links = $this->getCustomLinks();
foreach ($custom_links as $key => $link) {
if ($link['path'] == $path) {
$link_key = $key;
......@@ -329,11 +376,46 @@ class Simplesitemap {
}
$link_key = isset($link_key) ? $link_key : count($custom_links);
$custom_links[$link_key]['path'] = $path;
$this->addLinkSettings('entity', $settings, $custom_links[$link_key]);
$this->saveConfig('custom', $custom_links);
$this->addLinkSettings('custom', $settings, $custom_links[$link_key]); //todo: dirty
$this->configFactory->getEditable("simple_sitemap.custom")