web/drupal/modules/xmlsitemap/xmlsitemap.module
branchdrupal
changeset 74 0ff3ba646492
equal deleted inserted replaced
73:fcf75e232c5b 74:0ff3ba646492
       
     1 <?php
       
     2 // $Id: xmlsitemap.module,v 1.20.2.66 2009/06/23 11:54:41 earnie Exp $
       
     3 
       
     4 
       
     5 /**
       
     6  * @file
       
     7  * Creates a sitemap compatible with the sitemaps.org schema.
       
     8  */
       
     9 
       
    10 /**
       
    11  * @addtogroup xmlsitemap
       
    12  * @{
       
    13  */
       
    14 
       
    15 /*****************************************************************************
       
    16  * Public constants.
       
    17  ****************************************************************************/
       
    18 
       
    19 /**
       
    20  * The date format used in the sitemap.
       
    21  */
       
    22 if (!defined('DATE_W3C')) {
       
    23   define('DATE_W3C', 'Y-m-d\TH:i:s+00:00');
       
    24 }
       
    25 
       
    26 /**
       
    27  * The timestamp of server request to avoid repeatedly generating value.
       
    28  */
       
    29 if (!defined('REQUEST_TIME')) {
       
    30   if (isset($_SERVER['REQUEST_TIME'])) {
       
    31     define('REQUEST_TIME', $_SERVER['REQUEST_TIME']);
       
    32   }
       
    33   else {
       
    34     define('REQUEST_TIME', time());
       
    35   }
       
    36 }
       
    37 
       
    38 /**
       
    39  * The flag set when a sitemap link is not enabled.
       
    40  */
       
    41 define('XMLSITEMAP_LINK_DISABLED', 1);
       
    42 
       
    43 /**
       
    44  * The maximum number of links in one sitemap chunk file.
       
    45  */
       
    46 define('XMLSITEMAP_MAX_SITEMAP_LINKS', 50000);
       
    47 
       
    48 /**
       
    49  * The maximum filesize of a sitemap chunk file.
       
    50  */
       
    51 define('XMLSITEMAP_MAX_SITEMAP_FILESIZE', 10485760);
       
    52 
       
    53 /**
       
    54  * The maximum number of links in one sitemap index file.
       
    55  */
       
    56 define('XMLSITEMAP_MAX_SITEMAP_INDEX_LINKS', 1000);
       
    57 
       
    58 /**
       
    59  * The default number of links in one sitemap chunk file.
       
    60  */
       
    61 define('XMLSITEMAP_DEFAULT_SITEMAP_LINKS', 1000);
       
    62 
       
    63 /*****************************************************************************
       
    64  * Drupal hooks.
       
    65  ****************************************************************************/
       
    66 
       
    67 /**
       
    68  * Implementation of hook_form_alter().
       
    69  */
       
    70 function xmlsitemap_form_alter(&$form, &$form_state, $form_id) {
       
    71   switch ($form_id) {
       
    72     case 'locale_languages_configure_form':
       
    73     case 'path_admin_form':
       
    74     case 'pathauto_admin_settings':
       
    75     case 'system_clean_url_settings':
       
    76       $form['#submit'][] = 'xmlsitemap_settings_submit';
       
    77       break;
       
    78   }
       
    79 }
       
    80 
       
    81 /**
       
    82  * Implementation of hook_help().
       
    83  */
       
    84 function xmlsitemap_help($path, $arg) {
       
    85   switch ($path) {
       
    86     case 'admin/settings/xmlsitemap':
       
    87     case 'admin/settings/xmlsitemap/engines':
       
    88       $output = t('The sitemap is located at <a href="@sitemap">@sitemap</a>.', array('@sitemap' => url('sitemap.xml', array('absolute' => TRUE))));
       
    89       break;
       
    90 
       
    91     case 'admin/help#xmlsitemap':
       
    92       $output = '<p>'. t('XML sitemap automatically creates a sitemap that conforms to the <a href="@sitemaps.org">sitemaps.org specification</a>. This helps search engines keep their search results up to date.', array('@sitemaps.org' => 'http://www.sitemaps.org')) .'</p>';
       
    93       $output .= '<h3>'. t('Supporting modules') .'</h3>';
       
    94       $output .= '<p>'. t('By itself, the XML sitemap module adds only the front page of your site to the sitemap. Other types of links are handled by supporting modules.') .'</p>';
       
    95       $optional = '';
       
    96       foreach (module_implements('xmlsitemap_description', TRUE) as $module) {
       
    97         $function = $module .'_xmlsitemap_description';
       
    98         $optional .= $function();
       
    99       }
       
   100       if (!empty($optional)) {
       
   101         $output .= "<dl>$optional</dl>";
       
   102       }
       
   103       $output .= '<p>'. t('Links may be assigned a priority between 0.0 and 1.0. The default priority is 0.5. A priority of <em>Not in sitemap</em> excludes a link from the sitemap.') .'</p>';
       
   104       $output .= '<p>'. t('For more information, see the online handbook entry for <a href="@xmlsitemap">XML sitemap module</a>.', array('@xmlsitemap' => 'http://drupal.org/handbook/modules/gsitemap')) .'</p>';
       
   105       break;
       
   106 
       
   107     default:
       
   108       $output = '';
       
   109       break;
       
   110   }
       
   111   return $output;
       
   112 }
       
   113 
       
   114 /**
       
   115  * Implementation of hook_menu().
       
   116  */
       
   117 function xmlsitemap_menu() {
       
   118   $items = array();
       
   119   $access_config = array('administer site configuration');
       
   120   $access_content = array('access content');
       
   121   $items['admin/settings/xmlsitemap'] = array(
       
   122     'title' => 'XML sitemap',
       
   123     'description' => 'Configure the XML sitemap.',
       
   124     'page callback' => 'drupal_get_form',
       
   125     'page arguments' => array('xmlsitemap_settings'),
       
   126     'access arguments' => $access_config,
       
   127     'file' => 'xmlsitemap.admin.inc',
       
   128   );
       
   129   $items['admin/settings/xmlsitemap/sitemap'] = array(
       
   130     'title' => 'Sitemap',
       
   131     'description' => 'Configure the XML sitemap.',
       
   132     'weight' => -1,
       
   133     'type' => MENU_DEFAULT_LOCAL_TASK,
       
   134     'file' => 'xmlsitemap.admin.inc',
       
   135   );
       
   136   $items['admin/settings/xmlsitemap/tools'] = array(
       
   137     'title' => 'Tools',
       
   138     'description' => 'Sitemap tools.',
       
   139     'page callback' => 'drupal_get_form',
       
   140     'page arguments' => array('xmlsitemap_tools'),
       
   141     'access arguments' => $access_config,
       
   142     'type' => MENU_LOCAL_TASK,
       
   143     'file' => 'xmlsitemap.admin.inc',
       
   144   );
       
   145   $items['sitemap.xml'] = array(
       
   146     'title' => 'Sitemap index',
       
   147     'page callback' => 'xmlsitemap_output',
       
   148     'access arguments' => $access_content,
       
   149     'type' => MENU_CALLBACK,
       
   150     'file' => 'xmlsitemap.pages.inc',
       
   151   );
       
   152   $chunk_size = variable_get('xmlsitemap_chunk_size', XMLSITEMAP_DEFAULT_SITEMAP_LINKS);
       
   153   $link_count = xmlsitemap_link_count();
       
   154   if ($link_count > $chunk_size) {
       
   155     for ($chunk = 0; $chunk < $link_count / $chunk_size; ++$chunk) {
       
   156       $items["sitemap$chunk.xml"] = array(
       
   157         'title' => 'Sitemap !number',
       
   158         'title arguments' => array('!number' => $chunk),
       
   159         'page callback' => 'xmlsitemap_output',
       
   160         'page arguments' => array((string) $chunk),
       
   161         'access arguments' => $access_content,
       
   162         'type' => MENU_CALLBACK,
       
   163         'file' => 'xmlsitemap.pages.inc',
       
   164       );
       
   165     }
       
   166   }
       
   167   return $items;
       
   168 }
       
   169 
       
   170 /**
       
   171  * Implementation of hook_perm().
       
   172  */
       
   173 function xmlsitemap_perm() {
       
   174   return array('override node settings', 'override profile settings');
       
   175 }
       
   176 
       
   177 /**
       
   178  * Implementation of hook_robotstxt().
       
   179  */
       
   180 function xmlsitemap_robotstxt() {
       
   181   return array("Sitemap: ". url('sitemap.xml', array('absolute' => TRUE)));
       
   182 }
       
   183 
       
   184 /**
       
   185  * Implementation of hook_xmlsitemap_operations().
       
   186  */
       
   187 function xmlsitemap_xmlsitemap_operations() {
       
   188   return array(
       
   189     'delete_cache_files' => array(
       
   190       'label' => t('Delete the sitemap cache files'),
       
   191       'callback' => 'xmlsitemap_delete_cache_files',
       
   192     ),
       
   193     'flag_sitemap' => array(
       
   194       'label' => t('Flag the sitemap as requiring update'),
       
   195       'callback' => 'xmlsitemap_flag_sitemap',
       
   196     ),
       
   197   );
       
   198 }
       
   199 
       
   200 /*****************************************************************************
       
   201  * Public functions.
       
   202  ****************************************************************************/
       
   203 
       
   204 /**
       
   205  * Batch callback called when the batch operations are completed.
       
   206  */
       
   207 function xmlsitemap_batch_operations_finished($success, $results, $operations) {
       
   208   if ($success) {
       
   209     drupal_set_message(t('The update has been performed.'));
       
   210   }
       
   211   else {
       
   212     drupal_set_message(t('An error occurred and processing did not complete.'), 'error');
       
   213     $message = format_plural($count = count($results), '1 item successfully processed.', '@count items successfully processed.');
       
   214     if ($count) {
       
   215       $message .= theme('item_list', $results, t('Last items successfully processed:'));
       
   216     }
       
   217     drupal_set_message($message);
       
   218   }
       
   219 }
       
   220 
       
   221 /**
       
   222  * Return the language string used to identify the cache file for the sitemap
       
   223  * content.
       
   224  */
       
   225 function xmlsitemap_language_id() {
       
   226   global $language;
       
   227   return isset($language->language) ? $language->language : language_default('language');
       
   228 }
       
   229 
       
   230 /**
       
   231  * Return the array for the cron limit options.
       
   232  */
       
   233 function xmlsitemap_cron_options() {
       
   234   return array(
       
   235     '2000' => t('2000 rows'),
       
   236     '1500' => t('1500 rows'),
       
   237     '1000' => t('1000 rows'),
       
   238     '500' => t('500 rows'),
       
   239     '250' => t('250 rows'),
       
   240     '100' => t('100 rows'),
       
   241     '50' => t('50 rows'),
       
   242     '25' => t('25 rows'),
       
   243     '20' => t('20 rows'),
       
   244     '15' => t('15 rows'),
       
   245     '10' => t('10 rows'),
       
   246     '5' => t('5 rows'),
       
   247     '-1' => t('Do not process via cron'),
       
   248   );
       
   249 }
       
   250 
       
   251 /**
       
   252  * Delete the cache file used for the sitemap content, and mark the sitemap as
       
   253  * changed.
       
   254  */
       
   255 function xmlsitemap_delete_cache_files() {
       
   256   $parent_directory = variable_get('xmlsitemap_cache_directory', file_directory_path() .'/xmlsitemap');
       
   257   if (!is_dir($parent_directory)) {
       
   258     return;
       
   259   }
       
   260   file_scan_directory($parent_directory, 'xsm-.*\.xml', array('.', '..', 'CVS'), 'file_delete', FALSE);
       
   261   xmlsitemap_flag_sitemap();
       
   262   return;
       
   263 }
       
   264 
       
   265 /**
       
   266  * Mark the sitemap as changed, and the cache as needing update.
       
   267  */
       
   268 function xmlsitemap_flag_sitemap() {
       
   269   if (!variable_get('xmlsitemap_sitemap_is_changed', FALSE)) {
       
   270     variable_set('xmlsitemap_sitemap_is_changed', TRUE);
       
   271   }
       
   272   if (!variable_get('xmlsitemap_sitemap_needs_update', FALSE)) {
       
   273     variable_set('xmlsitemap_sitemap_needs_update', TRUE);
       
   274   }
       
   275 }
       
   276 
       
   277 /**
       
   278  * Return the number of links present in xmlsitemap table.
       
   279  */
       
   280 function xmlsitemap_link_count() {
       
   281   static $link_count;
       
   282   if (!isset($link_count)) {
       
   283     $link_count = db_result(db_query("SELECT COUNT(xsm.loc)". xmlsitemap_sitemap_query()));
       
   284   }
       
   285   return $link_count;
       
   286 }
       
   287 
       
   288 /**
       
   289  * Return the number of chunk files.
       
   290  */
       
   291 function xmlsitemap_chunk_count() {
       
   292   $link_count = xmlsitemap_link_count();
       
   293   $chunk_size = variable_get('xmlsitemap_chunk_size', XMLSITEMAP_DEFAULT_SITEMAP_LINKS);
       
   294   return ceil($link_count / $chunk_size);
       
   295 }
       
   296 
       
   297 /**
       
   298  * Return an array of sitemap priority options.
       
   299  *
       
   300  * @param $option
       
   301  *  If not given, the array will include priority values from 0.0 to 1.0.
       
   302  * - exclude: Add option to exclude item from sitemap.
       
   303  * - default: Add option to use default priority. Only for cases where a
       
   304  *   default priority exists.
       
   305  * - both: Add both the default and exclude options.
       
   306  *
       
   307  * @return
       
   308  *  An array of priority options.
       
   309  */
       
   310 function xmlsitemap_priority_options($option = '') {
       
   311   $options = array(
       
   312     '1' => t('1.0'),
       
   313     '0.9' => t('0.9'),
       
   314     '0.8' => t('0.8'),
       
   315     '0.7' => t('0.7'),
       
   316     '0.6' => t('0.6'),
       
   317     '0.5' => t('0.5'),
       
   318     '0.4' => t('0.4'),
       
   319     '0.3' => t('0.3'),
       
   320     '0.2' => t('0.2'),
       
   321     '0.1' => t('0.1'),
       
   322     '0' => t('0.0'),
       
   323   );
       
   324   if ($option == 'exclude' || $option == 'both') {
       
   325     $options['-1'] = t('Not in sitemap');
       
   326   }
       
   327   if ($option == 'default' || $option == 'both') {
       
   328     $options['-2'] = t('Default');
       
   329   }
       
   330   return $options;
       
   331 }
       
   332 
       
   333 /**
       
   334  * Determine the frequency of updates to a link.
       
   335  *
       
   336  * @param $interval
       
   337  *  The number of seconds since the last change, or the number of seconds
       
   338  *  between the last change, and the previous change.
       
   339  *
       
   340  * @return
       
   341  *  A string representing the update frequency according to the sitemaps.org
       
   342  *  protocol.
       
   343  */
       
   344 function xmlsitemap_sitemap_frequency($interval) {
       
   345   $frequencies = array(
       
   346     'always' => 3600,
       
   347     'hourly' => 86400,
       
   348     'daily' => 604800,
       
   349     'weekly' => 2419200,
       
   350     'monthly' => 29030400,
       
   351     'yearly' => 100000000,
       
   352   );
       
   353   if ($interval < 0 || !is_numeric($interval)) {
       
   354     return 'never';
       
   355   }
       
   356   foreach ($frequencies as $frequency => $value) {
       
   357     if ($interval < $value) {
       
   358       break;
       
   359     }
       
   360   }
       
   361   return $frequency;
       
   362 }
       
   363 
       
   364 /**
       
   365  * Complete the query used to select rows from the xmlsitemap table.
       
   366  */
       
   367 function xmlsitemap_sitemap_query() {
       
   368   global $language;
       
   369   $default = language_default();
       
   370   $language_query = "AND xsm.language IN ('". $language->language ."', '')";
       
   371   switch (variable_get('language_negotiation', LANGUAGE_NEGOTIATION_NONE)) {
       
   372     case LANGUAGE_NEGOTIATION_NONE:
       
   373       $language_query = '';
       
   374       break;
       
   375 
       
   376     case LANGUAGE_NEGOTIATION_PATH_DEFAULT:
       
   377     case LANGUAGE_NEGOTIATION_PATH:
       
   378       if (variable_get('xmlsitemap_all_links_to_default_language', 0) && $language->language == $default->language) {
       
   379         $language_query = '';
       
   380       }
       
   381       break;
       
   382   }
       
   383   return "
       
   384     FROM {xmlsitemap} xsm
       
   385     INNER JOIN {system} s ON s.name = xsm.module
       
   386     WHERE s.type = 'module'
       
   387       AND s.status = 1
       
   388       AND xsm.changefreq <> 0
       
   389       AND xsm.changed <> 0
       
   390       $language_query
       
   391       AND (xsm.priority >= 0 AND xsm.priority <= 1)
       
   392     ";
       
   393 }
       
   394 
       
   395 /**
       
   396  * Return an array used to add additional form fields in the user form.
       
   397  */
       
   398 function xmlsitemap_user_form_fieldset() {
       
   399   static $done = FALSE;
       
   400   $form = array();
       
   401   if (!$done) {
       
   402     $form['xmlsitemap'] = array(
       
   403       '#type' => 'fieldset',
       
   404       '#title' => t('XML sitemap'),
       
   405       '#collapsible' => TRUE,
       
   406       '#access' => user_access('override profile settings') || user_access('administer users'),
       
   407       '#weight' => 7,
       
   408     );
       
   409     $done = TRUE;
       
   410   }
       
   411   return $form;
       
   412 }
       
   413 
       
   414 /**
       
   415  * @} End of "addtogroup xmlsitemap".
       
   416  */
       
   417