...
 
Commits (6)
......@@ -704,3 +704,17 @@ function simple_sitemap_update_8301() {
]
);
}
/**
* Removing unused batch_process_limit key from simple_sitemap.settings
* configuration.
*/
function simple_sitemap_update_8302() {
$settings = \Drupal::service('config.factory')
->getEditable('simple_sitemap.settings');
if (NULL !== $settings->get('batch_process_limit')) {
$settings->clear('batch_process_limit');
$settings->save();
}
}
......@@ -195,11 +195,16 @@ function simple_sitemap_configurable_language_delete(ConfigurableLanguageInterfa
*/
function simple_sitemap_entity_delete(EntityInterface $entity) {
/** @var \Drupal\simple_sitemap\Simplesitemap $generator */
$generator = \Drupal::service('simple_sitemap.generator');
$generator->setVariants(TRUE)->removeEntityInstanceSettings(
$entity->getEntityTypeId(), $entity->id()
);
/** @var \Drupal\simple_sitemap\EntityHelper $entity_helper */
$entity_helper = \Drupal::service('simple_sitemap.entity_helper');
if ($entity_helper->supports($entity->getEntityType())) {
/** @var \Drupal\simple_sitemap\Simplesitemap $generator */
$generator = \Drupal::service('simple_sitemap.generator');
$generator->setVariants(TRUE)->removeEntityInstanceSettings(
$entity->getEntityTypeId(), $entity->id()
);
}
}
/**
......
......@@ -5,6 +5,7 @@ namespace Drupal\simple_sitemap;
use Drupal\Core\Entity\ContentEntityTypeInterface;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\EntityTypeBundleInfoInterface;
use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Database\Connection;
use Drupal\Core\Url;
......@@ -105,18 +106,24 @@ class EntityHelper {
* Objects of entity types that can be indexed by the sitemap.
*/
public function getSupportedEntityTypes() {
return array_filter($this->entityTypeManager->getDefinitions(), [$this, 'supports']);
}
/** @var \Drupal\Core\Entity\ContentEntityTypeInterface[] $entity_types */
$entity_types = $this->entityTypeManager->getDefinitions();
foreach ($entity_types as $entity_type_id => $entity_type) {
if (!$entity_type instanceof ContentEntityTypeInterface
|| !method_exists($entity_type, 'getBundleEntityType')
|| !$entity_type->hasLinkTemplate('canonical')) {
unset($entity_types[$entity_type_id]);
}
/**
* Determines if an entity type is supported or not.
*
* @return bool
* TRUE if entity type supported by Simple Sitemap, FALSE if not.
*/
public function supports(EntityTypeInterface $entity_type) {
if (!$entity_type instanceof ContentEntityTypeInterface
|| !method_exists($entity_type, 'getBundleEntityType')
|| !$entity_type->hasLinkTemplate('canonical')) {
return FALSE;
}
return $entity_types;
}
return TRUE;
}
/**
* Checks whether an entity type does not provide bundles.
......
......@@ -2,6 +2,7 @@
namespace Drupal\simple_sitemap\Form;
use Drupal\Core\Datetime\DateFormatter;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\simple_sitemap\Simplesitemap;
......@@ -25,18 +26,25 @@ class SimplesitemapSettingsForm extends SimplesitemapFormBase {
*/
protected $db;
/**
* @var \Drupal\Core\Datetime\DateFormatter
*/
protected $dateFormatter;
/**
* SimplesitemapSettingsForm constructor.
* @param \Drupal\simple_sitemap\Simplesitemap $generator
* @param \Drupal\simple_sitemap\Form\FormHelper $form_helper
* @param \Drupal\Core\Language\LanguageManager $language_manager
* @param \Drupal\Core\Database\Connection $database
* @param \Drupal\Core\Datetime\DateFormatter $date_formatter
*/
public function __construct(
Simplesitemap $generator,
FormHelper $form_helper,
LanguageManager $language_manager,
Connection $database
Connection $database,
DateFormatter $date_formatter
) {
parent::__construct(
$generator,
......@@ -44,6 +52,7 @@ class SimplesitemapSettingsForm extends SimplesitemapFormBase {
);
$this->languageManager = $language_manager;
$this->db = $database;
$this->dateFormatter = $date_formatter;
}
/**
......@@ -54,7 +63,8 @@ class SimplesitemapSettingsForm extends SimplesitemapFormBase {
$container->get('simple_sitemap.generator'),
$container->get('simple_sitemap.form_helper'),
$container->get('language_manager'),
$container->get('database')
$container->get('database'),
$container->get('date.formatter')
);
}
......@@ -134,6 +144,7 @@ class SimplesitemapSettingsForm extends SimplesitemapFormBase {
'default_variant' => $this->generator->getSetting('default_variant', NULL),
];
$sitemap_statuses = $this->fetchSitemapInstanceStatuses();
$published_timestamps = $this->fetchSitemapInstancePublishedTimestamps();
foreach ($sitemap_manager->getSitemapTypes() as $type_name => $type_definition) {
if (!empty($variants = $sitemap_manager->getSitemapVariants($type_name, FALSE))) {
$sitemap_generator = $sitemap_manager
......@@ -148,7 +159,7 @@ class SimplesitemapSettingsForm extends SimplesitemapFormBase {
];
$form['simple_sitemap_settings']['status']['types'][$type_name]['table'] = [
'#type' => 'table',
'#header' => [$this->t('Variant'), $this->t('Status'), /*$this->t('Actions')*/],
'#header' => [$this->t('Variant'), $this->t('Status')],
'#attributes' => ['class' => ['form-item', 'clearfix']],
];
foreach ($variants as $variant_name => $variant_definition) {
......@@ -163,19 +174,17 @@ class SimplesitemapSettingsForm extends SimplesitemapFormBase {
$row['status'] = $this->t('generating');
break;
case 1:
$row['status']['data']['#markup'] = $this->t('<a href="@url" target="_blank">published</a>',
['@url' => $sitemap_generator->setSitemapVariant($variant_name)->getSitemapUrl()]
$row['status']['data']['#markup'] = $this->t('<a href="@url" target="_blank">published on @time</a>',
['@url' => $sitemap_generator->setSitemapVariant($variant_name)->getSitemapUrl(), '@time' => $this->dateFormatter->format($published_timestamps[$variant_name])]
);
break;
case 2:
$row['status'] = $this->t('<a href="@url" target="_blank">published</a>, regenerating',
['@url' => $sitemap_generator->setSitemapVariant($variant_name)->getSitemapUrl()]
$row['status'] = $this->t('<a href="@url" target="_blank">published on @time</a>, regenerating',
['@url' => $sitemap_generator->setSitemapVariant($variant_name)->getSitemapUrl(), '@time' => $this->dateFormatter->format($published_timestamps[$variant_name])]
);
break;
}
}
// $row['actions'] = '';
$form['simple_sitemap_settings']['status']['types'][$type_name]['table']['#rows'][$variant_name] = $row;
unset($sitemap_statuses[$variant_name]);
}
......@@ -324,6 +333,8 @@ class SimplesitemapSettingsForm extends SimplesitemapFormBase {
* 0: Instance is unpublished
* 1: Instance is published
* 2: Instance is published but is being regenerated
*
* @todo Move to SitemapGeneratorBase or DefaultSitemapGenerator so it can be overwritten by sitemap types with custom storages.
*/
protected function fetchSitemapInstanceStatuses() {
$results = $this->db
......@@ -340,6 +351,17 @@ class SimplesitemapSettingsForm extends SimplesitemapFormBase {
return $instances;
}
/**
* @return array
*
* @todo Move to SitemapGeneratorBase or DefaultSitemapGenerator so it can be overwritten by sitemap types with custom storages.
*/
protected function fetchSitemapInstancePublishedTimestamps() {
return $this->db
->query('SELECT type, MAX(sitemap_created) FROM (SELECT sitemap_created, type FROM {simple_sitemap} WHERE status = :status) AS timestamps GROUP BY type', [':status' => 1])
->fetchAllKeyed(0, 1);
}
/**
* {@inheritdoc}
*/
......
......@@ -67,7 +67,7 @@ class SimplesitemapVariantsForm extends SimplesitemapFormBase {
$form_state->setErrorByName('', $this->t("<strong>Line @line</strong>: The variant name cannot be empty.", $placeholders));
}
if (!preg_match('/^[\w-_]+$/', $variant_name)) {
if (!preg_match('/^[\w\-_]+$/', $variant_name)) {
$form_state->setErrorByName('', $this->t("<strong>Line @line</strong>: The variant name <em>@name</em> can only include alphanumeric characters, dashes and underscores.", $placeholders));
}
......
......@@ -39,6 +39,7 @@ class DefaultSitemapGenerator extends SitemapGeneratorBase {
/**
* DefaultSitemapGenerator constructor.
*
* @param array $configuration
* @param string $plugin_id
* @param mixed $plugin_definition
......@@ -108,8 +109,18 @@ class DefaultSitemapGenerator extends SitemapGeneratorBase {
$this->writer->writeGeneratedBy();
$this->writer->startElement('urlset');
$this->addSitemapAttributes();
$this->addLinks($links);
$this->writer->endElement();
$this->writer->endDocument();
return $this->writer->outputMemory();
}
// Add attributes to document.
/**
* Adds attributes to the sitemap.
*/
protected function addSitemapAttributes() {
$attributes = self::$attributes;
if (!$this->isHreflangSitemap()) {
unset($attributes['xmlns:xhtml']);
......@@ -119,75 +130,105 @@ class DefaultSitemapGenerator extends SitemapGeneratorBase {
foreach ($attributes as $name => $value) {
$this->writer->writeAttribute($name, $value);
}
}
// Add URLs to document.
/**
* Adds URL elements to the sitemap.
*
* @param array $links
*/
protected function addLinks(array $links) {
$sitemap_variant = $this->sitemapVariant;
$this->moduleHandler->alter('simple_sitemap_links', $links, $sitemap_variant);
foreach ($links as $link) {
// Add each translation variant URL as location to the sitemap.
foreach ($links as $url_data) {
$this->writer->startElement('url');
$this->writer->writeElement('loc', $link['url']);
// If more than one language is enabled, add all translation variant URLs
// as alternate links to this location turning the sitemap into a hreflang
// sitemap.
if (isset($link['alternate_urls']) && $this->isHreflangSitemap()) {
foreach ($link['alternate_urls'] as $language_id => $alternate_url) {
$this->writer->startElement('xhtml:link');
$this->writer->writeAttribute('rel', 'alternate');
$this->writer->writeAttribute('hreflang', $language_id);
$this->writer->writeAttribute('href', $alternate_url);
$this->writer->endElement();
}
}
$this->addUrl($url_data);
$this->writer->endElement();
}
}
// Add lastmod if any.
if (isset($link['lastmod'])) {
$this->writer->writeElement('lastmod', $link['lastmod']);
}
/**
* Adds a URL element to the sitemap.
*
* @param array $url_data
* The array of properties for this URL.
*/
protected function addUrl(array $url_data) {
$this->writer->writeElement('loc', $url_data['url']);
// If more than one language is enabled, add all translation variant URLs
// as alternate links to this link turning the sitemap into a hreflang
// sitemap.
if (isset($url_data['alternate_urls']) && $this->isHreflangSitemap()) {
$this->addAlternateUrls($url_data['alternate_urls']);
}
// Add changefreq if any.
if (isset($link['changefreq'])) {
$this->writer->writeElement('changefreq', $link['changefreq']);
}
// Add lastmod if any.
if (isset($url_data['lastmod'])) {
$this->writer->writeElement('lastmod', $url_data['lastmod']);
}
// Add priority if any.
if (isset($link['priority'])) {
$this->writer->writeElement('priority', $link['priority']);
}
// Add changefreq if any.
if (isset($url_data['changefreq'])) {
$this->writer->writeElement('changefreq', $url_data['changefreq']);
}
// Add images if any.
if (!empty($link['images'])) {
foreach ($link['images'] as $image) {
$this->writer->startElement('image:image');
$this->writer->writeElement('image:loc', $image['path']);
if (strlen($image['title']) > 0) {
$this->writer->writeElement('image:title', $image['title']);
}
if (strlen($image['alt']) > 0) {
$this->writer->writeElement('image:caption', $image['alt']);
}
$this->writer->endElement();
// Add priority if any.
if (isset($url_data['priority'])) {
$this->writer->writeElement('priority', $url_data['priority']);
}
// Add images if any.
if (!empty($url_data['images'])) {
foreach ($url_data['images'] as $image) {
$this->writer->startElement('image:image');
$this->writer->writeElement('image:loc', $image['path']);
if (strlen($image['title']) > 0) {
$this->writer->writeElement('image:title', $image['title']);
}
if (strlen($image['alt']) > 0) {
$this->writer->writeElement('image:caption', $image['alt']);
}
$this->writer->endElement();
}
}
}
/**
* Adds all translation variant URLs as alternate URLs to a URL.
*
* @param array $alternate_urls
*/
protected function addAlternateUrls(array $alternate_urls) {
foreach ($alternate_urls as $language_id => $alternate_url) {
$this->writer->startElement('xhtml:link');
$this->addAlternateUrl($language_id, $alternate_url);
$this->writer->endElement();
}
$this->writer->endElement();
$this->writer->endDocument();
}
return $this->writer->outputMemory();
/**
* Adds a translation variant URL as alternate URL to a URL.
*
* @param $language_id
* @param $alternate_url
*/
protected function addAlternateUrl($language_id, $alternate_url) {
$this->writer->writeAttribute('rel', 'alternate');
$this->writer->writeAttribute('hreflang', $language_id);
$this->writer->writeAttribute('href', $alternate_url);
}
/**
* Checks if sitemap is hreflang compliant.
*
* @return bool
*/
protected function isHreflangSitemap() {
if (NULL === $this->isHreflangSitemap) {
$this->isHreflangSitemap = count(
array_diff_key($this->languageManager->getLanguages(),
$this->settings['excluded_languages'])
array_diff_key($this->languageManager->getLanguages(),
$this->settings['excluded_languages'])
) > 1;
}
return $this->isHreflangSitemap;
......
......@@ -215,7 +215,9 @@ abstract class EntityUrlGeneratorBase extends UrlGeneratorBase {
if ($field->getType() === 'image') {
foreach ($entity->get($field->getName())->getValue() as $value) {
$image_data[] = [
'path' => file_create_url(File::load($value['target_id'])->getFileUri()),
'path' => $this->replaceBaseUrlWithCustom(
file_create_url(File::load($value['target_id'])->getFileUri())
),
'alt' => $value['alt'],
'title' => $value['title'],
] ;
......