$t('XML sitemap'),
'value' => $t('Existing sitemap.xml file found.'),
'severity' => REQUIREMENT_ERROR,
'description' => $t('The XML sitemap module cannot display its XML output if there is an existing sitemap.xml file in your website root.'),
);
}
if ($phase == 'runtime') {
if (!user_access('access content', drupal_anonymous_user())) {
$requirements['xmlsitemap_access'] = array(
'title' => $t('XML sitemap anonymous content access'),
'value' => $t('Access denied'),
'description' => $t('In order to allow search engines to view the XML sitemap and content on your site, the anonymous user role must have the %permission permission.', array('@perm-link' => url('admin/user/permissions/' . DRUPAL_ANONYMOUS_RID, array('fragment' => 'module-node')), '%permission' => 'access content')),
'severity' => REQUIREMENT_ERROR,
);
}
if (!xmlsitemap_check_directory()) {
$requirements['xmlsitemap_directory'] = array(
'title' => $t('XML sitemap cache directory'),
'value' => $t('Not found or not writable'),
'severity' => REQUIREMENT_ERROR,
'description' => xmlsitemap_get_directory(),
);
}
$max_links = XMLSITEMAP_MAX_SITEMAP_LINKS * XMLSITEMAP_MAX_SITEMAP_LINKS;
if (xmlsitemap_get_link_count() > $max_links) {
$requirements['xmlsitemap_link_count'] = array(
'title' => $t('XML sitemap link count'),
'value' => xmlsitemap_get_link_count(),
'description' => $t('You have exceeded the number of links that your sitemap can contain (@num).', array('@num' => number_format($max_links))),
'severity' => REQUIREMENT_ERROR,
);
}
if (xmlsitemap_get_chunk_count() > XMLSITEMAP_MAX_SITEMAP_LINKS) {
$requirements['xmlsitemap_chunk_count'] = array(
'title' => $t('XML sitemap page count'),
'value' => xmlsitemap_get_chunk_count(),
'description' => $t('You have exceeded the number of sitemap pages (@number).', array('@number' => number_format(XMLSITEMAP_MAX_SITEMAP_LINKS))),
'severity' => REQUIREMENT_ERROR,
);
if (!in_array(xmlsitemap_get_chunk_size(), array(50000, 'auto'))) {
$requirements['xmlsitemap_chunk_count']['description'] .= ' ' . t('Please increase the number of links per page.');
}
}
// Check maximum file size.
$max_filesize = variable_get('xmlsitemap_max_filesize', 0);
$requirements['xmlsitemap_file_size'] = array(
'title' => $t('XML sitemap maximum file size'),
'value' => format_size($max_filesize),
);
if ($max_filesize > XMLSITEMAP_MAX_SITEMAP_FILESIZE) {
$requirements['xmlsitemap_file_size']['description'] = $t('You have exceeded the maximum sitemap file size of @size. If possible, decrease the number of links per sitemap page.', array('@size' => format_size(XMLSITEMAP_MAX_SITEMAP_FILESIZE)));
$requirements['xmlsitemap_file_size']['severity'] = REQUIREMENT_ERROR;
}
elseif (!variable_get('xmlsitemap_developer_mode', 0)) {
unset($requirements['xmlsitemap_file_size']);
}
// Check when the cached files were last generated.
$generated_last = xmlsitemap_var('generated_last');
$generated_ago = REQUEST_TIME - $generated_last;
$requirements['xmlsitemap_generated'] = array(
'title' => $t('XML sitemap'),
'value' => $generated_last ? $t('Last generated on !date (!interval ago).', array('!date' => format_date($generated_last, 'small'), '!interval' => format_interval($generated_ago))) : $t('Cached files have not been generated yet.'),
'severity' => REQUIREMENT_OK,
);
if (xmlsitemap_var('rebuild_needed')) {
$requirements['xmlsitemap_generated']['severity'] = REQUIREMENT_ERROR;
$requirements['xmlsitemap_generated']['description'] = $t('The XML sitemap data is out of sync and needs to be completely rebuilt.', array('@link-rebuild' => url('admin/settings/xmlsitemap/rebuild')));
}
elseif (xmlsitemap_var('regenerate_needed')) {
if ($generated_ago >= variable_get('cron_threshold_error', 1209600)) {
$requirements['xmlsitemap_generated']['severity'] = REQUIREMENT_ERROR;
}
elseif ($generated_ago >= variable_get('cron_threshold_warning', 172800)) {
$requirements['xmlsitemap_generated']['severity'] = REQUIREMENT_WARNING;
}
if ($requirements['xmlsitemap_generated']['severity']) {
$requirements['xmlsitemap_generated']['description'] = $t('The XML cached files are out of date and need to be regenerated. You can run cron manually to regenerate the sitemap files.', array('@link-cron' => url('admin/reports/status/run-cron', array('query' => drupal_get_destination()))));
}
}
}
return $requirements;
}
/**
* Implements hook_schema().
*/
function xmlsitemap_schema() {
// @todo Rename to xmlsitemap_link
$schema['xmlsitemap'] = array(
'description' => 'The base table for xmlsitemap links.',
'fields' => array(
'id' => array(
'description' => 'Primary key with type; a unique id for the item.',
'type' => 'int',
'not null' => TRUE,
'unsigned' => TRUE,
'default' => 0,
),
'type' => array(
'description' => 'Primary key with id; the type of item (e.g. node, user, etc.).',
'type' => 'varchar',
'length' => 32,
'not null' => TRUE,
'default' => '',
),
'subtype' => array(
'description' => 'A sub-type identifier for the link (node type, menu name, term VID, etc.).',
'type' => 'varchar',
'length' => 128,
'not null' => TRUE,
'default' => '',
),
'loc' => array(
'description' => 'The URL to the item relative to the Drupal path.',
'type' => 'varchar',
'length' => 255,
'not null' => TRUE,
'default' => '',
),
'language' => array(
'description' => 'The {languages}.language of this link or an empty string if it is language-neutral.',
'type' => 'varchar',
'length' => 12,
'not null' => TRUE,
'default' => '',
),
'access' => array(
'description' => 'A boolean that represents if the item is viewable by the anonymous user. This field is useful to store the result of node_access() so we can retain changefreq and priority_override information.',
'type' => 'int',
'size' => 'tiny',
'not null' => TRUE,
'default' => 1,
),
'status' => array(
'description' => 'An integer that represents if the item is included in the sitemap.',
'type' => 'int',
'size' => 'tiny',
'not null' => TRUE,
'default' => 1,
),
'status_override' => array(
'description' => 'A boolean that if TRUE means that the status field has been overridden from its default value.',
'type' => 'int',
'size' => 'tiny',
'not null' => TRUE,
'default' => 0,
),
'lastmod' => array(
'description' => 'The UNIX timestamp of last modification of the item.',
'type' => 'int',
'unsigned' => TRUE,
'not null' => TRUE,
'default' => 0,
),
'priority' => array(
'description' => 'The priority of this URL relative to other URLs on your site. Valid values range from 0.0 to 1.0.',
'type' => 'float',
'default' => NULL,
// @todo Convert this field to non-nullable.
//'default' => 0.5,
//'not null' => NULL,
),
'priority_override' => array(
'description' => 'A boolean that if TRUE means that the priority field has been overridden from its default value.',
'type' => 'int',
'size' => 'tiny',
'not null' => TRUE,
'default' => 0,
),
'changefreq' => array(
'description' => 'The average time in seconds between changes of this item.',
'type' => 'int',
'unsigned' => TRUE,
'not null' => TRUE,
'default' => 0,
),
'changecount' => array(
'description' => 'The number of times this item has been changed. Used to help calculate the next changefreq value.',
'type' => 'int',
'unsigned' => TRUE,
'not null' => TRUE,
'default' => 0,
),
),
'primary key' => array('id', 'type'),
'indexes' => array(
'loc' => array('loc'),
'access_status_loc' => array('access', 'status', 'loc'),
'type_subtype' => array('type', 'subtype'),
'language' => array('language'),
),
);
$schema['xmlsitemap_sitemap'] = array(
'fields' => array(
'smid' => array(
'description' => 'Sitemap ID',
'type' => 'serial',
'unsigned' => TRUE,
'not null' => TRUE,
),
'context_hash' => array(
'description' => 'The MD5 hash of the context field.',
'type' => 'varchar',
'length' => 32,
'not null' => TRUE,
'default' => '',
),
'context' => array(
'description' => 'Serialized array with the sitemaps context',
'type' => 'text',
'not null' => TRUE,
'serialize' => TRUE,
),
'updated' => array(
'type' => 'int',
'unsigned' => TRUE,
'not null' => TRUE,
'default' => 0,
),
'links' => array(
'type' => 'int',
'unsigned' => TRUE,
'not null' => TRUE,
'default' => 0,
),
'chunks' => array(
'type' => 'int',
'unsigned' => TRUE,
'not null' => TRUE,
'default' => 0,
),
//'queued' => array(
// 'type' => 'int',
// 'unsigned' => TRUE,
// 'not null' => TRUE,
// 'default' => 0,
// 'description' => 'Time when this sitemap was queued for regeneration, 0 if not queued.',
//),
),
'primary key' => array('smid'),
'unique keys' => array(
'context_hash' => array('context_hash'),
),
);
return $schema;
}
/**
* Implements hook_install().
*/
function xmlsitemap_install() {
// Add tables.
drupal_install_schema('xmlsitemap');
// Set this module's weight to 1 so xmlsitemap_cron() runs after all other
// xmlsitemap_x_cron() runs.
db_query("UPDATE {system} SET weight = 1 WHERE type = 'module' AND name = 'xmlsitemap'");
// Load the module.
drupal_load('module', 'xmlsitemap');
// Insert the homepage link into the {xmlsitemap} table so we do not show an
// empty sitemap after install.
db_query("INSERT INTO {xmlsitemap} (type, id, loc, priority, changefreq) VALUES ('frontpage', 0, '', %f, %d)", variable_get('xmlsitemap_frontpage_priority', 1.0), variable_get('xmlsitemap_frontpage_changefreq', XMLSITEMAP_FREQUENCY_DAILY));
// Insert the default context sitemap.
$context = serialize(array());
db_query("INSERT INTO {xmlsitemap_sitemap} (context, context_hash) VALUES ('%s', '%s')", $context, md5($context));
// @todo Does the sitemap show up on first install or is it a 404 page?
}
/**
* Implements hook_enable().
*/
function xmlsitemap_enable() {
// Ensure the file cache directory is available and ready.
xmlsitemap_check_directory();
variable_set('xmlsitemap_regenerate_needed', TRUE);
}
/**
* Implements hook_uninstall().
*/
function xmlsitemap_uninstall() {
// Remove tables.
drupal_uninstall_schema('xmlsitemap');
// Remove variables.
drupal_load('module', 'xmlsitemap');
$variables = array_keys(xmlsitemap_variables());
foreach ($variables as $variable) {
variable_del($variable);
}
// Remove the file cache directory.
xmlsitemap_clear_directory(NULL, TRUE);
}
/**
* Upgrade 6.x-1.x variables.
*/
function xmlsitemap_update_6196() {
$value = variable_get('xmlsitemap_cron_limit', 100);
variable_set('xmlsitemap_batch_limit', $value);
$value = variable_get('xmlsitemap_cache_directory', file_directory_path() . '/xmlsitemap');
if (strpos($value, file_directory_path() . '/') === 0) {
$value = str_replace(file_directory_path() . '/', '', $value);
}
else {
$value = 'xmlsitemap';
}
variable_set('xmlsitemap_path', $value);
$value = variable_get('xmlsitemap_use_stylesheet', FALSE);
variable_set('xmlsitemap_xsl', $value);
$value = variable_get('xmlsitemap_front_page_changefreq', 3600);
variable_set('xmlsitemap_frontpage_changefreq', $value);
$value = variable_get('xmlsitemap_front_page_priority', 1);
variable_set('xmlsitemap_frontpage_priority', $value);
// Intentionally set this variables so we get a generated sitemap ASAP.
variable_set('xmlsitemap_generated_last', 0);
variable_set('xmlsitemap_regenerate_needed', TRUE);
variable_del('xmlsitemap_chunk_size');
return array();
}
/**
* Upgrade the {xmlsitemap} table (drop and re-create).
*/
function xmlsitemap_update_6198() {
$ret = array();
if (db_column_exists('xmlsitemap', 'sid')) {
db_drop_table($ret, 'xmlsitemap');
$schema['xmlsitemap'] = array(
'description' => 'The base table for xmlsitemap links.',
'fields' => array(
'id' => array(
'description' => 'Primary key with type; a unique id for the item.',
'type' => 'int',
'not null' => TRUE,
'unsigned' => TRUE,
'default' => 0,
),
'type' => array(
'description' => 'Primary key with id; the type of item (e.g. node, user, etc.).',
'type' => 'varchar',
'length' => 32,
'not null' => TRUE,
'default' => '',
),
'subtype' => array(
'description' => 'A sub-type identifier for the link (node type, menu name, term VID, etc.).',
'type' => 'varchar',
'length' => 128,
'not null' => TRUE,
'default' => '',
),
'loc' => array(
'description' => 'The URL to the item relative to the Drupal path.',
'type' => 'varchar',
'length' => 255,
'not null' => TRUE,
'default' => '',
),
'language' => array(
'description' => 'The {languages}.language of this link or an empty string if it is language-neutral.',
'type' => 'varchar',
'length' => 12,
'not null' => TRUE,
'default' => '',
),
'access' => array(
'description' => 'A boolean that represents if the item is viewable by the anonymous user. This field is useful to store the result of node_access() so we can retain changefreq and priority_override information.',
'type' => 'int',
'size' => 'tiny',
'not null' => TRUE,
'default' => 1,
),
'status' => array(
'description' => 'An integer that represents if the item is included in the sitemap.',
'type' => 'int',
'size' => 'tiny',
'not null' => TRUE,
'default' => 1,
),
'status_override' => array(
'description' => 'A boolean that if TRUE means that the status field has been overridden from its default value.',
'type' => 'int',
'size' => 'tiny',
'not null' => TRUE,
'default' => 0,
),
'lastmod' => array(
'description' => 'The UNIX timestamp of last modification of the item.',
'type' => 'int',
'unsigned' => TRUE,
'not null' => TRUE,
'default' => 0,
),
'priority' => array(
'description' => 'The priority of this URL relative to other URLs on your site. Valid values range from 0.0 to 1.0.',
'type' => 'float',
'default' => NULL,
),
'priority_override' => array(
'description' => 'A boolean that if TRUE means that the priority field has been overridden from its default value.',
'type' => 'int',
'size' => 'tiny',
'not null' => TRUE,
'default' => 0,
),
'changefreq' => array(
'description' => 'The average time in seconds between changes of this item.',
'type' => 'int',
'unsigned' => TRUE,
'not null' => TRUE,
'default' => 0,
),
'changecount' => array(
'description' => 'The number of times this item has been changed. Used to help calculate the next changefreq value.',
'type' => 'int',
'unsigned' => TRUE,
'not null' => TRUE,
'default' => 0,
),
),
'primary key' => array('id', 'type'),
'indexes' => array(
'loc' => array('loc'),
'access_status_loc' => array('access', 'status', 'loc'),
'type_subtype' => array('type', 'subtype'),
'language' => array('language'),
),
);
db_create_table($ret, 'xmlsitemap', $schema['xmlsitemap']);
db_query("INSERT INTO {xmlsitemap} (type, id, loc, priority, changefreq) VALUES ('frontpage', 0, '', %f, %d)", variable_get('xmlsitemap_frontpage_priority', 1.0), variable_get('xmlsitemap_frontpage_changefreq', 86400));
// Force a rebuild for table schemas.
drupal_get_schema(NULL, TRUE);
}
return $ret;
}
/**
* Empty update.
*/
function xmlsitemap_update_6200() {
return array();
}
/**
* Cleanup any remaining 6.x-1.x tables, variables or weights.
*/
function xmlsitemap_update_6201() {
$ret = array();
if (db_table_exists('xmlsitemap_additional')) {
db_drop_table($ret, 'xmlsitemap_additional');
}
if (db_table_exists('xmlsitemap_modules')) {
db_drop_table($ret, 'xmlsitemap_modules');
}
if (db_table_exists('xmlsitemap_file')) {
db_drop_table($ret, 'xmlsitemap_file');
}
// Take care of any stray 6.x-1.x modules that are no longer supported.
$modules = array('xmlsitemap_file', 'xmlsitemap_helper', 'xmlsitemap_term');
module_disable($modules);
foreach ($modules as $module) {
drupal_set_installed_schema_version($module, SCHEMA_UNINSTALLED);
}
variable_del('xmlsitemap_all_links_to_default_language');
variable_del('xmlsitemap_cache_directory');
// xmlsitemap_chunk_size not deleted since we use the same variable name.
db_query("DELETE FROM {variable} WHERE name LIKE 'xmlsitemap_create_cache_result_%%'");
variable_del('xmlsitemap_cron_limit');
variable_del('xmlsitemap_cron_submit');
variable_del('xmlsitemap_cron_submit_frequency');
variable_del('xmlsitemap_front_page_changefreq');
variable_del('xmlsitemap_front_page_priority');
variable_del('xmlsitemap_log_access');
variable_del('xmlsitemap_previous_chunks_count');
variable_del('xmlsitemap_sitemap_is_changed');
variable_del('xmlsitemap_sitemap_needs_update');
variable_del('xmlsitemap_submit');
variable_del('xmlsitemap_update_sitemap_request');
variable_del('xmlsitemap_update_timestamp');
variable_del('xmlsitemap_use_stylesheet');
$ret[] = update_sql("UPDATE {system} SET weight = 1 WHERE type = 'module' AND name = 'xmlsitemap'");
return $ret;
}
/**
* Create the {xmlsitemap_sitemap} table and add the sitemap context data.
*/
function xmlsitemap_update_6202() {
$ret = array();
if (!db_table_exists('xmlsitemap_sitemap')) {
$schema['xmlsitemap_sitemap'] = array(
'fields' => array(
'smid' => array(
'description' => 'Sitemap ID',
'type' => 'serial',
'unsigned' => TRUE,
'not null' => TRUE,
),
'context_hash' => array(
'description' => 'The MD5 hash of the context field.',
'type' => 'varchar',
'length' => 32,
'not null' => TRUE,
'default' => '',
),
'context' => array(
'description' => 'Serialized array with the sitemaps context',
'type' => 'text',
'not null' => TRUE,
),
'updated' => array(
'type' => 'int',
'unsigned' => TRUE,
'not null' => TRUE,
'default' => 0,
),
'links' => array(
'type' => 'int',
'unsigned' => TRUE,
'not null' => TRUE,
'default' => 0,
),
'chunks' => array(
'type' => 'int',
'unsigned' => TRUE,
'not null' => TRUE,
'default' => 0,
),
),
'primary key' => array('smid'),
'unique keys' => array(
'context_hash' => array('context_hash'),
),
);
db_create_table($ret, 'xmlsitemap_sitemap', $schema['xmlsitemap_sitemap']);
}
// Add the default sitemap(s) and use language contexts if possible.
if (!db_result(db_query("SELECT COUNT(smid) FROM {xmlsitemap_sitemap}"))) {
// Refresh the schema and load the module if it's disabled.
drupal_get_schema(NULL, TRUE);
drupal_load('module', 'xmlsitemap');
if (module_exists('xmlsitemap_i18n') && $languages = variable_get('xmlsitemap_languages', array())) {
foreach ($languages as $language) {
$sitemap = array('context' => array('language' => $language));
xmlsitemap_sitemap_save($sitemap);
}
}
else {
$sitemap = array('context' => array());
xmlsitemap_sitemap_save($sitemap);
}
}
// Language variable is no longer needed, so go ahead and delete it.
variable_del('xmlsitemap_languages');
return $ret;
}