web/drupal/modules/xmlsitemap/xmlsitemap.module
author cavaliet@caf4f556-3d62-0410-8435-a86758001935
Fri, 21 Aug 2009 16:30:15 +0000
branchdrupal
changeset 75 a34abe7498a6
parent 74 0ff3ba646492
permissions -rw-r--r--
res/color/garland-5d26e3f9 added to the drupal folder in order to see the css

<?php
// $Id: xmlsitemap.module,v 1.20.2.66 2009/06/23 11:54:41 earnie Exp $


/**
 * @file
 * Creates a sitemap compatible with the sitemaps.org schema.
 */

/**
 * @addtogroup xmlsitemap
 * @{
 */

/*****************************************************************************
 * Public constants.
 ****************************************************************************/

/**
 * The date format used in the sitemap.
 */
if (!defined('DATE_W3C')) {
  define('DATE_W3C', 'Y-m-d\TH:i:s+00:00');
}

/**
 * The timestamp of server request to avoid repeatedly generating value.
 */
if (!defined('REQUEST_TIME')) {
  if (isset($_SERVER['REQUEST_TIME'])) {
    define('REQUEST_TIME', $_SERVER['REQUEST_TIME']);
  }
  else {
    define('REQUEST_TIME', time());
  }
}

/**
 * The flag set when a sitemap link is not enabled.
 */
define('XMLSITEMAP_LINK_DISABLED', 1);

/**
 * The maximum number of links in one sitemap chunk file.
 */
define('XMLSITEMAP_MAX_SITEMAP_LINKS', 50000);

/**
 * The maximum filesize of a sitemap chunk file.
 */
define('XMLSITEMAP_MAX_SITEMAP_FILESIZE', 10485760);

/**
 * The maximum number of links in one sitemap index file.
 */
define('XMLSITEMAP_MAX_SITEMAP_INDEX_LINKS', 1000);

/**
 * The default number of links in one sitemap chunk file.
 */
define('XMLSITEMAP_DEFAULT_SITEMAP_LINKS', 1000);

/*****************************************************************************
 * Drupal hooks.
 ****************************************************************************/

/**
 * Implementation of hook_form_alter().
 */
function xmlsitemap_form_alter(&$form, &$form_state, $form_id) {
  switch ($form_id) {
    case 'locale_languages_configure_form':
    case 'path_admin_form':
    case 'pathauto_admin_settings':
    case 'system_clean_url_settings':
      $form['#submit'][] = 'xmlsitemap_settings_submit';
      break;
  }
}

/**
 * Implementation of hook_help().
 */
function xmlsitemap_help($path, $arg) {
  switch ($path) {
    case 'admin/settings/xmlsitemap':
    case 'admin/settings/xmlsitemap/engines':
      $output = t('The sitemap is located at <a href="@sitemap">@sitemap</a>.', array('@sitemap' => url('sitemap.xml', array('absolute' => TRUE))));
      break;

    case 'admin/help#xmlsitemap':
      $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>';
      $output .= '<h3>'. t('Supporting modules') .'</h3>';
      $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>';
      $optional = '';
      foreach (module_implements('xmlsitemap_description', TRUE) as $module) {
        $function = $module .'_xmlsitemap_description';
        $optional .= $function();
      }
      if (!empty($optional)) {
        $output .= "<dl>$optional</dl>";
      }
      $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>';
      $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>';
      break;

    default:
      $output = '';
      break;
  }
  return $output;
}

/**
 * Implementation of hook_menu().
 */
function xmlsitemap_menu() {
  $items = array();
  $access_config = array('administer site configuration');
  $access_content = array('access content');
  $items['admin/settings/xmlsitemap'] = array(
    'title' => 'XML sitemap',
    'description' => 'Configure the XML sitemap.',
    'page callback' => 'drupal_get_form',
    'page arguments' => array('xmlsitemap_settings'),
    'access arguments' => $access_config,
    'file' => 'xmlsitemap.admin.inc',
  );
  $items['admin/settings/xmlsitemap/sitemap'] = array(
    'title' => 'Sitemap',
    'description' => 'Configure the XML sitemap.',
    'weight' => -1,
    'type' => MENU_DEFAULT_LOCAL_TASK,
    'file' => 'xmlsitemap.admin.inc',
  );
  $items['admin/settings/xmlsitemap/tools'] = array(
    'title' => 'Tools',
    'description' => 'Sitemap tools.',
    'page callback' => 'drupal_get_form',
    'page arguments' => array('xmlsitemap_tools'),
    'access arguments' => $access_config,
    'type' => MENU_LOCAL_TASK,
    'file' => 'xmlsitemap.admin.inc',
  );
  $items['sitemap.xml'] = array(
    'title' => 'Sitemap index',
    'page callback' => 'xmlsitemap_output',
    'access arguments' => $access_content,
    'type' => MENU_CALLBACK,
    'file' => 'xmlsitemap.pages.inc',
  );
  $chunk_size = variable_get('xmlsitemap_chunk_size', XMLSITEMAP_DEFAULT_SITEMAP_LINKS);
  $link_count = xmlsitemap_link_count();
  if ($link_count > $chunk_size) {
    for ($chunk = 0; $chunk < $link_count / $chunk_size; ++$chunk) {
      $items["sitemap$chunk.xml"] = array(
        'title' => 'Sitemap !number',
        'title arguments' => array('!number' => $chunk),
        'page callback' => 'xmlsitemap_output',
        'page arguments' => array((string) $chunk),
        'access arguments' => $access_content,
        'type' => MENU_CALLBACK,
        'file' => 'xmlsitemap.pages.inc',
      );
    }
  }
  return $items;
}

/**
 * Implementation of hook_perm().
 */
function xmlsitemap_perm() {
  return array('override node settings', 'override profile settings');
}

/**
 * Implementation of hook_robotstxt().
 */
function xmlsitemap_robotstxt() {
  return array("Sitemap: ". url('sitemap.xml', array('absolute' => TRUE)));
}

/**
 * Implementation of hook_xmlsitemap_operations().
 */
function xmlsitemap_xmlsitemap_operations() {
  return array(
    'delete_cache_files' => array(
      'label' => t('Delete the sitemap cache files'),
      'callback' => 'xmlsitemap_delete_cache_files',
    ),
    'flag_sitemap' => array(
      'label' => t('Flag the sitemap as requiring update'),
      'callback' => 'xmlsitemap_flag_sitemap',
    ),
  );
}

/*****************************************************************************
 * Public functions.
 ****************************************************************************/

/**
 * Batch callback called when the batch operations are completed.
 */
function xmlsitemap_batch_operations_finished($success, $results, $operations) {
  if ($success) {
    drupal_set_message(t('The update has been performed.'));
  }
  else {
    drupal_set_message(t('An error occurred and processing did not complete.'), 'error');
    $message = format_plural($count = count($results), '1 item successfully processed.', '@count items successfully processed.');
    if ($count) {
      $message .= theme('item_list', $results, t('Last items successfully processed:'));
    }
    drupal_set_message($message);
  }
}

/**
 * Return the language string used to identify the cache file for the sitemap
 * content.
 */
function xmlsitemap_language_id() {
  global $language;
  return isset($language->language) ? $language->language : language_default('language');
}

/**
 * Return the array for the cron limit options.
 */
function xmlsitemap_cron_options() {
  return array(
    '2000' => t('2000 rows'),
    '1500' => t('1500 rows'),
    '1000' => t('1000 rows'),
    '500' => t('500 rows'),
    '250' => t('250 rows'),
    '100' => t('100 rows'),
    '50' => t('50 rows'),
    '25' => t('25 rows'),
    '20' => t('20 rows'),
    '15' => t('15 rows'),
    '10' => t('10 rows'),
    '5' => t('5 rows'),
    '-1' => t('Do not process via cron'),
  );
}

/**
 * Delete the cache file used for the sitemap content, and mark the sitemap as
 * changed.
 */
function xmlsitemap_delete_cache_files() {
  $parent_directory = variable_get('xmlsitemap_cache_directory', file_directory_path() .'/xmlsitemap');
  if (!is_dir($parent_directory)) {
    return;
  }
  file_scan_directory($parent_directory, 'xsm-.*\.xml', array('.', '..', 'CVS'), 'file_delete', FALSE);
  xmlsitemap_flag_sitemap();
  return;
}

/**
 * Mark the sitemap as changed, and the cache as needing update.
 */
function xmlsitemap_flag_sitemap() {
  if (!variable_get('xmlsitemap_sitemap_is_changed', FALSE)) {
    variable_set('xmlsitemap_sitemap_is_changed', TRUE);
  }
  if (!variable_get('xmlsitemap_sitemap_needs_update', FALSE)) {
    variable_set('xmlsitemap_sitemap_needs_update', TRUE);
  }
}

/**
 * Return the number of links present in xmlsitemap table.
 */
function xmlsitemap_link_count() {
  static $link_count;
  if (!isset($link_count)) {
    $link_count = db_result(db_query("SELECT COUNT(xsm.loc)". xmlsitemap_sitemap_query()));
  }
  return $link_count;
}

/**
 * Return the number of chunk files.
 */
function xmlsitemap_chunk_count() {
  $link_count = xmlsitemap_link_count();
  $chunk_size = variable_get('xmlsitemap_chunk_size', XMLSITEMAP_DEFAULT_SITEMAP_LINKS);
  return ceil($link_count / $chunk_size);
}

/**
 * Return an array of sitemap priority options.
 *
 * @param $option
 *  If not given, the array will include priority values from 0.0 to 1.0.
 * - exclude: Add option to exclude item from sitemap.
 * - default: Add option to use default priority. Only for cases where a
 *   default priority exists.
 * - both: Add both the default and exclude options.
 *
 * @return
 *  An array of priority options.
 */
function xmlsitemap_priority_options($option = '') {
  $options = array(
    '1' => t('1.0'),
    '0.9' => t('0.9'),
    '0.8' => t('0.8'),
    '0.7' => t('0.7'),
    '0.6' => t('0.6'),
    '0.5' => t('0.5'),
    '0.4' => t('0.4'),
    '0.3' => t('0.3'),
    '0.2' => t('0.2'),
    '0.1' => t('0.1'),
    '0' => t('0.0'),
  );
  if ($option == 'exclude' || $option == 'both') {
    $options['-1'] = t('Not in sitemap');
  }
  if ($option == 'default' || $option == 'both') {
    $options['-2'] = t('Default');
  }
  return $options;
}

/**
 * Determine the frequency of updates to a link.
 *
 * @param $interval
 *  The number of seconds since the last change, or the number of seconds
 *  between the last change, and the previous change.
 *
 * @return
 *  A string representing the update frequency according to the sitemaps.org
 *  protocol.
 */
function xmlsitemap_sitemap_frequency($interval) {
  $frequencies = array(
    'always' => 3600,
    'hourly' => 86400,
    'daily' => 604800,
    'weekly' => 2419200,
    'monthly' => 29030400,
    'yearly' => 100000000,
  );
  if ($interval < 0 || !is_numeric($interval)) {
    return 'never';
  }
  foreach ($frequencies as $frequency => $value) {
    if ($interval < $value) {
      break;
    }
  }
  return $frequency;
}

/**
 * Complete the query used to select rows from the xmlsitemap table.
 */
function xmlsitemap_sitemap_query() {
  global $language;
  $default = language_default();
  $language_query = "AND xsm.language IN ('". $language->language ."', '')";
  switch (variable_get('language_negotiation', LANGUAGE_NEGOTIATION_NONE)) {
    case LANGUAGE_NEGOTIATION_NONE:
      $language_query = '';
      break;

    case LANGUAGE_NEGOTIATION_PATH_DEFAULT:
    case LANGUAGE_NEGOTIATION_PATH:
      if (variable_get('xmlsitemap_all_links_to_default_language', 0) && $language->language == $default->language) {
        $language_query = '';
      }
      break;
  }
  return "
    FROM {xmlsitemap} xsm
    INNER JOIN {system} s ON s.name = xsm.module
    WHERE s.type = 'module'
      AND s.status = 1
      AND xsm.changefreq <> 0
      AND xsm.changed <> 0
      $language_query
      AND (xsm.priority >= 0 AND xsm.priority <= 1)
    ";
}

/**
 * Return an array used to add additional form fields in the user form.
 */
function xmlsitemap_user_form_fieldset() {
  static $done = FALSE;
  $form = array();
  if (!$done) {
    $form['xmlsitemap'] = array(
      '#type' => 'fieldset',
      '#title' => t('XML sitemap'),
      '#collapsible' => TRUE,
      '#access' => user_access('override profile settings') || user_access('administer users'),
      '#weight' => 7,
    );
    $done = TRUE;
  }
  return $form;
}

/**
 * @} End of "addtogroup xmlsitemap".
 */