xmlsitemap.install 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491
  1. <?php
  2. // $Id: xmlsitemap.install,v 1.22 2010/01/24 03:57:17 davereid Exp $
  3. /**
  4. * @file
  5. * Install, update and uninstall functions for the xmlsitemap module.
  6. *
  7. * @ingroup xmlsitemap
  8. */
  9. /**
  10. * Implements hook_requirements().
  11. */
  12. function xmlsitemap_requirements($phase) {
  13. $requirements = array();
  14. $t = get_t();
  15. if (variable_get('clean_url', 0) && file_exists('./sitemap.xml')) {
  16. $requirements['xmlsitemap_file'] = array(
  17. 'title' => $t('XML sitemap'),
  18. 'value' => $t('Existing sitemap.xml file found.'),
  19. 'severity' => REQUIREMENT_ERROR,
  20. 'description' => $t('The XML sitemap module cannot display its XML output if there is an existing sitemap.xml file in your website root.'),
  21. );
  22. }
  23. if ($phase == 'runtime') {
  24. if (!user_access('access content', drupal_anonymous_user())) {
  25. $requirements['xmlsitemap_access'] = array(
  26. 'title' => $t('XML sitemap anonymous content access'),
  27. 'value' => $t('Access denied'),
  28. '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')),
  29. 'severity' => REQUIREMENT_ERROR,
  30. );
  31. }
  32. if (!xmlsitemap_check_directory()) {
  33. $requirements['xmlsitemap_directory'] = array(
  34. 'title' => $t('XML sitemap cache directory'),
  35. 'value' => $t('Not found or not writable'),
  36. 'severity' => REQUIREMENT_ERROR,
  37. 'description' => xmlsitemap_get_directory(),
  38. );
  39. }
  40. $max_links = XMLSITEMAP_MAX_SITEMAP_LINKS * XMLSITEMAP_MAX_SITEMAP_CHUNKS;
  41. if (xmlsitemap_get_link_count() > $max_links) {
  42. $requirements['xmlsitemap_link_count'] = array(
  43. 'title' => $t('XML sitemap link count'),
  44. 'value' => xmlsitemap_get_link_count(),
  45. 'description' => $t('You have exceeded the number of links that your sitemap can contain (@num).', array('@num' => number_format($max_links))),
  46. 'severity' => REQUIREMENT_ERROR,
  47. );
  48. }
  49. if (xmlsitemap_get_chunk_count() > XMLSITEMAP_MAX_SITEMAP_CHUNKS) {
  50. $requirements['xmlsitemap_chunk_count'] = array(
  51. 'title' => $t('XML sitemap page count'),
  52. 'value' => xmlsitemap_get_chunk_count(),
  53. 'description' => $t('You have exceeded the number of sitemap pages (1,000).'),
  54. 'severity' => REQUIREMENT_ERROR,
  55. );
  56. if (!in_array(xmlsitemap_get_chunk_size(), array(50000, 'auto'))) {
  57. $requirements['xmlsitemap_chunk_count']['description'] .= ' ' . t('Please increase the number of links per page.');
  58. }
  59. }
  60. // Check when the cached files were last generated.
  61. $generated_last = xmlsitemap_var('generated_last');
  62. $generated_ago = REQUEST_TIME - $generated_last;
  63. $requirements['xmlsitemap_generated'] = array(
  64. 'title' => $t('XML sitemap'),
  65. '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.'),
  66. 'severity' => REQUIREMENT_OK,
  67. );
  68. if (xmlsitemap_var('rebuild_needed')) {
  69. $requirements['xmlsitemap_generated']['severity'] = REQUIREMENT_ERROR;
  70. $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')));
  71. }
  72. elseif (xmlsitemap_var('regenerate_needed')) {
  73. if ($generated_ago >= variable_get('cron_threshold_error', 1209600)) {
  74. $requirements['xmlsitemap_generated']['severity'] = REQUIREMENT_ERROR;
  75. }
  76. elseif ($generated_ago >= variable_get('cron_threshold_warning', 172800)) {
  77. $requirements['xmlsitemap_generated']['severity'] = REQUIREMENT_WARNING;
  78. }
  79. if ($requirements['xmlsitemap_generated']['severity']) {
  80. $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', array('query' => drupal_get_destination()))));
  81. }
  82. }
  83. }
  84. return $requirements;
  85. }
  86. /**
  87. * Check the status of all hook_requirements() from xmlsitemap modules.
  88. */
  89. function xmlsitemap_check_status() {
  90. $messages = &drupal_static(__FUNCTION__);
  91. if (!isset($messages)) {
  92. // Cache the list of modules that are checked.
  93. if ($cache = cache_get('xmlsitemap:status:modules')) {
  94. $modules = $cache->data;
  95. }
  96. else {
  97. $modules = array();
  98. foreach (module_implements('requirements') as $module) {
  99. if (strpos($module, 'xmlsitemap') !== FALSE) {
  100. $modules[] = $module;
  101. }
  102. }
  103. cache_set('xmlsitemap:status:modules', $modules);
  104. }
  105. $messages = array();
  106. foreach ($modules as $module) {
  107. module_load_install($module);
  108. $requirements = module_invoke($module, 'requirements', 'runtime');
  109. foreach ($requirements as $requirement) {
  110. if (isset($requirement['severity']) && max(REQUIREMENT_OK, $requirement['severity'])) {
  111. $messages[] = $requirement['description'];
  112. }
  113. }
  114. }
  115. if ($messages) {
  116. $message = t('One or more problems were detected with your XML sitemap configuration: !messages', array('!messages' => theme('item_list', array('items' => $messages))));
  117. if (user_access('access site reports')) {
  118. $message .= t('Check the <a href="@status-report">status report</a> for more information.', array('@status-report' => url('admin/reports/status')));
  119. }
  120. drupal_set_message($message, 'warning', FALSE);
  121. }
  122. }
  123. return !empty($messages);
  124. }
  125. /**
  126. * Implements hook_install().
  127. */
  128. function xmlsitemap_install() {
  129. // Set this module's weight to 1 so xmlsitemap_cron() runs after all other
  130. // xmlsitemap_x_cron() runs.
  131. db_update('system')
  132. ->fields(array('weight' => 1))
  133. ->condition('type', 'module')
  134. ->condition('name', 'xmlsitemap')
  135. ->execute();
  136. // Load the module so we can use xmlsitemap_var().
  137. drupal_load('module', 'xmlsitemap');
  138. // Add files directory.
  139. xmlsitemap_check_directory();
  140. // Insert the homepage link into the {xmlsitemap} table so we do not show an
  141. // empty sitemap after install.
  142. 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));
  143. // @todo Does the sitemap show up on first install or is it a 404 page?
  144. }
  145. /**
  146. * Implements hook_enable().
  147. */
  148. function xmlsitemap_enable() {
  149. variable_set('xmlsitemap_regenerate_needed', TRUE);
  150. }
  151. /**
  152. * Implements hook_uninstall().
  153. */
  154. function xmlsitemap_uninstall() {
  155. // Remove variables.
  156. drupal_load('module', 'xmlsitemap');
  157. $variables = array_keys(xmlsitemap_variables());
  158. foreach ($variables as $variable) {
  159. variable_del($variable);
  160. }
  161. // Remove files directory.
  162. xmlsitemap_clear_directory(TRUE);
  163. }
  164. /**
  165. * Implements hook_schema().
  166. */
  167. function xmlsitemap_schema() {
  168. $schema['xmlsitemap'] = array(
  169. 'description' => 'The base table for xmlsitemap links.',
  170. 'fields' => array(
  171. 'id' => array(
  172. 'description' => 'Primary key with type; a unique id for the item.',
  173. 'type' => 'int',
  174. 'not null' => TRUE,
  175. 'unsigned' => TRUE,
  176. 'default' => 0,
  177. ),
  178. 'type' => array(
  179. 'description' => 'Primary key with id; the type of item (e.g. node, user, etc.).',
  180. 'type' => 'varchar',
  181. 'length' => 32,
  182. 'not null' => TRUE,
  183. 'default' => '',
  184. ),
  185. 'subtype' => array(
  186. 'description' => 'A sub-type identifier for the link (node type, menu name, term VID, etc.).',
  187. 'type' => 'varchar',
  188. 'length' => 128,
  189. 'not null' => TRUE,
  190. 'default' => '',
  191. ),
  192. 'loc' => array(
  193. 'description' => 'The URL to the item relative to the Drupal path.',
  194. 'type' => 'varchar',
  195. 'length' => 255,
  196. 'not null' => TRUE,
  197. 'default' => '',
  198. ),
  199. 'language' => array(
  200. 'description' => 'The {languages}.language of this link or an empty string if it is language-neutral.',
  201. 'type' => 'varchar',
  202. 'length' => 12,
  203. 'not null' => TRUE,
  204. 'default' => '',
  205. ),
  206. 'access' => array(
  207. '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.',
  208. 'type' => 'int',
  209. 'size' => 'tiny',
  210. 'not null' => TRUE,
  211. 'default' => 1,
  212. ),
  213. 'status' => array(
  214. 'description' => 'An integer that represents if the item is included in the sitemap.',
  215. 'type' => 'int',
  216. 'size' => 'tiny',
  217. 'not null' => TRUE,
  218. 'default' => 1,
  219. ),
  220. 'status_override' => array(
  221. 'description' => 'A boolean that if TRUE means that the status field has been overridden from its default value.',
  222. 'type' => 'int',
  223. 'size' => 'tiny',
  224. 'not null' => TRUE,
  225. 'default' => 0,
  226. ),
  227. 'lastmod' => array(
  228. 'description' => 'The UNIX timestamp of last modification of the item.',
  229. 'type' => 'int',
  230. 'unsigned' => TRUE,
  231. 'not null' => TRUE,
  232. 'default' => 0,
  233. ),
  234. 'priority' => array(
  235. 'description' => 'The priority of this URL relative to other URLs on your site. Valid values range from 0.0 to 1.0.',
  236. 'type' => 'float',
  237. 'default' => NULL,
  238. // @todo Convert this field to non-nullable.
  239. //'default' => 0.5,
  240. //'not null' => NULL,
  241. ),
  242. 'priority_override' => array(
  243. 'description' => 'A boolean that if TRUE means that the priority field has been overridden from its default value.',
  244. 'type' => 'int',
  245. 'size' => 'tiny',
  246. 'not null' => TRUE,
  247. 'default' => 0,
  248. ),
  249. 'changefreq' => array(
  250. 'description' => 'The average time in seconds between changes of this item.',
  251. 'type' => 'int',
  252. 'unsigned' => TRUE,
  253. 'not null' => TRUE,
  254. 'default' => 0,
  255. ),
  256. 'changecount' => array(
  257. 'description' => 'The number of times this item has been changed. Used to help calculate the next changefreq value.',
  258. 'type' => 'int',
  259. 'unsigned' => TRUE,
  260. 'not null' => TRUE,
  261. 'default' => 0,
  262. ),
  263. ),
  264. 'primary key' => array('id', 'type'),
  265. 'indexes' => array(
  266. 'loc' => array('loc'),
  267. 'access_status_loc' => array('access', 'status', 'loc'),
  268. 'type_subtype' => array('type', 'subtype'),
  269. 'language' => array('language'),
  270. ),
  271. );
  272. return $schema;
  273. }
  274. // @todo Remove these update functions before alpha.
  275. function xmlsitemap_update_1() {
  276. db_drop_unique_key('xmlsitemap', 'loc');
  277. }
  278. function xmlsitemap_update_2() {
  279. if (!variable_get('xmlsitemap_base_url', '')) {
  280. variable_set('xmlsitemap_base_url', $GLOBALS['base_url']);
  281. }
  282. }
  283. function xmlsitemap_update_3() {
  284. db_add_index('xmlsitemap', 'loc', array('loc'));
  285. }
  286. function xmlsitemap_update_4() {
  287. $field = array(
  288. 'type' => 'int',
  289. 'size' => 'tiny',
  290. 'default' => 1,
  291. 'unsigned' => TRUE,
  292. );
  293. db_change_field('xmlsitemap', 'status', 'status', $field);
  294. db_add_index('xmlsitemap', 'status', array('status'));
  295. }
  296. function xmlsitemap_update_5() {
  297. db_drop_primary_key('xmlsitemap');
  298. db_add_primary_key('xmlsitemap', array('id', 'type'));
  299. }
  300. function xmlsitemap_update_6() {
  301. if (db_column_exists('xmlsitemap', 'language')) {
  302. db_drop_index('xmlsitemap', 'language');
  303. db_drop_field('xmlsitemap', 'language');
  304. }
  305. variable_set('xmlsitemap_generated_last', variable_get('xmlsitemap_regenerate_last', 0));
  306. variable_del('xmlsitemap_regenerate_last');
  307. }
  308. function xmlsitemap_update_7() {
  309. if (xmlsitemap_load_link(array('type' => 'custom'))) {
  310. drupal_install_modules(array('xmlsitemap_custom'));
  311. }
  312. variable_del('xmlsitemap_custom_links');
  313. }
  314. function xmlsitemap_update_8() {
  315. $field = array(
  316. 'type' => 'float',
  317. 'default' => NULL,
  318. );
  319. db_add_field('xmlsitemap', 'priority_override', $field);
  320. }
  321. function xmlsitemap_update_9() {
  322. $field = array(
  323. 'type' => 'int',
  324. 'default' => 0,
  325. 'unsigned' => TRUE,
  326. 'not null' => TRUE,
  327. );
  328. db_change_field('xmlsitemap', 'lastmod', 'lastmod', $field);
  329. }
  330. function xmlsitemap_update_10() {
  331. db_update('system')
  332. ->fields(array('weight' => 1))
  333. ->condition('type', 'module')
  334. ->condition('name', 'xmlsitemap')
  335. ->execute();
  336. }
  337. function xmlsitemap_update_11() {
  338. // Delete any items with NULL status and drop the status index.
  339. db_delete('xmlsitemap')
  340. ->isNull('status')
  341. ->execute();
  342. db_drop_index('xmlsitemap', 'status');
  343. // Rename status to access.
  344. $field = array(
  345. 'type' => 'int',
  346. 'size' => 'tiny',
  347. 'default' => 1,
  348. 'unsigned' => TRUE,
  349. 'not null' => TRUE,
  350. );
  351. db_change_field('xmlsitemap', 'status', 'access', $field);
  352. // Add a status field.
  353. $field = array(
  354. 'type' => 'int',
  355. 'size' => 'tiny',
  356. 'default' => 1,
  357. );
  358. db_add_field('xmlsitemap', 'status', $field);
  359. db_add_index('xmlsitemap', 'access_status', array('access', 'status'));
  360. }
  361. function xmlsitemap_update_12() {
  362. db_drop_index('xmlsitemap', 'access_status');
  363. db_add_index('xmlsitemap', 'access_status_loc', array('access', 'status', 'loc'));
  364. }
  365. function xmlsitemap_update_13() {
  366. db_change_field('xmlsitemap', 'priority_override', 'priority_override_value', array('type' => 'float', 'default' => NULL));
  367. $override_field = array(
  368. 'type' => 'int',
  369. 'size' => 'tiny',
  370. 'default' => 0,
  371. 'not null' => TRUE,
  372. );
  373. db_add_field('xmlsitemap', 'status_override', $override_field);
  374. db_add_field('xmlsitemap', 'priority_override', $override_field);
  375. db_update('xmlsitemap')
  376. ->fields(array('priority_override' => 1))
  377. ->expression('priority', 'priority_override_value')
  378. ->isNotNull('priority_override_value')
  379. ->execute();
  380. db_update('xmlsitemap')
  381. ->fields(array('priority' => 0.5))
  382. ->isNull('priority_override_value')
  383. ->execute();
  384. db_drop_field('xmlsitemap', 'priority_override_value');
  385. }
  386. function xmlsitemap_update_14() {
  387. db_add_field('xmlsitemap', 'subtype', array('type' => 'varchar', 'length' => 32, 'default' => NULL));
  388. $fields = array('node' => 'node_type', 'menu' => 'menu_name', 'taxonomy' => 'term_vid');
  389. foreach ($fields as $type => $field) {
  390. if (db_column_exists('xmlsitemap', $field)) {
  391. db_update('xmlsitemap')
  392. ->fields(array('subtype', $field))
  393. ->condition('type', $type)
  394. ->execute();
  395. db_drop_index('xmlsitemap', $field);
  396. db_drop_field('xmlsitemap', $field);
  397. }
  398. }
  399. db_add_index('xmlsitemap', 'type_subtype', array('type', 'subtype'));
  400. }
  401. function xmlsitemap_update_15() {
  402. $or = db_or();
  403. $or->isNull('status');
  404. $or->isNull('access');
  405. db_delete('xmlsitemap')
  406. ->condition($or)
  407. ->execute();
  408. $field = array(
  409. 'type' => 'int',
  410. 'size' => 'tiny',
  411. 'default' => 1,
  412. 'not null' => TRUE,
  413. );
  414. db_change_field('xmlsitemap', 'access', 'access', $field);
  415. db_change_field('xmlsitemap', 'status', 'status', $field);
  416. }
  417. function xmlsitemap_update_16() {
  418. $field = array(
  419. 'type' => 'varchar',
  420. 'length' => 12,
  421. 'not null' => TRUE,
  422. 'default' => '',
  423. );
  424. db_add_field('xmlsitemap', 'language', $field);
  425. db_add_index('xmlsitemap', 'language', array('language'));
  426. }
  427. function xmlsitemap_update_17() {
  428. db_update('xmlsitemap')
  429. ->fields(array('access' => 1))
  430. ->condition('access', 1, '>')
  431. ->execute();
  432. db_update('xmlsitemap')
  433. ->fields(array('status' => 1))
  434. ->condition('status', 1, '>')
  435. ->execute();
  436. }
  437. function xmlsitemap_update_18() {
  438. $field = array(
  439. 'type' => 'varchar',
  440. 'length' => 32,
  441. 'not null' => TRUE,
  442. 'default' => '',
  443. );
  444. db_change_field('xmlsitemap', 'type', 'type', $field);
  445. $field['length'] = 128;
  446. db_change_field('xmlsitemap', 'subtype', 'subtype', $field);
  447. }
  448. //@todo Update {xmlsitemap}.language from '' to LANGUAGE_NONE.