xmlsitemap.pages.inc 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. <?php
  2. /**
  3. * @file
  4. * Page callbacks for the xmlsitemap module.
  5. *
  6. * @ingroup xmlsitemap
  7. */
  8. /**
  9. * Get the sitemap chunk/page of the current request.
  10. */
  11. function xmlsitemap_get_current_chunk(stdClass $sitemap) {
  12. // Check if we should be displaing the index.
  13. if (!isset($_GET['page']) || !is_numeric($_GET['page'])) {
  14. if ($sitemap->chunks > 1) {
  15. return 'index';
  16. }
  17. else {
  18. return 1;
  19. }
  20. }
  21. else {
  22. return (int) $_GET['page'];
  23. }
  24. }
  25. /**
  26. * Output a sitemap page.
  27. *
  28. * @see xmlsitemap_sitemap_load_by_context()
  29. * @see xmlsitemap_get_current_chunk()
  30. * @see xmlsitemap_sitemap_get_file()
  31. * @see xmlsitemap_output_file()
  32. */
  33. function xmlsitemap_output_chunk() {
  34. $sitemap = xmlsitemap_sitemap_load_by_context();
  35. if (!$sitemap) {
  36. return MENU_NOT_FOUND;
  37. }
  38. $chunk = xmlsitemap_get_current_chunk($sitemap);
  39. $file = xmlsitemap_sitemap_get_file($sitemap, $chunk);
  40. // Provide debugging information if enabled.
  41. if (variable_get('xmlsitemap_developer_mode', 0) && isset($_GET['debug'])) {
  42. $output = array();
  43. $context = xmlsitemap_get_current_context();
  44. $output[] = "Current context: " . print_r($context, TRUE);
  45. $output[] = "Sitemap: " . print_r($sitemap, TRUE);
  46. $output[] = "Chunk: $chunk";
  47. $output[] = "Cache file location: $file";
  48. $output[] = "Cache file exists: " . (file_exists($file) ? 'Yes' : 'No');
  49. return implode('<br />', $output);
  50. }
  51. return xmlsitemap_output_file($file);
  52. }
  53. /**
  54. * Output the contents of a file to the browser and check caching headers.
  55. */
  56. function xmlsitemap_output_file($file, array $headers = array()) {
  57. if (!file_exists($file) || !is_readable($file)) {
  58. return MENU_NOT_FOUND;
  59. }
  60. $mtime = filemtime($file);
  61. $last_modified = gmdate(DATE_RFC1123, $mtime);
  62. $etag = '"' . md5($last_modified) . '"';
  63. // See if the client has provided the required HTTP headers.
  64. $if_modified_since = isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) ? stripslashes($_SERVER['HTTP_IF_MODIFIED_SINCE']) : FALSE;
  65. $if_none_match = isset($_SERVER['HTTP_IF_NONE_MATCH']) ? stripslashes($_SERVER['HTTP_IF_NONE_MATCH']) : FALSE;
  66. if ($if_modified_since && $if_none_match && $if_none_match == $etag && $if_modified_since == $last_modified) {
  67. header('HTTP/1.1 304 Not Modified');
  68. // All 304 responses must send an etag if the 200 response for the same
  69. // object contained an etag.
  70. header('Etag: ' . $etag);
  71. exit;
  72. }
  73. $headers += array(
  74. 'Content-type' => 'text/xml; charset=utf-8',
  75. 'Last-modified' => $last_modified,
  76. 'Etag' => $etag,
  77. 'Expires' => gmdate(DATE_RFC1123, $mtime + variable_get('xmlsitemap_minimum_lifetime', 0)),
  78. 'Cache-Control' => 'must-revalidate',
  79. 'X-Robots-Tag' => 'noindex, follow',
  80. );
  81. // Transfer the file as output.
  82. xmlsitemap_file_transfer($file, $headers);
  83. }
  84. /**
  85. * Modified version of file_transfer() that invokes hook_exit()s afterwards.
  86. *
  87. * @see file_transfer()
  88. */
  89. function xmlsitemap_file_transfer($uri, $headers) {
  90. if (ob_get_level()) {
  91. ob_end_clean();
  92. }
  93. foreach ($headers as $name => $value) {
  94. drupal_add_http_header($name, $value);
  95. }
  96. drupal_send_headers();
  97. // Attempt to increase time to transfer file.
  98. drupal_set_time_limit(240);
  99. $scheme = variable_get('file_default_scheme', 'public');
  100. // Transfer file in 16 KB chunks to save memory usage.
  101. if ($scheme && file_stream_wrapper_valid_scheme($scheme) && $fd = fopen($uri, 'rb')) {
  102. while (!feof($fd)) {
  103. print fread($fd, 1024 * 16);
  104. }
  105. fclose($fd);
  106. // Disable session manipulation if PHP transferred a file.
  107. drupal_save_session(FALSE);
  108. }
  109. else {
  110. drupal_not_found();
  111. }
  112. drupal_exit();
  113. }
  114. /**
  115. * Output an XML transformation file for the sitemap XML.
  116. */
  117. function xmlsitemap_output_xsl() {
  118. // Read the XSL content from the file.
  119. $module_path = drupal_get_path('module', 'xmlsitemap');
  120. $xsl_content = file_get_contents($module_path . '/xsl/xmlsitemap.xsl');
  121. // Make sure the strings in the XSL content are translated properly.
  122. $replacements = array(
  123. 'Sitemap file' => t('Sitemap file'),
  124. 'Generated by the <a href="https://www.drupal.org/project/xmlsitemap">Drupal XML sitemap</a>.' => t('Generated by the <a href="@link-xmlsitemap">Drupal XML sitemap</a>.', array('@link-xmlsitemap' => 'https://www.drupal.org/project/xmlsitemap')),
  125. 'Number of sitemaps in this index' => t('Number of sitemaps in this index'),
  126. 'Click on the table headers to change sorting.' => t('Click on the table headers to change sorting.'),
  127. 'Sitemap URL' => t('Sitemap URL'),
  128. 'Last modification date' => t('Last modification date'),
  129. 'Number of URLs in this sitemap' => t('Number of URLs in this sitemap'),
  130. 'URL location' => t('URL location'),
  131. 'Change frequency' => t('Change frequency'),
  132. 'Priority' => t('Priority'),
  133. '[jquery]' => base_path() . 'misc/jquery.js',
  134. '[jquery-tablesort]' => base_path() . $module_path . '/xsl/jquery.tablesorter.min.js',
  135. '[xsl-js]' => base_path() . $module_path . '/xsl/xmlsitemap.xsl.js',
  136. '[xsl-css]' => base_path() . $module_path . '/xsl/xmlsitemap.xsl.css',
  137. );
  138. $xsl_content = strtr($xsl_content, $replacements);
  139. // Output the XSL content.
  140. drupal_add_http_header('Content-type', 'application/xml; charset=utf-8');
  141. drupal_add_http_header('X-Robots-Tag', 'noindex, follow');
  142. print $xsl_content;
  143. }