sites_simple_sitemap-1.0.0-alpha4/src/Queue/QueueWorkerDecorator.php
src/Queue/QueueWorkerDecorator.php
<?php
namespace Drupal\sites_simple_sitemap\Queue;
use Drupal\Component\Utility\Timer;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Extension\ModuleHandlerInterface;
use Drupal\Core\KeyValueStore\KeyValueFactoryInterface;
use Drupal\Core\Lock\LockBackendInterface;
use Drupal\simple_sitemap\Entity\SimpleSitemap;
use Drupal\simple_sitemap\Logger;
use Drupal\simple_sitemap\Queue\QueueWorker;
use Drupal\simple_sitemap\Queue\SimpleSitemapQueue;
use Drupal\simple_sitemap\Settings;
use Drupal\sites\SitePluginManager;
use Drupal\sites_simple_sitemap\SitesSimpleSitemapService;
/**
* The sites_simple_sitemap.simple_sitemap.queue_worker service.
*/
class QueueWorkerDecorator extends QueueWorker {
/**
* QueueWorkerDecorator constructor.
*
* @param \Drupal\simple_sitemap\Settings $settings
* The simple_sitemap.settings service.
* @param \Drupal\Core\KeyValueStore\KeyValueFactoryInterface $key_value
* The Key/Value factory service.
* @param \Drupal\simple_sitemap\Queue\SimpleSitemapQueue $element_queue
* Simple XML Sitemap queue handler.
* @param \Drupal\simple_sitemap\Logger $logger
* Simple XML Sitemap logger.
* @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
* The module handler service.
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
* The entity type manager.
* @param \Drupal\Core\Lock\LockBackendInterface $lock
* The lock backend that should be used.
* @param \Drupal\sites\SitePluginManager $siteManager
* The site manager.
* @param \Drupal\sites_simple_sitemap\SitesSimpleSitemapService $sitesSimpleSitemapService
* The default sitemap manager.
*/
public function __construct(
Settings $settings,
KeyValueFactoryInterface $key_value,
SimpleSitemapQueue $element_queue,
Logger $logger,
ModuleHandlerInterface $module_handler,
EntityTypeManagerInterface $entity_type_manager,
LockBackendInterface $lock,
protected readonly SitePluginManager $siteManager,
protected readonly SitesSimpleSitemapService $sitesSimpleSitemapService,
) {
parent::__construct($settings, $key_value, $element_queue, $logger, $module_handler, $entity_type_manager, $lock);
}
/**
* {@inheritdoc}
*/
public function rebuildQueue($sitemaps = []): QueueWorkerDecorator {
if (!empty($sites_sitemaps = $this->sitesSimpleSitemapService->generateSitesSitemaps($sitemaps))) {
$sitemaps = array_merge($sitemaps, $sites_sitemaps);
}
return parent::rebuildQueue($sitemaps);
}
/**
* {@inheritdoc}
*/
public function generate(string $from = self::GENERATE_TYPE_FORM): QueueWorkerDecorator {
$this->generatorSettings = [
'base_url' => $this->settings->get('base_url', ''),
'xsl' => $this->settings->get('xsl', TRUE),
'default_variant' => $this->settings->get('default_variant'),
'skip_untranslated' => $this->settings->get('skip_untranslated', FALSE),
'remove_duplicates' => $this->settings->get('remove_duplicates', TRUE),
'excluded_languages' => $this->settings->get('excluded_languages', []),
];
$this->maxLinks = $this->settings->get('max_links', 2000);
$max_execution_time = $this->settings->get('generate_duration', 10000);
Timer::start('simple_sitemap_generator');
$this->unstashResults();
if (!$this->generationInProgress()) {
$this->rebuildQueue(SimpleSitemap::loadMultiple());
}
// Acquire a lock for max execution time + 5 seconds. If max_execution time
// is unlimited then lock for 1 hour.
$lock_timeout = $max_execution_time > 0 ? ($max_execution_time / 1000) + 5 : static::GENERATE_LOCK_TIMEOUT;
if (!$this->lock->acquire(static::LOCK_ID, $lock_timeout)) {
throw new \RuntimeException('Unable to acquire a lock for sitemap generation');
}
foreach ($this->queue->yieldItem() as $element) {
if (!empty($max_execution_time) && Timer::read('simple_sitemap_generator') >= $max_execution_time) {
break;
}
try {
if ($this->sitemapProcessedNow && !$this->sitemapProcessedNow->isEnabled()) {
$this->queue->deleteItem($element);
$this->elementsRemaining--;
continue;
}
if ($this->sitemapProcessedNow === NULL || $element->data['sitemap'] !== $this->sitemapProcessedNow->id()) {
if (NULL !== $this->sitemapProcessedNow) {
$this->generateSitemapChunksFromResults(TRUE);
$this->publishCurrentSitemap();
}
$this->processedPaths = [];
// The differences to the parent method are in the following method.
if (!$this->setProcessedSitemap($element)) {
continue;
}
}
$this->generateResultsFromElement($element);
if (!empty($this->maxLinks) && count($this->results) >= $this->maxLinks) {
$this->generateSitemapChunksFromResults();
}
}
catch (\Exception $e) {
watchdog_exception('simple_sitemap', $e);
}
// @todo May want to use deleteItems() instead.
$this->queue->deleteItem($element);
$this->elementsRemaining--;
}
if ($this->getQueuedElementCount() === 0) {
$this->generateSitemapChunksFromResults(TRUE);
$this->publishCurrentSitemap();
}
else {
$this->stashResults();
}
$this->lock->release(static::LOCK_ID);
return $this;
}
/**
* Set the processed sitemap.
*
* @param mixed $element
* Element to process.
*
* @return bool
* TRUE if the sitemap was set, FALSE otherwise.
*/
protected function setProcessedSitemap($element) {
// Load the parent sitemap entity.
$parent_sitemap_id = strtok($element->data['sitemap'], ':');
if (($this->sitemapProcessedNow = $this->entityTypeManager->getStorage('simple_sitemap')->load($parent_sitemap_id)) === NULL) {
$this->queue->deleteItem($element);
$this->elementsRemaining--;
return FALSE;
}
// Change the sitemap ID to original.
$this->sitemapProcessedNow->set('id', $element->data['sitemap']);
return TRUE;
}
}
