Commit 6f19dd67 authored by voleger's avatar voleger Committed by RenatoG
Browse files

Issue #3033569 by voleger, RenatoG: Remove xmlsitemap.module.orig file

parent 3d3c2043
<?php
/**
* @file
* @defgroup xmlsitemap XML sitemap
*/
/**
* @file
* Main file for the xmlsitemap module.
*/
use Drupal\Component\Utility\Crypt;
use Drupal\Component\Utility\Unicode;
use Drupal\Component\Utility\UrlHelper;
use Drupal\Core\Cache\Cache;
use Drupal\Core\Database\Query\AlterableInterface;
use Drupal\Core\Entity\ContentEntityInterface;
use Drupal\Core\Entity\ContentEntityTypeInterface;
use Drupal\Core\Entity\EntityForm;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\Query\QueryInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Language\LanguageInterface;
use Drupal\Core\Link;
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\Core\Url;
use Drupal\xmlsitemap\Entity\XmlSitemap;
use Drupal\xmlsitemap\XmlSitemapInterface;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
/**
* The maximum number of links in one sitemap chunk file.
*/
const XMLSITEMAP_MAX_SITEMAP_LINKS = 50000;
/**
* The maximum filesize of a sitemap chunk file.
*/
const XMLSITEMAP_MAX_SITEMAP_FILESIZE = 10485760;
/**
* Xmlsitemap Frequencies.
*/
const XMLSITEMAP_FREQUENCY_YEARLY = 31449600;
// 60 * 60 * 24 * 7 * 52.
const XMLSITEMAP_FREQUENCY_MONTHLY = 2419200;
// 60 * 60 * 24 * 7 * 4.
const XMLSITEMAP_FREQUENCY_WEEKLY = 604800;
// 60 * 60 * 24 * 7.
const XMLSITEMAP_FREQUENCY_DAILY = 86400;
// 60 * 60 * 24.
const XMLSITEMAP_FREQUENCY_HOURLY = 3600;
// 60 * 60.
const XMLSITEMAP_FREQUENCY_ALWAYS = 60;
/**
* Short lastmod timestamp format.
*/
const XMLSITEMAP_LASTMOD_SHORT = 'Y-m-d';
/**
* Medium lastmod timestamp format.
*/
const XMLSITEMAP_LASTMOD_MEDIUM = 'Y-m-d\TH:i\Z';
/**
* Long lastmod timestamp format.
*/
const XMLSITEMAP_LASTMOD_LONG = 'c';
/**
* The default inclusion status for link types in the sitemaps.
*/
const XMLSITEMAP_STATUS_DEFAULT = 0;
/**
* The default priority for link types in the sitemaps.
*/
const XMLSITEMAP_PRIORITY_DEFAULT = 0.5;
/**
* Implements hook_hook_info().
*/
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_link_bundle_access_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;
}
/**
* Implements hook_help().
*/
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')) {
// Alert the user to any potential problems detected by hook_requirements.
$output .= _xmlsitemap_get_blurb();
}
return $output;
}
/**
* Implements hook_theme().
*/
function xmlsitemap_theme() {
return [
'xmlsitemap_content_settings_table' => [
'render element' => 'element',
'file' => 'xmlsitemap.module',
],
];
}
/**
* Menu access callback; determines if the user can use the rebuild links page.
*
* @return bool
* Returns TRUE if current user can access rebuild form. FALSE otherwise.
*/
function _xmlsitemap_rebuild_form_access() {
$rebuild_types = xmlsitemap_get_rebuildable_link_types();
return !empty($rebuild_types) && \Drupal::currentUser()->hasPermission('administer xmlsitemap');
}
/**
* Implements hook_cron().
*
* @todo Use new Queue system. Need to add {sitemap}.queued.
* @todo Regenerate one at a time?
*/
function xmlsitemap_cron() {
// If cron sitemap file regeneration is disabled, stop.
if (\Drupal::config('xmlsitemap.settings')->get('disable_cron_regeneration')) {
return;
}
// If there were no new or changed links, skip.
if (!\Drupal::state()->get('xmlsitemap_regenerate_needed')) {
return;
}
// If the minimum sitemap lifetime hasn't been passed, skip.
$lifetime = REQUEST_TIME - \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'));
// Regenerate the sitemap XML files.
xmlsitemap_run_unprogressive_batch('xmlsitemap_regenerate_batch');
}
/**
* Implements hook_modules_installed().
*/
function xmlsitemap_modules_installed(array $modules) {
Cache::invalidateTags(['xmlsitemap']);
}
/**
* Implements hook_modules_uninstalled().
*/
function xmlsitemap_modules_uninstalled(array $modules) {
Cache::invalidateTags(['xmlsitemap']);
}
/**
* Implements hook_robotstxt().
*/
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;
}
}
/**
* Internal default variables config for xmlsitemap_var().
*
* @return array
* Array with config variables of xmlsitemap.settings config object.
*/
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,
];
}
/**
* Internal default variables state for xmlsitemap_var().
*
* @return array
* Array with state variables defined by xmlsitemap module.
*/
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,
];
}
/**
* Internal implementation of variable_get().
*/
function xmlsitemap_var($name, $default = NULL) {
$defaults = &drupal_static(__FUNCTION__);
if (!isset($defaults)) {
$defaults = xmlsitemap_config_variables();
$defaults += xmlsitemap_state_variables();
}
// @todo Remove when stable.
if (!isset($defaults[$name])) {
trigger_error(strtr('Default variable for %variable not found.', ['%variable' => drupal_placeholder($name)]));
}
if (\Drupal::state()->get($name, NULL) === NULL) {
return \Drupal::config('xmlsitemap.settings')->get($name);
}
return \Drupal::state()->get($name);
}
/**
* @defgroup xmlsitemap_api XML sitemap API.
* @{
* This is the XML sitemap API to be used by modules wishing to work with
* XML sitemap and/or link data.
*/
/**
* Load an XML sitemap array from the database.
*
* @param mixed $smid
* An XML sitemap ID.
*
* @return \Drupal\xmlsitemap\XmlSitemapInterface
* The XML sitemap object.
*/
function xmlsitemap_sitemap_load($smid) {
$sitemap = xmlsitemap_sitemap_load_multiple([$smid]);
return $sitemap ? reset($sitemap) : FALSE;
}
/**
* Load multiple XML sitemaps from the database.
*
* @param array|bool $smids
* An array of XML sitemap IDs, or FALSE to load all XML sitemaps.
* @param array $conditions
* An array of conditions in the form 'field' => $value.
*
* @return \Drupal\xmlsitemap\XmlSitemapInterface[]
* An array of XML sitemap objects.
*/
function xmlsitemap_sitemap_load_multiple($smids = [], array $conditions = []) {
if ($smids !== FALSE) {
$conditions['smid'] = $smids;
}
else {
$conditions['smid'] = NULL;
}
$storage = Drupal::entityTypeManager()->getStorage('xmlsitemap');
/** @var \Drupal\xmlsitemap\XmlSitemapInterface[] $sitemaps */
$sitemaps = $storage->loadMultiple($conditions['smid']);
if (count($sitemaps) <= 0) {
return [];
}
return $sitemaps;
}
/**
* Save changes to an XML sitemap or add a new XML sitemap.
*
* @param Drupal\xmlsitemap\XmlSitemapInterface $sitemap
* The XML sitemap array to be saved. If $sitemap->smid is omitted, a new
* XML sitemap will be added.
*
* @todo Save the sitemap's URL as a column?
*/
function xmlsitemap_sitemap_save(XmlSitemapInterface $sitemap) {
$context = $sitemap->context;
if (!isset($context) || !$context) {
$sitemap->context = [];
}
// Make sure context is sorted before saving the hash.
$sitemap->setOriginalId($sitemap->isNew() ? NULL : $sitemap->getId());
$sitemap->setId(xmlsitemap_sitemap_get_context_hash($context));
// If the context was changed, we need to perform additional actions.
if (!$sitemap->isNew() && $sitemap->getId() != $sitemap->getOriginalId()) {
// Rename the files directory so the sitemap does not break.
$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);
// Mark the sitemaps as needing regeneration.
\Drupal::state()->set('xmlsitemap_regenerate_needed', TRUE);
}
$sitemap->save();
return $sitemap;
}
/**
* Delete an XML sitemap.
*
* @param string $smid
* An XML sitemap ID.
*/
function xmlsitemap_sitemap_delete($smid) {
xmlsitemap_sitemap_delete_multiple([$smid]);
}
/**
* Delete multiple XML sitemaps.
*
* @param array $smids
* An array of XML sitemap IDs.
*/
function xmlsitemap_sitemap_delete_multiple(array $smids) {
if (!empty($smids)) {
$sitemaps = xmlsitemap_sitemap_load_multiple($smids);
foreach ($sitemaps as $sitemap) {
//xmlsitemap_clear_directory($sitemap, TRUE);
$sitemap->delete();
\Drupal::moduleHandler()->invokeAll('xmlsitemap_sitemap_delete', [$sitemap]);
}
}
}
/**
* Return the expected file path for a specific sitemap chunk.
*
* @param Drupal\xmlsitemap\XmlSitemapInterface $sitemap
* An XmlSitemapInterface sitemap object.
* @param string $chunk
* An optional specific chunk in the sitemap. Defaults to the index page.
*
* @return string
* File path for a specific sitemap chunk.
*/
function xmlsitemap_sitemap_get_file(XmlSitemapInterface $sitemap, $chunk = 'index') {
return xmlsitemap_get_directory($sitemap) . "/{$chunk}.xml";
}
/**
* Find the maximum file size of all a sitemap's XML files.
*
* @param \Drupal\xmlsitemap\XmlSitemapInterface $sitemap
* The XML sitemap object.
*/
function xmlsitemap_sitemap_get_max_filesize(XmlSitemapInterface $sitemap) {
$dir = xmlsitemap_get_directory($sitemap);
$sitemap->setMaxFileSize(0);
foreach (file_scan_directory($dir, '/\.xml$/') as $file) {
$sitemap->setMaxFileSize(max($sitemap->getMaxFileSize(), filesize($file->uri)));
}
return $sitemap->getMaxFileSize();
}
/**
* Returns the hash string for a context.
*
* @param array $context
* Context to be hashed.
*
* @return string
* Hash string for the context.
*/
function xmlsitemap_sitemap_get_context_hash(array &$context) {
ksort($context);
return Crypt::hashBase64(serialize($context));
}
/**
* Returns the uri elements of an XML sitemap.
*
* @param \Drupal\xmlsitemap\XmlSitemapInterface $sitemap
* The sitemap represented by and XmlSitemapInterface object.
*
* @return array
* An array containing the 'path' and 'options' keys used to build the uri of
* the XML sitemap, and matching the signature of url().
*/
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' => \Drupal::state()->get('xmlsitemap_base_url'),
];
return $uri;
}
/**
* @} End of "defgroup xmlsitemap_api"
*/
function xmlsitemap_get_directory(XmlSitemapInterface $sitemap = NULL) {
$directory = &drupal_static(__FUNCTION__);
if (!isset($directory)) {
$directory = \Drupal::config('xmlsitemap.settings')->get('path');
}
if (empty($directory)) {
return FALSE;
}
elseif ($sitemap != NULL && !empty($sitemap->id)) {
return file_build_uri($directory . '/' . $sitemap->id);
}
else {
return file_build_uri($directory);
}
}
/**
* Check that the sitemap files directory exists and is writable.
*/
function xmlsitemap_check_directory(XmlSitemapInterface $sitemap = NULL) {
$directory = xmlsitemap_get_directory($sitemap);
$result = file_prepare_directory($directory, FILE_CREATE_DIRECTORY | FILE_MODIFY_PERMISSIONS);
if (!$result) {
\Drupal::logger('file system')->error('The directory %directory does not exist or is not writable.', ['%directory' => $directory]);
}
return $result;
}
/**
* Check all directories.
*/
function xmlsitemap_check_all_directories() {
$directories = [];
$sitemaps = xmlsitemap_sitemap_load_multiple(FALSE);
foreach ($sitemaps as $sitemap) {
$directory = xmlsitemap_get_directory($sitemap);
$directories[$directory] = $directory;
}
foreach ($directories as $directory) {
$result = file_prepare_directory($directory, FILE_CREATE_DIRECTORY | FILE_MODIFY_PERMISSIONS);
if ($result) {
$directories[$directory] = TRUE;
}
else {
$directories[$directory] = FALSE;
}
}
return $directories;
}
/**
* Clears sitemap directory.
*
* @param \Drupal\xmlsitemap\XmlSitemapInterface $sitemap
* Sitemap entity.
* @param bool $delete
* If TRUE, delete the path directory afterwards.
*
* @return bool
* Returns TRUE is operation was successful, FALSE otherwise.
*/
function xmlsitemap_clear_directory(XmlSitemapInterface $sitemap = NULL, $delete = FALSE) {
if ($directory = xmlsitemap_get_directory($sitemap)) {
return _xmlsitemap_delete_recursive($directory, $delete);
}
else {
return FALSE;
}
}
/**
* Move a directory to a new location.
*
* @param string $old_dir
* A string specifying the filepath or URI of the original directory.
* @param string $new_dir
* A string specifying the filepath or URI of the new directory.
* @param int $replace
* Behavior when the destination file already exists.
* Replace behavior when the destination file already exists.
*
* @return bool
* TRUE if the directory was moved successfully. FALSE otherwise.
*/
function xmlsitemap_directory_move($old_dir, $new_dir, $replace = FILE_EXISTS_REPLACE) {
$success = file_prepare_directory($new_dir, FILE_CREATE_DIRECTORY | FILE_MODIFY_PERMISSIONS);
$old_path = drupal_realpath($old_dir);
$new_path = drupal_realpath($new_dir);
if (!is_dir($old_path) || !is_dir($new_path) || !$success) {
return FALSE;
}
$files = file_scan_directory($old_dir, '/.*/');
foreach ($files as $file) {
$file->uri_new = $new_dir . '/' . basename($file->filename);
$success &= (bool) file_unmanaged_move($file->uri, $file->uri_new, $replace);
}
// The remove the directory.
$success &= \Drupal::service('file_system')->rmdir($old_dir);
return $success;
}
/**
* Recursively delete all files and folders in the specified filepath.
*
* This is a backport of Drupal 8's file_unmanaged_delete_recursive().
*
* Note that this only deletes visible files with write permission.
*
* @param string $path
* A filepath relative to the Drupal root directory.
* @param bool $delete_root
* A boolean if TRUE will delete the $path directory afterwards.
*
* @return bool
* TRUE if operation was successful, FALSE otherwise.
*/
function _xmlsitemap_delete_recursive($path, $delete_root = FALSE) {
// Resolve streamwrapper URI to local path.
$path = drupal_realpath($path);
if (is_dir($path)) {
$dir = dir($path);
while (($entry = $dir->read()) !== FALSE) {
if ($entry == '.' || $entry == '..') {
continue;
}
$entry_path = $path . '/' . $entry;
file_unmanaged_delete_recursive($entry_path, NULL);
}
$dir->close();
return $delete_root ? \Drupal::service('file_system')->rmdir($path) : TRUE;
}
return file_unmanaged_delete($path);
}
/**
* Returns information about supported sitemap link types.
*
* @param mixed $type
* (optional) The link type to return information for. If omitted,
* information for all link types is returned.
* @param mixed $reset
* (optional) Boolean whether to reset the static cache and do nothing. Only
* used for tests.
*
* @return array
* Info about sitemap link.
*
* @see hook_xmlsitemap_link_info()
* @see hook_xmlsitemap_link_info_alter()
*/
function xmlsitemap_get_link_info($type = NULL, $reset = FALSE) {
$language = \Drupal::languageManager()->getCurrentLanguage();
$link_info = &drupal_static(__FUNCTION__);
if ($reset) {
$link_info = NULL;
foreach (\Drupal::languageManager()->getLanguages() as $lang) {
\Drupal::cache()->delete('xmlsitemap:link_info:' . $lang->getId());
}
}