Commit f52ee40c authored by gbyte.co's avatar gbyte.co

Issue #2863371 by JeroenT: Generation of sitemap with chunks uses a lot of memory

parent 6685dd03
......@@ -91,16 +91,148 @@ class Simplesitemap {
}
/**
* Fetches all sitemap chunks indexed by chunk ID.
* Returns a specific sitemap setting or a default value if setting does not
* exist.
*
* @return string
* @param string $name
* Name of the setting, like 'max_links'.
*
* @param mixed $default
* Value to be returned if the setting does not exist in the configuration.
*
* @return mixed
* The current setting from configuration or a default value.
*/
protected function fetchSitemapChunks() {
public function getSetting($name, $default = FALSE) {
$setting = $this->configFactory
->get('simple_sitemap.settings')
->get($name);
return NULL !== $setting ? $setting : $default;
}
/**
* Stores a specific sitemap setting in configuration.
*
* @param string $name
* Setting name, like 'max_links'.
* @param mixed $setting
* The setting to be saved.
*
* @return $this
*/
public function saveSetting($name, $setting) {
$this->configFactory->getEditable("simple_sitemap.settings")
->set($name, $setting)->save();
return $this;
}
/**
* Returns the whole sitemap, a requested sitemap chunk,
* or the sitemap index file.
*
* @param int $chunk_id
*
* @return string|false
* If no sitemap id provided, either a sitemap index is returned, or the
* whole sitemap, if the amount of links does not exceed the max links
* setting. If a sitemap id is provided, a sitemap chunk is returned. False
* if sitemap is not retrievable from the database.
*/
public function getSitemap($chunk_id = NULL) {
$chunk_info = $this->fetchSitemapChunkInfo();
if (NULL === $chunk_id || !isset($chunk_info[$chunk_id])) {
if (count($chunk_info) > 1) {
// Return sitemap index, if there are multiple sitemap chunks.
return $this->getSitemapIndex($chunk_info);
}
else {
// Return sitemap if there is only one chunk.
return count($chunk_info) === 1
&& isset($chunk_info[SitemapGenerator::FIRST_CHUNK_INDEX])
? $this->fetchSitemapChunk(SitemapGenerator::FIRST_CHUNK_INDEX)
->sitemap_string
: FALSE;
}
}
else {
// Return specific sitemap chunk.
return $this->fetchSitemapChunk($chunk_id)->sitemap_string;
}
}
/**
* Fetches all sitemap chunk timestamps keyed by chunk ID.
*
* @return array
* An array containing chunk creation timestamps keyed by chunk ID.
*/
protected function fetchSitemapChunkInfo() {
return $this->db
->query("SELECT * FROM {simple_sitemap}")
->query("SELECT id, sitemap_created FROM {simple_sitemap}")
->fetchAllAssoc('id');
}
/**
* Fetches a single sitemap chunk by ID.
*
* @param int $id
* The chunk ID.
*
* @return object
* A sitemap chunk object.
*/
private function fetchSitemapChunk($id) {
return $this->db->query('SELECT * FROM {simple_sitemap} WHERE id = :id',
[':id' => $id])->fetchObject();
}
/**
* Generates the sitemap for all languages and saves it to the db.
*
* @param string $from
* Can be 'form', 'cron', 'drush' or 'nobatch'.
* This decides how the batch process is to be run.
*/
public function generateSitemap($from = 'form') {
$this->sitemapGenerator
->setGenerator($this)
->setGenerateFrom($from)
->startGeneration();
}
/**
* Generates and returns the sitemap index as string.
*
* @param array $chunks
* Sitemap chunks which to generate the index from.
*
* @return string
* The sitemap index.
*/
protected function getSitemapIndex($chunks) {
return $this->sitemapGenerator
->setGenerator($this)
->generateSitemapIndex($chunks);
}
/**
* Returns a 'time ago' string of last timestamp generation.
*
* @return string|false
* Formatted timestamp of last sitemap generation, otherwise FALSE.
*/
public function getGeneratedAgo() {
$chunks = $this->fetchSitemapChunkInfo();
if (isset($chunks[SitemapGenerator::FIRST_CHUNK_INDEX]->sitemap_created)) {
return $this->dateFormatter
->formatInterval(REQUEST_TIME - $chunks[SitemapGenerator::FIRST_CHUNK_INDEX]
->sitemap_created);
}
return FALSE;
}
/**
* Enables sitemap support for an entity type. Enabled entity types show
* sitemap settings on their bundle setting forms. If an enabled entity type
......@@ -500,118 +632,4 @@ class Simplesitemap {
->set('links', [])->save();
return $this;
}
/**
* Returns the whole sitemap, a requested sitemap chunk,
* or the sitemap index file.
*
* @param int $chunk_id
*
* @return string|false
* If no sitemap id provided, either a sitemap index is returned, or the
* whole sitemap, if the amount of links does not exceed the max links
* setting. If a sitemap id is provided, a sitemap chunk is returned. False
* if sitemap is not retrievable from the database.
*/
public function getSitemap($chunk_id = NULL) {
$chunks = $this->fetchSitemapChunks();
if (NULL === $chunk_id || !isset($chunks[$chunk_id])) {
// Return sitemap index, if there are multiple sitemap chunks.
if (count($chunks) > 1) {
return $this->getSitemapIndex($chunks);
}
// Return sitemap if there is only one chunk.
else {
if (isset($chunks[1])) {
return $chunks[1]->sitemap_string;
}
return FALSE;
}
}
// Return specific sitemap chunk.
else {
return $chunks[$chunk_id]->sitemap_string;
}
}
/**
* Generates the sitemap for all languages and saves it to the db.
*
* @param string $from
* Can be 'form', 'cron', 'drush' or 'nobatch'.
* This decides how the batch process is to be run.
*/
public function generateSitemap($from = 'form') {
$this->sitemapGenerator
->setGenerator($this)
->setGenerateFrom($from)
->startGeneration();
}
/**
* Generates and returns the sitemap index as string.
*
* @param array $chunks
* Sitemap chunks which to generate the index from.
*
* @return string
* The sitemap index.
*/
protected function getSitemapIndex($chunks) {
return $this->sitemapGenerator
->setGenerator($this)
->generateSitemapIndex($chunks);
}
/**
* Returns a specific sitemap setting or a default value if setting does not
* exist.
*
* @param string $name
* Name of the setting, like 'max_links'.
*
* @param mixed $default
* Value to be returned if the setting does not exist in the configuration.
*
* @return mixed
* The current setting from configuration or a default value.
*/
public function getSetting($name, $default = FALSE) {
$setting = $this->configFactory
->get('simple_sitemap.settings')
->get($name);
return NULL !== $setting ? $setting : $default;
}
/**
* Stores a specific sitemap setting in configuration.
*
* @param string $name
* Setting name, like 'max_links'.
* @param mixed $setting
* The setting to be saved.
*
* @return $this
*/
public function saveSetting($name, $setting) {
$this->configFactory->getEditable("simple_sitemap.settings")
->set($name, $setting)->save();
return $this;
}
/**
* Returns a 'time ago' string of last timestamp generation.
*
* @return string|false
* Formatted timestamp of last sitemap generation, otherwise FALSE.
*/
public function getGeneratedAgo() {
$chunks = $this->fetchSitemapChunks();
if (isset($chunks[1]->sitemap_created)) {
return $this->dateFormatter
->formatInterval(REQUEST_TIME - $chunks[1]->sitemap_created);
}
return FALSE;
}
}
......@@ -19,6 +19,7 @@ class SitemapGenerator {
const XMLNS = 'http://www.sitemaps.org/schemas/sitemap/0.9';
const XMLNS_XHTML = 'http://www.w3.org/1999/xhtml';
const GENERATED_BY = 'Generated by the Simple XML sitemap Drupal module: https://drupal.org/project/simple_sitemap.';
const FIRST_CHUNK_INDEX = 1;
/**
* @var \Drupal\simple_sitemap\Batch\Batch
......@@ -200,7 +201,9 @@ class SitemapGenerator {
$this->moduleHandler->alter('simple_sitemap_links', $links);
$values = [
'id' => $remove_sitemap ? 1 : $this->db->query('SELECT MAX(id) FROM {simple_sitemap}')->fetchField() + 1,
'id' => $remove_sitemap ? self::FIRST_CHUNK_INDEX
: $this->db->query('SELECT MAX(id) FROM {simple_sitemap}')
->fetchField() + 1,
'sitemap_string' => $this->generateSitemapChunk($links),
'sitemap_created' => REQUEST_TIME,
];
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment