diff --git a/domain_simple_sitemap.info.yml b/domain_simple_sitemap.info.yml index 6972f23..5fbf8aa 100644 --- a/domain_simple_sitemap.info.yml +++ b/domain_simple_sitemap.info.yml @@ -1,8 +1,7 @@ name: Domain Access Simple Sitemap type: module description: Module for generating sitemaps on domains with Domain Access module. -core: 8.x -core_version_requirement: ^8 || ^9 +core_version_requirement: ^9 || ^10 package: SEO configure: domain_simple_sitemap.settings dependencies: diff --git a/domain_simple_sitemap.module b/domain_simple_sitemap.module index b51b504..fd88f52 100644 --- a/domain_simple_sitemap.module +++ b/domain_simple_sitemap.module @@ -6,6 +6,9 @@ */ use Drupal\Core\Entity\EntityInterface; +use Drupal\Core\Entity\EntityTypeInterface; +use Drupal\Core\Form\FormStateInterface; +use Drupal\simple_sitemap\Entity\SimpleSitemapType; /** * Implements hook_ENTITY_TYPE_insert(). @@ -13,9 +16,7 @@ use Drupal\Core\Entity\EntityInterface; function domain_simple_sitemap_domain_insert(EntityInterface $domain) { /** @var \Drupal\domain_simple_sitemap\DomainSitemapManager $domainSitemapManager */ $domainSitemapManager = Drupal::service('domain_simple_sitemap.manager'); - if ($domain->isNew()) { - $domainSitemapManager->addSitemapVariant($domain); - } + $domainSitemapManager->addSitemapVariant($domain); } /** @@ -57,7 +58,7 @@ function domain_simple_sitemap_simple_sitemap_links_alter(array &$links, $sitema // Resolve this variant to a domain. $storage = \Drupal::entityTypeManager()->getStorage('domain'); - if ($domain = $storage->load($sitemap_variant)) { + if (isset($sitemap_variant->type) && $domain = $storage->load($sitemap_variant->type)) { // The base URL of the domain is also its path. $front = $domain->getPath(); // Load the domain's configuration to find the front page. @@ -81,3 +82,62 @@ function domain_simple_sitemap_simple_sitemap_links_alter(array &$links, $sitema } } } + +/** + * Implements hook_form_FORM_ID_alter(). + * + * Alter the sitemap variant edit form to select domain. + */ +function domain_simple_sitemap_form_simple_sitemap_type_edit_form_alter(&$form, FormStateInterface $form_state, $form_id) { + // Get the Simple Sitemap Type entity we are editing. + $simple_sitemap = $form_state->getformObject()->getEntity(); + // Create an options array of all domains. + $storage = \Drupal::entityTypeManager()->getStorage('domain'); + $domains = $storage->loadMultiple(); + $options = []; + foreach ($domains as $key => $domain) { + $options[$key] = $domain->label(); + } + + // Dont't allow multiple options on url_generator field becaus then the #states based on that field value wont work. + // $form['url_generators']['#multiple'] = FALSE; + // Create our domain select form element. + $form['sitemap_domain'] = [ + '#type' => 'select', + '#title' => t('Select domain for this sitemap'), + '#options' => $options, + '#default_value' => $simple_sitemap->getThirdPartySetting('domain_simple_sitemap', 'sitemap_domain'), + '#weight' => 1, + // '#states' => [ + // 'visible' => [ + // ':input[name="url_generators"]' => ['value' => 'domain_entity'], + // ], + // 'required' => [ + // ':input[name="url_generators"]' => ['value' => 'domain_entity'], + // ], + // ], + ]; + $form['#entity_builders'][] = '_domain_simple_sitemap_sitemap_type_form_builder'; +} + +/** + * Entity builder for the migration config entity. + */ +function _domain_simple_sitemap_sitemap_type_form_builder($entity_type, SimpleSitemapType $simple_sitemap, &$form, FormStateInterface $form_state) { + // If a domain was selected, save it as third party setting. + if ($form_state->getValue('sitemap_domain')) { + $simple_sitemap->setThirdPartySetting('domain_simple_sitemap', 'sitemap_domain', $form_state->getValue('sitemap_domain')); + return; + } + // If not, remove third party setting. + $simple_sitemap->unsetThirdPartySetting('domain_simple_sitemap', 'sitemap_domain'); +} + +/** + * @param EntityTypeInterface[] $entity_types + */ +function domain_simple_sitemap_entity_type_build(&$entity_types) { + if (isset($entity_types['simple_sitemap'])) { + $entity_types['simple_sitemap']->setClass('Drupal\domain_simple_sitemap\Entity\DomainSimpleSitemap'); + } +} diff --git a/domain_simple_sitemap.services.yml b/domain_simple_sitemap.services.yml index c5d2017..b0dc297 100644 --- a/domain_simple_sitemap.services.yml +++ b/domain_simple_sitemap.services.yml @@ -5,4 +5,4 @@ services: - { name: event_subscriber } domain_simple_sitemap.manager: class: Drupal\domain_simple_sitemap\DomainSitemapManager - arguments: ['@entity_type.manager', '@simple_sitemap.generator', '@domain.validator'] + arguments: ['@entity_type.manager', '@domain.validator'] diff --git a/src/Controller/DomainSimpleSitemapController.php b/src/Controller/DomainSimpleSitemapController.php index 32d5881..51cfbd9 100644 --- a/src/Controller/DomainSimpleSitemapController.php +++ b/src/Controller/DomainSimpleSitemapController.php @@ -2,24 +2,27 @@ namespace Drupal\domain_simple_sitemap\Controller; +use Drupal\Core\Cache\CacheableResponse; +use Drupal\Core\Entity\EntityTypeManagerInterface; use Drupal\domain\DomainNegotiatorInterface; -use Drupal\simple_sitemap\Controller\SimplesitemapController; -use Drupal\simple_sitemap\Simplesitemap; -use Drupal\simple_sitemap\SimplesitemapManager; +use Drupal\simple_sitemap\Controller\SimpleSitemapController; +use Drupal\simple_sitemap\Manager\EntityManager; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\HttpFoundation\Request; +use Drupal\simple_sitemap\Manager\Generator; +use Symfony\Component\HttpFoundation\Response; /** * Class DomainSimpleSitemapController. * * @package Drupal\simple_sitemap\Controller */ -class DomainSimpleSitemapController extends SimplesitemapController { +class DomainSimpleSitemapController extends SimpleSitemapController { /** * Drupal `simple_sitemap.generator` service. * - * @var \Drupal\simple_sitemap\Simplesitemap + * @var \Drupal\simple_sitemap\Manager\Generator */ protected $generator; @@ -31,36 +34,36 @@ class DomainSimpleSitemapController extends SimplesitemapController { protected $domainNegotiator; /** - * Drupal `simple_sitemap.manager` service. + * The entity type manager. * - * @var \Drupal\simple_sitemap\SimplesitemapManager + * @var \Drupal\Core\Entity\EntityTypeManagerInterface */ - protected $sitemapManager; + protected $entityTypeManager; /** * DomainSitemapController constructor. * - * @param \Drupal\simple_sitemap\Simplesitemap $generator - * Drupal `simple_sitemap.generator` service. + * @param \Drupal\simple_sitemap\Manager\Generator $generator + * The simple_sitemap.generator service. * @param \Drupal\domain\DomainNegotiatorInterface $domain_negoriator * Drupal `domain.negotiator` service. - * @param \Drupal\simple_sitemap\SimplesitemapManager $sitemap_manager - * Drupal `simple_sitemap.manager` service. + * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entityTypeManager + * The entity type manager. */ - public function __construct(Simplesitemap $generator, DomainNegotiatorInterface $domain_negoriator, SimplesitemapManager $sitemap_manager) { + public function __construct(Generator $generator, DomainNegotiatorInterface $domain_negoriator, EntityTypeManagerInterface $entityTypeManager) { $this->generator = $generator; $this->domainNegotiator = $domain_negoriator; - $this->sitemapManager = $sitemap_manager; + $this->entityTypeManager = $entityTypeManager; } /** * {@inheritdoc} */ - public static function create(ContainerInterface $container) { + public static function create(ContainerInterface $container): SimpleSitemapController { return new static( $container->get('simple_sitemap.generator'), $container->get('domain.negotiator'), - $container->get('simple_sitemap.manager') + $container->get('entity_type.manager') ); } @@ -69,21 +72,32 @@ class DomainSimpleSitemapController extends SimplesitemapController { * * {@inheritdoc} */ - public function getSitemap(Request $request, $variant = NULL) { + public function getSitemap(Request $request, ?string $variant = NULL): Response { if (empty($variant)) { $active_domain = $this->domainNegotiator->getActiveId(); if (!empty($active_domain)) { - $all_sitemap_variants = $this->sitemapManager - ->getSitemapVariants('domain'); + $sitemap_types = $this->entityTypeManager->getStorage('simple_sitemap_type')->loadMultiple(); - if (array_key_exists($active_domain, $all_sitemap_variants)) { - $variant = $active_domain; + foreach ($sitemap_types as $st_id => $sitemap_type) { + $st_domain = $sitemap_type->getThirdPartySetting('domain_simple_sitemap', 'sitemap_domain'); + if ($st_domain === $active_domain) { + $sitemap_variants = $this->entityTypeManager->getStorage('simple_sitemap')->loadByProperties(['type' => $st_id]); + foreach (array_keys($sitemap_variants) as $sitemap_variant) { + $variant = $sitemap_variant; + } + } } + } } - return parent::getSitemap($request, $variant); + $response = parent::getSitemap($request, $variant); + if ($response instanceof CacheableResponse) { + $response->getCacheableMetadata() + ->addCacheContexts(['url']); + } + return $response; } } diff --git a/src/DomainSitemapManager.php b/src/DomainSitemapManager.php index b06f99a..a4358f7 100644 --- a/src/DomainSitemapManager.php +++ b/src/DomainSitemapManager.php @@ -5,7 +5,7 @@ namespace Drupal\domain_simple_sitemap; use Drupal\Core\Entity\EntityTypeManagerInterface; use Drupal\domain\DomainInterface; use Drupal\domain\DomainValidatorInterface; -use Drupal\simple_sitemap\Simplesitemap; +use Drupal\simple_sitemap\Entity\SimpleSitemapType; /** * The service for domain_simple_sitemap module. @@ -21,13 +21,6 @@ class DomainSitemapManager { */ protected $entityTypeManager; - /** - * The simple sitemap generator. - * - * @var \Drupal\simple_sitemap\Simplesitemap - */ - protected $simpleSitemapManager; - /** * The domain validator. * @@ -40,18 +33,14 @@ class DomainSitemapManager { * * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entityTypeManager * The entity type manager. - * @param \Drupal\simple_sitemap\Simplesitemap $simpleSitemapManager - * The simple sitemap manager. * @param \Drupal\domain\DomainValidatorInterface $domainValidator * The domain validator service. */ public function __construct( EntityTypeManagerInterface $entityTypeManager, - Simplesitemap $simpleSitemapManager, DomainValidatorInterface $domainValidator ) { $this->entityTypeManager = $entityTypeManager; - $this->simpleSitemapManager = $simpleSitemapManager; $this->domainValidator = $domainValidator; } @@ -62,56 +51,53 @@ class DomainSitemapManager { * The domain to validate for syntax and uniqueness. */ public function addSitemapVariant(DomainInterface $domain) { - // Create an sitemap variant. - $manager = $this->simpleSitemapManager->getSitemapManager(); - $manager->addSitemapVariant($domain->id(), [ - 'type' => 'domain', - 'label' => $domain->label(), - ]); - // Generate the site map. - $generator = $manager->getSitemapGenerator('default'); - $generator->setSitemapVariant($domain->id()); - $generator->setSettings(['excluded_languages' => [], 'xsl' => TRUE]); - if ($domain->status()) { - $generator->generate([]); - $generator->publish(); + // Test if it does not already exist. + $sitemap_type = SimpleSitemapType::load($domain->id()); + if (!is_null($sitemap_type)) { + \Drupal::logger('domain_simple_sitemap')->notice('Failed creating new sitemap type because it already exists: ' . $domain->id()); + return; } + // Create a new sitemap type for the domain. + $type_storage = \Drupal::entityTypeManager()->getStorage('simple_sitemap_type'); + if ($type_storage->load($domain->id()) === NULL) { + $domain_sitemap = $type_storage->create([ + 'id' => $domain->id(), + 'label' => $domain->label() . ' sitemap', + 'description' => 'Sitemap type for domain: ' . $domain->label(), + 'sitemap_generator' => 'default', + 'url_generators' => [ + 'domain_entity', + 'custom', + 'entity', + 'entity_menu_link_content', + 'arbitrary', + ], + ]); + // Set the domain to the sitemap type via third party settings. + $domain_sitemap->setThirdPartySetting('domain_simple_sitemap', 'sitemap_domain', $domain->id()); + // Save our new sitemap type. + $domain_sitemap->save(); + } + + // Generate the site map. + /** @var \Drupal\simple_sitemap\Manager\Generator $generator */ + $generator = \Drupal::service('simple_sitemap.generator'); + $generator + ->rebuildQueue() + ->generate(); } /** * Delete sitemap variant for domain. * * @param \Drupal\domain\DomainInterface $domain - * The domain to validate for syntax and uniqueness. + * The domain of which to delete the sitemap type from. */ public function deleteSitemapVariant(DomainInterface $domain) { - // Remove the sitemap variant. - $manager = $this->simpleSitemapManager->getSitemapManager(); - $manager->removeSitemapVariants([$domain->id()]); - // Remove the sitemap. - $generator = $manager->getSitemapGenerator('default'); - $generator->setSitemapVariant($domain->id()); - $generator->setSettings(['excluded_languages' => []]); - $generator->remove(); - } - - /** - * Checks a domain exists by trying to do an http request to it. - * - * @param \Drupal\domain\DomainInterface $domain - * The domain to validate for syntax and uniqueness. - * - * @return int - * The server response code for the request. - * - * @see domain_validate() - */ - private function checkDomain(DomainInterface $domain) { - $response = $this->domainValidator->checkResponse($domain); - if ($response >= 200 && $response <= 299) { - return TRUE; + $sitemap_type = SimpleSitemapType::load($domain->id()); + if ($sitemap_type) { + $sitemap_type->delete(); } - return FALSE; } } diff --git a/src/Entity/DomainSimpleSitemap.php b/src/Entity/DomainSimpleSitemap.php new file mode 100644 index 0000000..61c9163 --- /dev/null +++ b/src/Entity/DomainSimpleSitemap.php @@ -0,0 +1,47 @@ + $options['delta']] : []; + unset($options['delta']); + + if (empty($options['base_url'])) { + /** @var \Drupal\simple_sitemap\Settings $settings */ + $settings = \Drupal::service('simple_sitemap.settings'); + $options['base_url'] = $settings->get('base_url') ?: $GLOBALS['base_url']; + + $storage = \Drupal::entityTypeManager()->getStorage('domain'); + $domains = $storage->loadMultiple(); + $sitemap_type = $this->get('type'); + + // Try to get domain's path. + foreach ($domains as $key => $domain) { + if ($key == $sitemap_type) { + $options['base_url'] = rtrim($domain->getPath(), '/'); + } + } + } + $options['language'] = $this->languageManager()->getLanguage(LanguageInterface::LANGCODE_NOT_APPLICABLE); + + return Url::fromRoute( + 'simple_sitemap.sitemap_default', + $parameters, + $options); + } + +} diff --git a/src/Form/DomainSimpleSitemapConfigForm.php b/src/Form/DomainSimpleSitemapConfigForm.php index 2e0cffc..6a0f53d 100644 --- a/src/Form/DomainSimpleSitemapConfigForm.php +++ b/src/Form/DomainSimpleSitemapConfigForm.php @@ -116,7 +116,7 @@ class DomainSimpleSitemapConfigForm extends ConfigFormBase { ]; $form['domain_sitemap_variants'] = [ - '#markup' => Link::createFromRoute('You can check existing sitemap variants of domains', 'simple_sitemap.sitemaps') + '#markup' => Link::createFromRoute('You can check existing sitemap variants of domains', 'entity.simple_sitemap.collection') ->toString(), ]; @@ -206,7 +206,7 @@ class DomainSimpleSitemapConfigForm extends ConfigFormBase { ->setProgressMessage($this->t('Completed @current of @total.')) ->setErrorMessage($this->t('An error has occurred.')); - $this->batchBuilder->setFile(drupal_get_path('module', 'domain_simple_sitemap') . '/src/Form/DomainSimpleSitemapConfigForm.php'); + $this->batchBuilder->setFile(\Drupal::service('extension.list.module')->getPath('domain_simple_sitemap') . '/src/Form/DomainSimpleSitemapConfigForm.php'); $this->batchBuilder->addOperation([ $this, 'batchProcess', diff --git a/src/Plugin/simple_sitemap/UrlGenerator/DomainEntityUrlGenerator.php b/src/Plugin/simple_sitemap/UrlGenerator/DomainEntityUrlGenerator.php index 19eaa24..0ebab51 100644 --- a/src/Plugin/simple_sitemap/UrlGenerator/DomainEntityUrlGenerator.php +++ b/src/Plugin/simple_sitemap/UrlGenerator/DomainEntityUrlGenerator.php @@ -3,7 +3,6 @@ namespace Drupal\domain_simple_sitemap\Plugin\simple_sitemap\UrlGenerator; use Drupal\Core\Url; -use Drupal\domain\Entity\Domain; use Drupal\domain_access\DomainAccessManagerInterface; use Drupal\simple_sitemap\Plugin\simple_sitemap\UrlGenerator\EntityUrlGenerator; @@ -22,207 +21,134 @@ class DomainEntityUrlGenerator extends EntityUrlGenerator { /** * {@inheritdoc} */ - public function getDataSets() { + public function getDataSets(): array { $data_sets = []; $sitemap_entity_types = $this->entityHelper->getSupportedEntityTypes(); + $all_bundle_settings = $this->entitiesManager->setVariants($this->sitemap->id())->getAllBundleSettings(); + $domainStorage = \Drupal::entityTypeManager()->getStorage('domain'); + $original_domain = \Drupal::service('domain.negotiator')->getActiveDomain(); + + if (isset($all_bundle_settings[$this->sitemap->id()])) { + foreach ($all_bundle_settings[$this->sitemap->id()] as $entity_type_name => $bundles) { + if (!isset($sitemap_entity_types[$entity_type_name])) { + continue; + } - foreach ($this->generator - ->setVariants($this->sitemapVariant) - ->getBundleSettings() as $entity_type_name => $bundles) { - if (isset($sitemap_entity_types[$entity_type_name])) { - // Skip this entity type - // if another plugin is written to override its generation. - foreach ($this->urlGeneratorManager->getDefinitions() as $plugin) { - if (isset($plugin['settings']['overrides_entity_type']) - && $plugin['settings']['overrides_entity_type'] === $entity_type_name) { - continue 2; - } + if ($this->isOverwrittenForEntityType($entity_type_name)) { + continue; } $entityTypeStorage = $this->entityTypeManager->getStorage($entity_type_name); $keys = $sitemap_entity_types[$entity_type_name]->getKeys(); foreach ($bundles as $bundle_name => $bundle_settings) { - // Skip if "Content type" is excluded for selected Variant - // (Index entities of this type in /admin/structure/types/manage/page) - if (!empty($bundle_settings['index'])) { - $query = $entityTypeStorage->getQuery(); + if ($bundle_settings['index']) { + $query = $entityTypeStorage->getQuery()->accessCheck(FALSE); - if (empty($keys['id'])) { - $query->sort($keys['id'], 'ASC'); + if (!empty($keys['id'])) { + $query->sort($keys['id']); } if (!empty($keys['bundle'])) { $query->condition($keys['bundle'], $bundle_name); } - if (!empty($keys['status'])) { + if (!empty($keys['published'])) { + $query->condition($keys['published'], 1); + } + elseif (!empty($keys['status'])) { $query->condition($keys['status'], 1); } - $activeId = \Drupal::service('domain.negotiator')->getActiveId(); - $domainSource = "field_domain_source"; - - if (!empty($keys['bundle'])) { - if ($keys['bundle'] == 'type' && $entity_type_name == 'node') { - $source_only = \Drupal::config('domain_simple_sitemap.settings') - ->get('domain_simple_sitemap_filter'); - if ($source_only) { - // Filter by Node Domain source. - $query->condition($domainSource . '.target_id', $activeId); - } - else { - // Filtered by Node Domain access. - $orGroupDomain = $query->orConditionGroup() - ->condition(DomainAccessManagerInterface::DOMAIN_ACCESS_FIELD . '.target_id', $activeId) - ->condition(DomainAccessManagerInterface::DOMAIN_ACCESS_ALL_FIELD, 1); - $query->condition($orGroupDomain); - } - foreach ($query->execute() as $entity_id) { - $data_sets[] = [ - 'entity_type' => $entity_type_name, - 'id' => $entity_id, - 'domain_source' => $activeId, - ]; - } - } - elseif ($keys['bundle'] == 'vid' && $entity_type_name == 'taxonomy_term') { - // For taxonomy. - foreach ($query->execute() as $entity_id) { - $data_sets[] = [ - 'entity_type' => $entity_type_name, - 'id' => $entity_id, - 'domain_source' => $activeId, - ]; - } + // Get the selected domain for the sitemap type. + $sitemap_domain_id = $this->sitemap->getType()->getThirdPartySetting('domain_simple_sitemap', 'sitemap_domain'); + if (!$sitemap_domain_id) { + continue; + } + // Activate the domain. + $domain = $domainStorage->load($sitemap_domain_id); + \Drupal::service('domain.negotiator')->setActiveDomain($domain); + // Filter nodes based on their Domain Access settings. + $domain_entity = FALSE; + $all_bundle_fields = \Drupal::service('entity_field.manager')->getFieldDefinitions($entity_type_name, $bundle_name); + if (\Drupal::service('module_handler')->moduleExists('domain_entity')) { + if (array_key_exists(\Drupal\domain_entity\DomainEntityMapper::FIELD_NAME, $all_bundle_fields)) { + // Setting this query tag will cause the domain_entity module + // to alter the query to add domain access conditions. + $query->addTag($entity_type_name . '_access'); + $domain_entity = TRUE; } - else { - // For all other bundles. - foreach ($query->execute() as $entity_id) { - $data_sets[] = [ - 'entity_type' => $entity_type_name, - 'id' => $entity_id, - 'domain_source' => $activeId, - ]; - } + } + if (!$domain_entity && array_key_exists(DomainAccessManagerInterface::DOMAIN_ACCESS_FIELD, $all_bundle_fields)) { + $orGroupDomain = $query->orConditionGroup() + ->condition(DomainAccessManagerInterface::DOMAIN_ACCESS_FIELD, $sitemap_domain_id) + ->condition(DomainAccessManagerInterface::DOMAIN_ACCESS_ALL_FIELD, 1); + $query->condition($orGroupDomain); + } + + // Shift access check to EntityUrlGeneratorBase for language + // specific access. + // See https://www.drupal.org/project/simple_sitemap/issues/3102450. + $query->accessCheck(FALSE); + + $data_set = [ + 'entity_type' => $entity_type_name, + 'id' => [], + 'domain' => $sitemap_domain_id, + ]; + $entities = []; + foreach ($query->execute() as $entity_id) { + $entities[] = $entity_id; + $data_set['id'][] = $entity_id; + if (count($data_set['id']) >= $this->entitiesPerDataset) { + $data_sets[] = $data_set; + $data_set['id'] = []; } } + + // Add the last data set if there are some IDs gathered. + if (!empty($data_set['id'])) { + $data_sets[] = $data_set; + } } } } } + \Drupal::service('domain.negotiator')->setActiveDomain($original_domain); return $data_sets; } + /** * {@inheritdoc} */ - protected function processDataSet($data_set) { - // Equal $entity->id(). - $entity_id = $data_set['id']; - // Equal $entity->getEntityTypeId(). - $entity_type_name = $data_set['entity_type']; - $entity_source = $data_set['domain_source']; - - if (empty($entity = $this->entityTypeManager->getStorage($entity_type_name) - ->load($entity_id))) { - return FALSE; - } - - // Remove Entity of other sources. - if ($this->sitemapVariant != $entity_source) { - return FALSE; + public function generate($data_set): array { + $original_domain = \Drupal::service('domain.negotiator')->getActiveDomain(); + // Set active domain to the one matching the dataset. + if (isset($data_set['domain'])) { + $domainStorage = \Drupal::entityTypeManager()->getStorage('domain'); + $domain = $domainStorage->load($data_set['domain']); + \Drupal::service('domain.negotiator')->setActiveDomain($domain); } - $entity_settings = $this->generator - ->setVariants($this->sitemapVariant) - ->getEntityInstanceSettings($entity_type_name, $entity_id); - - if (empty($entity_settings['index'])) { - return FALSE; - } - - // Domain & URL variables. - $url_object = $entity->toUrl(); - $url_object->setOption('absolute', TRUE); - - // Do not include external paths. - if (!$url_object->isRouted()) { - return FALSE; - } - - $path = $url_object->getInternalPath(); - $url_object->setOption('absolute', TRUE); - // Photos. - $url_photo_formatted = ""; - if (!empty($entity_settings['include_images'])) { - $url_photo = $this->getImages($this->sitemapVariant, $entity_type_name, $entity_id); - if (!empty($url_photo)) { - $url_photo_formatted = Url::fromUri($url_photo); + $path_data_sets = $this->processDataSet($data_set); + $url_variant_sets = []; + foreach ($path_data_sets as $path_data) { + if (isset($path_data['url']) && $path_data['url'] instanceof Url) { + $url_object = $path_data['url']; + unset($path_data['url']); + $url_variant_sets[] = $this->getUrlVariants($path_data, $url_object); } } - $paths = []; - $paths[] = [ - 'url' => $url_object, - 'lastmod' => method_exists($entity, 'getChangedTime') ? date('c', $entity->getChangedTime()) : NULL, - 'priority' => isset($entity_settings['priority']) ? $entity_settings['priority'] : NULL, - 'changefreq' => !empty($entity_settings['changefreq']) ? $entity_settings['changefreq'] : NULL, - 'images' => !empty($url_photo_formatted) ? $url_photo_formatted : [], - // Additional info useful in hooks. - 'meta' => [ - 'path' => $path, - 'entity_info' => [ - 'entity_type' => $entity_type_name, - 'id' => $entity_id, - ], - ], - ]; - return $paths; - } - - /** - * Set Sitemap Variant for specific domain. - * - * @param string $sitemap_variant - * The sitemap variant. - * - * @return $this - */ - public function setSitemapVariant($sitemap_variant) { - parent::setSitemapVariant($sitemap_variant); - $domain = Domain::load($sitemap_variant); - \Drupal::service('domain.negotiator')->setActiveDomain($domain); - return $this; - } - - /** - * Get images field from entity's fields. - * - * @param string $current_variant - * The current sitemap variant. - * @param string $entity_type_name - * The entity name of type. - * @param mixed $entity_id - * The Entity ID. - * - * @return string - * A string containing a URL that may be used to access the image file. - */ - protected function getImages($current_variant, $entity_type_name, $entity_id) { - $term_obj = $this->entityTypeManager->getStorage($entity_type_name) - ->load($entity_id); - // TODO : change "field_photo" by something not specific. - if (empty($term_obj)) { - return ""; - } - if ($term_obj->hasField('field_image') && isset($term_obj->get('field_image')->entity)) { - return file_create_url($term_obj->get('field_image')->entity->getFileUri()); - } - elseif ($term_obj->hasField('field_photo') && isset($term_obj->get('field_photo')->entity)) { - return file_create_url($term_obj->get('field_photo')->entity->getFileUri()); - } - elseif ($term_obj->hasField('field_img') && isset($term_obj->get('field_img')->entity)) { - return file_create_url($term_obj->get('field_img')->entity->getFileUri()); + // Make sure to clear entity memory cache so it does not build up resulting + // in a constant increase of memory. + // See https://www.drupal.org/project/simple_sitemap/issues/3170261 and + // https://www.drupal.org/project/simple_sitemap/issues/3202233 + if ($this->entityTypeManager->getDefinition($data_set['entity_type'])->isStaticallyCacheable()) { + $this->entityMemoryCache->deleteAll(); } + + \Drupal::service('domain.negotiator')->setActiveDomain($original_domain); + return array_merge([], ...$url_variant_sets); } /** @@ -234,7 +160,8 @@ class DomainEntityUrlGenerator extends EntityUrlGenerator { * @return string * A replaced URL. */ - protected function replaceBaseUrlWithCustom($url) { + protected function replaceBaseUrlWithCustom(string $url): string { + /** @var \Drupal\domain\DomainInterface $domain */ $domain = \Drupal::service('domain.negotiator')->getActiveDomain(); $url_parts = explode("/", $url); /* diff --git a/src/Routing/RouteSubscriber.php b/src/Routing/RouteSubscriber.php index 0892f69..1e1181f 100644 --- a/src/Routing/RouteSubscriber.php +++ b/src/Routing/RouteSubscriber.php @@ -18,11 +18,9 @@ class RouteSubscriber extends RouteSubscriberBase { * {@inheritdoc} */ public function alterRoutes(RouteCollection $collection) { - if ($route = $collection->get('simple_sitemap.sitemap_default')) { - $route->setDefaults([ - '_controller' => '\Drupal\domain_simple_sitemap\Controller\DomainSimpleSitemapController::getSitemap', - ]); - } + if ($route = $collection->get('simple_sitemap.sitemap_default')) { + $route->setDefault('_controller', '\Drupal\domain_simple_sitemap\Controller\DomainSimpleSitemapController::getSitemap'); + } } }