Unverified Commit 51e0081e authored by Dave Reid's avatar Dave Reid

Merge branch '8.x-1.x' into 2.x

parents 9c5ca515 db623fda
......@@ -3,13 +3,15 @@
namespace Drupal\xmlsitemap\Controller;
use Drupal\Component\Serialization\Json;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Controller\ControllerBase;
use Drupal\Core\State\StateInterface;
use Drupal\xmlsitemap\Entity\XmlSitemap;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Drupal\Core\State\StateInterface;
use Symfony\Component\HttpFoundation\BinaryFileResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
/**
* Class for Xml Sitemap Controller.
......@@ -26,14 +28,24 @@ class XmlSitemapController extends ControllerBase {
*/
protected $state;
/**
* The configuration factory.
*
* @var \Drupal\Core\Config\ConfigFactoryInterface
*/
protected $configFactory;
/**
* Constructs a new XmlSitemapController object.
*
* @param \Drupal\Core\State\StateInterface $state
* The state service.
* @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
* The configuration factory.
*/
public function __construct(StateInterface $state) {
public function __construct(StateInterface $state, ConfigFactoryInterface $config_factory) {
$this->state = $state;
$this->configFactory = $config_factory;
}
/**
......@@ -41,7 +53,8 @@ class XmlSitemapController extends ControllerBase {
*/
public static function create(ContainerInterface $container) {
return new static(
$container->get('state')
$container->get('state'),
$container->get('config.factory')
);
}
......@@ -51,11 +64,12 @@ class XmlSitemapController extends ControllerBase {
* @param \Symfony\Component\HttpFoundation\Request $request
* The request object.
*
* @throws \Symfony\Component\HttpKernel\Exception\NotFoundHttpException
*
* @return \Symfony\Component\HttpFoundation\Response
* @return \Symfony\Component\HttpFoundation\BinaryFileResponse
* The sitemap in XML format or plain text if xmlsitemap_developer_mode flag
* is set.
*
* @throws \Symfony\Component\HttpKernel\Exception\NotFoundHttpException
* If the sitemap is not found or the sitemap file is not readable.
*/
public function renderSitemapXml(Request $request) {
$headers = [];
......@@ -82,13 +96,59 @@ class XmlSitemapController extends ControllerBase {
$headers['X-XmlSitemap-Cache-Hit'] = file_exists($file) ? 'HIT' : 'MISS';
}
return $this->getSitemapResponse($file, $request, $headers);
}
/**
* Creates a response object that will output the sitemap file.
*
* @param string $file
* File uri.
* @param \Symfony\Component\HttpFoundation\Request $request
* The current request.
* @param array $headers
* An array of response headers
*
* @return \Symfony\Component\HttpFoundation\BinaryFileResponse
* The sitemap response object.
*
* @throws \Symfony\Component\HttpKernel\Exception\NotFoundHttpException
* If the sitemap is not found or the sitemap file is not readable.
*/
public function getSitemapResponse($file, Request $request, array $headers = []) {
if (!is_file($file) || !is_readable($file)) {
$exception = new NotFoundHttpException();
$exception->setHeaders($headers);
throw $exception;
}
return xmlsitemap_output_file(new Response(), $file, $headers);
$headers += [
'Content-Type' => 'text/xml; charset=utf-8',
'X-Robots-Tag' => 'noindex, follow',
];
$lifetime = $this->configFactory->get('xmlsitemap.settings')->get('minimum_lifetime');
$response = new BinaryFileResponse($file, 200, $headers);
$response->setPrivate();
$response->headers->addCacheControlDirective('must-revalidate');
//if ($lifetime) {
// $response->headers->addCacheControlDirective('max-age', $lifetime);
//}
// Manually set the etag value instead of hashing the contents of the file.
$last_modified = $response->getFile()->getMTime();
$response->setEtag(md5($last_modified));
// Set expiration using the minimum lifetime.
$response->setExpires(new \DateTime('@' . ($last_modified + $lifetime)));
// Because we do not want this page to be cached, we manually check the
// modified headers.
$response->isNotModified($request);
return $response;
}
/**
......@@ -122,10 +182,10 @@ class XmlSitemapController extends ControllerBase {
$xsl_content = strtr($xsl_content, $replacements);
// Output the XSL content.
$response = new Response($xsl_content);
$response->headers->set('Content-type', 'application/xml; charset=utf-8');
$response->headers->set('X-Robots-Tag', 'noindex, nofollow');
return $response;
return new Response($xsl_content, 200, [
'Content-Type' => 'application/xml; charset=utf-8',
'X-Robots-Tag' => 'noindex, nofollow',
]);
}
}
......@@ -72,16 +72,7 @@ class XmlSitemapLinkBundleSettingsForm extends ConfigFormBase {
$this->bundle_type = $bundle;
$request = $this->getRequest();
if (!$request->isXmlHttpRequest() && $admin_path = xmlsitemap_get_bundle_path($entity, $bundle)) {
// If this is a non-ajax form, redirect to the bundle administration page.
$destination = $this->getDestinationArray();
$request->query->remove('destination');
$url = Url::fromUri($admin_path, ['query' => [$destination]]);
return new RedirectResponse($url);
}
else {
$form['#title'] = $this->t('@bundle XML sitemap settings', ['@bundle' => $bundle]);
}
$form['#title'] = $this->t('@bundle XML sitemap settings', ['@bundle' => $bundle]);
xmlsitemap_add_link_bundle_settings($form, $form_state, $entity, $bundle);
$form['xmlsitemap']['#type'] = 'markup';
......
......@@ -8,6 +8,7 @@ use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Database\Connection;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Extension\ModuleHandlerInterface;
use Drupal\Core\File\Exception\DirectoryNotReadyException;
use Drupal\Core\File\FileSystemInterface;
use Drupal\Core\Language\LanguageInterface;
use Drupal\Core\Language\LanguageManagerInterface;
......@@ -402,7 +403,9 @@ class XmlSitemapGenerator implements XmlSitemapGeneratorInterface {
$context['sandbox']['max'] = XMLSITEMAP_MAX_SITEMAP_LINKS;
// Clear the cache directory for this sitemap before generating any files.
xmlsitemap_check_directory($context['sandbox']['sitemap']);
if (!xmlsitemap_check_directory($context['sandbox']['sitemap'])) {
throw new DirectoryNotReadyException("The sitemap directory could not be created or is not writable.");
}
xmlsitemap_clear_directory($context['sandbox']['sitemap']);
}
......@@ -523,17 +526,18 @@ class XmlSitemapGenerator implements XmlSitemapGeneratorInterface {
}
$info = $context['sandbox']['info'];
$entity_type = $this->entityTypeManager->getDefinition($entity_type_id);
$query = $this->entityTypeManager->getStorage($entity_type_id)->getQuery();
$query->condition($entity_type->getKey('id'), $context['sandbox']['last_id'], '>');
if ($entity_type->hasKey('bundle')) {
$query->condition($entity_type->getKey('bundle'), $context['sandbox']['bundles'], 'IN');
$query->condition($info['entity keys']['id'], $context['sandbox']['last_id'], '>');
if (!empty($info['entity keys']['bundle'])) {
$query->condition($info['entity keys']['bundle'], $context['sandbox']['bundles'], 'IN');
}
$query->addTag('xmlsitemap_link_bundle_access');
// Access for entities is checked individually for the anonymous user
// when each item is processed. We can skip the access check for the
// query.
$query->accessCheck(FALSE);
$query->addTag('xmlsitemap_rebuild');
$query->addMetaData('entity_type_id', $entity_type_id);
$query->addMetaData('entity_info', $info);
if (!isset($context['sandbox']['max'])) {
$count_query = clone $query;
......@@ -546,7 +550,7 @@ class XmlSitemapGenerator implements XmlSitemapGeneratorInterface {
}
// PostgreSQL cannot have the ORDERED BY in the count query.
$query->sort($entity_type->getKey('id'));
$query->sort($info['entity keys']['id']);
// Get batch limit.
$limit = $this->config->get('batch_limit');
......
......@@ -29,23 +29,8 @@ class DirectoryTest extends KernelTestBase {
$fileSystem->saveData('File unrelated to XML sitemap', 'public://file.txt');
$fileSystem->saveData('Test contents', 'public://xmlsitemap/test/index.xml');
// Set the directory to an empty value.
\Drupal::configFactory()->getEditable('xmlsitemap.settings')->clear('path')->save();
drupal_static_reset('xmlsitemap_get_directory');
$result = xmlsitemap_clear_directory(NULL, TRUE);
// Test that nothing was deleted.
$this->assertFileExists('public://xmlsitemap/test/index.xml');
$this->assertDirectoryExists('public://not-xmlsitemap');
$this->assertFileExists('public://file.txt');
$this->assertFalse($result);
// Reset the value back to the default.
\Drupal::configFactory()->getEditable('xmlsitemap.settings')->set('path', 'xmlsitemap')->save();
drupal_static_reset('xmlsitemap_get_directory');
$result = xmlsitemap_clear_directory(NULL, TRUE);
// Test that only the xmlsitemap directory was deleted.
$result = xmlsitemap_clear_directory(NULL, TRUE);
$this->assertDirectoryNotExists('public://xmlsitemap/test');
$this->assertDirectoryExists('public://not-xmlsitemap');
$this->assertFileExists('public://file.txt');
......
......@@ -28,11 +28,6 @@ function hook_xmlsitemap_link_info() {
'bundles' => [
'mysubtype1' => [
'label' => t('My subtype 1'),
// If your bundles have an administrative UI, list it.
'admin' => [
'real path' => 'admin/settings/mymodule/mysubtype1/edit',
'access arguments' => ['administer mymodule'],
],
'xmlsitemap' => [
'status' => XMLSITEMAP_STATUS_DEFAULT,
'priority' => XMLSITEMAP_PRIORITY_DEFAULT,
......
......@@ -21,8 +21,6 @@ use Drupal\Core\Entity\ContentEntityInterface;
use Drupal\Core\Entity\ContentEntityTypeInterface;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\Core\Entity\Query\QueryInterface;
use Drupal\Core\File\Exception\FileException;
use Drupal\Core\File\FileSystemInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Language\LanguageInterface;
......@@ -30,11 +28,10 @@ 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;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
/**
* The maximum number of links in one sitemap chunk file.
......@@ -107,7 +104,7 @@ function xmlsitemap_hook_info() {
'xmlsitemap_sitemap_delete',
'xmlsitemap_sitemap_link_url_options_alter',
'query_xmlsitemap_generate_alter',
'query_xmlsitemap_link_bundle_access_alter',
'query_xmlsitemap_index_links_alter',
'form_xmlsitemap_sitemap_edit_form_alter',
'xmlsitemap_rebuild_clear',
];
......@@ -429,13 +426,7 @@ function xmlsitemap_sitemap_get_max_filesize(XmlSitemapInterface $sitemap) {
$sitemap->setMaxFileSize(0);
/** @var \Drupal\Core\File\FileSystemInterface $file_system */
$file_system = \Drupal::service('file_system');
try {
$files = $file_system->scanDirectory($dir, '/\.xml$/');
}
catch (FileException $e) {
// Ignore and return empty array for BC.
$files = [];
}
$files = $file_system->scanDirectory($dir, '/\.xml$/');
foreach ($files as $file) {
$sitemap->setMaxFileSize(max($sitemap->getMaxFileSize(), filesize($file->uri)));
}
......@@ -484,13 +475,10 @@ function xmlsitemap_sitemap_uri(XmlSitemapInterface $sitemap) {
function xmlsitemap_get_directory(XmlSitemapInterface $sitemap = NULL) {
$directory = &drupal_static(__FUNCTION__);
if (!isset($directory)) {
$directory = \Drupal::config('xmlsitemap.settings')->get('path');
$directory = \Drupal::config('xmlsitemap.settings')->get('path') ?: 'xmlsitemap';
}
if (empty($directory)) {
return FALSE;
}
elseif ($sitemap != NULL && !empty($sitemap->id)) {
if ($sitemap != NULL && !empty($sitemap->id)) {
return file_build_uri($directory . '/' . $sitemap->id);
}
else {
......@@ -505,7 +493,7 @@ function xmlsitemap_check_directory(XmlSitemapInterface $sitemap = NULL) {
$directory = xmlsitemap_get_directory($sitemap);
/** @var \Drupal\Core\File\FileSystemInterface $filesystem */
$filesystem = \Drupal::service('file_system');
$result = $filesystem->prepareDirectory($directory, $filesystem::CREATE_DIRECTORY | $filesystem::MODIFY_PERMISSIONS);
$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]);
}
......@@ -552,12 +540,8 @@ function xmlsitemap_check_all_directories() {
* 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;
}
$directory = xmlsitemap_get_directory($sitemap);
return _xmlsitemap_delete_recursive($directory, $delete);
}
/**
......@@ -621,7 +605,7 @@ function _xmlsitemap_delete_recursive($path, $delete_root = FALSE) {
if (is_dir($path)) {
$dir = dir($path);
while (($entry = $dir->read()) !== FALSE) {
if ($entry == '.' || $entry == '..') {
if ($entry === '.' || $entry === '..') {
continue;
}
$entry_path = $path . '/' . $entry;
......@@ -646,6 +630,9 @@ function xmlsitemap_entity_type_build(array &$entity_types) {
'comment',
// Shortcut items.
'shortcut',
// Custom Token module.
// @see https://www.drupal.org/project/token_custom/issues/3150038
'token_custom',
];
/** @var $entity_types \Drupal\Core\Entity\EntityTypeInterface[] */
......@@ -747,6 +734,11 @@ function xmlsitemap_get_link_info($type = NULL, $reset = FALSE) {
'id' => $entity_type->getKey('id'),
'bundle' => $entity_type->getKey('bundle'),
],
'xmlsitemap' => [
// Add in the default callbacks for entity types.
'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',
],
];
}
......@@ -757,12 +749,6 @@ function xmlsitemap_get_link_info($type = NULL, $reset = FALSE) {
'base table' => FALSE,
'bundles' => [],
];
if (!isset($info['xmlsitemap']['process callback']) && !empty($info['entity keys'])) {
$info['xmlsitemap']['process callback'] = 'xmlsitemap_xmlsitemap_process_entity_links';
}
if (!isset($info['xmlsitemap']['rebuild callback']) && !empty($info['entity keys']['id'])) {
$info['xmlsitemap']['rebuild callback'] = 'xmlsitemap_rebuild_batch_fetch';
}
foreach ($info['bundles'] as $bundle => &$bundle_info) {
$bundle_info += [
'xmlsitemap' => [],
......@@ -787,7 +773,16 @@ function xmlsitemap_get_link_info($type = NULL, $reset = FALSE) {
// Cache by language since this info contains translated strings.
// Also include entity type tags since this is tied to entity and bundle
// information.
\Drupal::cache()->set($cid, $link_info, Cache::PERMANENT, ['xmlsitemap', 'entity_types', 'entity_bundles']);
\Drupal::cache()->set(
$cid,
$link_info,
Cache::PERMANENT,
[
'xmlsitemap',
'entity_types',
'entity_bundles',
]
);
}
}
......@@ -840,18 +835,13 @@ function xmlsitemap_get_link_type_indexed_status($entity_type_id, $bundle = '')
try {
$query = \Drupal::entityQuery($entity_type_id);
if ($bundle) {
$query->condition($entity_type->getKey('bundle'), $bundle, '=');
if ($bundle && $entity_type->hasKey('bundle')) {
$query->condition($entity_type->getKey('bundle'), $bundle);
}
$query->addTag('xmlsitemap_link_bundle_access');
// We are only using this for totals, so we can skip the access check.
$query->accessCheck(FALSE);
$query->addTag('xmlsitemap_link_indexed_status');
$query->addMetaData('entity_type_id', $entity_type_id);
$query->addMetaData('bundle', $bundle);
$query->addMetaData('entity_info', $info);
$query->count();
$status['total'] = $query->execute();
$status['total'] = $query->count()->execute();
return $status;
}
catch (\Exception $e) {
......@@ -986,28 +976,13 @@ function xmlsitemap_link_bundle_delete($entity, $bundle, $delete_links = TRUE) {
*
* @return bool
* If TRUE, access is allowed, FALSE otherwise.
*
* @deprecated in xmlsitemap:8.x-1.1 and is removed from xmlsitemap:2.0.0.
*
* @see https://www.drupal.org/project/xmlsitemap/issues/3156088
*/
function xmlsitemap_link_bundle_access($entity, $bundle = NULL) {
if (is_array($entity) && !isset($bundle)) {
$bundle = $entity;
}
else {
$bundle = xmlsitemap_link_bundle_load($entity, $bundle);
}
if (isset($bundle['info']['admin'])) {
$admin = $bundle['info']['admin'];
$admin += ['access arguments' => []];
if (!isset($admin['access callback']) && count($admin['access arguments']) == 1) {
$admin['access callback'] = 'user_access';
}
if (!empty($admin['access callback'])) {
return call_user_func_array($admin['access callback'], $admin['access arguments']);
}
}
@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;
}
......@@ -1021,19 +996,14 @@ function xmlsitemap_link_bundle_access($entity, $bundle = NULL) {
*
* @return mixed
* Path of bundle, or FALSE if it does not exist.
*
* @deprecated in xmlsitemap:8.x-1.1 and is removed from xmlsitemap:2.0.0.
*
* @see https://www.drupal.org/project/xmlsitemap/issues/3156088
*/
function xmlsitemap_get_bundle_path($entity, $bundle) {
$info = xmlsitemap_get_link_info($entity);
if (!empty($info['bundles'][$bundle]['admin']['real path'])) {
return $info['bundles'][$bundle]['admin']['real path'];
}
elseif (!empty($info['bundles'][$bundle]['admin']['path'])) {
return $info['bundles'][$bundle]['admin']['path'];
}
else {
return FALSE;
}
@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;
}
/**
......@@ -1208,7 +1178,7 @@ function xmlsitemap_form_submit_flag_regenerate(array $form, FormStateInterface
*
* @param array $form
* Form array.
* @param string $entity
* @param string $entity_type
* Entity type id.
* @param string $bundle
* Bundle id.
......@@ -1217,14 +1187,12 @@ function xmlsitemap_form_submit_flag_regenerate(array $form, FormStateInterface
*
* @todo Add changefreq overridability.
*/
function xmlsitemap_add_form_link_options(array &$form, $entity, $bundle, $id) {
$info = xmlsitemap_get_link_info($entity);
if (!$link = \Drupal::service('xmlsitemap.link_storage')->load($entity, $id)) {
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, $bundle);
$bundle_info = xmlsitemap_link_bundle_load($entity_type, $bundle);
$link += [
'access' => 1,
'status' => $bundle_info['status'],
......@@ -1237,27 +1205,17 @@ function xmlsitemap_add_form_link_options(array &$form, $entity, $bundle, $id) {
];
$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') || xmlsitemap_link_bundle_access($bundle_info),
'#access' => $currentUser->hasPermission('administer xmlsitemap') || ($admin_permission && $currentUser->hasPermission($admin_permission)),
'#group' => 'advanced',
];
if (xmlsitemap_link_bundle_access($bundle_info) && $path = xmlsitemap_get_bundle_path($entity, $bundle)) {
$form['xmlsitemap']['description'] = [
'#prefix' => '<div class="description">',
'#suffix' => '</div>',
'#markup' => t('The default XML sitemap settings for this @bundle can be changed <a href="@link-type">here</a>.', [
'@bundle' => mb_strtolower($info['bundle label']),
'@link-type' => Url::fromUri($path, ['query' => \Drupal::destination()->getAsArray()])->toString(),
]),
];
}
// Show a warning if the link is not accessible and will not be included in
// the sitemap.
if ($id && !$link['access']) {
......@@ -1630,38 +1588,56 @@ function xmlsitemap_form_alter(array &$form, FormStateInterface $form_state, $fo
function xmlsitemap_xmlsitemap_index_links($limit) {
$entity_type_manager = \Drupal::entityTypeManager();
$entity_types = $entity_type_manager->getDefinitions();
$bundles = \Drupal::service('entity_type.bundle.info')->getAllBundleInfo();
foreach ($entity_types as $entity_type_id => $entity_type) {
// Don't try to loop over non-content entity types or with no bundle
// defined.
if (!$entity_type instanceof ContentEntityTypeInterface || !isset($bundles[$entity_type_id])) {
// If an entity type is not supported it will not have link info.
$info = xmlsitemap_get_link_info($entity_type_id);
if (empty($info)) {
continue;
}
$entity_bundles = [];
foreach ($bundles[$entity_type_id] as $bundle => $bundle_info) {
if (!xmlsitemap_link_bundle_check_enabled($entity_type_id, $bundle)) {
continue;
}
$entity_bundles[] = $bundle;
}
if (empty($entity_bundles)) {
$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 ($entity_type->hasKey('bundle')) {
$bundle_key = $entity_type->getKey('bundle');
$query->condition($bundle_key, $entity_bundles, 'IN');
if (!empty($info['entity keys']['bundle'])) {
$query->condition($info['entity keys']['bundle'], $bundles, 'IN');
}
$ids = $query->execute();
// Chunk the array into batch sizes.
$chunks = array_chunk($ids, \Drupal::config('xmlsitemap.settings')->get('batch_limit'));
foreach ($chunks as $chunk) {
xmlsitemap_xmlsitemap_process_entity_links($entity_type_id, $chunk);
// Perform a subquery against the xmlsitemap table to ensure that we are
// only looking for items that we have not already indexed.
$subquery = \Drupal::database()->select('xmlsitemap', 'x');
$subquery->addField('x', 'id');
$subquery->condition('type', $entity_type_id);
// If the storage for this entity type is against a SQL backend, perform
// a direct subquery condition to avoid needing to load all the IDs.
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');
}
// Access for entities is checked individually for the anonymous user
// when each item is processed. We can skip the access check for the
// query.
$query->accessCheck(FALSE);
$query->addTag('xmlsitemap_index_links');
if ($ids = $query->execute()) {
// Chunk the array into batch sizes.
$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) {
......@@ -2021,24 +1997,6 @@ function xmlsitemap_xmlsitemap_sitemap_operations() {
return $operations;
}
/**
* Implements hook_query_TAG_alter().
*
* @todo Check if this query alter is still needed.
*/
function xmlsitemap_query_xmlsitemap_link_bundle_access_alter(AlterableInterface $query) {
if ($query instanceof QueryInterface && $entity_type_id = $query->getMetaData('entity_type_id')) {
$entity_type = \Drupal::entityTypeManager()->getDefinition($entity_type_id);
if ($entity_type->hasKey('bundle')) {
$bundle = $query->getMetaData('bundle');
if (empty($bundle)) {
$bundle = xmlsitemap_get_link_type_enabled_bundles($entity_type_id);
}
$query->condition($entity_type->getKey('bundle'), $bundle, is_array($bundle) ? 'IN' : '=');
}
}
}
/**
* XML sitemap link type settings callback for frontpage link entity.
*
......@@ -2335,90 +2293,23 @@ function xmlsitemap_get_current_chunk(XmlSitemapInterface $sitemap, Request $req
* @param array $headers
* Headers of the response.
*
* @throws \Symfony\Component\HttpKernel\Exception\NotFoundHttpException
* Throws an exception when sitemap xml file does not exist.
*