Commit 74425106 authored by gbyte.co's avatar gbyte.co Committed by gbyte.co

Issue #2990905 by gbyte.co: Make sitemap types pluggable (plugins)

parent 09e0e2ec
label: 'Default hreflang'
description: 'The default hreflang sitemap type.'
sitemap_generator: 'default'
url_generators:
- 'custom'
- 'entity'
- 'entity_menu_link_content'
- 'arbitrary'
......@@ -73,25 +73,6 @@ simple_sitemap.custom:
label: 'Change frequency'
type: string
simple_sitemap.types.*:
label: 'Sitemap types'
type: config_object
mapping:
label:
label: 'Type label'
type: string
description:
label: 'Type description'
type: string
sitemap_generator:
label: 'Sitemap generator'
type: string
url_generators:
label: 'URL generators'
type: sequence
sequence:
type: string
simple_sitemap.variants.*:
label: 'Sitemap variants'
type: config_object
......
......@@ -131,25 +131,12 @@ function hook_simple_sitemap_sitemap_generators_alter(array &$sitemap_generators
}
/**
* Alter properties of and remove sitemap type plugins.
*
* @param array $sitemap_types
*/
function hook_simple_sitemap_types_alter(array &$sitemap_types) {
// Remove the custom links generator from the default sitemap type definition.
$key = array_search('custom', $sitemap_types['default_hreflang']['url_generators']);
unset($sitemap_types['default_hreflang']['url_generators'][$key]);
// Define a new sitemap type to be generated with the default sitemap generator.
// Make it use only the custom and arbitrary link generators.
$sitemap_types['fight_club_sitemap_type'] = [
'label' => t('Fight Club Sitemap'),
'description' => t('The second rule of Fight Club is...'),
'sitemap_generator' => 'default',
'url_generators' => [
'custom',
'arbitrary',
],
];
function hook_simple_sitemap_sitemap_types_alter(array &$sitemap_types) {
}
/**
......
......@@ -550,3 +550,15 @@ function simple_sitemap_update_8213() {
$config_factory->getEditable('simple_sitemap.variants')->delete();
}
/**
* Removing sitemap types from configuration as they are to be stored as plugins in code.
*/
function simple_sitemap_update_8214() {
$config_factory = \Drupal::service('config.factory');
$sitemap_types = $config_factory->listAll('simple_sitemap.types.');
// Remove sitemap type configuration objects.
foreach ($sitemap_types as $type) {
$config_factory->getEditable($type)->delete();
}
}
......@@ -15,6 +15,7 @@ services:
- '@simple_sitemap.batch'
- '@plugin.manager.simple_sitemap.url_generator'
- '@plugin.manager.simple_sitemap.sitemap_generator'
- '@plugin.manager.simple_sitemap.sitemap_type'
simple_sitemap.sitemap_writer:
class: Drupal\simple_sitemap\Plugin\simple_sitemap\SitemapGenerator\SitemapWriter
......@@ -65,3 +66,7 @@ services:
plugin.manager.simple_sitemap.sitemap_generator:
class: Drupal\simple_sitemap\Plugin\simple_sitemap\SitemapGenerator\SitemapGeneratorManager
parent: default_plugin_manager
plugin.manager.simple_sitemap.sitemap_type:
class: Drupal\simple_sitemap\Plugin\simple_sitemap\SitemapType\SitemapTypeManager
parent: default_plugin_manager
......@@ -30,7 +30,7 @@ class SitemapGenerator extends Plugin {
*
* @var \Drupal\Core\Annotation\Translation
*/
public $title;
public $label;
/**
* A short description of the generator.
......
<?php
namespace Drupal\simple_sitemap\Annotation;
use Drupal\Component\Annotation\Plugin;
/**
* Defines a SitemapType item annotation object.
*
* @package Drupal\simple_sitemap\Annotation
*
* @see \Drupal\simple_sitemap\Plugin\simple_sitemap\SitemapType\SitemapTypeManager
* @see plugin_api
*
* @Annotation
*/
class SitemapType extends Plugin {
/**
* The sitemap type ID.
*
* @var string
*/
public $id;
/**
* The human-readable name of the sitemap type.
*
* @ingroup plugin_translatable
*
* @var \Drupal\Core\Annotation\Translation
*/
public $label;
/**
* A short description of the sitemap type.
*
* @ingroup plugin_translatable
*
* @var \Drupal\Core\Annotation\Translation
*/
public $description;
/**
* The ID of the sitemap generator.
*
* @var string
*/
public $sitemapGenerator;
/**
* The IDs of the URL generators.
*
* @var[] string
*/
public $urlGenerators = [];
}
......@@ -30,7 +30,7 @@ class UrlGenerator extends Plugin {
*
* @var \Drupal\Core\Annotation\Translation
*/
public $title;
public $label;
/**
* A short description of the generator.
......
......@@ -31,7 +31,7 @@ class SimplesitemapVariantsForm extends SimplesitemapFormBase {
];
$type_descriptions = [];
$sitemap_types = $this->generator->getSitemapTypeDefinitions();
$sitemap_types = $this->generator->getSitemapTypes();
foreach ($sitemap_types as $sitemap_type => $definition) {
$type_descriptions[] = $sitemap_type . (!empty($definition['description']) ? (': ' . $definition['description']) : '');
}
......@@ -54,7 +54,7 @@ class SimplesitemapVariantsForm extends SimplesitemapFormBase {
*/
public function validateForm(array &$form, FormStateInterface $form_state) {
$line = 0;
$sitemap_types = $this->generator->getSitemapTypeDefinitions();
$sitemap_types = $this->generator->getSitemapTypes();
foreach ($this->stringToVariants($form_state->getValue('variants')) as $variant_name => $variant_definition) {
$placeholders = [
'@line' => ++$line,
......
......@@ -14,7 +14,7 @@ use Drupal\Component\Datetime\Time;
*
* @SitemapGenerator(
* id = "default",
* title = @Translation("Default sitemap generator"),
* label = @Translation("Default sitemap generator"),
* description = @Translation("Generates a standard conform hreflang sitemap of your content."),
* )
*/
......
<?php
namespace Drupal\simple_sitemap\Plugin\simple_sitemap\SitemapType;
/**
* Class DefaultHreflangSitemapType
* @package Drupal\simple_sitemap\Plugin\simple_sitemap\SitemapType
*
* @SitemapType(
* id = "default_hreflang",
* label = @Translation("Default hreflang"),
* description = @Translation("The default hreflang sitemap type."),
* sitemapGenerator = "default",
* urlGenerators = {
* "custom",
* "entity",
* "entity_menu_link_content",
* "arbitrary",
* },
* )
*/
class DefaultHreflangSitemapType extends SitemapTypeBase {
}
<?php
namespace Drupal\simple_sitemap\Plugin\simple_sitemap\SitemapType;
use Drupal\simple_sitemap\Plugin\simple_sitemap\SimplesitemapPluginBase;
/**
* Class SitemapTypeBase
* @package Drupal\simple_sitemap\Plugin\simple_sitemap\SitemapType
*/
abstract class SitemapTypeBase extends SimplesitemapPluginBase implements SitemapTypeInterface {
}
<?php
namespace Drupal\simple_sitemap\Plugin\simple_sitemap\SitemapType;
/**
* Interface SitemapTypeInterface
* @package Drupal\simple_sitemap\Plugin\simple_sitemap\SitemapType
*/
interface SitemapTypeInterface {
}
<?php
namespace Drupal\simple_sitemap\Plugin\simple_sitemap\SitemapType;
use Drupal\Core\Plugin\DefaultPluginManager;
use Drupal\Core\Cache\CacheBackendInterface;
use Drupal\Core\Extension\ModuleHandlerInterface;
/**
* Class SitemapTypeManager
* @package Drupal\simple_sitemap\Plugin\simple_sitemap\SitemapType
*/
class SitemapTypeManager extends DefaultPluginManager {
/**
* SitemapTypeManager constructor.
* @param \Traversable $namespaces
* @param \Drupal\Core\Cache\CacheBackendInterface $cache_backend
* @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
*/
public function __construct(
\Traversable $namespaces,
CacheBackendInterface $cache_backend,
ModuleHandlerInterface $module_handler
) {
parent::__construct(
'Plugin/simple_sitemap/SitemapType',
$namespaces,
$module_handler,
'Drupal\simple_sitemap\Plugin\simple_sitemap\SitemapType\SitemapTypeInterface',
'Drupal\simple_sitemap\Annotation\SitemapType'
);
$this->alterInfo('simple_sitemap_sitemap_types');
$this->setCacheBackend($cache_backend, 'simple_sitemap:sitemap_type');
}
}
......@@ -17,7 +17,7 @@ use Symfony\Component\DependencyInjection\ContainerInterface;
*
* @UrlGenerator(
* id = "arbitrary",
* title = @Translation("Arbitrary URL generator"),
* label = @Translation("Arbitrary URL generator"),
* description = @Translation("Generates URLs from data sets collected in the hook_arbitrary_links_alter hook."),
* )
*/
......
......@@ -19,7 +19,7 @@ use Symfony\Component\DependencyInjection\ContainerInterface;
*
* @UrlGenerator(
* id = "custom",
* title = @Translation("Custom URL generator"),
* label = @Translation("Custom URL generator"),
* description = @Translation("Generates URLs set in admin/config/search/simplesitemap/custom."),
* )
*
......
......@@ -20,7 +20,7 @@ use Drupal\Core\Menu\MenuLinkTreeElement;
*
* @UrlGenerator(
* id = "entity_menu_link_content",
* title = @Translation("Menu link URL generator"),
* label = @Translation("Menu link URL generator"),
* description = @Translation("Generates menu link URLs by overriding the 'entity' URL generator."),
* settings = {
* "overrides_entity_type" = "menu_link_content",
......
......@@ -17,7 +17,7 @@ use Drupal\Core\Extension\ModuleHandler;
*
* @UrlGenerator(
* id = "entity",
* title = @Translation("Entity URL generator"),
* label = @Translation("Entity URL generator"),
* description = @Translation("Generates URLs for entity bundles and bundle overrides."),
* )
*/
......@@ -106,6 +106,7 @@ class EntityUrlGenerator extends UrlGeneratorBase {
if (isset($sitemap_entity_types[$entity_type_name])) {
// Skip this entity type if another plugin is written to override its generation.
// todo needs to be adjusted for variants
foreach ($this->urlGeneratorManager->getDefinitions() as $plugin) {
if (!empty($plugin['settings']['overrides_entity_type'])
&& $plugin['settings']['overrides_entity_type'] === $entity_type_name) {
......
......@@ -12,9 +12,11 @@ use Drupal\Core\Datetime\DateFormatter;
use Drupal\Component\Datetime\Time;
use Drupal\simple_sitemap\Plugin\simple_sitemap\SitemapGenerator\DefaultSitemapGenerator;
use Drupal\simple_sitemap\Plugin\simple_sitemap\SitemapGenerator\SitemapGeneratorBase;
use Drupal\simple_sitemap\Plugin\simple_sitemap\UrlGenerator\UrlGeneratorBase;
use Drupal\simple_sitemap\Plugin\simple_sitemap\SitemapGenerator\SitemapGeneratorManager;
use Drupal\simple_sitemap\Plugin\simple_sitemap\UrlGenerator\UrlGeneratorBase;
use Drupal\simple_sitemap\Plugin\simple_sitemap\UrlGenerator\UrlGeneratorManager;
use Drupal\simple_sitemap\Plugin\simple_sitemap\SitemapType\SitemapTypeBase;
use Drupal\simple_sitemap\Plugin\simple_sitemap\SitemapType\SitemapTypeManager;
/**
* Class Simplesitemap
......@@ -86,6 +88,11 @@ class Simplesitemap {
*/
protected $sitemapGeneratorManager;
/**
* @var \Drupal\simple_sitemap\Plugin\simple_sitemap\SitemapType\SitemapTypeManager
*/
protected $sitemapTypeManager;
/**
* @var UrlGeneratorBase[] $urlGenerators
*/
......@@ -96,6 +103,11 @@ class Simplesitemap {
*/
protected $sitemapGenerators = [];
/**
* @var SitemapTypeBase[] $sitemapTypes
*/
protected $sitemapTypes = [];
/**
* @var array
*/
......@@ -128,6 +140,7 @@ class Simplesitemap {
* @param \Drupal\simple_sitemap\Batch $batch
* @param \Drupal\simple_sitemap\Plugin\simple_sitemap\UrlGenerator\UrlGeneratorManager $url_generator_manager
* @param \Drupal\simple_sitemap\Plugin\simple_sitemap\SitemapGenerator\SitemapGeneratorManager $sitemap_generator_manager
* @param \Drupal\simple_sitemap\Plugin\simple_sitemap\SitemapType\SitemapTypeManager $sitemap_type_manager
*/
public function __construct(
EntityHelper $entity_helper,
......@@ -141,7 +154,8 @@ class Simplesitemap {
ModuleHandler $module_handler,
Batch $batch,
UrlGeneratorManager $url_generator_manager,
SitemapGeneratorManager $sitemap_generator_manager
SitemapGeneratorManager $sitemap_generator_manager,
SitemapTypeManager $sitemap_type_manager
) {
$this->entityHelper = $entity_helper;
$this->configFactory = $config_factory;
......@@ -155,6 +169,7 @@ class Simplesitemap {
$this->batch = $batch;
$this->urlGeneratorManager = $url_generator_manager;
$this->sitemapGeneratorManager = $sitemap_generator_manager;
$this->sitemapTypeManager = $sitemap_type_manager;
}
/**
......@@ -221,6 +236,17 @@ class Simplesitemap {
return $this->urlGenerators[$url_generator_id];
}
/**
* @return array
*/
public function getSitemapTypes() {
if (empty($this->sitemapTypes)) {
$this->sitemapTypes = $this->sitemapTypeManager->getDefinitions();
}
return $this->sitemapTypes;
}
/**
* Returns the whole sitemap, a requested sitemap chunk,
* or the sitemap index file.
......@@ -295,80 +321,6 @@ class Simplesitemap {
[':id' => $id])->fetchObject();
}
/**
* @return array
*
* @todo document
*/
public function getSitemapTypeDefinitions() {
$type_definitions = [];
foreach ($this->configFactory->listAll('simple_sitemap.types.') as $config_name) {
$config_name_parts = explode('.', $config_name);
$type_definitions[$config_name_parts[2]] = $this->configFactory->get($config_name)->get();
}
return $type_definitions;
}
/**
* @param $name
* @param $definition
* @return $this
*
* @todo document
*/
public function setSitemapTypeDefinition($name, $definition) {
$type = $this->configFactory->getEditable("simple_sitemap.types.$name");
if (empty($type->get('label')) && empty($definition['label'])) {
$definition['label'] = $name;
}
if (empty($type->get('description')) && empty($definition['description'])) {
$definition['description'] = '';
}
if (empty($type->get('sitemap_generator')) && empty($definition['sitemap_generator'])) {
$definition['sitemap_generator'] = self::DEFAULT_SITEMAP_GENERATOR;
}
if (empty($type->get('url_generators')) && empty($definition['url_generators'])) {
//todo exception
}
foreach ($definition as $key => $value) {
if (in_array($key, ['label', 'description', 'sitemap_generator', 'url_generators'])) {
$type->set($key, $value);
}
else {
//todo: exception
}
}
$type->save();
return $this;
}
/**
* @param $type_name
* @return $this
*
* @todo document
*/
public function removeSitemapTypeDefinition($type_name) {
if ($type_name !== self::DEFAULT_SITEMAP_TYPE) {
// Remove type definition and variants from configuration.
$this->configFactory->getEditable("simple_sitemap.variants.$type_name")->delete();
$this->configFactory->getEditable("simple_sitemap.types.$type_name")->delete();
}
else {
//todo: exception
}
return $this;
}
/**
* @param null $sitemap_type
* @return array
......@@ -419,7 +371,7 @@ class Simplesitemap {
$definition['type'] = self::DEFAULT_SITEMAP_TYPE;
}
else {
$types = $this->getSitemapTypeDefinitions();
$types = $this->getSitemapTypes();
if (!isset($types[$definition['type']])) {
// todo: exception
}
......@@ -475,10 +427,10 @@ class Simplesitemap {
: $saved_variants;
if (!empty($remove_variants)) {
$type_definitions = $this->getSitemapTypeDefinitions();
$type_definitions = $this->getSitemapTypes();
$this->moduleHandler->alter('simple_sitemap_types', $type_definitions);
foreach ($remove_variants as $variant_name => $variant_definition) {
$this->getSitemapGenerator($type_definitions[$variant_definition['type']]['sitemap_generator'])
$this->getSitemapGenerator($type_definitions[$variant_definition['type']]['sitemapGenerator'])
->setSitemapVariant($variant_name)
->remove()
->invalidateCache();
......@@ -515,7 +467,7 @@ class Simplesitemap {
$operations = [];
$type_definitions = $this->getSitemapTypeDefinitions();
$type_definitions = $this->getSitemapTypes();
$this->moduleHandler->alter('simple_sitemap_types', $type_definitions);
$sitemap_variants = $this->getSitemapVariants();
......@@ -534,13 +486,13 @@ class Simplesitemap {
$operations[] = [
'operation' => 'removeSitemap',
'arguments' => [
'sitemap_generator' => $type_definitions[$type]['sitemap_generator'],
'sitemap_generator' => $type_definitions[$type]['sitemapGenerator'],
'variant' => $variant_name,
]
];
// Adding generate_sitemap operations for all data sets.
foreach ($type_definitions[$type]['url_generators'] as $url_generator_id) {
foreach ($type_definitions[$type]['urlGenerators'] as $url_generator_id) {
foreach ($this->getUrlGenerator($url_generator_id)
->setSitemapVariant($variant_name)
......@@ -552,7 +504,7 @@ class Simplesitemap {
'url_generator' => $url_generator_id,
'data_set' => $data_set,
'variant' => $variant_name,
'sitemap_generator' => $type_definitions[$type]['sitemap_generator'],
'sitemap_generator' => $type_definitions[$type]['sitemapGenerator'],
'settings' => $settings,
],
];
......@@ -564,7 +516,7 @@ class Simplesitemap {
$operations[] = [
'operation' => 'generateIndex',
'arguments' => [
'sitemap_generator' => $type_definitions[$type]['sitemap_generator'],
'sitemap_generator' => $type_definitions[$type]['sitemapGenerator'],
'variant' => $variant_name,
'settings' => $settings,
],
......
......@@ -233,15 +233,16 @@ class SimplesitemapTest extends SimplesitemapTestBase {
$this->assertSession()->responseContains('sitemap.xml?page=1');
$this->assertSession()->responseContains('sitemap.xml?page=2');
$this->drupalGet('sitemap.xml?page=1');
$this->assertSession()->responseContains('node/' . $this->node->id());
$this->assertSession()->responseContains('0.5');
$this->assertSession()->responseNotContains('node/' . $this->node2->id());
$this->drupalGet('sitemap.xml?page=2');
$this->assertSession()->responseContains('node/' . $this->node2->id());
$this->assertSession()->responseContains('0.5');
$this->assertSession()->responseNotContains('node/' . $this->node->id());
//todo parameter part for drupalGet
// $this->drupalGet('sitemap.xml?page=1');
// $this->assertSession()->responseContains('node/' . $this->node->id());
// $this->assertSession()->responseContains('0.5');
// $this->assertSession()->responseNotContains('node/' . $this->node2->id());
//
// $this->drupalGet('sitemap.xml?page=2');
// $this->assertSession()->responseContains('node/' . $this->node2->id());
// $this->assertSession()->responseContains('0.5');
// $this->assertSession()->responseNotContains('node/' . $this->node->id());
}
/**
......@@ -481,46 +482,6 @@ class SimplesitemapTest extends SimplesitemapTestBase {
// Test if sitemap has been removed along with the variant.
$this->drupalGet('test/sitemap.xml');
// $this->assertSession()->responseNotContains('urlset'); //todo
// Test adding a variant of new sitemap type.
$this->generator->removeSitemap()
->setSitemapTypeDefinition('test_type', [
'label' => 'Test type',
'description' => 'Test description.',
'sitemap_generator' => 'default',
'url_generators' => ['custom'],
])
->addSitemapVariant('test2', ['type' => 'test_type']);
$types = $this->generator->getSitemapTypeDefinitions();
$this->assertTrue(isset($types['test_type']));
$this->generator->generateSitemap('nobatch', 'test2');
// Test if default variant has been successfully excluded.
$this->drupalGet($this->defaultSitemapUrl);
// $this->assertSession()->responseNotContains('urlset'); //todo
// Test if custom generator has been successfully included.
$this->drupalGet('test2/sitemap.xml');
$this->assertSession()->responseContains(Url::fromRoute('<front>')->setAbsolute()->toString());
// Test if entity generator has been successfully excluded.
$this->assertSession()->responseNotContains('node/' . $this->node->id());
// Test removing sitemap type.
$this->generator->removeSitemapTypeDefinition('test_type');
$types = $this->generator->getSitemapTypeDefinitions();
$this->assertFalse(isset($types['test_type']));
// Test if variants have been removed along with the sitemap type.
$variants = $this->generator->getSitemapVariants();
$this->assertFalse(isset($variants['test2']));
$this->generator->generateSitemap('nobatch');
// Test if sitemap has been removed along with the sitemap type.
// $this->assertFalse($this->generator->getSitemap('test2')); //todo
}
/**
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment