Unverified Commit 7d359e91 authored by Dave Reid's avatar Dave Reid Committed by Dave Reid

Issue #2941164 by Dave Reid, WidgetsBurritos: Added support for using...

Issue #2941164 by Dave Reid, WidgetsBurritos: Added support for using rel="alternate" rather than multiple sitemaps by language context.
parent dd04a284
......@@ -4,9 +4,8 @@ namespace Drupal\xmlsitemap\Form;
use Drupal\Core\Entity\EntityForm;
use Drupal\Core\Entity\EntityStorageException;
use Drupal\Core\Language\LanguageInterface;
use Drupal\Core\Render\Element;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Language\LanguageInterface;
/**
* Provides a form for creating and editing xmlsitemap entities.
......@@ -35,14 +34,14 @@ class XmlSitemapForm extends EntityForm {
'#title' => $this->t('Label'),
'#maxlength' => 255,
'#default_value' => $xmlsitemap->label(),
'#description' => $this->t('Label for the Example.'),
'#description' => $this->t('Label for the XML sitemap.'),
'#required' => TRUE,
];
$form['context'] = [
'#tree' => TRUE,
];
$visible_children = Element::getVisibleChildren($form['context']);
if (empty($visible_children)) {
if (!xmlsitemap_get_context_info()) {
$form['context']['empty'] = [
'#type' => 'markup',
'#markup' => '<p>' . $this->t('There are currently no XML sitemap contexts available.') . '</p>',
......
......@@ -92,13 +92,6 @@ class XmlSitemapListBuilderTest extends XmlSitemapTestBase {
$this->drupalPostForm('admin/config/search/xmlsitemap/add', $edit, t('Save'));
$this->assertText(t('There is another sitemap saved with the same context.'));
$edit = [
'label' => 'Undefined',
'context[language]' => 'und',
];
$this->drupalPostForm('admin/config/search/xmlsitemap/add', $edit, t('Save'));
$this->assertText(t('There is another sitemap saved with the same context.'));
$sitemaps = XmlSitemap::loadMultiple();
foreach ($sitemaps as $sitemap) {
$label = $sitemap->label();
......
......@@ -278,7 +278,7 @@ class XmlSitemapGenerator implements XmlSitemapGeneratorInterface {
$query = $this->connection->select('xmlsitemap', 'x');
$query->fields('x', [
'loc', 'type', 'subtype', 'lastmod', 'changefreq', 'changecount', 'priority', 'language', 'access', 'status',
'loc', 'type', 'subtype', 'id', 'lastmod', 'changefreq', 'changecount', 'priority', 'language', 'access', 'status',
]);
$query->condition('x.access', 1);
$query->condition('x.status', 1);
......@@ -293,6 +293,9 @@ class XmlSitemapGenerator implements XmlSitemapGeneratorInterface {
$links = $query->execute();
while ($link = $links->fetchAssoc()) {
// Preserve the language code for hook_xmlsitemap_element_alter().
$link['langcode'] = $link['language'];
$link['language'] = $link['language'] != LanguageInterface::LANGCODE_NOT_SPECIFIED ? xmlsitemap_language_load($link['language']) : $url_options['language'];
$link_options = [
'language' => $link['language'],
......
......@@ -93,6 +93,17 @@ class XmlSitemapStorage extends ConfigEntityStorage {
// Load the entity URI.
$entity->uri = xmlsitemap_sitemap_uri($entity);
// Load in the default contexts if they haven't been set yet.
$contexts = xmlsitemap_get_context_info();
foreach ($contexts as $context_key => $context) {
if (!isset($entity->context[$context_key]) && isset($context['default'])) {
$entity->context[$context_key] = $context['default'];
}
}
// Remove invalid contexts.
$entity->context = array_intersect_key($entity->context, $contexts);
}
return $entities;
......
......@@ -147,6 +147,8 @@ class XmlSitemapWriter extends \XMLWriter {
*/
public function getRootAttributes() {
$attributes['xmlns'] = 'http://www.sitemaps.org/schemas/sitemap/0.9';
// @todo Should content_moderation implement hook_xmlsitemap_root_attributes_alter() instead?
$attributes['xmlns:xhtml'] = 'http://www.w3.org/1999/xhtml';
if (\Drupal::state()->get('xmlsitemap_developer_mode')) {
$attributes['xmlns:xsi'] = 'http://www.w3.org/2001/XMLSchema-instance';
$attributes['xsi:schemaLocation'] = 'http://www.sitemaps.org/schemas/sitemap/0.9';
......
......@@ -10,6 +10,7 @@
* Main file for the xmlsitemap module.
*/
use Drupal\Component\Plugin\Exception\PluginNotFoundException;
use Drupal\Component\Utility\Crypt;
use Drupal\Component\Utility\Environment;
use Drupal\Component\Utility\UrlHelper;
......@@ -1662,40 +1663,31 @@ function xmlsitemap_entity_translation_delete(EntityInterface $translation) {
}
/**
* Implements hook_xmlsitemap_context_info().
* Implements hook_xmlsitemap_context_info() for language module.
*/
function xmlsitemap_xmlsitemap_context_info() {
if (!\Drupal::moduleHandler()->moduleExists('language')) {
return [];
}
function language_xmlsitemap_context_info() {
$context['language'] = [
'label' => t('Language'),
'summary callback' => 'language_name',
'default' => \Drupal::languageManager()->getDefaultLanguage(),
'default' => \Drupal::languageManager()->getDefaultLanguage()->getId(),
];
return $context;
}
/**
* Implements hook_xmlsitemap_context().
* Implements hook_xmlsitemap_context() for language module.
*/
function xmlsitemap_xmlsitemap_context() {
if (!\Drupal::moduleHandler()->moduleExists('language')) {
return [];
}
function language_xmlsitemap_context() {
$language = \Drupal::languageManager()->getCurrentLanguage();
$context['language'] = $language->getId();
return $context;
}
/**
* Implements hook_xmlsitemap_context_url_options().
* Implements hook_xmlsitemap_context_url_options() for language module.
*/
function xmlsitemap_xmlsitemap_context_url_options(array $context) {
function language_xmlsitemap_context_url_options(array $context) {
$options = [];
if (!\Drupal::moduleHandler()->moduleExists('language')) {
return $options;
}
if (isset($context['language'])) {
$options['language'] = xmlsitemap_language_load($context['language']);
}
......@@ -1703,24 +1695,21 @@ function xmlsitemap_xmlsitemap_context_url_options(array $context) {
}
/**
* Implements hook_form_FORM_ID_alter().
* Implements hook_form_FORM_ID_alter() for language module.
*/
function xmlsitemap_form_xmlsitemap_sitemap_edit_form_alter(&$form, FormStateInterface $form_state) {
if (!\Drupal::moduleHandler()->moduleExists('language')) {
return;
}
function language_form_xmlsitemap_sitemap_edit_form_alter(&$form, FormStateInterface $form_state) {
$options = [];
$languages = \Drupal::languageManager()->getLanguages();
foreach ($languages as $language_key => $language) {
$options[$language_key] = $language->getName();
}
$options[LanguageInterface::LANGCODE_NOT_SPECIFIED] = t('Undefined language');
$form['context']['language'] = [
'#type' => 'select',
'#title' => t('Language'),
'#options' => $options,
'#default_value' => isset($form['#entity']->context['language']) ? $form['#entity']->context['language'] : LanguageInterface::LANGCODE_NOT_SPECIFIED,
'#default_value' => isset($form['#entity']->context['language']) ? $form['#entity']->context['language'] : \Drupal::languageManager()->getDefaultLanguage()->getId(),
'#description' => t('Most sites should only need a sitemap for their default language since translated content is now added to the sitemap using alternate links. If you truly need a sitemap for multiple languages, it is still possible to do so.'),
];
}
......@@ -1730,36 +1719,25 @@ function xmlsitemap_form_xmlsitemap_sitemap_edit_form_alter(&$form, FormStateInt
* Set the regeneration needed flag if settings are changed.
*/
function xmlsitemap_form_language_admin_overview_form_alter(&$form, FormStateInterface $form_state) {
if (!\Drupal::moduleHandler()->moduleExists('language')) {
return;
}
array_unshift($form['#submit'], 'xmlsitemap_form_submit_flag_regenerate');
}
/**
* Implements hook_query_TAG_alter().
*
* @see i18n_db_rewrite_where()
* Implements hook_query_TAG_alter() for language module.
*/
function xmlsitemap_query_xmlsitemap_generate_alter(AlterableInterface $query) {
if (!\Drupal::moduleHandler()->moduleExists('language')) {
return;
}
function language_query_xmlsitemap_generate_alter(AlterableInterface $query) {
$mode = \Drupal::config('xmlsitemap.settings')->get('i18n_selection_mode') ?: 'simple';
$mode = \Drupal::config('xmlsitemap.settings')->get('i18n_selection_mode');
if (!$mode) {
$mode = 'simple';
if ($mode === 'off') {
return;
}
/** @var \Drupal\xmlsitemap\XmlSitemapInterface $sitemap */
$sitemap = $query->getMetaData('sitemap');
if (!isset($sitemap->context['language']) || $mode == 'off') {
return;
}
// Get languages to simplify query building.
$current = $sitemap->context['language'];
$default = \Drupal::languageManager()->getDefaultLanguage()->getId();
$current = isset($sitemap->context['language']) ? $sitemap->context['language'] : $default;
if ($mode == 'mixed' && $current == $default) {
// If mode is mixed but current = default, is the same as 'simple'.
......@@ -1807,6 +1785,94 @@ function xmlsitemap_query_xmlsitemap_generate_alter(AlterableInterface $query) {
}
}
/**
* Implements hook_xmlsitemap_element_alter() for language module.
*/
function language_xmlsitemap_element_alter(array &$element, array $link, XmlSitemapInterface $sitemap) {
// Add alternate links for each language for generic links.
if ($link['langcode'] === LanguageInterface::LANGCODE_NOT_SPECIFIED) {
$languages = \Drupal::languageManager()->getLanguages();
unset($languages[$sitemap->context['language']]);
foreach ($languages as $language) {
_xmlsitemap_element_add_alternate_lang($element, $link['loc'], $language, $sitemap);
}
}
}
/**
* Implements hook_xmlsitemap_element_alter() for content_translation module.
*/
function content_translation_xmlsitemap_element_alter(array &$element, array $link, XmlSitemapInterface $sitemap) {
if ($link['langcode'] === LanguageInterface::LANGCODE_NOT_SPECIFIED) {
return;
}
// Check if content translation is enabled for this type. This helps avoid
// the below query for each sitemap link, better for performance.
$enabled = &drupal_static(__FUNCTION__, []);
if (!isset($enabled[$link['type']])) {
/** @var \Drupal\content_translation\ContentTranslationManagerInterface $manager */
$manager = \Drupal::service('content_translation.manager');
try {
$enabled[$link['type']] = $manager->isEnabled($link['type']);
}
catch (PluginNotFoundException $exception) {
// Not a valid entity type.
$enabled[$link['type']] = FALSE;
}
}
// Add alternate links for each item's translation.
if ($enabled[$link['type']]) {
$query = \Drupal::database()->select('xmlsitemap', 'x');
$query->fields('x', ['loc', 'language']);
$query->condition('x.type', $link['type']);
$query->condition('x.id', $link['id']);
$query->condition('x.language', [$link['langcode'], LanguageInterface::LANGCODE_NOT_SPECIFIED], 'NOT IN');
$query->condition('x.access', 1);
$query->condition('x.status', 1);
$language_links = $query->execute();
while ($language_link = $language_links->fetchAssoc()) {
_xmlsitemap_element_add_alternate_lang($element, $language_link['loc'], xmlsitemap_language_load($language_link['language']), $sitemap);
}
}
}
/**
* Adds alternate language links to a sitemap element.
*
* @param array $element
* The sitemap element from hook_xmlsitemap_element_alter().
* @param string $loc
* The location for the URL.
* @param \Drupal\Core\Language\LanguageInterface $language
* The alternate language.
* @param \Drupal\xmlsitemap\XmlSitemapInterface $sitemap
* The current sitemap being generated for the element.
*
* @internal
*/
function _xmlsitemap_element_add_alternate_lang(array &$element, $loc, LanguageInterface $language, XmlSitemapInterface $sitemap) {
$url_options = $sitemap->uri['options'];
$url_options += [
'absolute' => TRUE,
'base_url' => rtrim(Settings::get('xmlsitemap_base_url', \Drupal::state()->get('xmlsitemap_base_url')), '/'),
'alias' => FALSE,
];
$alternate_href = Url::fromUri('internal:' . $loc, ['language' => $language] + $url_options)->toString();
if ($alternate_href !== $element['loc']) {
$element[] = [
'key' => 'xhtml:link',
'attributes' => [
'rel' => 'alternate',
'hreflang' => $language->getId(),
'href' => $alternate_href,
],
];
}
}
/**
* Implements hook_xmlsitemap_link_info().
*/
......
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