From 938eef8b783ecbcc0fc58d5639b4eaae51fb3ce2 Mon Sep 17 00:00:00 2001 From: Andrew Welch Date: Wed, 19 Jun 2024 17:09:01 -0400 Subject: [PATCH 01/15] refactor: Skip validation if `typeId` or others are empty --- src/models/MetaBundle.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/models/MetaBundle.php b/src/models/MetaBundle.php index 5d9596002..01273131e 100644 --- a/src/models/MetaBundle.php +++ b/src/models/MetaBundle.php @@ -274,6 +274,7 @@ public function rules(): array ], 'number', 'min' => 1, + 'skipOnEmpty' => true, ], [ [ From 0902f2a1eee47316238ebd995e1e3476f72fe531 Mon Sep 17 00:00:00 2001 From: Andrew Welch Date: Thu, 20 Jun 2024 15:54:35 -0400 Subject: [PATCH 02/15] refactor: Up the memory limit --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 3bc6600a3..ad6fb64b8 100644 --- a/composer.json +++ b/composer.json @@ -63,7 +63,7 @@ "vlucas/phpdotenv": "^3.0" }, "scripts": { - "phpstan": "phpstan --ansi --memory-limit=1G", + "phpstan": "phpstan --ansi --memory-limit=2G", "check-cs": "ecs check --ansi", "fix-cs": "ecs check --fix --ansi", "test": "codecept run unit --coverage-xml" From 1442449fe3e63988ac0574e907c3a5e769cdef00 Mon Sep 17 00:00:00 2001 From: "Hector D. Byrd" Date: Mon, 8 Jul 2024 09:50:33 +0300 Subject: [PATCH 03/15] feat: Paginated sitemaps - Add `sitemapPageSize` Sitemap setting - Remove the `GenerateSiteamp` queue job --- src/console/controllers/SitemapController.php | 35 ++-- src/controllers/SitemapController.php | 9 +- src/helpers/Sitemap.php | 153 +++++++++--------- src/jobs/GenerateSitemap.php | 89 ---------- src/models/MetaSitemapVars.php | 6 + src/models/SitemapIndexTemplate.php | 44 +++-- src/models/SitemapTemplate.php | 101 ++++++------ src/services/Helper.php | 4 +- src/services/Sitemaps.php | 6 +- .../_includes/fields/_sitemapPageSize.twig | 53 ++++++ .../settings/_includes/tab-sitemap.twig | 18 ++- 11 files changed, 269 insertions(+), 249 deletions(-) delete mode 100644 src/jobs/GenerateSitemap.php create mode 100644 src/templates/settings/_includes/fields/_sitemapPageSize.twig diff --git a/src/console/controllers/SitemapController.php b/src/console/controllers/SitemapController.php index 6384bc005..d4eedd7de 100644 --- a/src/console/controllers/SitemapController.php +++ b/src/console/controllers/SitemapController.php @@ -83,6 +83,7 @@ public function actionGenerate() foreach ($siteIds as $siteId) { $metaBundles = Seomatic::$plugin->metaBundles->getContentMetaBundlesForSiteId($siteId); Seomatic::$plugin->metaBundles->pruneVestigialMetaBundles($metaBundles); + /** @var MetaBundle $metaBundle */ foreach ($metaBundles as $metaBundle) { $process = false; @@ -97,17 +98,33 @@ public function actionGenerate() . ', siteId ' . $siteId . PHP_EOL; - // Generate the sitemap so it is in the cache + + $seoElement = Seomatic::$plugin->seoElements->getSeoElementByMetaBundleType($metaBundle->sourceBundleType); + $elementQuery = $seoElement::sitemapElementsQuery($metaBundle); + $pageSize = $metaBundle->metaSitemapVars->sitemapPageSize; + + if (!empty($pageSize)) { + $total = min($elementQuery->count(), $metaBundle->metaSitemapVars->sitemapLimit); + $pageCount = ceil($total / $pageSize); + } else { + $pageCount = 1; + } + $site = Craft::$app->getSites()->getSiteById($metaBundle->sourceSiteId); + $sitemap = SitemapTemplate::create(); if ($site) { - $sitemap = SitemapTemplate::create(); - $sitemap->render([ - 'groupId' => $site->groupId, - 'siteId' => $metaBundle->sourceSiteId, - 'handle' => $metaBundle->sourceHandle, - 'type' => $metaBundle->sourceBundleType, - 'immediately' => true, - ]); + for ($pageNum = 1; $pageNum <= $pageCount; $pageNum++) { + echo sprintf('Generating page %d of %d' . PHP_EOL, $pageNum, $pageCount); + $sitemap->render([ + 'groupId' => $site->groupId, + 'siteId' => $metaBundle->sourceSiteId, + 'handle' => $metaBundle->sourceHandle, + 'type' => $metaBundle->sourceBundleType, + 'page' => $pageNum + ]); + } + // Generate the sitemap so it is in the cache + } echo '---' . PHP_EOL; diff --git a/src/controllers/SitemapController.php b/src/controllers/SitemapController.php index 12c9e78f9..db9255276 100644 --- a/src/controllers/SitemapController.php +++ b/src/controllers/SitemapController.php @@ -120,8 +120,14 @@ public function actionSitemapEmptyStyles(): Response * * @return Response */ - public function actionSitemap(int $groupId, string $type, string $handle, int $siteId): Response + public function actionSitemap(int $groupId, string $type, string $handle, int $siteId, string $file): Response { + $page = null; + + if (preg_match('/sitemap-p([\d]+)\.xml/i', $file, $matches)) { + $page = $matches[1]; + } + $xml = Seomatic::$plugin->sitemaps->renderTemplate( Sitemaps::SEOMATIC_SITEMAP_CONTAINER, [ @@ -129,6 +135,7 @@ public function actionSitemap(int $groupId, string $type, string $handle, int $s 'type' => $type, 'handle' => $handle, 'siteId' => $siteId, + 'page' => $page ] ); $headers = Craft::$app->response->headers; diff --git a/src/helpers/Sitemap.php b/src/helpers/Sitemap.php index 98467ba95..1027f5648 100644 --- a/src/helpers/Sitemap.php +++ b/src/helpers/Sitemap.php @@ -11,14 +11,11 @@ use craft\elements\MatrixBlock; use craft\errors\SiteNotFoundException; use craft\fields\Assets as AssetsField; -use craft\queue\Queue; use DateTime; -use nystudio107\fastcgicachebust\FastcgiCacheBust; use nystudio107\seomatic\base\SeoElementInterface; use nystudio107\seomatic\events\IncludeSitemapEntryEvent; use nystudio107\seomatic\fields\SeoSettings; use nystudio107\seomatic\helpers\Field as FieldHelper; -use nystudio107\seomatic\jobs\GenerateSitemap; use nystudio107\seomatic\models\MetaBundle; use nystudio107\seomatic\models\SitemapTemplate; use nystudio107\seomatic\Seomatic; @@ -26,7 +23,6 @@ use verbb\supertable\elements\SuperTableBlockElement as SuperTableBlock; use yii\base\Event; use yii\base\Exception; -use yii\caching\TagDependency; use yii\helpers\Html; use function array_intersect_key; use function count; @@ -55,33 +51,26 @@ class Sitemap */ const EVENT_INCLUDE_SITEMAP_ENTRY = 'includeSitemapEntry'; + /** + * @const The number of assets to return in a single paginated query + */ + const SITEMAP_QUERY_PAGE_SIZE = 100; + /** * Generate a sitemap with the passed in $params * * @param array $params - * @return void + * @return string * @throws SiteNotFoundException */ - public static function generateSitemap(array $params) + public static function generateSitemap(array $params): ?string { - /** @var Queue $queue */ - $queue = $params['queue'] ?? null; - /** @var GenerateSitemap|null $job */ - $job = $params['job'] ?? null; - - if (!$job) { - $groupId = $params['groupId']; - $siteId = $params['siteId']; - $handle = $params['handle']; - $type = $params['type']; - $queueJobCacheKey = $params['queueJobCacheKey']; - } else { - $groupId = $job->groupId; - $siteId = $job->siteId; - $handle = $job->handle; - $type = $job->type; - $queueJobCacheKey = $job->queueJobCacheKey; - } + + $groupId = $params['groupId']; + $type = $params['type']; + $handle = $params['handle']; + $siteId = $params['siteId']; + $page = $params['page']; // Get an array of site ids for this site group $groupSiteIds = []; @@ -108,11 +97,6 @@ public static function generateSitemap(array $params) $groupSiteIds = Craft::$app->getSites()->allSiteIds; } - // Output some info if this is a console app - if ($job && Craft::$app instanceof ConsoleApplication) { - echo $job->description . PHP_EOL; - } - $lines = []; // Sitemap index XML header and opening tag $lines[] = ''; @@ -125,7 +109,7 @@ public static function generateSitemap(array $params) ); // If it doesn't exist, exit if ($metaBundle === null) { - return; + return null; } $multiSite = count($metaBundle->sourceAltSiteSettings) > 1; $totalElements = null; @@ -142,47 +126,78 @@ public static function generateSitemap(array $params) } $urlsetLine .= '>'; $lines[] = $urlsetLine; + // Get all of the elements for this meta bundle type $seoElement = Seomatic::$plugin->seoElements->getSeoElementByMetaBundleType($metaBundle->sourceBundleType); + if ($seoElement !== null) { // Ensure `null` so that the resulting element query is correct if (empty($metaBundle->metaSitemapVars->sitemapLimit)) { $metaBundle->metaSitemapVars->sitemapLimit = null; } + $totalElements = $seoElement::sitemapElementsQuery($metaBundle)->count(); if ($metaBundle->metaSitemapVars->sitemapLimit && ($totalElements > $metaBundle->metaSitemapVars->sitemapLimit)) { $totalElements = $metaBundle->metaSitemapVars->sitemapLimit; } } + // If no elements exist, just exit if (!$totalElements) { - return; + return null; } + // Stash the sitemap attributes so they can be modified on a per-entry basis $stashedSitemapAttrs = $metaBundle->metaSitemapVars->getAttributes(); $stashedGlobalVarsAttrs = $metaBundle->metaGlobalVars->getAttributes(); // Use craft\db\Paginator to paginate the results so we don't exceed any memory limits // See batch() and each() discussion here: https://github.com/yiisoft/yii2/issues/8420 // and here: https://github.com/craftcms/cms/issues/7338 - $paginator = new Paginator($seoElement::sitemapElementsQuery($metaBundle), [ - 'pageSize' => GenerateSitemap::SITEMAP_QUERY_PAGE_SIZE, - ]); - $currentElement = 0; - // Iterate through the paginated results - while ($currentElement < $totalElements) { + + $elementQuery = $seoElement::sitemapElementsQuery($metaBundle); + + // If page provided + // Provide just that page + + $sitemapPageSize = $metaBundle->metaSitemapVars->sitemapPageSize; + + $elementQuery->limit($metaBundle->metaSitemapVars->sitemapLimit ?? null); + + // If this is not a paged sitemap, go through full resultss + if (is_null($sitemapPageSize)) { + $pagedSitemap = false; + $paginator = new Paginator($elementQuery, [ + 'pageSize' => self::SITEMAP_QUERY_PAGE_SIZE, + ]); $elements = $paginator->getPageResults(); + } else { + $sitemapPage = empty($page) ? 1 : $page; + $pagedSitemap = true; + $elementQuery->limit($sitemapPageSize); + $elementQuery->offset(($sitemapPage - 1) * $sitemapPageSize); + $elements = $elementQuery->all(); + $totalElements = $sitemapPageSize; + } + + $currentElement = 1; + + do { if (Craft::$app instanceof ConsoleApplication) { - echo 'Query ' . $paginator->getCurrentPage() . '/' . $paginator->getTotalPages() - . ' - elements: ' . $paginator->getTotalResults() - . PHP_EOL; + if ($pagedSitemap) { + $message = sprintf('Query %d elements', + 1, + 1, + $totalElements); + } else { + $message = sprintf('Query %d / %d - elements: %d', + $paginator->getCurrentPage(), + $paginator->getTotalPages(), + $paginator->getTotalResults()); + } + echo $message . PHP_EOL; } /** @var Element $element */ foreach ($elements as $element) { - if ($job) { - $job->updateProgress($currentElement++ / $totalElements); - } else { - $currentElement++; - } // Output some info if this is a console app if (Craft::$app instanceof ConsoleApplication) { echo "Processing element {$currentElement}/{$totalElements} - {$element->title}" . PHP_EOL; @@ -413,41 +428,25 @@ public static function generateSitemap(array $params) } } } + $currentElement++; + } + + if ($pagedSitemap) { + break; + } + + if ($paginator->getCurrentPage() == $paginator->getTotalPages()) { + break; } + $paginator->currentPage++; - } + $elements = $paginator->getPageResults(); + } while (!empty($elements)); + // Sitemap closing tag $lines[] = ''; - $cache = Craft::$app->getCache(); - $cacheKey = SitemapTemplate::CACHE_KEY . $groupId . $type . $handle . $siteId; - $dependency = new TagDependency([ - 'tags' => [ - SitemapTemplate::GLOBAL_SITEMAP_CACHE_TAG, - SitemapTemplate::SITEMAP_CACHE_TAG . $handle . $siteId, - ], - ]); - $lines = implode('', $lines); - // Cache sitemap cache; we use this instead of Seomatic::$cacheDuration because for - // Control Panel requests, we set Seomatic::$cacheDuration = 1 so that they are never - // cached - $cacheDuration = Seomatic::$devMode - ? Seomatic::DEVMODE_CACHE_DURATION - : null; - $result = $cache->set($cacheKey, $lines, $cacheDuration, $dependency); - // Remove the queue job id from the cache too - $cache->delete($queueJobCacheKey); - Craft::debug('Sitemap cache result: ' . print_r($result, true) . ' for cache key: ' . $cacheKey, __METHOD__); - // Output some info if this is a console app - if (Craft::$app instanceof ConsoleApplication) { - echo 'Sitemap cache result: ' . print_r($result, true) . ' for cache key: ' . $cacheKey . PHP_EOL; - } - // If the FastCGI Cache Bust plugin is installed, clear its caches too - /** @var FastcgiCacheBust $plugin */ - $plugin = Craft::$app->getPlugins()->getPlugin('fastcgi-cache-bust'); - if ($plugin !== null) { - $plugin->cache->clearAll(); - } + return implode('', $lines); } @@ -623,4 +622,8 @@ protected static function assetFilesSitemapLink(Asset $asset, MetaBundle $metaBu } } } + + protected static function getElementListSitemap(array $elements) { + + } } diff --git a/src/jobs/GenerateSitemap.php b/src/jobs/GenerateSitemap.php deleted file mode 100644 index ce2ee8397..000000000 --- a/src/jobs/GenerateSitemap.php +++ /dev/null @@ -1,89 +0,0 @@ - $this->groupId, - 'siteId' => $this->siteId, - 'handle' => $this->handle, - 'type' => $this->type, - 'queueJobCacheKey' => $this->queueJobCacheKey, - 'queue' => $queue, - 'job' => $this, - ]; - - $this->queue = $queue; - Sitemap::generateSitemap($params); - } - - /** - * Wrapper for `setProgress()` - * @param float $progress - */ - public function updateProgress(float $progress) - { - $this->setProgress($this->queue, $progress); - } - - // Protected Methods - // ========================================================================= - - /** - * @inheritdoc - */ - protected function defaultDescription(): string - { - return Craft::t('app', 'Generating {handle} sitemap', [ - 'handle' => $this->handle, - ]); - } -} diff --git a/src/models/MetaSitemapVars.php b/src/models/MetaSitemapVars.php index 9bc13b9d4..a219748e8 100644 --- a/src/models/MetaSitemapVars.php +++ b/src/models/MetaSitemapVars.php @@ -76,6 +76,11 @@ class MetaSitemapVars extends InheritableSettingsModel */ public $sitemapLimit; + /** + * @var null|int + */ + public $sitemapPageSize; + /** * @var null|int */ @@ -150,6 +155,7 @@ public function rules(): array [ [ 'sitemapLimit', + 'sitemapPageSize', ], 'integer', ], diff --git a/src/models/SitemapIndexTemplate.php b/src/models/SitemapIndexTemplate.php index ff67e8d90..6133f9d6c 100644 --- a/src/models/SitemapIndexTemplate.php +++ b/src/models/SitemapIndexTemplate.php @@ -178,36 +178,50 @@ public function render(array $params = []): string if (in_array($metaBundle->sourceSiteId, $groupSiteIds, false) && $sitemapUrls && $robotsEnabled) { - $sitemapUrl = Seomatic::$plugin->sitemaps->sitemapUrlForBundle( - $metaBundle->sourceBundleType, - $metaBundle->sourceHandle, - $metaBundle->sourceSiteId - ); // Get all of the elements for this meta bundle type $seoElement = Seomatic::$plugin->seoElements->getSeoElementByMetaBundleType($metaBundle->sourceBundleType); $totalElements = 0; + $pageCount = 0; + if ($seoElement !== null) { // Ensure `null` so that the resulting element query is correct if (empty($metaBundle->metaSitemapVars->sitemapLimit)) { $metaBundle->metaSitemapVars->sitemapLimit = null; } + $totalElements = $seoElement::sitemapElementsQuery($metaBundle)->count(); + if ($metaBundle->metaSitemapVars->sitemapLimit && ($totalElements > $metaBundle->metaSitemapVars->sitemapLimit)) { $totalElements = $metaBundle->metaSitemapVars->sitemapLimit; } + + $pageSize = $metaBundle->metaSitemapVars->sitemapPageSize; + $pageCount = (!empty($pageSize) && $pageSize > 0) ? ceil($totalElements / $pageSize) : 1; } + // Only add a sitemap to the sitemap index if there's at least 1 element in the resulting sitemap - if ($totalElements > 0) { - $lines[] = ''; - $lines[] = ''; - $lines[] = Html::encode($sitemapUrl); - $lines[] = ''; - if ($metaBundle->sourceDateUpdated !== null) { - $lines[] = ''; - $lines[] = $metaBundle->sourceDateUpdated->format(DateTime::W3C); - $lines[] = ''; + if ($totalElements > 0 && $pageCount > 0) { + for ($page = 1; $page <= $pageCount; $page++) { + $sitemapUrl = Seomatic::$plugin->sitemaps->sitemapUrlForBundle( + $metaBundle->sourceBundleType, + $metaBundle->sourceHandle, + $metaBundle->sourceSiteId, + $pageCount > 1 ? $page : 0 // No paging, if only one page + ); + + $lines[] = ''; + $lines[] = ''; + $lines[] = Html::encode($sitemapUrl); + $lines[] = ''; + + if ($metaBundle->sourceDateUpdated !== null) { + $lines[] = ''; + $lines[] = $metaBundle->sourceDateUpdated->format(DateTime::W3C); + $lines[] = ''; + } + + $lines[] = ''; } - $lines[] = ''; } } } diff --git a/src/models/SitemapTemplate.php b/src/models/SitemapTemplate.php index ce2815762..eb1856ac2 100644 --- a/src/models/SitemapTemplate.php +++ b/src/models/SitemapTemplate.php @@ -12,12 +12,12 @@ namespace nystudio107\seomatic\models; use Craft; -use craft\queue\QueueInterface; +use craft\console\Application as ConsoleApplication; +use nystudio107\fastcgicachebust\FastcgiCacheBust; use nystudio107\seomatic\base\FrontendTemplate; use nystudio107\seomatic\base\SitemapInterface; use nystudio107\seomatic\helpers\SiteHelper; use nystudio107\seomatic\helpers\Sitemap; -use nystudio107\seomatic\jobs\GenerateSitemap; use nystudio107\seomatic\Seomatic; use yii\caching\TagDependency; use yii\web\NotFoundHttpException; @@ -106,11 +106,12 @@ public function render(array $params = []): string $type = $params['type']; $handle = $params['handle']; $siteId = $params['siteId']; + $page = $params['page'] ?? 0; + // If $throwException === false it means we're trying to regenerate the sitemap due to an invalidation // rather than a request for the actual sitemap, so don't try to run the queue immediately $throwException = $params['throwException'] ?? true; - // Only regenerate the sitemap via queue job if it's via an invalidation of the sitemap cache - $immediately = $params['immediately'] ?? $throwException; + $request = Craft::$app->getRequest(); $metaBundle = Seomatic::$plugin->metaBundles->getMetaBundleBySourceHandle($type, $handle, $siteId); // If it doesn't exist, throw a 404 @@ -148,68 +149,58 @@ public function render(array $params = []): string } $cache = Craft::$app->getCache(); - $uniqueKey = $groupId . $type . $handle . $siteId; + $pageCacheSuffix = 's' . (int)$metaBundle->metaSitemapVars->sitemapPageSize . 'p' . $page; + + $uniqueKey = $groupId . $type . $handle . $siteId . $pageCacheSuffix; $cacheKey = self::CACHE_KEY . $uniqueKey; - $queueJobCacheKey = self::QUEUE_JOB_CACHE_KEY . $uniqueKey; $result = $cache->get($cacheKey); + // If the sitemap isn't cached, start a job to create it // Even if it is cached, if $throwException === false we should regenerate it, as it is part of // an invalidation if ($result === false || $throwException === false) { - $queue = Craft::$app->getQueue(); - // If there's an existing queue job, release it so queue jobs don't stack - $existingJobId = $cache->get($queueJobCacheKey); - // Make sure the queue uses the Craft web interface - if ($existingJobId && $queue instanceof QueueInterface) { - $queue->release($existingJobId); - $cache->delete($queueJobCacheKey); - } - // See if we should regenerate this sitemap immediately, or via queue job - if ($immediately) { - Sitemap::generateSitemap([ - 'groupId' => $groupId, - 'type' => $type, - 'handle' => $handle, - 'siteId' => $siteId, - 'queueJobCacheKey' => $queueJobCacheKey, - ]); - } else { - // Push a new queue job - $jobId = $queue->push(new GenerateSitemap([ - 'groupId' => $groupId, - 'type' => $type, - 'handle' => $handle, - 'siteId' => $siteId, - 'queueJobCacheKey' => $queueJobCacheKey, - ])); - - // Stash the queue job id in the cache for future reference - $cacheDuration = 3600; + $sitemap = Sitemap::generateSitemap([ + 'groupId' => $groupId, + 'type' => $type, + 'handle' => $handle, + 'siteId' => $siteId, + 'page' => $page + ]); + + if ($sitemap) { $dependency = new TagDependency([ 'tags' => [ self::GLOBAL_SITEMAP_CACHE_TAG, - self::CACHE_KEY . $uniqueKey, + self::SITEMAP_CACHE_TAG . $handle . $siteId . $pageCacheSuffix, ], ]); - $cache->set($queueJobCacheKey, $jobId, $cacheDuration, $dependency); - Craft::debug( - Craft::t( - 'seomatic', - 'Started GenerateSitemap queue job id: {jobId} with cache key {cacheKey}', - [ - 'jobId' => $jobId, - 'cacheKey' => $cacheKey, - ] - ), - __METHOD__ - ); - } - // Try it again now - $result = $cache->get($cacheKey); - if ($result !== false) { - return $result; + $cacheDuration = Seomatic::$devMode + ? Seomatic::DEVMODE_CACHE_DURATION + : null; + + $result = $cache->set($cacheKey, $sitemap, $cacheDuration, $dependency); + + // Output some info if this is a console app + if (Craft::$app instanceof ConsoleApplication) { + echo 'Sitemap cache result: ' . print_r($result, true) . ' for cache key: ' . $cacheKey . PHP_EOL; + } + + // If the FastCGI Cache Bust plugin is installed, clear its caches too + /** @var FastcgiCacheBust $plugin */ + $plugin = Craft::$app->getPlugins()->getPlugin('fastcgi-cache-bust'); + if ($plugin !== null) { + $plugin->cache->clearAll(); + } + + // Try it again now + $sitemap = $cache->get($cacheKey); + + if ($sitemap !== false) { + return $sitemap; + } } + // Return a 503 Service Unavailable an a Retry-After so bots will try back later $lines = []; $response = Craft::$app->getResponse(); @@ -231,6 +222,10 @@ public function render(array $params = []): string $lines = implode("\r\n", $lines); return $lines; + } else { + if (Craft::$app instanceof ConsoleApplication) { + echo 'Found in cache' . PHP_EOL; + } } return $result; diff --git a/src/services/Helper.php b/src/services/Helper.php index 44fa696f8..77d0f034c 100644 --- a/src/services/Helper.php +++ b/src/services/Helper.php @@ -336,9 +336,9 @@ public static function siteGroupSitemaps(): string * * @return string */ - public static function sitemapUrlForBundle(string $sourceType, string $sourceHandle, int $siteId = null): string + public static function sitemapUrlForBundle(string $sourceType, string $sourceHandle, int $siteId = null, int $page = 0): string { - return Seomatic::$plugin->sitemaps->sitemapUrlForBundle($sourceType, $sourceHandle, $siteId); + return Seomatic::$plugin->sitemaps->sitemapUrlForBundle($sourceType, $sourceHandle, $siteId, $page); } /** diff --git a/src/services/Sitemaps.php b/src/services/Sitemaps.php index 4484a20ef..42cebd758 100644 --- a/src/services/Sitemaps.php +++ b/src/services/Sitemaps.php @@ -349,7 +349,7 @@ public function submitSitemapForElement(ElementInterface $element) * * @return string */ - public function sitemapUrlForBundle(string $sourceBundleType, string $sourceHandle, int $siteId = null): string + public function sitemapUrlForBundle(string $sourceBundleType, string $sourceHandle, int $siteId = null, int $page = null): string { $url = ''; $sites = Craft::$app->getSites(); @@ -373,7 +373,9 @@ public function sitemapUrlForBundle(string $sourceBundleType, string $sourceHand . $metaBundle->sourceHandle . '-' . $metaBundle->sourceSiteId - . '-sitemap.xml', + . '-sitemap' + . (!empty($page) ? '-p' . $page : '') + .'.xml', null, null, $siteId diff --git a/src/templates/settings/_includes/fields/_sitemapPageSize.twig b/src/templates/settings/_includes/fields/_sitemapPageSize.twig new file mode 100644 index 000000000..78ff92779 --- /dev/null +++ b/src/templates/settings/_includes/fields/_sitemapPageSize.twig @@ -0,0 +1,53 @@ +{% set inheritedFrom = seomatic.helper.findInheritableBundle(parentBundles, "sitemapPageSize", "metaSitemapVars") %} +{% set hasInheritableValues = inheritedFrom is not null %} + +{% set additionalVars = { + 'isInherited': seomatic.helper.isInherited(metaSitemapVars, "sitemapPageSize"), + 'fieldLabel': "Sitemap Page Size"|t("seomatic"), + 'settingName': 'sitemapPageSize', + 'labelFor': 'metaSitemapVars-sitemapPageSize', + 'overrideNamespace': 'metaSitemapVars' +} %} + +{% embed "seomatic/settings/_includes/fields/_inheritableField.twig" with additionalVars %} + {% macro sitemapPageSizeField(sitemapPageSizeOptions, metaSitemapVars, suffix) %} + {% set disabled = suffix|length > 0 %} +
+

+ {{ "Controls how many entries will there be per page in this sitemap."|t("seomatic") }} +

+
+ + {% import "_includes/forms" as forms %} + {% namespace "metaSitemapVars" %} + {{ forms.selectField({ + id: "sitemapPageSize" ~ suffix, + name: "sitemapPageSize", + options: sitemapPageSizeOptions, + value: metaSitemapVars.sitemapPageSize, + errors: metaSitemapVars.getErrors("sitemapPageSize"), + disabled: disabled, + }) }} + + {% endnamespace %} + {% endmacro %} + + {% set sitemapPageSizeOptions = { + (null): "Single page", + "1000": "1000", + "500": "500", + "200": "200", + "100": "100", + "50": "50", + "10": "10", + "5": "5", + } %} + + {% block inheritedValues %} + {{ _self.sitemapPageSizeField(sitemapPageSizeOptions, inheritedFrom.metaSitemapVars ?? metaSitemapVars, "-inherited") }} + {% endblock %} + + {% block field %} + {{ _self.sitemapPageSizeField(sitemapPageSizeOptions, metaSitemapVars, "") }} + {% endblock %} +{% endembed %} diff --git a/src/templates/settings/_includes/tab-sitemap.twig b/src/templates/settings/_includes/tab-sitemap.twig index c36776552..844f4b8fa 100644 --- a/src/templates/settings/_includes/tab-sitemap.twig +++ b/src/templates/settings/_includes/tab-sitemap.twig @@ -7,9 +7,15 @@
{{ 'View Sitemap Index'|t("seomatic") }} - {{ "View #{currentSourceBundleType |capitalize} Sitemap"|t("seomatic") }} + {% if metaSitemapVars.sitemapPageSize %} + {{ "View first page of #{currentSourceBundleType |capitalize} Sitemap"|t("seomatic") }} + {% else %} + {{ "View #{currentSourceBundleType |capitalize} Sitemap"|t("seomatic") }} + {% endif %} {% endif %} @@ -65,6 +71,12 @@ {% include "seomatic/settings/_includes/fields/_sitemapLimit.twig" %} {% endif %} + {# ############## Sitemap Page Size ############## #} + + {% if field is not defined or 'sitemapPageSize' in field.sitemapEnabledFields %} + {% include "seomatic/settings/_includes/fields/_sitemapPageSize.twig" %} + {% endif %} + {% namespace "metaSitemapVars" %} {% if (field is not defined or 'structureDepth' in field.sitemapEnabledFields) and sourceType == 'structure' %} {{ forms.selectField({ From 5ca174fd5c48ea317152dd398de3b5cc981cf682 Mon Sep 17 00:00:00 2001 From: "Hector D. Byrd" Date: Tue, 9 Jul 2024 10:07:49 +0300 Subject: [PATCH 04/15] chore: Cleanup --- src/console/controllers/SitemapController.php | 7 +++---- src/controllers/SitemapController.php | 2 +- src/helpers/Sitemap.php | 15 +++++++-------- src/models/SitemapTemplate.php | 2 +- src/services/Sitemaps.php | 2 +- src/translations/en/seomatic.php | 2 +- 6 files changed, 14 insertions(+), 16 deletions(-) diff --git a/src/console/controllers/SitemapController.php b/src/console/controllers/SitemapController.php index d4eedd7de..b54f97d37 100644 --- a/src/console/controllers/SitemapController.php +++ b/src/console/controllers/SitemapController.php @@ -113,18 +113,17 @@ public function actionGenerate() $site = Craft::$app->getSites()->getSiteById($metaBundle->sourceSiteId); $sitemap = SitemapTemplate::create(); if ($site) { - for ($pageNum = 1; $pageNum <= $pageCount; $pageNum++) { + for ($pageNum = 1; $pageNum <= $pageCount; $pageNum++) { echo sprintf('Generating page %d of %d' . PHP_EOL, $pageNum, $pageCount); $sitemap->render([ 'groupId' => $site->groupId, 'siteId' => $metaBundle->sourceSiteId, 'handle' => $metaBundle->sourceHandle, 'type' => $metaBundle->sourceBundleType, - 'page' => $pageNum + 'page' => $pageNum, ]); } - // Generate the sitemap so it is in the cache - + // Generate the sitemap so it is in the cache } echo '---' . PHP_EOL; diff --git a/src/controllers/SitemapController.php b/src/controllers/SitemapController.php index db9255276..f3ef37466 100644 --- a/src/controllers/SitemapController.php +++ b/src/controllers/SitemapController.php @@ -135,7 +135,7 @@ public function actionSitemap(int $groupId, string $type, string $handle, int $s 'type' => $type, 'handle' => $handle, 'siteId' => $siteId, - 'page' => $page + 'page' => $page, ] ); $headers = Craft::$app->response->headers; diff --git a/src/helpers/Sitemap.php b/src/helpers/Sitemap.php index 1027f5648..edb6f790a 100644 --- a/src/helpers/Sitemap.php +++ b/src/helpers/Sitemap.php @@ -65,7 +65,6 @@ class Sitemap */ public static function generateSitemap(array $params): ?string { - $groupId = $params['groupId']; $type = $params['type']; $handle = $params['handle']; @@ -163,7 +162,7 @@ public static function generateSitemap(array $params): ?string $elementQuery->limit($metaBundle->metaSitemapVars->sitemapLimit ?? null); - // If this is not a paged sitemap, go through full resultss + // If this is not a paged sitemap, go through full results if (is_null($sitemapPageSize)) { $pagedSitemap = false; $paginator = new Paginator($elementQuery, [ @@ -177,6 +176,9 @@ public static function generateSitemap(array $params): ?string $elementQuery->offset(($sitemapPage - 1) * $sitemapPageSize); $elements = $elementQuery->all(); $totalElements = $sitemapPageSize; + $paginator = new Paginator($elementQuery, [ + 'pageSize' => $sitemapPageSize, + ]); } $currentElement = 1; @@ -184,10 +186,7 @@ public static function generateSitemap(array $params): ?string do { if (Craft::$app instanceof ConsoleApplication) { if ($pagedSitemap) { - $message = sprintf('Query %d elements', - 1, - 1, - $totalElements); + $message = sprintf('Query %d elements', 1); } else { $message = sprintf('Query %d / %d - elements: %d', $paginator->getCurrentPage(), @@ -623,7 +622,7 @@ protected static function assetFilesSitemapLink(Asset $asset, MetaBundle $metaBu } } - protected static function getElementListSitemap(array $elements) { - + protected static function getElementListSitemap(array $elements) + { } } diff --git a/src/models/SitemapTemplate.php b/src/models/SitemapTemplate.php index eb1856ac2..b7e4015ed 100644 --- a/src/models/SitemapTemplate.php +++ b/src/models/SitemapTemplate.php @@ -164,7 +164,7 @@ public function render(array $params = []): string 'type' => $type, 'handle' => $handle, 'siteId' => $siteId, - 'page' => $page + 'page' => $page, ]); if ($sitemap) { diff --git a/src/services/Sitemaps.php b/src/services/Sitemaps.php index 42cebd758..9a9e381bd 100644 --- a/src/services/Sitemaps.php +++ b/src/services/Sitemaps.php @@ -375,7 +375,7 @@ public function sitemapUrlForBundle(string $sourceBundleType, string $sourceHand . $metaBundle->sourceSiteId . '-sitemap' . (!empty($page) ? '-p' . $page : '') - .'.xml', + . '.xml', null, null, $siteId diff --git a/src/translations/en/seomatic.php b/src/translations/en/seomatic.php index dfea3e81f..a14ec25d5 100644 --- a/src/translations/en/seomatic.php +++ b/src/translations/en/seomatic.php @@ -524,5 +524,5 @@ 'Asset Transform for Images' => 'Asset Transform for Images', 'Sitemap Asset Transform' => 'Sitemap Asset Transform', 'Controls whether SEOmatic will use `hreflang` tags that point to the paginated page rather than the root page on paginated pages. [Learn More](https://moz.com/community/q/hreflang-alternate-pagination)' => 'Controls whether SEOmatic will use `hreflang` tags that point to the paginated page rather than the root page on paginated pages. [Learn More](https://moz.com/community/q/hreflang-alternate-pagination)', - 'Primary' => 'Primary' + 'Primary' => 'Primary', ]; From 32a6dec368b638e17c03c09b3242f1aee015c1f7 Mon Sep 17 00:00:00 2001 From: "Hector D. Byrd" Date: Wed, 10 Jul 2024 09:27:05 +0300 Subject: [PATCH 05/15] chore: Fix logging output --- src/helpers/Sitemap.php | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/helpers/Sitemap.php b/src/helpers/Sitemap.php index edb6f790a..602f03075 100644 --- a/src/helpers/Sitemap.php +++ b/src/helpers/Sitemap.php @@ -154,12 +154,7 @@ public static function generateSitemap(array $params): ?string // and here: https://github.com/craftcms/cms/issues/7338 $elementQuery = $seoElement::sitemapElementsQuery($metaBundle); - - // If page provided - // Provide just that page - $sitemapPageSize = $metaBundle->metaSitemapVars->sitemapPageSize; - $elementQuery->limit($metaBundle->metaSitemapVars->sitemapLimit ?? null); // If this is not a paged sitemap, go through full results @@ -186,7 +181,7 @@ public static function generateSitemap(array $params): ?string do { if (Craft::$app instanceof ConsoleApplication) { if ($pagedSitemap) { - $message = sprintf('Query %d elements', 1); + $message = sprintf('Query %d elements', $sitemapPageSize); } else { $message = sprintf('Query %d / %d - elements: %d', $paginator->getCurrentPage(), From 7aaf2387d3d8e72ee130601547165955eda5b461 Mon Sep 17 00:00:00 2001 From: "Hector D. Byrd" Date: Wed, 10 Jul 2024 09:27:35 +0300 Subject: [PATCH 06/15] fix: Fix paging when generating multiple pages via CLI --- src/console/controllers/SitemapController.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/console/controllers/SitemapController.php b/src/console/controllers/SitemapController.php index b54f97d37..bc37d26a7 100644 --- a/src/console/controllers/SitemapController.php +++ b/src/console/controllers/SitemapController.php @@ -101,10 +101,11 @@ public function actionGenerate() $seoElement = Seomatic::$plugin->seoElements->getSeoElementByMetaBundleType($metaBundle->sourceBundleType); $elementQuery = $seoElement::sitemapElementsQuery($metaBundle); - $pageSize = $metaBundle->metaSitemapVars->sitemapPageSize; + $pageSize = (int) $metaBundle->metaSitemapVars->sitemapPageSize; + $sitemapLimit = (int) $metaBundle->metaSitemapVars->sitemapLimit; if (!empty($pageSize)) { - $total = min($elementQuery->count(), $metaBundle->metaSitemapVars->sitemapLimit); + $total = empty($sitemapLimit) ? $elementQuery->count() : min($elementQuery->count(), $sitemapLimit); $pageCount = ceil($total / $pageSize); } else { $pageCount = 1; From 31365d541398962de9b8ccc5e3724ddef2472afb Mon Sep 17 00:00:00 2001 From: Andrew Welch Date: Thu, 11 Jul 2024 13:23:28 +0800 Subject: [PATCH 07/15] chore: Version 3.5.0 --- CHANGELOG.md | 4 ++++ composer.json | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 450ebe1b5..7e9c9b673 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # SEOmatic Changelog +## 3.5.0 - UNRELEASED +### Added +* Remove queue generated sitemaps, switch to paginated sitemaps to allow them to be rendered at web response time, but still be managable in size + ## 3.4.78 - 2024.05.13 ### Added * Added a setting in Plugin Settings -> Tags to specify which site should be used as the `x-default` for `hreflang` tags ([1162](https://github.com/nystudio107/craft-seomatic/issues/1162)) diff --git a/composer.json b/composer.json index ad6fb64b8..7be2955d6 100644 --- a/composer.json +++ b/composer.json @@ -2,7 +2,7 @@ "name": "nystudio107/craft-seomatic", "description": "SEOmatic facilitates modern SEO best practices & implementation for Craft CMS 3. It is a turnkey SEO system that is comprehensive, powerful, and flexible.", "type": "craft-plugin", - "version": "3.4.78", + "version": "3.5.0", "keywords": [ "craft", "cms", From 7f23900fad9ca6395df7ce38822bc5ece5e263d7 Mon Sep 17 00:00:00 2001 From: Andrew Welch Date: Thu, 11 Jul 2024 13:24:23 +0800 Subject: [PATCH 08/15] chore: Switch to `check-cs` to throw errors during CI --- .github/workflows/code-analysis.yaml | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/.github/workflows/code-analysis.yaml b/.github/workflows/code-analysis.yaml index 1cdafb4f7..5e2650ba7 100644 --- a/.github/workflows/code-analysis.yaml +++ b/.github/workflows/code-analysis.yaml @@ -14,12 +14,10 @@ jobs: fail-fast: false matrix: actions: - - - name: 'PHPStan' + - name: 'PHPStan' run: composer phpstan - - - name: 'Coding Standards' - run: composer fix-cs + - name: 'Coding Standards' + run: composer check-cs name: ${{ matrix.actions.name }} runs-on: ubuntu-latest steps: From 185b20b44cc328444a784679a6d9f097f580de1b Mon Sep 17 00:00:00 2001 From: Andrew Welch Date: Thu, 11 Jul 2024 14:03:13 +0800 Subject: [PATCH 09/15] refactor: Default `sitemapPageSize` to `200` --- src/models/MetaSitemapVars.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/models/MetaSitemapVars.php b/src/models/MetaSitemapVars.php index a219748e8..636d1ee5b 100644 --- a/src/models/MetaSitemapVars.php +++ b/src/models/MetaSitemapVars.php @@ -79,7 +79,7 @@ class MetaSitemapVars extends InheritableSettingsModel /** * @var null|int */ - public $sitemapPageSize; + public $sitemapPageSize = 200; /** * @var null|int From 28ba47a8f67c3c266ef33645d72b47e2627e2743 Mon Sep 17 00:00:00 2001 From: Andrew Welch Date: Thu, 11 Jul 2024 16:50:39 +0800 Subject: [PATCH 10/15] refactor: Remove "Submit Sitemap Changes" lightswitch --- src/templates/settings/plugin/_includes/sitemaps.twig | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/src/templates/settings/plugin/_includes/sitemaps.twig b/src/templates/settings/plugin/_includes/sitemaps.twig index bcb232a72..c9a0f2c5d 100644 --- a/src/templates/settings/plugin/_includes/sitemaps.twig +++ b/src/templates/settings/plugin/_includes/sitemaps.twig @@ -24,16 +24,6 @@ errors: settings.getErrors("regenerateSitemapsAutomatically"), }) }} - {{ forms.lightswitchField({ - label: "Submit Sitemap Changes"|t("seomatic"), - instructions: "Should sitemaps be submitted to search engines automatically whenever there are changes?"|t("seomatic"), - id: "submitSitemaps", - name: "submitSitemaps", - on: settings.submitSitemaps, - warning: configWarning("submitSitemaps", "seomatic"), - errors: settings.getErrors("submitSitemaps"), - }) }} - {{ forms.lightswitchField({ label: "Exclude Non-Canonical URLs"|t("seomatic"), instructions: "Should items where the entry URL doesn't match the canonical URL be excluded?"|t("seomatic"), From 98b1045b64e253d85533be4e22af36e489ecbb00 Mon Sep 17 00:00:00 2001 From: Andrew Welch Date: Thu, 11 Jul 2024 16:52:51 +0800 Subject: [PATCH 11/15] docs: Update to remove queue discussion, and mention paginated sitemaps --- docs/docs/configuring/content-seo.md | 12 +++++------- docs/docs/configuring/plugin-settings.md | 1 - 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/docs/docs/configuring/content-seo.md b/docs/docs/configuring/content-seo.md index 91f6c5b94..558801fb6 100644 --- a/docs/docs/configuring/content-seo.md +++ b/docs/docs/configuring/content-seo.md @@ -40,21 +40,19 @@ SEOmatic automatically creates a sitemap index for each of your Site Groups. Thi Instead of one massive sitemap that must be updated any time anything changes, only the sitemap for the Section, Category Group, or Commerce Product Type will be updated when something changes in it. +Additionally, sitemaps are paginated according to the **Sitemap Page Size** setting (which defaults to `500` per page), to allow for a large number of entries in the sitemaps without hurting performance. + SEOmatic can automatically include files such as `.pdf`, `.xls`, `.doc` and other indexable file types in Asset fields or Asset fields in matrix or Neo blocks. In addition, SEOmatic can automatically create [Image sitemaps](https://support.google.com/webmasters/answer/178636?hl=en) and [Video sitemaps](https://developers.google.com/webmasters/videosearch/sitemaps) from images & videos in Asset fields or Asset fields in matrix or Neo blocks. -Sitemap Indexes are automatically submitted to search engines whenever a new Section, Category Group, or Commerce Product Type is added. - -Section Sitemaps are automatically submitted to search engines whenever a new Element in that Section, Category Group, or Commerce Product Type is added. +Search engines no longer allow for sitemap submission via, but rather will re-crawl your sitemaps on a regular basis to find new pages. ### Sitemap Generation -Because XML sitemaps can be time-intensive to generate with a growing number of entries, SEOmatic creates your sitemaps via a queue job and caches the result. The cache is automatically broken whenever something in that sitemap is changed, and a new queue job is created to regenerate it. - -If `runQueueAutomatically` is set to `false` in [General Config Settings](https://craftcms.com/docs/3.x/config/config-settings.html#runqueueautomatically) the Queue job to create the sitemap will not be run during the http request for the sitemap. You’ll need to run it manually via whatever means you use to run the Queue. +SEOmatic generates sitemaps on-demmand when requested on the frontend, and then caches the sitemap for future requests so they are fast. -Normally SEOmatic will regenerate the sitemap for a Section, Category Group, or Product any time you save an element. However, if you are importing a large number of elements, or prefer to regenerate the sitemap manually you can set disable the **Regenerate Sitemaps Automatically** option in SEOmatic’s Plugin Settings. +Normally SEOmatic will invalidate the cache for a sitemap for a Section, Category Group, or Product any time you save an element. However, if you prefer to regenerate the sitemap manually you can set disable the **Regenerate Sitemaps Automatically** option in SEOmatic’s Plugin Settings. ![Screenshot of a console running the following command to generate a blog sitemap: `./craft seomatic/sitemap/generate --siteId=1 --handle=blog`](../resources/screenshots/seomatic-sitemap-console-command.png) diff --git a/docs/docs/configuring/plugin-settings.md b/docs/docs/configuring/plugin-settings.md index da99c394c..bd29e2070 100644 --- a/docs/docs/configuring/plugin-settings.md +++ b/docs/docs/configuring/plugin-settings.md @@ -10,7 +10,6 @@ Plugin Settings let you control various SEOmatic settings across all sites/langu * **Automatic Render Enabled** – Controls whether SEOmatic automatically renders metadata on your pages. If you turn this off, you will need to manually render the metadata via `seomatic.tag.render()`, `seomatic.link.render()`, etc. Selectively disable rendering via Twig with `{% do seomatic.config.renderEnabled(false) %}`. * **Sitemaps Enabled** – Controls whether SEOmatic will automatically render front-end sitemaps for your site. * **Regenerate Sitemaps Automatically** – Controls whether sitemaps will automatically be regenerated when entries are saved. -* **Submit Sitemap Changes** – Should sitemaps be submitted to search engines automatically whenever there are changes? * **Include Homepage in Breadcrumbs** – Should the homepage be included in the generated Breadcrumbs JSON-LD? * **Manually Set SEOmatic Environment** – If off, SEOmatic will automatically attempt to determine the current environment. Turn this on to manually set the environment. * **Environment** – The server environment, either `live`, `staging`, or `local`. If `devMode` is on, SEOmatic will override this setting to local Development. This setting controls whether certain things render; for instance only in the `live` production environment will Google Analytics and other tracking tags send analytics data. SEOmatic also automatically sets the `robots` tag to `none` for everything but the `live` production environment. From 54b161b9b206c9ca752207a1710ac13b5b39c9ca Mon Sep 17 00:00:00 2001 From: Andrew Welch Date: Thu, 11 Jul 2024 16:57:25 +0800 Subject: [PATCH 12/15] refactor: default to `500` --- src/models/MetaSitemapVars.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/models/MetaSitemapVars.php b/src/models/MetaSitemapVars.php index 636d1ee5b..0542b635e 100644 --- a/src/models/MetaSitemapVars.php +++ b/src/models/MetaSitemapVars.php @@ -79,7 +79,7 @@ class MetaSitemapVars extends InheritableSettingsModel /** * @var null|int */ - public $sitemapPageSize = 200; + public $sitemapPageSize = 500; /** * @var null|int From 91718b9ac356e86a6832ed6ad5f44ce3f30bc092 Mon Sep 17 00:00:00 2001 From: Andrew Welch Date: Thu, 11 Jul 2024 16:59:01 +0800 Subject: [PATCH 13/15] refactor: Better description of pagination --- src/templates/settings/_includes/fields/_sitemapPageSize.twig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/templates/settings/_includes/fields/_sitemapPageSize.twig b/src/templates/settings/_includes/fields/_sitemapPageSize.twig index 78ff92779..0a8d4d766 100644 --- a/src/templates/settings/_includes/fields/_sitemapPageSize.twig +++ b/src/templates/settings/_includes/fields/_sitemapPageSize.twig @@ -14,7 +14,7 @@ {% set disabled = suffix|length > 0 %}

- {{ "Controls how many entries will there be per page in this sitemap."|t("seomatic") }} + {{ "Controls how many entries will there be per page in this sitemap. If there are more entries than this in the sitemap, they will be paginated in additional sitemap indexes."|t("seomatic") }}

From bfded3e6017ed2533a248c49b6e7a16b0da289c3 Mon Sep 17 00:00:00 2001 From: Andrew Welch Date: Fri, 12 Jul 2024 12:33:28 +0800 Subject: [PATCH 14/15] refactor: Change `GLOBAL_SITEMAP_CACHE_TAG` to automatically invalidate stale old caches --- src/base/SitemapInterface.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/base/SitemapInterface.php b/src/base/SitemapInterface.php index 2ba68aaca..4edb6886c 100644 --- a/src/base/SitemapInterface.php +++ b/src/base/SitemapInterface.php @@ -21,5 +21,5 @@ interface SitemapInterface // Constants // ========================================================================= - const GLOBAL_SITEMAP_CACHE_TAG = 'seomatic_sitemap'; + const GLOBAL_SITEMAP_CACHE_TAG = 'seomatic_sitemap_v2'; } From 25149a361a191d376a743d78cfdab048482d4093 Mon Sep 17 00:00:00 2001 From: Andrew Welch Date: Fri, 12 Jul 2024 12:33:38 +0800 Subject: [PATCH 15/15] chore: Version 3.5.0 --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7e9c9b673..6b36f6077 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # SEOmatic Changelog -## 3.5.0 - UNRELEASED +## 3.5.0 - 2024.07.12 ### Added * Remove queue generated sitemaps, switch to paginated sitemaps to allow them to be rendered at web response time, but still be managable in size