xmlsitemap.install 15.6 KB
Newer Older
Darren Oh's avatar
Darren Oh committed
1 2 3
<?php
// $Id$

4
/**
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
 * @file
 * Install, update and uninstall functions for the xmlsitemap module.
 *
 * @ingroup xmlsitemap
 */

/**
 * Implements hook_requirements().
 */
function xmlsitemap_requirements($phase) {
  $requirements = array();
  $t = get_t();

  if (variable_get('clean_url', 0) && file_exists('./sitemap.xml')) {
    $requirements['xmlsitemap_file'] = array(
      'title' => $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') {
28 29 30 31
    if (!user_access('access content', drupal_anonymous_user())) {
      $requirements['xmlsitemap_access'] = array(
        'title' => $t('XML sitemap anonymous content access'),
        'value' => $t('Access denied'),
32
        '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 <a href="@perm-link">%permission</a> permission.', array('@perm-link' => url('admin/config/people/permissions/' . DRUPAL_ANONYMOUS_RID, array('fragment' => 'module-node')), '%permission' => 'access content')),
33 34 35
        'severity' => REQUIREMENT_ERROR,
      );
    }
36
    if (!xmlsitemap_check_directory()) {
37 38 39 40
      $requirements['xmlsitemap_directory'] = array(
        'title' => $t('XML sitemap cache directory'),
        'value' => $t('Not found or not writable'),
        'severity' => REQUIREMENT_ERROR,
41
        'description' => xmlsitemap_get_directory(),
42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74
      );
    }
    $max_links = XMLSITEMAP_MAX_SITEMAP_LINKS * XMLSITEMAP_MAX_SITEMAP_CHUNKS;
    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_CHUNKS) {
      $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 (1,000).'),
        '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 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;
75
      $requirements['xmlsitemap_generated']['description'] = $t('The XML sitemap data is out of sync and needs to be <a href="@link-rebuild">completely rebuilt<a>.', array('@link-rebuild' => url('admin/config/search/xmlsitemap/rebuild')));
76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125
    }
    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 <a href="@link-cron">run cron manually</a> to regenerate the sitemap files.', array('@link-cron' => url('admin/reports/status/run-cron')));
      }
    }
  }
  return $requirements;
}

/**
 * Check the status of all hook_requirements() from xmlsitemap modules.
 *
 * @param $return_only
 *   If TRUE, will return the result, otherwise it will show a message.
 * @return
 *   TRUE if there is a warning or error requirement, or FALSE otherwise.
 */
function xmlsitemap_check_status() {
  $severity = REQUIREMENT_OK;

  foreach (module_implements('requirements') as $module) {
    if (strpos($module, 'xmlsitemap') !== FALSE) {
      module_load_install($module);
      $requirements = module_invoke($module, 'requirements', 'runtime');
      $severity = max($severity, drupal_requirements_severity($requirements));
    }
  }

  return $severity == REQUIREMENT_ERROR;
}

/**
 * Implements hook_install().
 */
function xmlsitemap_install() {
  // 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 so we can use xmlsitemap_var().
  drupal_load('module', 'xmlsitemap');

  // Add files directory.
126
  xmlsitemap_check_directory();
127 128 129

  // Insert the homepage link into the {xmlsitemap} table so we do not show an
  // empty sitemap after install.
Dave Reid's avatar
Dave Reid committed
130
  db_query("INSERT INTO {xmlsitemap} (type, id, loc, priority, changefreq, language) VALUES ('frontpage', 0, '', :priority, :changefreq, :language)", array(':priority' => xmlsitemap_var('frontpage_priority'), 'changefreq' => xmlsitemap_var('frontpage_changefreq'), ':language' => LANGUAGE_NONE));
131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153

  // @todo Does the sitemap show up on first install or is it a 404 page?
}

/**
 * Implements hook_enable().
 */
function xmlsitemap_enable() {
  variable_set('xmlsitemap_regenerate_needed', TRUE);
}

/**
 * Implements hook_uninstall().
 */
function xmlsitemap_uninstall() {
  // Remove variables.
  drupal_load('module', 'xmlsitemap');
  $variables = array_keys(xmlsitemap_variables());
  foreach ($variables as $variable) {
    variable_del($variable);
  }

  // Remove files directory.
154
  xmlsitemap_clear_directory(TRUE);
155 156 157 158
}

/**
 * Implements hook_schema().
159 160
 */
function xmlsitemap_schema() {
161 162
  $schema['xmlsitemap'] = array(
    'description' => 'The base table for xmlsitemap links.',
163
    'fields' => array(
164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192
      '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' => 12,
        'not null' => TRUE,
        'default' => '',
      ),
      'subtype' => array(
        'description' => 'A sub-type identifier for the link (node type, menu name, term VID, etc.).',
        'type' => 'varchar',
        'length' => 32,
        'default' => NULL,
      ),
      '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.',
193
        'type' => 'varchar',
194
        'length' => 12,
195 196 197
        'not null' => TRUE,
        'default' => '',
      ),
198 199
      '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.',
200
        'type' => 'int',
201 202 203
        'size' => 'tiny',
        'not null' => TRUE,
        'default' => 1,
204
      ),
205 206
      'status' => array(
        'description' => 'An integer that represents if the item is included in the sitemap.',
207
        'type' => 'int',
208 209 210 211 212 213 214 215
        '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',
216 217 218
        'not null' => TRUE,
        'default' => 0,
      ),
219 220
      'lastmod' => array(
        'description' => 'The UNIX timestamp of last modification of the item.',
221 222 223 224 225 226
        'type' => 'int',
        'unsigned' => TRUE,
        'not null' => TRUE,
        'default' => 0,
      ),
      'priority' => array(
227
        'description' => 'The priority of this URL relative to other URLs on your site. Valid values range from 0.0 to 1.0.',
228
        'type' => 'float',
229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253
        '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,
254 255
      ),
    ),
256
    'primary key' => array('id', 'type'),
257
    'indexes' => array(
258 259 260 261
      'loc' => array('loc'),
      'access_status_loc' => array('access', 'status', 'loc'),
      'type_subtype' => array('type', 'subtype'),
      'language' => array('language'),
262 263 264 265 266 267
    ),
  );

  return $schema;
}

268 269 270 271 272
// @todo Remove these update functions before alpha.
function xmlsitemap_update_1() {
  $ret = array();
  db_drop_unique_key($ret, 'xmlsitemap', 'loc');
  return $ret;
273 274
}

275 276 277
function xmlsitemap_update_2() {
  if (!variable_get('xmlsitemap_base_url', '')) {
    variable_set('xmlsitemap_base_url', $GLOBALS['base_url']);
278
  }
279
  return array();
Darren Oh's avatar
Darren Oh committed
280 281
}

282 283 284 285 286
function xmlsitemap_update_3() {
  $ret = array();
  db_add_index($ret, 'xmlsitemap', 'loc', array('loc'));
  return $ret;
}
Darren Oh's avatar
Darren Oh committed
287

288 289 290 291 292 293 294 295 296 297 298 299
function xmlsitemap_update_4() {
  $ret = array();
  $field = array(
    'type' => 'int',
    'size' => 'tiny',
    'default' => 1,
    'unsigned' => TRUE,
  );
  db_change_field($ret, 'xmlsitemap', 'status', 'status', $field);
  db_add_index($ret, 'xmlsitemap', 'status', array('status'));
  return $ret;
}
Darren Oh's avatar
Darren Oh committed
300

301 302 303 304 305 306
function xmlsitemap_update_5() {
  $ret = array();
  db_drop_primary_key($ret, 'xmlsitemap');
  db_add_primary_key($ret, 'xmlsitemap', array('id', 'type'));
  return $ret;
}
Darren Oh's avatar
Darren Oh committed
307

308 309 310 311 312
function xmlsitemap_update_6() {
  $ret = array();
  if (db_column_exists('xmlsitemap', 'language')) {
    db_drop_index($ret, 'xmlsitemap', 'language');
    db_drop_field($ret, 'xmlsitemap', 'language');
Darren Oh's avatar
Darren Oh committed
313
  }
314 315 316
  variable_set('xmlsitemap_generated_last', variable_get('xmlsitemap_regenerate_last', 0));
  variable_del('xmlsitemap_regenerate_last');
  return $ret;
317 318
}

319 320 321 322
function xmlsitemap_update_7() {
  $ret = array();
  if (xmlsitemap_load_link(array('type' => 'custom'))) {
    drupal_install_modules(array('xmlsitemap_custom'));
323
  }
324 325
  variable_del('xmlsitemap_custom_links');
  return $ret;
Darren Oh's avatar
Darren Oh committed
326 327
}

328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417
function xmlsitemap_update_8() {
  $ret = array();
  $field = array(
    'type' => 'float',
    'default' => NULL,
  );
  db_add_field($ret, 'xmlsitemap', 'priority_override', $field);
  return $ret;
}

function xmlsitemap_update_9() {
  $ret = array();
  $field = array(
    'type' => 'int',
    'default' => 0,
    'unsigned' => TRUE,
    'not null' => TRUE,
  );
  db_change_field($ret, 'xmlsitemap', 'lastmod', 'lastmod', $field);
  return $ret;
}

function xmlsitemap_update_10() {
  $ret = array();
  $ret[] = update_sql("UPDATE {system} SET weight = 1 WHERE type = 'module' AND name = 'xmlsitemap'");
  return $ret;
}

function xmlsitemap_update_11() {
  $ret = array();

  // Delete any items with NULL status and drop the status index.
  $ret[] = update_sql("DELETE FROM {xmlsitemap} WHERE status IS NULL");
  db_drop_index($ret, 'xmlsitemap', 'status');

  // Rename status to access.
  $field = array(
    'type' => 'int',
    'size' => 'tiny',
    'default' => 1,
    'unsigned' => TRUE,
    'not null' => TRUE,
  );
  db_change_field($ret, 'xmlsitemap', 'status', 'access', $field);

  // Add a status field.
  $field = array(
    'type' => 'int',
    'size' => 'tiny',
    'default' => 1,
  );
  db_add_field($ret, 'xmlsitemap', 'status', $field);

  db_add_index($ret, 'xmlsitemap', 'access_status', array('access', 'status'));
  return $ret;
}

function xmlsitemap_update_12() {
  $ret = array();
  db_drop_index($ret, 'xmlsitemap', 'access_status');
  db_add_index($ret, 'xmlsitemap', 'access_status_loc', array('access', 'status', 'loc'));
  return $ret;
}

function xmlsitemap_update_13() {
  $ret = array();
  db_change_field($ret, 'xmlsitemap', 'priority_override', 'priority_override_value', array('type' => 'float', 'default' => NULL));
  $override_field = array(
    'type' => 'int',
    'size' => 'tiny',
    'default' => 0,
    'not null' => TRUE,
  );
  db_add_field($ret, 'xmlsitemap', 'status_override', $override_field);
  db_add_field($ret, 'xmlsitemap', 'priority_override', $override_field);
  $ret[] = update_sql("UPDATE {xmlsitemap} SET priority_override = 1, priority = priority_override_value WHERE priority_override_value IS NOT NULL");
  $ret[] = update_sql("UPDATE {xmlsitemap} SET priority = 0.5 WHERE priority_override_value IS NULL");
  db_drop_field($ret, 'xmlsitemap', 'priority_override_value');
  return $ret;
}

function xmlsitemap_update_14() {
  $ret = array();
  db_add_field($ret, 'xmlsitemap', 'subtype', array('type' => 'varchar', 'length' => 32, 'default' => NULL));
  $fields = array('node' => 'node_type', 'menu' => 'menu_name', 'taxonomy' => 'term_vid');
  foreach ($fields as $type => $field) {
    if (db_column_exists('xmlsitemap', $field)) {
      $ret[] = update_sql("UPDATE {xmlsitemap} SET subtype = $field WHERE type = '$type'");
      db_drop_index($ret, 'xmlsitemap', $field);
      db_drop_field($ret, 'xmlsitemap', $field);
Darren Oh's avatar
Darren Oh committed
418 419
    }
  }
420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435
  db_add_index($ret, 'xmlsitemap', 'type_subtype', array('type', 'subtype'));
  return $ret;
}

function xmlsitemap_update_15() {
  $ret = array();
  $ret[] = update_sql("DELETE FROM {xmlsitemap} WHERE status IS NULL OR access IS NULL");
  $field = array(
    'type' => 'int',
    'size' => 'tiny',
    'default' => 1,
    'not null' => TRUE,
  );
  db_change_field($ret, 'xmlsitemap', 'access', 'access', $field);
  db_change_field($ret, 'xmlsitemap', 'status', 'status', $field);
  return $ret;
Darren Oh's avatar
Darren Oh committed
436
}
437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466

function xmlsitemap_update_16() {
  $ret = array();
  $field = array(
    'type' => 'varchar',
    'length' => 12,
    'not null' => TRUE,
    'default' => '',
  );
  db_add_field($ret, 'xmlsitemap', 'language', $field);
  db_add_index($ret, 'xmlsitemap', 'language', array('language'));
  return $ret;
}

function xmlsitemap_update_17() {
  $ret = array();
  $ret[] = update_sql("UPDATE {xmlsitemap} SET access = 1 WHERE access > 1");
  $ret[] = update_sql("UPDATE {xmlsitemap} SET status = 1 WHERE status > 1");
  return $ret;
}

/**
 * These strings exist only for the extractor to pick them up and make them
 * available for translation. Putting them here keeps them from being parsed
 * on normal pages.
 *
 * Idea borrowed from the date and event modules. Thanks karens and killes!
 */
//function _xmlsitemap_translation_strings() {
//}