View source
<?php
use Drupal\Component\Utility\Crypt;
use Drupal\Component\Utility\Environment;
use Drupal\Component\Utility\UrlHelper;
use Drupal\Core\Cache\Cache;
use Drupal\Core\Database\Query\AlterableInterface;
use Drupal\Core\Database\Query\Condition;
use Drupal\Core\Entity\ContentEntityFormInterface;
use Drupal\Core\Entity\ContentEntityInterface;
use Drupal\Core\Entity\ContentEntityTypeInterface;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\Core\File\FileSystemInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Language\LanguageInterface;
use Drupal\Core\Link;
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\Core\Site\Settings;
use Drupal\Core\Url;
use Drupal\xmlsitemap\Controller\XmlSitemapController;
use Drupal\xmlsitemap\Entity\XmlSitemap;
use Drupal\xmlsitemap\XmlSitemapInterface;
use Symfony\Component\HttpFoundation\Request;
const XMLSITEMAP_MAX_SITEMAP_LINKS = 50000;
const XMLSITEMAP_MAX_SITEMAP_FILESIZE = 52528800;
const XMLSITEMAP_FREQUENCY_YEARLY = 31449600;
const XMLSITEMAP_FREQUENCY_MONTHLY = 2419200;
const XMLSITEMAP_FREQUENCY_WEEKLY = 604800;
const XMLSITEMAP_FREQUENCY_DAILY = 86400;
const XMLSITEMAP_FREQUENCY_HOURLY = 3600;
const XMLSITEMAP_FREQUENCY_ALWAYS = 60;
const XMLSITEMAP_LASTMOD_SHORT = 'Y-m-d';
const XMLSITEMAP_LASTMOD_MEDIUM = 'Y-m-d\\TH:i\\Z';
const XMLSITEMAP_LASTMOD_LONG = 'c';
const XMLSITEMAP_STATUS_DEFAULT = 0;
const XMLSITEMAP_PRIORITY_DEFAULT = 0.5;
function xmlsitemap_hook_info() {
$hooks = [
'xmlsitemap_link_info',
'xmlsitemap_link_info_alter',
'xmlsitemap_link_alter',
'xmlsitemap_index_links',
'xmlsitemap_context_info',
'xmlsitemap_context_info_alter',
'xmlsitemap_context_url_options',
'xmlsitemap_context',
'xmlsitemap_element_alter',
'xmlsitemap_root_attributes_alter',
'xmlsitemap_sitemap_insert',
'xmlsitemap_sitemap_update',
'xmlsitemap_sitemap_operations',
'xmlsitemap_sitemap_delete',
'xmlsitemap_sitemap_link_url_options_alter',
'query_xmlsitemap_generate_alter',
'query_xmlsitemap_index_links_alter',
'form_xmlsitemap_sitemap_edit_form_alter',
'xmlsitemap_rebuild_clear',
];
$hooks = array_combine($hooks, $hooks);
foreach ($hooks as $hook => $info) {
$hooks[$hook] = [
'group' => 'xmlsitemap',
];
}
return $hooks;
}
function xmlsitemap_help($route_name, RouteMatchInterface $route_match) {
$output = '';
switch ($route_name) {
case 'help.page.xmlsitemap':
case 'xmlsitemap.admin_settings':
case 'xmlsitemap.entities_settings':
case 'entity.xmlsitemap.edit_form':
case 'entity.xmlsitemap.delete_form':
return;
case 'xmlsitemap.admin_search':
break;
case 'xmlsitemap.admin_search_list':
break;
case 'xmlsitemap.admin_rebuild':
$output .= '<p>' . t("This action rebuilds your site's XML sitemap and regenerates the cached files, and may be a lengthy process. If you just installed XML sitemap, this can be helpful to import all your site's content into the sitemap. Otherwise, this should only be used in emergencies.") . '</p>';
}
$currentUser = \Drupal::currentUser();
if (strpos($route_name, 'xmlsitemap') !== FALSE && $currentUser
->hasPermission('administer xmlsitemap')) {
$output .= _xmlsitemap_get_blurb();
}
return $output;
}
function xmlsitemap_theme() {
return [
'xmlsitemap_content_settings_table' => [
'render element' => 'element',
'file' => 'xmlsitemap.module',
],
];
}
function _xmlsitemap_rebuild_form_access() {
$rebuild_types = xmlsitemap_get_rebuildable_link_types();
return !empty($rebuild_types) && \Drupal::currentUser()
->hasPermission('administer xmlsitemap');
}
function xmlsitemap_cron() {
if (\Drupal::config('xmlsitemap.settings')
->get('disable_cron_regeneration')) {
return;
}
if (!\Drupal::state()
->get('xmlsitemap_regenerate_needed')) {
return;
}
$lifetime = \Drupal::time()
->getRequestTime() - \Drupal::state()
->get('xmlsitemap_generated_last');
if ($lifetime < \Drupal::config('xmlsitemap.settings')
->get('minimum_lifetime')) {
return;
}
xmlsitemap_xmlsitemap_index_links(\Drupal::config('xmlsitemap.settings')
->get('batch_limit'));
xmlsitemap_run_unprogressive_batch('xmlsitemap_regenerate_batch');
}
function xmlsitemap_modules_installed(array $modules) {
Cache::invalidateTags([
'xmlsitemap',
]);
}
function xmlsitemap_modules_uninstalled(array $modules) {
Cache::invalidateTags([
'xmlsitemap',
]);
}
function xmlsitemap_robotstxt() {
if ($sitemap = XmlSitemap::loadByContext()) {
$uri = xmlsitemap_sitemap_uri($sitemap);
$path = UrlHelper::isExternal($uri['path']) ? $uri['path'] : 'base://' . $uri['path'];
$robotstxt[] = 'Sitemap: ' . Url::fromUri($path, $uri['options'])
->toString();
return $robotstxt;
}
}
function xmlsitemap_config_variables() {
return [
'minimum_lifetime' => 0,
'xsl' => 1,
'prefetch_aliases' => 1,
'chunk_size' => 'auto',
'batch_limit' => 100,
'path' => 'xmlsitemap',
'frontpage_priority' => 1.0,
'frontpage_changefreq' => XMLSITEMAP_FREQUENCY_DAILY,
'lastmod_format' => XMLSITEMAP_LASTMOD_MEDIUM,
'gz' => FALSE,
'disable_cron_regeneration' => FALSE,
];
}
function xmlsitemap_state_variables() {
return [
'xmlsitemap_rebuild_needed' => FALSE,
'xmlsitemap_regenerate_needed' => TRUE,
'xmlsitemap_base_url' => '',
'xmlsitemap_generated_last' => 0,
'xmlsitemap_developer_mode' => 0,
'max_chunks' => NULL,
'max_filesize' => NULL,
];
}
function xmlsitemap_var($name, $default = NULL) {
$defaults =& drupal_static(__FUNCTION__);
if (!isset($defaults)) {
$defaults = xmlsitemap_config_variables();
$defaults += xmlsitemap_state_variables();
}
if (!isset($defaults[$name])) {
trigger_error("Default variable for {$name} not found.");
}
if (\Drupal::state()
->get($name, NULL) === NULL) {
return \Drupal::config('xmlsitemap.settings')
->get($name);
}
return \Drupal::state()
->get($name);
}
function xmlsitemap_sitemap_load($smid) {
$sitemap = xmlsitemap_sitemap_load_multiple([
$smid,
]);
return $sitemap ? reset($sitemap) : FALSE;
}
function xmlsitemap_sitemap_load_multiple($smids = [], array $conditions = []) {
if ($smids !== FALSE) {
$conditions['smid'] = $smids;
}
else {
$conditions['smid'] = NULL;
}
$storage = Drupal::entityTypeManager()
->getStorage('xmlsitemap');
$sitemaps = $storage
->loadMultiple($conditions['smid']);
if (count($sitemaps) <= 0) {
return [];
}
return $sitemaps;
}
function xmlsitemap_sitemap_save(XmlSitemapInterface $sitemap) {
$context = $sitemap->context;
if (!isset($context) || !$context) {
$sitemap->context = [];
}
$sitemap
->setOriginalId($sitemap
->isNew() ? NULL : $sitemap
->getId());
$sitemap
->setId(xmlsitemap_sitemap_get_context_hash($context));
if (!$sitemap
->isNew() && $sitemap
->getId() != $sitemap
->getOriginalId()) {
$old_sitemap = xmlsitemap_sitemap_load($sitemap
->getOriginalId());
$old_dir = xmlsitemap_get_directory($old_sitemap);
$new_dir = xmlsitemap_get_directory($sitemap);
xmlsitemap_directory_move($old_dir, $new_dir);
\Drupal::state()
->set('xmlsitemap_regenerate_needed', TRUE);
}
$sitemap
->save();
return $sitemap;
}
function xmlsitemap_sitemap_delete($smid) {
xmlsitemap_sitemap_delete_multiple([
$smid,
]);
}
function xmlsitemap_sitemap_delete_multiple(array $smids) {
if (!empty($smids)) {
$sitemaps = xmlsitemap_sitemap_load_multiple($smids);
foreach ($sitemaps as $sitemap) {
$sitemap
->delete();
\Drupal::moduleHandler()
->invokeAll('xmlsitemap_sitemap_delete', [
$sitemap,
]);
}
}
}
function xmlsitemap_sitemap_get_file(XmlSitemapInterface $sitemap, $chunk = 'index') {
return xmlsitemap_get_directory($sitemap) . "/{$chunk}.xml";
}
function xmlsitemap_sitemap_get_max_filesize(XmlSitemapInterface $sitemap) {
$dir = xmlsitemap_get_directory($sitemap);
$sitemap
->setMaxFileSize(0);
$file_system = \Drupal::service('file_system');
$files = $file_system
->scanDirectory($dir, '/\\.xml$/');
foreach ($files as $file) {
$sitemap
->setMaxFileSize(max($sitemap
->getMaxFileSize(), filesize($file->uri)));
}
return $sitemap
->getMaxFileSize();
}
function xmlsitemap_sitemap_get_context_hash(array &$context) {
ksort($context);
return Crypt::hashBase64(serialize($context));
}
function xmlsitemap_sitemap_uri(XmlSitemapInterface $sitemap) {
$uri['path'] = 'sitemap.xml';
$uri['options'] = \Drupal::moduleHandler()
->invokeAll('xmlsitemap_context_url_options', [
$sitemap->context,
]);
$context = $sitemap->context;
\Drupal::moduleHandler()
->alter('xmlsitemap_context_url_options', $uri['options'], $context);
$uri['options'] += [
'absolute' => TRUE,
'base_url' => Settings::get('xmlsitemap_base_url', \Drupal::state()
->get('xmlsitemap_base_url')),
];
return $uri;
}
function xmlsitemap_get_directory(XmlSitemapInterface $sitemap = NULL) {
$directory =& drupal_static(__FUNCTION__);
if (!isset($directory)) {
$directory = \Drupal::config('xmlsitemap.settings')
->get('path') ?: 'xmlsitemap';
}
if ($sitemap != NULL && !empty($sitemap->id)) {
return file_build_uri($directory . '/' . $sitemap->id);
}
else {
return file_build_uri($directory);
}
}
function xmlsitemap_check_directory(XmlSitemapInterface $sitemap = NULL) {
$directory = xmlsitemap_get_directory($sitemap);
$filesystem = \Drupal::service('file_system');
$result = $filesystem
->prepareDirectory($directory, FileSystemInterface::CREATE_DIRECTORY | FileSystemInterface::MODIFY_PERMISSIONS);
if (!$result) {
\Drupal::logger('file system')
->error('The directory %directory does not exist or is not writable.', [
'%directory' => $directory,
]);
}
return $result;
}
function xmlsitemap_check_all_directories() {
$directories = [];
$sitemaps = xmlsitemap_sitemap_load_multiple(FALSE);
foreach ($sitemaps as $sitemap) {
$directory = xmlsitemap_get_directory($sitemap);
$directories[$directory] = $directory;
}
$filesystem = \Drupal::service('file_system');
foreach ($directories as $directory) {
$result = $filesystem
->prepareDirectory($directory, $filesystem::CREATE_DIRECTORY | $filesystem::MODIFY_PERMISSIONS);
if ($result) {
$directories[$directory] = TRUE;
}
else {
$directories[$directory] = FALSE;
}
}
return $directories;
}
function xmlsitemap_clear_directory(XmlSitemapInterface $sitemap = NULL, $delete = FALSE) {
$directory = xmlsitemap_get_directory($sitemap);
return _xmlsitemap_delete_recursive($directory, $delete);
}
function xmlsitemap_directory_move($old_dir, $new_dir, $replace = FileSystemInterface::EXISTS_REPLACE) {
$filesystem = \Drupal::service('file_system');
$success = $filesystem
->prepareDirectory($new_dir, $filesystem::CREATE_DIRECTORY | $filesystem::MODIFY_PERMISSIONS);
$old_path = $filesystem
->realpath($old_dir);
$new_path = $filesystem
->realpath($new_dir);
if (!is_dir($old_path) || !is_dir($new_path) || !$success) {
return FALSE;
}
$files = $filesystem
->scanDirectory($old_dir, '/.*/');
foreach ($files as $file) {
$file->uri_new = $new_dir . '/' . basename($file->filename);
$success &= (bool) $filesystem
->move($file->uri, $file->uri_new, $replace);
}
$success &= $filesystem
->rmdir($old_dir);
return $success;
}
function _xmlsitemap_delete_recursive($path, $delete_root = FALSE) {
$filesystem = \Drupal::service('file_system');
$path = $filesystem
->realpath($path);
if (is_dir($path)) {
$dir = dir($path);
while (($entry = $dir
->read()) !== FALSE) {
if ($entry === '.' || $entry === '..') {
continue;
}
$entry_path = $path . '/' . $entry;
$filesystem
->deleteRecursive($entry_path);
}
$dir
->close();
return $delete_root ? $filesystem
->rmdir($path) : TRUE;
}
return $filesystem
->delete($path);
}
function xmlsitemap_entity_type_build(array &$entity_types) {
$unsupported_types = [
'block_content',
'comment',
'shortcut',
'redirect',
'token_custom',
];
foreach ($unsupported_types as $entity_type_id) {
if (isset($entity_types[$entity_type_id])) {
$entity_types[$entity_type_id]
->set('xmlsitemap', FALSE);
}
}
}
function xmlsitemap_is_entity_type_supported(EntityTypeInterface $entity_type) {
$status = $entity_type
->get('xmlsitemap');
if ($status !== NULL) {
return $status;
}
if (!$entity_type instanceof ContentEntityTypeInterface) {
return FALSE;
}
if ($entity_type
->isInternal()) {
return FALSE;
}
if (!$entity_type
->hasLinkTemplate('canonical') && !$entity_type
->getUriCallback()) {
return FALSE;
}
if ($entity_type
->getBundleEntityType() && !\Drupal::service('entity_type.bundle.info')
->getBundleInfo($entity_type
->id())) {
return FALSE;
}
return TRUE;
}
function xmlsitemap_get_link_info($type = NULL, $reset = FALSE) {
$language = \Drupal::languageManager()
->getCurrentLanguage();
$link_info =& drupal_static(__FUNCTION__);
if ($reset) {
$link_info = NULL;
\Drupal::service('cache_tags.invalidator')
->invalidateTags([
'xmlsitemap',
]);
}
if (!isset($link_info)) {
$cid = 'xmlsitemap:link_info:' . $language
->getId();
if ($cache = \Drupal::cache()
->get($cid)) {
$link_info = $cache->data;
}
else {
$link_info = [];
$entity_types = \Drupal::entityTypeManager()
->getDefinitions();
foreach ($entity_types as $key => $entity_type) {
if (!xmlsitemap_is_entity_type_supported($entity_type)) {
continue;
}
$link_info[$key] = [
'label' => $entity_type
->getLabel(),
'type' => $entity_type
->id(),
'base table' => $entity_type
->getBaseTable(),
'bundles' => \Drupal::service('entity_type.bundle.info')
->getBundleInfo($entity_type
->id()),
'bundle label' => $entity_type
->getBundleLabel(),
'entity keys' => [
'id' => $entity_type
->getKey('id'),
'bundle' => $entity_type
->getKey('bundle'),
],
'xmlsitemap' => [
'process callback' => $entity_type
->get('xmlsitemap')['process callback'] ?? 'xmlsitemap_xmlsitemap_process_entity_links',
'rebuild callback' => $entity_type
->get('xmlsitemap')['process callback'] ?? 'xmlsitemap_rebuild_batch_fetch',
],
];
}
$link_info = array_merge($link_info, \Drupal::moduleHandler()
->invokeAll('xmlsitemap_link_info'));
foreach ($link_info as $key => &$info) {
$info += [
'type' => $key,
'base table' => FALSE,
'bundles' => [],
];
foreach ($info['bundles'] as $bundle => &$bundle_info) {
$bundle_info += [
'xmlsitemap' => [],
];
$bundle_info['xmlsitemap'] += xmlsitemap_link_bundle_load($key, $bundle, FALSE);
}
}
\Drupal::moduleHandler()
->alter('xmlsitemap_link_info', $link_info);
uasort($link_info, function ($a, $b) {
if ($a['type'] === 'frontpage') {
return -1;
}
if ($b['type'] === 'frontpage') {
return 1;
}
return strnatcmp($a['label'], $b['label']);
});
\Drupal::cache()
->set($cid, $link_info, Cache::PERMANENT, [
'xmlsitemap',
'entity_types',
'entity_bundles',
]);
}
}
if (isset($type)) {
return isset($link_info[$type]) ? $link_info[$type] : NULL;
}
return $link_info;
}
function xmlsitemap_get_link_type_enabled_bundles($entity_type) {
$bundles = [];
$info = xmlsitemap_get_link_info($entity_type);
foreach ($info['bundles'] as $bundle => $bundle_info) {
$settings = xmlsitemap_link_bundle_load($entity_type, $bundle);
if (!empty($settings['status'])) {
$bundles[] = $bundle;
}
}
return $bundles;
}
function xmlsitemap_get_link_type_indexed_status($entity_type_id, $bundle = '') {
$info = xmlsitemap_get_link_info($entity_type_id);
$database = \Drupal::database();
$entity_type = \Drupal::entityTypeManager()
->getDefinition($entity_type_id);
$status['indexed'] = $database
->query("SELECT COUNT(id) FROM {xmlsitemap} WHERE type = :entity AND subtype = :bundle", [
':entity' => $entity_type_id,
':bundle' => $bundle,
])
->fetchField();
$status['visible'] = $database
->query("SELECT COUNT(id) FROM {xmlsitemap} WHERE type = :entity AND subtype = :bundle AND status = 1 AND access = 1", [
':entity' => $entity_type_id,
':bundle' => $bundle,
])
->fetchField();
try {
$query = \Drupal::entityQuery($entity_type_id);
if ($bundle && $entity_type
->hasKey('bundle')) {
$query
->condition($entity_type
->getKey('bundle'), $bundle);
}
$query
->accessCheck(FALSE);
$query
->addTag('xmlsitemap_link_indexed_status');
$status['total'] = $query
->count()
->execute();
return $status;
} catch (\Exception $e) {
$status['total'] = 0;
}
return $status;
}
function xmlsitemap_link_bundle_settings_save($entity, $bundle, array $settings, $update_links = TRUE) {
if ($update_links) {
$old_settings = xmlsitemap_link_bundle_load($entity, $bundle);
if ($settings['status'] != $old_settings['status']) {
\Drupal::service('xmlsitemap.link_storage')
->updateMultiple([
'status' => $settings['status'],
], [
'type' => $entity,
'subtype' => $bundle,
'status_override' => 0,
]);
}
if ($settings['priority'] != $old_settings['priority']) {
\Drupal::service('xmlsitemap.link_storage')
->updateMultiple([
'priority' => $settings['priority'],
], [
'type' => $entity,
'subtype' => $bundle,
'priority_override' => 0,
]);
}
}
foreach ($settings as $key => $value) {
\Drupal::configFactory()
->getEditable("xmlsitemap.settings.{$entity}.{$bundle}")
->set($key, $value)
->save();
}
foreach (\Drupal::languageManager()
->getLanguages() as $lang) {
\Drupal::cache()
->delete('xmlsitemap:link_info:' . $lang
->getId());
}
xmlsitemap_get_link_info(NULL, TRUE);
}
function xmlsitemap_link_bundle_rename($entity, $bundle_old, $bundle_new) {
if ($bundle_old != $bundle_new) {
if (!\Drupal::config("xmlsitemap.settings.{$entity}.{$bundle_old}")
->isNew()) {
$settings = xmlsitemap_link_bundle_load($entity, $bundle_old);
\Drupal::configFactory()
->getEditable("xmlsitemap.settings.{$entity}.{$bundle_old}")
->delete();
xmlsitemap_link_bundle_settings_save($entity, $bundle_new, $settings, FALSE);
\Drupal::service('xmlsitemap.link_storage')
->updateMultiple([
'subtype' => $bundle_new,
], [
'type' => $entity,
'subtype' => $bundle_old,
]);
}
}
}
function xmlsitemap_link_bundle_load($entity, $bundle, $load_bundle_info = TRUE) {
$info = [
'entity' => $entity,
'bundle' => $bundle,
];
if ($load_bundle_info) {
$entity_info = xmlsitemap_get_link_info($entity);
if (isset($entity_info['bundles'][$bundle])) {
$info['info'] = $entity_info['bundles'][$bundle];
}
}
$bundle_settings = \Drupal::config("xmlsitemap.settings.{$entity}.{$bundle}")
->get();
if ($bundle_settings) {
$info += $bundle_settings;
}
$info += [
'status' => XMLSITEMAP_STATUS_DEFAULT,
'priority' => XMLSITEMAP_PRIORITY_DEFAULT,
'changefreq' => 0,
];
return $info;
}
function xmlsitemap_link_bundle_delete($entity, $bundle, $delete_links = TRUE) {
\Drupal::configFactory()
->getEditable("xmlsitemap.settings.{$entity}.{$bundle}")
->delete();
if ($delete_links) {
\Drupal::service('xmlsitemap.link_storage')
->deleteMultiple([
'type' => $entity,
'subtype' => $bundle,
]);
}
xmlsitemap_get_link_info(NULL, TRUE);
}
function xmlsitemap_link_bundle_access($entity, $bundle = NULL) {
@trigger_error(__FUNCTION__ . ' is deprecated in xmlsitemap:8.x-1.1 and will be removed in xmlsitemap:2.0.0. See https://www.drupal.org/project/xmlsitemap/issues/3156088', E_USER_DEPRECATED);
return FALSE;
}
function xmlsitemap_get_bundle_path($entity, $bundle) {
@trigger_error(__FUNCTION__ . ' is deprecated in xmlsitemap:8.x-1.1 and will be removed in xmlsitemap:2.0.0. See https://www.drupal.org/project/xmlsitemap/issues/3156088', E_USER_DEPRECATED);
return FALSE;
}
function xmlsitemap_entity_bundle_rename($entity_type_id, $bundle_old, $bundle_new) {
xmlsitemap_link_bundle_rename($entity_type_id, $bundle_old, $bundle_new);
}
function xmlsitemap_entity_bundle_delete($entity_type_id, $bundle) {
xmlsitemap_link_bundle_delete($entity_type_id, $bundle, TRUE);
}
function xmlsitemap_get_changefreq($interval) {
if ($interval <= 0 || !is_numeric($interval)) {
return FALSE;
}
foreach (xmlsitemap_get_changefreq_options() as $value => $frequency) {
if ($interval <= $value) {
return $frequency;
}
}
return 'never';
}
function xmlsitemap_get_chunk_count($reset = FALSE) {
static $chunks;
if (!isset($chunks) || $reset) {
$count = max(xmlsitemap_get_link_count($reset), 1);
$chunks = ceil($count / xmlsitemap_get_chunk_size($reset));
}
return $chunks;
}
function xmlsitemap_get_link_count($reset = FALSE) {
static $count;
if (!isset($count) || $reset) {
$count = \Drupal::database()
->query("SELECT COUNT(id) FROM {xmlsitemap} WHERE access = 1 AND status = 1")
->fetchField();
}
return $count;
}
function xmlsitemap_get_chunk_size($reset = FALSE) {
static $size;
if (!isset($size) || $reset) {
$size = xmlsitemap_var('chunk_size');
if ($size === 'auto') {
$count = max(xmlsitemap_get_link_count($reset), 1);
$size = min(ceil($count / 10000) * 5000, XMLSITEMAP_MAX_SITEMAP_LINKS);
}
}
return $size;
}
function xmlsitemap_recalculate_changefreq(array &$link) {
$time = \Drupal::time()
->getRequestTime();
$link['changefreq'] = round(($link['changefreq'] * $link['changecount'] + ($time - $link['lastmod'])) / ($link['changecount'] + 1));
$link['changecount']++;
$link['lastmod'] = $time;
}
function xmlsitemap_calculate_changefreq(array $timestamps) {
sort($timestamps);
$count = count($timestamps) - 1;
$diff = 0;
for ($i = 0; $i < $count; $i++) {
$diff += $timestamps[$i + 1] - $timestamps[$i];
}
return $count > 0 ? round($diff / $count) : 0;
}
function xmlsitemap_form_submit_flag_regenerate(array $form, FormStateInterface $form_state) {
$values = $form_state
->getValues();
foreach ($values as $variable => $value) {
if (\Drupal::config('xmlsitemap.settings')
->get($variable) == NULL) {
$stored_value = 'not_a_variable';
}
else {
$stored_value = \Drupal::config('xmlsitemap.settings')
->get($variable);
}
if (is_array($value) && !$form_state
->isValueEmpty('array_filter')) {
$value = array_keys(array_filter($value));
}
if ($stored_value != 'not_a_variable' && $stored_value != $value) {
\Drupal::state()
->set('xmlsitemap_regenerate_needed', TRUE);
\Drupal::messenger()
->addWarning(t('XML sitemap settings have been modified and the files should be regenerated. You can <a href="@run-cron">run cron manually</a> to regenerate the cached files.', [
'@run-cron' => Url::fromRoute('system.run_cron', [], [
'query' => \Drupal::destination()
->getAsArray(),
])
->toString(),
]), FALSE);
return;
}
}
}
function xmlsitemap_add_form_link_options(array &$form, $entity_type, $bundle, $id) {
if (!($link = \Drupal::service('xmlsitemap.link_storage')
->load($entity_type, $id))) {
$link = [];
}
$bundle_info = xmlsitemap_link_bundle_load($entity_type, $bundle);
$link += [
'access' => 1,
'status' => $bundle_info['status'],
'status_default' => $bundle_info['status'],
'status_override' => 0,
'priority' => $bundle_info['priority'],
'priority_default' => $bundle_info['priority'],
'priority_override' => 0,
'changefreq' => $bundle_info['changefreq'],
];
$currentUser = \Drupal::currentUser();
$admin_permission = \Drupal::entityTypeManager()
->getDefinition($entity_type)
->getAdminPermission();
$form['xmlsitemap'] = [
'#type' => 'details',
'#tree' => TRUE,
'#title' => t('XML sitemap'),
'#collapsible' => TRUE,
'#collapsed' => !$link['status_override'] && !$link['priority_override'],
'#access' => $currentUser
->hasPermission('administer xmlsitemap') || $admin_permission && $currentUser
->hasPermission($admin_permission),
'#group' => 'advanced',
];
if ($id && !$link['access']) {
$form['xmlsitemap']['warning'] = [
'#type' => 'markup',
'#prefix' => '<p><strong>',
'#suffix' => '</strong></p>',
'#value' => 'This item is not currently visible to anonymous users, so it will not be included in the sitemap.',
];
}
$form['xmlsitemap']['status'] = [
'#type' => 'select',
'#title' => t('Inclusion'),
'#options' => xmlsitemap_get_status_options($link['status_default']),
'#default_value' => $link['status_override'] ? $link['status'] : 'default',
];
$form['xmlsitemap']['status_default'] = [
'#type' => 'value',
'#value' => $link['status_default'],
];
$form['xmlsitemap']['status_override'] = [
'#type' => 'value',
'#value' => $link['status_override'],
];
$form['xmlsitemap']['priority'] = [
'#type' => 'select',
'#title' => t('Priority'),
'#options' => xmlsitemap_get_priority_options($link['priority_default']),
'#default_value' => $link['priority_override'] ? number_format($link['priority'], 1) : 'default',
'#description' => t('The priority of this URL relative to other URLs on your site.'),
'#states' => [
'invisible' => [
'select[name="xmlsitemap[status]"]' => [
'value' => '0',
],
],
],
];
$form['xmlsitemap']['changefreq'] = [
'#type' => 'select',
'#title' => t('Change frequency'),
'#options' => xmlsitemap_get_changefreq_options(),
'#default_value' => $link['changefreq'],
'#description' => t('Select the frequency of changes.'),
'#states' => [
'invisible' => [
'select[name="xmlsitemap[status]"]' => [
'value' => '0',
],
],
],
];
if (!$link['status_default']) {
$form['xmlsitemap']['priority']['#states']['visible'] = [
'select[name="xmlsitemap[status]"]' => [
'value' => '1',
],
];
}
$form['xmlsitemap']['priority_default'] = [
'#type' => 'value',
'#value' => $link['priority_default'],
];
$form['xmlsitemap']['priority_override'] = [
'#type' => 'value',
'#value' => $link['priority_override'],
];
array_unshift($form['actions']['submit']['#submit'], 'xmlsitemap_process_form_link_options');
if (!empty($form['actions']['publish']['#submit'])) {
array_unshift($form['actions']['publish']['#submit'], 'xmlsitemap_process_form_link_options');
}
}
function xmlsitemap_process_form_link_options(array $form, FormStateInterface $form_state) {
$link = $form_state
->getValue('xmlsitemap');
$fields = [
'status' => XMLSITEMAP_STATUS_DEFAULT,
'priority' => XMLSITEMAP_PRIORITY_DEFAULT,
];
foreach ($fields as $field => $default) {
if ($link[$field] === 'default') {
$link[$field] = isset($link[$field . '_default']) ? $link[$field . '_default'] : $default;
$link[$field . '_override'] = 0;
}
else {
$link[$field . '_override'] = 1;
}
}
$form_state
->setValue('xmlsitemap', $link);
$entity = $form_state
->getFormObject()
->getEntity();
$entity->xmlsitemap = $form_state
->getValue('xmlsitemap');
}
function xmlsitemap_link_bundle_settings_form_submit($form, &$form_state) {
$entity = $form['xmlsitemap']['#entity'];
$bundle = $form['xmlsitemap']['#bundle'];
if (empty($bundle)) {
$entity_info = $form['xmlsitemap']['#entity_info'];
if (isset($entity_info['bundle keys']['bundle'])) {
$bundle_key = $entity_info['bundle keys']['bundle'];
if ($form_state
->hasValue($bundle_key)) {
$bundle = $form_state
->getValue($bundle_key);
$form['xmlsitemap']['#bundle'] = $bundle;
}
}
}
xmlsitemap_link_bundle_settings_save($entity, $bundle, $form_state
->getValue('xmlsitemap'));
$entity_info = $form['xmlsitemap']['#entity_info'];
if (!empty($form['xmlsitemap']['#show_message'])) {
\Drupal::messenger()
->addStatus(t('XML sitemap settings for the @bundle-label %bundle have been saved.', [
'@bundle-label' => mb_strtolower($entity_info['bundle label']),
'%bundle' => $entity_info['bundles'][$bundle]['label'],
]));
}
$form_state
->unsetValue('xmlsitemap');
}
function xmlsitemap_get_changefreq_options() {
return [
XMLSITEMAP_FREQUENCY_ALWAYS => 'always',
XMLSITEMAP_FREQUENCY_HOURLY => 'hourly',
XMLSITEMAP_FREQUENCY_DAILY => 'daily',
XMLSITEMAP_FREQUENCY_WEEKLY => 'weekly',
XMLSITEMAP_FREQUENCY_MONTHLY => 'monthly',
XMLSITEMAP_FREQUENCY_YEARLY => 'yearly',
];
}
function xmlsitemap_language_load($language = LanguageInterface::LANGCODE_NOT_SPECIFIED) {
$languages =& drupal_static(__FUNCTION__);
if (!isset($languages)) {
$languages = \Drupal::languageManager()
->getLanguages();
$languages[LanguageInterface::LANGCODE_NOT_SPECIFIED] = NULL;
}
return isset($languages[$language]) ? $languages[$language] : NULL;
}
function xmlsitemap_get_context_info($context = NULL, $reset = FALSE) {
$language = \Drupal::languageManager()
->getCurrentLanguage();
$info =& drupal_static(__FUNCTION__);
if ($reset) {
$info = NULL;
}
elseif ($cached = \Drupal::cache()
->get('xmlsitemap:context_info:' . $language
->getId())) {
$info = $cached->data;
}
if (!isset($info)) {
$info = \Drupal::moduleHandler()
->invokeAll('xmlsitemap_context_info');
\Drupal::moduleHandler()
->alter('xmlsitemap_context_info', $info);
ksort($info);
\Drupal::cache()
->set('xmlsitemap:context_info:' . $language
->getId(), $info, Cache::PERMANENT, [
'xmlsitemap',
]);
}
if (isset($context)) {
return isset($info[$context]) ? $info[$context] : NULL;
}
return $info;
}
function xmlsitemap_get_current_context() {
$context =& drupal_static(__FUNCTION__);
if (!isset($context)) {
$context = \Drupal::moduleHandler()
->invokeAll('xmlsitemap_context');
\Drupal::moduleHandler()
->alter('xmlsitemap_context', $context);
ksort($context);
}
return $context;
}
function _xmlsitemap_sitemap_context_summary(XmlSitemapInterface $sitemap, $context_key, array $context_info) {
$context_value = isset($sitemap->context[$context_key]) ? $sitemap->context[$context_key] : NULL;
if (!isset($context_value)) {
return t('Default');
}
elseif (!empty($context_info['summary callback'])) {
return $context_info['summary callback']($context_value);
}
else {
return $context_value;
}
}
function xmlsitemap_run_unprogressive_batch() {
$batch = batch_get();
$lock = \Drupal::lock();
if (!empty($batch)) {
return FALSE;
}
$args = func_get_args();
$batch_callback = array_shift($args);
if (!$lock
->acquire($batch_callback)) {
return FALSE;
}
Environment::setTimeLimit(240);
$batch = call_user_func_array($batch_callback, $args);
batch_set($batch);
$batch =& batch_get();
$batch['progressive'] = FALSE;
if (PHP_SAPI === 'cli' && function_exists('drush_backend_batch_process')) {
drush_backend_batch_process();
}
else {
batch_process();
}
$lock
->release($batch_callback);
return TRUE;
}
function xmlsitemap_get_operation_link($url, array $options = []) {
static $destination;
if (!isset($destination)) {
$destination = \Drupal::destination()
->getAsArray();
}
$link = [
'href' => $url,
] + $options;
$link += [
'query' => $destination,
];
return $link;
}
function theme_xmlsitemap_content_settings_table(array $variables) {
return '<h4>' . $variables['build']['#title'] . '</h4>' . \Drupal::service('renderer')
->render($variables['build']);
}
function xmlsitemap_form_alter(array &$form, FormStateInterface $form_state, $form_id) {
$form_object = $form_state
->getFormObject();
if ($form_object instanceof ContentEntityFormInterface) {
$entity = $form_object
->getEntity();
$operations = [
'default',
'edit',
];
if ($entity
->getEntityTypeId() === 'user') {
$operations[] = 'register';
}
if (in_array($form_object
->getOperation(), $operations, TRUE) && xmlsitemap_link_bundle_check_enabled($entity
->getEntityTypeId(), $entity
->bundle())) {
xmlsitemap_add_form_link_options($form, $entity
->getEntityTypeId(), $entity
->bundle(), $entity
->id());
$form['xmlsitemap']['#weight'] = 10;
}
}
}
function xmlsitemap_xmlsitemap_index_links($limit) {
$entity_type_manager = \Drupal::entityTypeManager();
$entity_types = $entity_type_manager
->getDefinitions();
foreach ($entity_types as $entity_type_id => $entity_type) {
$info = xmlsitemap_get_link_info($entity_type_id);
if (empty($info)) {
continue;
}
$bundles = xmlsitemap_get_link_type_enabled_bundles($entity_type_id);
if (empty($bundles)) {
continue;
}
try {
$query = $entity_type_manager
->getStorage($entity_type_id)
->getQuery();
$query
->range(0, $limit);
if (!empty($info['entity keys']['bundle'])) {
$query
->condition($info['entity keys']['bundle'], $bundles, 'IN');
}
$subquery = \Drupal::database()
->select('xmlsitemap', 'x');
$subquery
->addField('x', 'id');
$subquery
->condition('type', $entity_type_id);
if ($query instanceof \Drupal\Core\Entity\Query\Sql\Query) {
$query
->condition($info['entity keys']['id'], $subquery, 'NOT IN');
}
else {
$query
->condition($info['entity keys']['id'], $subquery
->execute()
->fetchCol(), 'NOT IN');
}
$query
->accessCheck(FALSE);
$query
->addTag('xmlsitemap_index_links');
if ($ids = $query
->execute()) {
$chunks = array_chunk($ids, \Drupal::config('xmlsitemap.settings')
->get('batch_limit'));
foreach ($chunks as $chunk) {
$info['xmlsitemap']['process callback']($entity_type_id, $chunk);
}
\Drupal::logger('xmlsitemap')
->info('Indexed @count new @type items.', [
'@count' => count($ids),
'@type' => $entity_type_id,
]);
}
} catch (\Exception $e) {
watchdog_exception('xmlsitemap', $e);
}
}
}
function xmlsitemap_xmlsitemap_process_entity_links($entity_type_id, array $entity_ids) {
$entities = \Drupal::entityTypeManager()
->getStorage($entity_type_id)
->loadMultiple($entity_ids);
foreach ($entities as $entity) {
xmlsitemap_xmlsitemap_process_entity_link($entity);
}
\Drupal::entityTypeManager()
->getStorage($entity_type_id)
->resetCache();
}
function xmlsitemap_xmlsitemap_process_entity_link(EntityInterface $entity) {
$link_storage = \Drupal::service('xmlsitemap.link_storage');
if ($entity instanceof ContentEntityInterface) {
$translation_languages = $entity
->getTranslationLanguages();
foreach ($translation_languages as $langcode => $language) {
$translation = $entity
->getTranslation($langcode);
$link = $link_storage
->create($translation);
$context = [
$link['type'] => $entity,
'entity' => $entity,
];
$link_storage
->save($link, $context);
}
if (isset($entity->original)) {
$original_translation_languages = $entity->original
->getTranslationLanguages();
$removed_translation_languages = array_diff(array_keys($original_translation_languages), array_keys($translation_languages));
if (!empty($removed_translation_languages)) {
$link_storage
->deleteMultiple([
'type' => $entity
->getEntityTypeId(),
'id' => $entity
->id(),
'language' => $removed_translation_languages,
]);
}
}
}
else {
$link = $link_storage
->create($entity);
$context = [
$link['type'] => $entity,
'entity' => $entity,
];
$link_storage
->save($link, $context);
}
}
function xmlsitemap_entity_insert(EntityInterface $entity) {
if (xmlsitemap_link_bundle_check_enabled($entity
->getEntityTypeId(), $entity
->bundle())) {
xmlsitemap_xmlsitemap_process_entity_link($entity);
}
}
function xmlsitemap_entity_update(EntityInterface $entity) {
if (xmlsitemap_link_bundle_check_enabled($entity
->getEntityTypeId(), $entity
->bundle())) {
xmlsitemap_xmlsitemap_process_entity_link($entity);
}
}
function xmlsitemap_entity_delete(EntityInterface $entity) {
$langcode = $entity
->language() ? $entity
->language()
->getId() : NULL;
\Drupal::service('xmlsitemap.link_storage')
->delete($entity
->getEntityTypeId(), $entity
->id(), $langcode);
}
function xmlsitemap_entity_translation_delete(EntityInterface $translation) {
\Drupal::service('xmlsitemap.link_storage')
->delete($translation
->getEntityTypeId(), $translation
->id(), $translation
->language()
->getId());
}
function language_xmlsitemap_context_info() {
$context['language'] = [
'label' => t('Language'),
'summary callback' => 'language_name',
'default' => \Drupal::languageManager()
->getDefaultLanguage()
->getId(),
];
return $context;
}
function language_xmlsitemap_context() {
$language = \Drupal::languageManager()
->getCurrentLanguage();
$context['language'] = $language
->getId();
return $context;
}
function language_xmlsitemap_context_url_options(array $context) {
$options = [];
if (isset($context['language'])) {
$options['language'] = xmlsitemap_language_load($context['language']);
}
return $options;
}
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();
}
$form['context']['language'] = [
'#type' => 'select',
'#title' => t('Language'),
'#options' => $options,
'#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.'),
];
}
function xmlsitemap_form_language_admin_overview_form_alter(&$form, FormStateInterface $form_state) {
array_unshift($form['#submit'], 'xmlsitemap_form_submit_flag_regenerate');
}
function language_query_xmlsitemap_generate_alter(AlterableInterface $query) {
$mode = \Drupal::config('xmlsitemap.settings')
->get('i18n_selection_mode') ?: 'simple';
if ($mode === 'off') {
return;
}
$sitemap = $query
->getMetaData('sitemap');
$default = \Drupal::languageManager()
->getDefaultLanguage()
->getId();
$current = isset($sitemap->context['language']) ? $sitemap->context['language'] : $default;
if ($mode == 'mixed' && $current == $default) {
$mode = 'simple';
}
switch ($mode) {
case 'simple':
$query
->condition('language', [
$current,
LanguageInterface::LANGCODE_NOT_SPECIFIED,
], 'IN');
break;
case 'mixed':
$query
->condition('language', [
$current,
$default,
LanguageInterface::LANGCODE_NOT_SPECIFIED,
], 'IN');
break;
case 'default':
$query
->condition('language', [
$default,
LanguageInterface::LANGCODE_NOT_SPECIFIED,
], 'IN');
break;
case 'strict':
$node_condition = new Condition('AND');
$node_condition
->condition('type', 'node', '=');
$node_condition
->condition('language', $current, '=');
$normal_condition = new Condition('AND');
$normal_condition
->condition('type', 'node', '<>');
$normal_condition
->condition('language', [
$current,
LanguageInterface::LANGCODE_NOT_SPECIFIED,
], 'IN');
$condition = new Condition('OR');
$condition
->condition($node_condition);
$condition
->condition($normal_condition);
$query
->condition($condition);
break;
case 'off':
break;
}
}
function language_xmlsitemap_element_alter(array &$element, array $link, XmlSitemapInterface $sitemap) {
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);
}
}
}
function content_translation_xmlsitemap_element_alter(array &$element, array $link, XmlSitemapInterface $sitemap) {
if ($link['langcode'] === LanguageInterface::LANGCODE_NOT_SPECIFIED) {
return;
}
$loc_whitelist =& drupal_static(__FUNCTION__);
if (!isset($loc_whitelist)) {
$loc_whitelist = FALSE;
if ($types = array_keys(\Drupal::service('content_translation.manager')
->getSupportedEntityTypes())) {
$query = \Drupal::database()
->select('xmlsitemap', 'x');
$query
->distinct(TRUE);
$query
->addExpression('SUBSTRING_INDEX(x.loc, :slash, 2)', 'path', [
':slash' => '/',
]);
$query
->condition('x.type', $types, 'IN');
$whitelist_paths = $query
->execute()
->fetchCol();
$loc_whitelist = '/^(' . implode('|', array_map(function ($path) {
return preg_quote($path . '/', '/') . '.*';
}, $whitelist_paths)) . ')/';
}
}
if ($loc_whitelist && preg_match($loc_whitelist, $link['loc'])) {
$query = \Drupal::database()
->select('xmlsitemap', 'x');
$query
->fields('x', [
'loc',
'language',
]);
$query
->condition('x.loc', $link['loc']);
$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);
}
}
}
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,
],
];
}
}
function xmlsitemap_xmlsitemap_link_info() {
return [
'frontpage' => [
'label' => t('Frontpage'),
'xmlsitemap' => [
'settings callback' => 'xmlsitemap_link_frontpage_settings',
],
],
];
}
function xmlsitemap_xmlsitemap_link_alter(&$link) {
if ($link['type'] == 'frontpage' || $link['loc'] == '/' || $link['loc'] == Drupal::config('system.site')
->get('page.front')) {
$link['priority'] = \Drupal::config('xmlsitemap.settings')
->get('frontpage_priority');
$link['changefreq'] = \Drupal::config('xmlsitemap.settings')
->get('frontpage_changefreq');
}
}
function xmlsitemap_xmlsitemap_links() {
$links[] = [
'type' => 'frontpage',
'id' => 0,
'loc' => '/',
];
return $links;
}
function xmlsitemap_xmlsitemap_sitemap_operations() {
$operations['update'] = [
'label' => t('Update cached files'),
'action past' => t('Updated'),
'callback' => 'xmlsitemap_sitemap_multiple_update',
];
return $operations;
}
function xmlsitemap_link_frontpage_settings(array &$form) {
if (\Drupal::currentUser()
->hasPermission('administer site configuration')) {
$form['#description'] = t('The front page path can be changed in the <a href="@url-frontpage">site information configuration</a>.', [
'@url-frontpage' => Url::fromRoute('system.site_information_settings')
->toString(),
]);
}
$form['frontpage_priority'] = [
'#type' => 'select',
'#title' => t('Priority'),
'#options' => xmlsitemap_get_priority_options(),
'#default_value' => \Drupal::config('xmlsitemap.settings')
->get('frontpage_priority'),
];
$form['frontpage_changefreq'] = [
'#type' => 'select',
'#title' => t('Change frequency'),
'#options' => xmlsitemap_get_changefreq_options(),
'#default_value' => \Drupal::config('xmlsitemap.settings')
->get('frontpage_changefreq'),
];
return $form;
}
function xmlsitemap_sitemap_multiple_update(array $smids) {
$batch = xmlsitemap_regenerate_batch($smids);
batch_set($batch);
}
function xmlsitemap_add_form_entity_summary(array &$form, $entity, array $entity_info) {
$priorities = xmlsitemap_get_priority_options(NULL, FALSE);
$statuses = xmlsitemap_get_status_options(NULL);
$rows = [];
$totals = [
'total' => 0,
'indexed' => 0,
'visible' => 0,
];
foreach ($entity_info['bundles'] as $bundle => $bundle_info) {
if (!xmlsitemap_link_bundle_check_enabled($entity, $bundle)) {
continue;
}
$status = xmlsitemap_get_link_type_indexed_status($entity, $bundle);
$totals['total'] += $status['total'];
$totals['indexed'] += $status['indexed'];
$totals['visible'] += $status['visible'];
$rows[] = [
Link::createFromRoute($bundle_info['label'], 'xmlsitemap.admin_settings_bundle', [
'entity' => $entity,
'bundle' => $bundle,
]),
$statuses[$bundle_info['xmlsitemap']['status'] ? 1 : 0],
$priorities[number_format($bundle_info['xmlsitemap']['priority'], 1)],
$status['total'],
$status['indexed'],
$status['visible'],
];
}
if ($rows) {
$header = [
isset($entity_info['bundle label']) ? $entity_info['bundle label'] : '',
t('Inclusion'),
t('Priority'),
t('Available'),
t('Indexed'),
t('Visible'),
];
$rows[] = [
[
'data' => t('Totals'),
'colspan' => 3,
'header' => TRUE,
],
[
'data' => $totals['total'],
'header' => TRUE,
],
[
'data' => $totals['indexed'],
'header' => TRUE,
],
[
'data' => $totals['visible'],
'header' => TRUE,
],
];
$form['summary'] = [
'#theme' => 'table',
'#header' => $header,
'#rows' => $rows,
];
}
}
function xmlsitemap_add_link_bundle_settings(array &$form, FormStateInterface $form_state, $entity, $bundle) {
$entity_info = xmlsitemap_get_link_info($entity);
$bundle_info = xmlsitemap_link_bundle_load($entity, $bundle);
$form['xmlsitemap'] = [
'#type' => 'details',
'#title' => t('XML sitemap'),
'#collapsible' => TRUE,
'#collapsed' => TRUE,
'#access' => \Drupal::currentUser()
->hasPermission('administer xmlsitemap'),
'#group' => 'advanced',
'#tree' => TRUE,
'#entity' => $entity,
'#bundle' => $bundle,
'#entity_info' => $entity_info,
'#bundle_info' => $bundle_info,
];
$form['xmlsitemap']['description'] = [
'#prefix' => '<div class="description">',
'#suffix' => '</div>',
'#markup' => t('Changing these type settings will affect any items of this type that have either inclusion or priority set to default.'),
];
$form['xmlsitemap']['status'] = [
'#type' => 'select',
'#title' => t('Inclusion'),
'#options' => xmlsitemap_get_status_options(),
'#default_value' => (int) $bundle_info['status'],
];
$form['xmlsitemap']['priority'] = [
'#type' => 'select',
'#title' => t('Default priority'),
'#options' => xmlsitemap_get_priority_options(),
'#default_value' => $bundle_info['priority'],
'#states' => [
'invisible' => [
'select[name="xmlsitemap[status]"]' => [
'value' => '0',
],
],
],
];
$form['xmlsitemap']['changefreq'] = [
'#type' => 'select',
'#title' => t('Default change frequency'),
'#options' => xmlsitemap_get_changefreq_options(),
'#default_value' => $bundle_info['changefreq'],
'#states' => [
'invisible' => [
'select[name="xmlsitemap[status]"]' => [
'value' => '0',
],
],
],
];
}
function xmlsitemap_get_priority_options($default = NULL, $guides = TRUE) {
$options = [];
$priorities = [
'1.0' => t('1.0'),
'0.9' => t('0.9'),
'0.8' => t('0.8'),
'0.7' => t('0.7'),
'0.6' => t('0.6'),
'0.5' => t('0.5'),
'0.4' => t('0.4'),
'0.3' => t('0.3'),
'0.2' => t('0.2'),
'0.1' => t('0.1'),
'0.0' => t('0.0'),
];
if (isset($default)) {
$default = number_format($default, 1);
$options['default'] = t('Default (@value)', [
'@value' => $priorities[$default],
]);
}
$options += $priorities;
if ($guides) {
$options['1.0'] .= ' ' . t('(highest)');
$options['0.5'] .= ' ' . t('(normal)');
$options['0.0'] .= ' ' . t('(lowest)');
}
return $options;
}
function xmlsitemap_get_status_options($default = NULL) {
$options = [];
$statuses = [
1 => t('Included'),
0 => t('Excluded'),
];
if (isset($default)) {
$default = $default ? 1 : 0;
$options['default'] = t('Default (@value)', [
'@value' => mb_strtolower($statuses[$default]),
]);
}
$options += $statuses;
return $options;
}
function xmlsitemap_get_current_chunk(XmlSitemapInterface $sitemap, Request $request = NULL) {
if (!isset($request)) {
$request = \Drupal::request();
}
$query = $request->query;
$query_page = $query
->get('page');
if (!isset($query_page) || !is_numeric($query_page)) {
if ($sitemap
->getChunks() > 1) {
return 'index';
}
else {
return 1;
}
}
else {
return (int) $query_page;
}
}
function xmlsitemap_output_file(Response $response, $file, array $headers = []) {
@trigger_error(__FUNCTION__ . ' is deprecated in xmlsitemap:8.x-1.0 and will be removed in xmlsitemap:2.0.0. Use \\Drupal\\xmlsitemap\\Controller\\XmlSitemapController::getSitemapResponse. See https://www.drupal.org/project/xmlsitemap/issues/2869214', E_USER_DEPRECATED);
$controller = \Drupal::classResolver(XmlSitemapController::class);
return $controller
->getSitemapResponse($file, \Drupal::request(), $headers + $response->headers
->all());
}
function _xmlsitemap_get_blurb($check_version = TRUE) {
static $blurb;
if (!isset($blurb)) {
$blurb = FALSE;
if (!$check_version || ($version = _xmlsitemap_get_version()) && preg_match('/dev|unstable|alpha|beta|HEAD/i', $version)) {
$sponsors = [
\Drupal::linkGenerator()
->generate('Symantec', Url::fromUri('http://www.symantec.com/', [
'attributes' => [
'target' => 'blank',
],
])),
\Drupal::linkGenerator()
->generate('WebWise Solutions', Url::fromUri('http://www.webwiseone.com/', [
'attributes' => [
'target' => 'blank',
],
])),
\Drupal::linkGenerator()
->generate('Volacci', Url::fromUri('http://www.volacci.com/', [
'attributes' => [
'target' => 'blank',
],
])),
\Drupal::linkGenerator()
->generate('lanetro', Url::fromUri('http://www.lanetro.com/', [
'attributes' => [
'target' => 'blank',
],
])),
\Drupal::linkGenerator()
->generate('Coupons Dealuxe', Url::fromUri('http://couponsdealuxe.com/', [
'attributes' => [
'target' => 'blank',
],
])),
];
$blurb = '<div class="description"><p>Thank you for helping test the XML sitemap module rewrite. Please consider helping offset developer free time by <a href="http://davereid.chipin.com/" target="blank">donating</a> or if your company is interested in sponsoring the rewrite or a specific feature, please <a href="http://davereid.net/contact" target="blank">contact the developer</a>. Thank you to the following current sponsors: ' . implode(', ', $sponsors) . ', and all the individuals that have donated. This message will not be seen in the stable versions.</p></div>';
}
}
return $blurb;
}
function _xmlsitemap_get_version() {
static $version;
if (!isset($version)) {
$modules = \Drupal::service('extension.list.module')
->getList();
$version = $modules['xmlsitemap']->info['version'];
}
return $version;
}
function xmlsitemap_check_status() {
$messages =& drupal_static(__FUNCTION__);
if (!isset($messages)) {
if ($cache = \Drupal::cache()
->get('xmlsitemap:registry:requirements')) {
$modules = $cache->data;
}
else {
$modules = [];
\Drupal::moduleHandler()
->loadAllIncludes('install');
foreach (\Drupal::moduleHandler()
->getImplementations('requirements') as $module) {
if (strpos($module, 'xmlsitemap') !== FALSE) {
$modules[] = $module;
}
}
\Drupal::cache()
->set('xmlsitemap:registry:requirements', $modules, Cache::PERMANENT, [
'xmlsitemap',
]);
}
$messages = [];
foreach ($modules as $module) {
module_load_install($module);
$requirements = \Drupal::moduleHandler()
->invoke($module, 'requirements', [
'runtime',
]);
foreach ($requirements as $requirement) {
if (isset($requirement['severity']) && max(REQUIREMENT_OK, $requirement['severity'])) {
$messages[] = $requirement['description'];
}
}
}
if ($messages) {
$messages = [
'#type' => 'item_list',
'#items' => [
$messages,
],
];
$message = t('One or more problems were detected with your XML sitemap configuration: @messages', [
'@messages' => \Drupal::service('renderer')
->render($messages),
]);
\Drupal::messenger()
->addWarning($message, FALSE);
if (\Drupal::currentUser()
->hasPermission('access site reports')) {
\Drupal::messenger()
->addWarning(t('Check the <a href="@status-report">status report</a> for more information.', [
'@status-report' => Url::fromRoute('system.status')
->toString(),
]), FALSE);
}
}
}
return !empty($messages);
}
function _xmlsitemap_regenerate_before() {
\Drupal::service('xmlsitemap_generator')
->regenerateBefore();
}
function xmlsitemap_regenerate_batch(array $smids = []) {
if (empty($smids)) {
$sitemaps = \Drupal::entityTypeManager()
->getStorage('xmlsitemap')
->loadMultiple();
foreach ($sitemaps as $sitemap) {
$smids[] = $sitemap
->id();
}
}
$t = 't';
$batch = [
'operations' => [],
'error_message' => $t('An error has occurred.'),
'finished' => 'xmlsitemap_regenerate_batch_finished',
'title' => t('Regenerating Sitemap'),
];
$batch['operations'][] = [
'xmlsitemap_batch_variable_set',
[
[
'xmlsitemap_regenerate_needed' => TRUE,
],
],
];
$batch['operations'][] = [
'_xmlsitemap_regenerate_before',
[],
];
foreach ($smids as $smid) {
$batch['operations'][] = [
'xmlsitemap_regenerate_batch_generate',
[
$smid,
],
];
$batch['operations'][] = [
'xmlsitemap_regenerate_batch_generate_index',
[
$smid,
],
];
}
$batch['operations'][] = [
'xmlsitemap_batch_variable_set',
[
[
'xmlsitemap_regenerate_needed' => FALSE,
],
],
];
return $batch;
}
function xmlsitemap_regenerate_batch_generate($smid, &$context = []) {
\Drupal::service('xmlsitemap_generator')
->regenerateBatchGenerate($smid, $context);
}
function xmlsitemap_regenerate_batch_generate_index($smid, &$context = []) {
\Drupal::service('xmlsitemap_generator')
->regenerateBatchGenerateIndex($smid, $context);
}
function xmlsitemap_regenerate_batch_finished($success, array $results, array $operations, $elapsed) {
\Drupal::service('xmlsitemap_generator')
->regenerateBatchFinished($success, $results, $operations, $elapsed);
}
function xmlsitemap_rebuild_batch(array $entity_type_ids, $save_custom = FALSE) {
$batch = [
'operations' => [],
'finished' => 'xmlsitemap_rebuild_batch_finished',
'title' => t('Rebuilding Sitemap'),
'file' => drupal_get_path('module', 'xmlsitemap') . '/xmlsitemap.generate.inc',
];
$batch['operations'][] = [
'xmlsitemap_batch_variable_set',
[
[
'xmlsitemap_rebuild_needed' => TRUE,
],
],
];
$batch['operations'][] = [
'xmlsitemap_rebuild_batch_clear',
[
$entity_type_ids,
(bool) $save_custom,
],
];
foreach ($entity_type_ids as $entity_type_id) {
$info = xmlsitemap_get_link_info($entity_type_id);
$batch['operations'][] = [
$info['xmlsitemap']['rebuild callback'],
[
$entity_type_id,
],
];
}
$batch['operations'][] = [
'xmlsitemap_batch_variable_set',
[
[
'xmlsitemap_rebuild_needed' => FALSE,
],
],
];
$regenerate_batch = xmlsitemap_regenerate_batch();
$batch['operations'] = array_merge($batch['operations'], $regenerate_batch['operations']);
return $batch;
}
function xmlsitemap_batch_variable_set(array $variables) {
\Drupal::service('xmlsitemap_generator')
->batchVariableSet($variables);
}
function xmlsitemap_rebuild_batch_clear(array $entity_type_ids, $save_custom, &$context = []) {
\Drupal::service('xmlsitemap_generator')
->rebuildBatchClear($entity_type_ids, $save_custom, $context);
}
function xmlsitemap_rebuild_batch_fetch($entity_type_id, &$context) {
\Drupal::service('xmlsitemap_generator')
->rebuildBatchFetch($entity_type_id, $context);
}
function xmlsitemap_rebuild_batch_finished($success, array $results, array $operations, $elapsed) {
\Drupal::service('xmlsitemap_generator')
->rebuildBatchFinished($success, $results, $operations, $elapsed);
}
function xmlsitemap_get_rebuildable_link_types() {
$rebuild_types = [];
$entities = xmlsitemap_get_link_info();
foreach ($entities as $entity => $info) {
if (empty($info['xmlsitemap']['rebuild callback'])) {
continue;
}
if (!empty($info['bundles']) && !xmlsitemap_get_link_type_enabled_bundles($entity)) {
continue;
}
$rebuild_types[] = $entity;
}
return $rebuild_types;
}
function xmlsitemap_link_bundle_enable($entity_type_id, $bundle_id) {
if (\Drupal::config("xmlsitemap.settings.{$entity_type_id}.{$bundle_id}")
->isNew()) {
$settings = [
'status' => XMLSITEMAP_STATUS_DEFAULT,
'priority' => XMLSITEMAP_PRIORITY_DEFAULT,
'changefreq' => 0,
];
xmlsitemap_link_bundle_settings_save($entity_type_id, $bundle_id, $settings);
}
return TRUE;
}
function xmlsitemap_link_bundle_check_enabled($entity_type_id, $bundle_id) {
return !\Drupal::config("xmlsitemap.settings.{$entity_type_id}.{$bundle_id}")
->isNew();
}
function xmlsitemap_link_entity_check_enabled($entity_type_id) {
$configuration = \Drupal::configFactory()
->listAll("xmlsitemap.settings.{$entity_type_id}.");
return !empty($configuration);
}
function metatag_xmlsitemap_link_alter(array &$link, array $context) {
$enabled =& drupal_static(__FUNCTION__);
if (!isset($enabled)) {
$enabled = \Drupal::config('xmlsitemap.settings')
->get('metatag_exclude_noindex');
}
if ($enabled && !empty($context['entity']) && $context['entity'] instanceof ContentEntityInterface && $link['access']) {
$metatagManager = \Drupal::service('metatag.manager');
$metatags = $metatagManager
->tagsFromEntity($context['entity']);
if (!empty($metatags['robots']) && strpos($metatags['robots'], 'noindex') !== FALSE) {
$link['access'] = FALSE;
}
}
}