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

Adding sitemap index and possibility to set the amount of links per sitemap chunk.

parent 9d6ed0e8
......@@ -4,3 +4,6 @@ custom:
priority: 1
entity_types: []
settings:
max_links: 2000
......@@ -14,7 +14,8 @@ function simplesitemap_schema() {
'fields' => array(
'id' => array(
'description' => 'Sitemap chunk unique identifier.',
'type' => 'serial',
'type' => 'int',
'size' => 'small',
'not null' => TRUE,
),
'sitemap_string' => array(
......@@ -76,3 +77,16 @@ function simplesitemap_update_8103() {
), array('primary key' => array('id')));
return t('Before the sitemap can be accessed, it must be regenerated manually or via cron run.');
}
/**
* Modifying database structure to accommodate sitemap chunks.
*/
function simplesitemap_update_8104() {
db_truncate('simplesitemap')->execute();
db_change_field('simplesitemap', 'id', 'id', array(
'type' => 'int',
'size' => 'small',
'not null' => TRUE,
));
return t('Before the sitemap can be accessed, it must be regenerated manually or via cron run.');
}
File mode changed from 100644 to 100755
......@@ -5,6 +5,13 @@ simplesitemap.sitemap:
requirements:
_permission: 'access content'
simplesitemap.chunk:
path: '/sitemaps/{sitemap_id}/sitemap.xml'
defaults:
_controller: '\Drupal\simplesitemap\Controller\SimplesitemapController::get_sitemap'
requirements:
_permission: 'access content'
simplesitemap.settings:
path: '/admin/config/search/simplesitemap'
defaults:
......
......@@ -15,12 +15,12 @@ use Drupal\simplesitemap\Simplesitemap;
class SimplesitemapController {
/**
* Generates the sitemap.
* Returns the whole sitemap, a requested sitemap chunk, or the sitemap index file.
*/
public function get_sitemap() {
public function get_sitemap($sitemap_id = NULL) {
$sitemap = new Simplesitemap;
$output = $sitemap->get_sitemap();
$output = $sitemap->get_sitemap($sitemap_id);
// Display sitemap with correct xml header.
return new Response($output, Response::HTTP_OK, array('content-type' => 'application/xml'));
......
File mode changed from 100644 to 100755
......@@ -35,6 +35,9 @@ class SimplesitemapSettingsForm extends ConfigFormBase {
*/
public function buildForm(array $form, FormStateInterface $form_state) {
$sitemap = new Simplesitemap;
$settings = $sitemap->get_settings();
$form['simplesitemap_settings']['rebuild'] = array(
'#title' => t('Rebuild sitemap'),
'#type' => 'fieldset',
......@@ -48,7 +51,44 @@ class SimplesitemapSettingsForm extends ConfigFormBase {
'#validate' => array(), // Skip form-level validator.
);
return $form;
$form['simplesitemap_settings']['settings'] = array(
'#title' => t('Other settings'),
'#type' => 'fieldset',
'#markup' => '<p>' . t('Various sitemap settings.') . '</p>',
);
$form['simplesitemap_settings']['settings']['max_links'] = array(
'#title' => t('Maximum links in a sitemap'),
'#description' => t("The maximum number of links one sitemap can hold. If more links are generated than set here, a sitemap index will be created and the links split into several sub-sitemaps.<br/>50 000 links is the maximum Google will parse per sitemap, however it is advisable to set this to a lower number. If left blank, all links will be shown on a single sitemap."),
'#type' => 'textfield',
'#maxlength' => 5,
'#size' => 5,
'#default_value' => $settings['max_links'],
);
return parent::buildForm($form, $form_state);
}
/**
* {@inheritdoc}
*/
public function validateForm(array &$form, FormStateInterface $form_state) {
$max_links = $form_state->getValue('max_links');
if ($max_links != '') {
if (!is_numeric($max_links) || $max_links < 1 || $max_links != round($max_links)) {
$form_state->setErrorByName('', t("The value of the max links field must be a positive integer and greater than 1."));
}
}
}
/**
* {@inheritdoc}
*/
public function submitForm(array &$form, FormStateInterface $form_state) {
$sitemap = new Simplesitemap;
$settings = $sitemap->get_settings();
$settings['max_links'] = $form_state->getValue('max_links');
$sitemap->save_settings($settings);
}
public function rebuild_sitemap(array &$form, FormStateInterface $form_state) {
......
......@@ -17,7 +17,7 @@ class Simplesitemap {
private $sitemap;
function __construct() {
$this->set_config();
$this->initialize();
}
public static function get_form_entity($form_state) {
......@@ -38,7 +38,7 @@ class Simplesitemap {
return FALSE;
}
private function set_config() {
private function initialize() {
$this->get_config_from_db();
$this->get_sitemap_from_db();
}
......@@ -46,8 +46,10 @@ class Simplesitemap {
// Get sitemap from database.
private function get_sitemap_from_db() {
//todo: update for chunked sitemaps
$result = db_query("SELECT sitemap_string FROM {simplesitemap}")->fetchAll();
$this->sitemap = !empty($result[0]->sitemap_string) ? $result[0]->sitemap_string : NULL;
$result = db_query("SELECT id, sitemap_string FROM {simplesitemap}")->fetchAllAssoc('id');
foreach ($result as $sitemap_id => $sitemap) {
$this->sitemap[$sitemap_id] = $sitemap->sitemap_string;
}
}
// Get sitemap settings from configuration storage.
......@@ -63,38 +65,73 @@ class Simplesitemap {
$this->save_config('custom', $custom_links);
}
public function save_settings($settings) {
$this->save_config('settings', $settings);
}
private function save_config($key, $value) {
\Drupal::service('config.factory')->getEditable('simplesitemap.settings')
->set($key, $value)->save();
$this->set_config();
$this->initialize();
}
public function get_sitemap() {
public function get_sitemap($sitemap_id = NULL) {
if (empty($this->sitemap)) {
$this->generate_sitemap();
}
return $this->sitemap;
if (is_null($sitemap_id) || !isset($this->sitemap[$sitemap_id])) {
// Return sitemap index, if there are multiple sitemap chunks.
if (count($this->sitemap) > 1) {
return $this->get_sitemap_index();
}
// Return sitemap if there is only one chunk.
else {
return $this->sitemap[0];
}
}
// Return specific sitemap chunk.
else {
return $this->sitemap[$sitemap_id];
}
}
public function generate_sitemap() {
$generator = new SitemapGenerator();
$generator->set_custom_links($this->config->get('custom'));
$generator->set_entity_types($this->config->get('entity_types'));
$this->sitemap = $generator->generate_sitemap();
$settings = $this->get_settings();
$this->sitemap = $generator->generate_sitemap($settings['max_links']);
$this->save_sitemap();
drupal_set_message(t("The <a href='@url' target='_blank'>XML sitemap</a> has been regenerated for all languages.",
array('@url' => $GLOBALS['base_url'] . '/sitemap.xml')));
}
private function save_sitemap() {
//todo: update for chunked sitemaps
db_merge('simplesitemap')
->key(array('id' => 1))
->fields(array(
'id' => 1,
'sitemap_string' => $this->sitemap,
))
->execute();
db_truncate('simplesitemap')->execute();
$values = array();
foreach($this->sitemap as $sitemap_id => $sitemap_string) {
$values[] = array(
'id' => $sitemap_id,
'sitemap_string' => $sitemap_string,
//todo: add 'changed' info in new column?
);
}
$query = db_insert('simplesitemap')->fields(array('id', 'sitemap_string'));
foreach ($values as $record) {
$query->values($record);
}
$query->execute();
}
private function get_sitemap_index() {
$generator = new SitemapGenerator();
return $generator->generate_sitemap_index($this->sitemap);
}
public function get_entity_types() {
......@@ -104,4 +141,8 @@ class Simplesitemap {
public function get_custom_links() {
return $this->config->get('custom');
}
public function get_settings() {
return $this->config->get('settings');
}
}
......@@ -28,9 +28,11 @@ class SitemapGenerator {
private $custom;
private $links;
private $languages;
private $default_language_id;
function __construct() {
$this->languages = \Drupal::languageManager()->getLanguages();
$this->default_language_id = \Drupal::languageManager()->getDefaultLanguage()->getId();
$this->links = array();
}
......@@ -51,12 +53,43 @@ class SitemapGenerator {
$this->custom = is_array($custom) ? $custom : array();
}
public function generate_sitemap() {
public function generate_sitemap($max_links = NULL) {
$this->generate_custom_links();
$this->generate_entity_links();
$default_language_id = \Drupal::languageManager()->getDefaultLanguage()->getId();
$sitemaps = array();
if (!empty($max_links) && count($this->links) > 0) {
foreach(array_chunk($this->links, $max_links) as $sitemap_id => $sitemap_links) {
$sitemaps[] = $this->generate_sitemap_chunk($sitemap_links);
}
}
else {
$sitemaps[] = $this->generate_sitemap_chunk($this->links);
}
return $sitemaps;
}
public function generate_sitemap_index($sitemap) {
$writer = new XMLWriter();
$writer->openMemory();
$writer->setIndent(TRUE);
$writer->startDocument(self::XML_VERSION, self::ENCODING);
$writer->startElement('sitemapindex');
$writer->writeAttribute('xmlns', self::XMLNS);
foreach ($sitemap as $sitemap_id => $sitemap_string) {
$writer->startElement('sitemap');
$writer->writeElement('loc', $GLOBALS['base_url'] . '/sitemaps/' . $sitemap_id . '/' . 'sitemap.xml');
//todo: lastmod
$writer->endElement();
}
$writer->endElement();
$writer->endDocument();
return $writer->outputMemory();
}
private function generate_sitemap_chunk($sitemap_links) {
$writer = new XMLWriter();
$writer->openMemory();
......@@ -66,20 +99,20 @@ class SitemapGenerator {
$writer->writeAttribute('xmlns', self::XMLNS);
$writer->writeAttribute('xmlns:xhtml', self::XMLNS_XHTML);
foreach ($this->links as $link) {
foreach ($sitemap_links as $link) {
$writer->startElement('url');
// Adding url to standard language.
$writer->writeElement('loc', $link['url'][$default_language_id]);
$writer->writeElement('loc', $link['url'][$this->default_language_id]);
// Adding alternate urls (other languages).
if (count($link['url']) > 1) {
foreach($link['url'] as $language_id => $localised_url) {
$writer->startElement('xhtml:link');
$writer->writeAttribute('rel', 'alternate');
$writer->writeAttribute('hreflang', $language_id);
$writer->writeAttribute('href', $localised_url);
$writer->endElement();
$writer->startElement('xhtml:link');
$writer->writeAttribute('rel', 'alternate');
$writer->writeAttribute('hreflang', $language_id);
$writer->writeAttribute('href', $localised_url);
$writer->endElement();
}
}
......
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