web/drupal/modules/xmlsitemap/xmlsitemap_node/xmlsitemap_node.module
branchdrupal
changeset 74 0ff3ba646492
equal deleted inserted replaced
73:fcf75e232c5b 74:0ff3ba646492
       
     1 <?php
       
     2 // $Id: xmlsitemap_node.module,v 1.19.2.128 2009/07/24 18:03:38 earnie Exp $
       
     3 
       
     4 /**
       
     5  * @file
       
     6  * Adds nodes to the sitemap.
       
     7  */
       
     8 
       
     9 /**
       
    10  * @addtogroup xmlsitemap
       
    11  * @{
       
    12  */
       
    13 
       
    14 /*****************************************************************************
       
    15  * Drupal hooks.
       
    16  ****************************************************************************/
       
    17 
       
    18 /**
       
    19  * Implementation of hook_comment().
       
    20  */
       
    21 function xmlsitemap_node_comment($a1, $op) {
       
    22   switch ($op) {
       
    23     case 'insert':
       
    24     case 'update':
       
    25     case 'delete':
       
    26     case 'publish':
       
    27     case 'unpublish':
       
    28       $maxcomments = (integer) db_result(db_query('SELECT MAX(comment_count) FROM {node_comment_statistics}'));
       
    29       if ($nid = is_array($a1) ? $a1['nid'] : $a1->nid) {
       
    30         if (!($node = node_load($nid))) {
       
    31           return;
       
    32         }
       
    33         $comments = (integer) db_result(db_query('SELECT comment_count
       
    34           FROM {node_comment_statistics}
       
    35           WHERE nid = %d', $nid)
       
    36         );
       
    37         $query = "SELECT nid, changed, previously_changed, comment_ratio, priority_override
       
    38           FROM {xmlsitemap_node}
       
    39           WHERE nid = %d";
       
    40         if (($link = db_fetch_object(db_query($query, $nid))) !== FALSE) {
       
    41           $row = $link;
       
    42           if ($node->changed > $row->changed) {
       
    43             $row->previously_changed = $row->changed;
       
    44             $row->changed = $node->changed;
       
    45           }
       
    46         }
       
    47         else {
       
    48           $row = new stdClass();
       
    49           $row->nid = $nid;
       
    50           $row->changed = $node->changed;
       
    51           $row->previously_changed = $node->created;
       
    52         }
       
    53         if ($maxcomments > 1) {
       
    54           $row->comment_ratio = $comments / $maxcomments;
       
    55         }
       
    56         drupal_write_record('xmlsitemap_node', $row, ($link !== FALSE) ? 'nid' : NULL);
       
    57       }
       
    58       break;
       
    59   }
       
    60 }
       
    61 
       
    62 /**
       
    63  * Implementation of hook_cron().
       
    64  */
       
    65 function xmlsitemap_node_cron() {
       
    66   if (($limit = variable_get('xmlsitemap_cron_limit', 100)) != -1) {
       
    67     $sql = "SELECT n.* FROM {node} n
       
    68       LEFT JOIN {xmlsitemap_node} xn ON xn.nid = n.nid
       
    69       WHERE xn.nid IS NULL
       
    70         AND n.status <> 0";
       
    71     $result = db_query_range($sql, 0, $limit);
       
    72     while ($node = db_fetch_object($result)) {
       
    73       if (module_exists('comment')) {
       
    74         $maxcomments = (integer) db_result(db_query('SELECT MAX(comment_count) FROM {node_comment_statistics}'));
       
    75         $comments = (integer) db_result(db_query('SELECT comment_count
       
    76           FROM {node_comment_statistics}
       
    77           WHERE nid = %d', $node->nid)
       
    78         );
       
    79       }
       
    80       else {
       
    81         $maxcomments = 0;
       
    82       }
       
    83       $row = new stdClass();
       
    84       $row->nid = $node->nid;
       
    85       $row->changed = $node->changed;
       
    86       $row->previously_changed = $node->created;
       
    87       if ($maxcomments > 1) {
       
    88         $row->comment_ratio = $comments / $maxcomments;
       
    89       }
       
    90       drupal_write_record('xmlsitemap_node', $row);
       
    91     }
       
    92     if ($result) {
       
    93       xmlsitemap_flag_sitemap();
       
    94     }
       
    95   }
       
    96 }
       
    97 
       
    98 /**
       
    99  * Implementation of hook_form_alter().
       
   100  */
       
   101 function xmlsitemap_node_form_alter(&$form, &$form_state, $form_id) {
       
   102   if (isset($form['type']) && $form_id == $form['type']['#value'] .'_node_form') {
       
   103     $node = $form['#node'];
       
   104     if (!isset($form['xmlsitemap'])) {
       
   105       $form['xmlsitemap'] = array(
       
   106         '#type' => 'fieldset',
       
   107         '#title' => t('XML sitemap'),
       
   108         '#collapsible' => TRUE,
       
   109         '#access' => user_access('override node priority') || user_access('administer nodes'),
       
   110         '#weight' => 30,
       
   111       );
       
   112     }
       
   113     $options = xmlsitemap_priority_options('both');
       
   114     $default = variable_get('xmlsitemap_node_type_priority_'. $node->type, '0.5');
       
   115     $form['xmlsitemap']['priority_override'] = array(
       
   116       '#type' => 'select',
       
   117       '#title' => t('Priority'),
       
   118       '#description' => t('The default priority is %priority.', array('%priority' => $options[$default])),
       
   119       '#default_value' => isset($node->priority_override) ? $node->priority_override : -2.0,
       
   120       '#options' => $options,
       
   121       '#access' => user_access('override node priority') || user_access('administer nodes'),
       
   122     );
       
   123   }
       
   124 }
       
   125 
       
   126 /**
       
   127  * Implementation of hook_form_FORM_ID_alter().
       
   128  */
       
   129 function xmlsitemap_node_form_node_type_form_alter(&$form, &$from_state) {
       
   130   if (isset($form['identity']['type'])) {
       
   131     if (!isset($form['xmlsitemap'])) {
       
   132       $form['xmlsitemap'] = array(
       
   133         '#type' => 'fieldset',
       
   134         '#title' => t('XML sitemap'),
       
   135         '#collapsible' => TRUE,
       
   136         '#weight' => 30,
       
   137       );
       
   138     }
       
   139     $form['xmlsitemap']['xmlsitemap_node_type_priority'] = array(
       
   140       '#type' => 'select',
       
   141       '#title' => t('Priority adjustment'),
       
   142       '#description' => t('This number will be added to the priority of this content type.'),
       
   143       '#default_value' => variable_get('xmlsitemap_node_type_priority_'. $form['#node_type']->type, 0.5),
       
   144       '#options' => xmlsitemap_priority_options('exclude'),
       
   145     );
       
   146     $form['#submit'][] = 'xmlsitemap_node_type_submit';
       
   147   }
       
   148 }
       
   149 
       
   150 /**
       
   151  * Implementation of hook_form_FORM_ID_alter().
       
   152  */
       
   153 function xmlsitemap_node_form_xmlsitemap_settings_alter(&$form, &$from_state) {
       
   154   $options = xmlsitemap_priority_options();
       
   155   $form['xmlsitemap_node'] = array(
       
   156     '#type' => 'fieldset',
       
   157     '#title' => t('Node settings'),
       
   158     '#description' => t('The settings for the nodes to include in the sitemap.'),
       
   159     '#collapsible' => TRUE,
       
   160     '#weight' => 1,
       
   161   );
       
   162   $form['xmlsitemap_node']['xmlsitemap_node_promote_priority'] = array(
       
   163     '#type' => 'select',
       
   164     '#title' => t('Promotion priority adjustment'),
       
   165     '#description' => t("This number will be added to the priority of each post that is promoted to the front page. This setting doesn't apply for the nodes for which the priority is overriden."),
       
   166     '#default_value' => variable_get('xmlsitemap_node_promote_priority', 0.3),
       
   167     '#options' => $options,
       
   168   );
       
   169   $form['xmlsitemap_node']['xmlsitemap_node_comment_priority'] = array(
       
   170     '#type' => 'select',
       
   171     '#title' => t('Comment ratio priority adjustment'),
       
   172     '#description' => t("This number will be added to the priority of the post with the highest number of comments; for the other posts, the number is calculated proportionally to the number of comments. This doesn't apply if the maximum number of comments is one, nor for the nodes for which the priority is overriden."),
       
   173     '#default_value' => variable_get('xmlsitemap_node_comment_priority', 0.2),
       
   174     '#options' => $options,
       
   175   );
       
   176 }
       
   177 
       
   178 /**
       
   179  * Implementation of hook_node_operations().
       
   180  */
       
   181 function xmlsitemap_node_node_operations() {
       
   182   $operations = array(
       
   183     'xmlsitemap_add_nodes' => array(
       
   184       'label' => t('Add the selected posts to the XML sitemap'),
       
   185       'callback' => '_xmlsitemap_node_priority_operations',
       
   186       'callback arguments' => array('priority' => 0.5),
       
   187     ),
       
   188     'xmlsitemap_change_nodes_priority' => array(
       
   189       'label' => t('Change the XML sitemap priority of the selected posts to default'),
       
   190       'callback' => '_xmlsitemap_node_priority_operations',
       
   191       'callback arguments' => array('priority' => -2.0),
       
   192     ),
       
   193     'xmlsitemap_remove_nodes' => array(
       
   194       'label' => t('Remove the selected posts from the XML sitemap'),
       
   195       'callback' => '_xmlsitemap_node_priority_operations',
       
   196       'callback arguments' => array('priority' => -1.0),
       
   197     ),
       
   198   );
       
   199   return $operations;
       
   200 }
       
   201 
       
   202 /**
       
   203  * Implementation of hook_node_type().
       
   204  */
       
   205 function xmlsitemap_node_node_type($op, $info) {
       
   206   if ($op == 'delete') {
       
   207     variable_del('xmlsitemap_node_type_priority_'. $info->type);
       
   208   }
       
   209   elseif ($op == 'update' && !empty($info->old_type) && $info->type != $info->old_type) {
       
   210     variable_set('xmlsitemap_node_type_priority_'. $info->type, variable_get('xmlsitemap_node_type_priority_'. $info->old_type, 0.5));
       
   211     variable_del('xmlsitemap_node_type_priority_'. $info->old_type);
       
   212   }
       
   213 }
       
   214 
       
   215 /**
       
   216  * Implementation of hook_nodeapi().
       
   217  */
       
   218 function xmlsitemap_node_nodeapi(&$node, $op, $teaser = NULL, $page = NULL) {
       
   219   switch ($op) {
       
   220     case 'prepare':
       
   221       if (isset($node->nid)) {
       
   222         $priority_override = db_result(db_query("SELECT priority_override
       
   223           FROM {xmlsitemap_node} WHERE nid = %d",
       
   224           $node->nid)
       
   225         );
       
   226         $node->priority_override = $priority_override !== FALSE ? $priority_override : -2.0;
       
   227       }
       
   228       break;
       
   229     case 'insert':
       
   230       $row = new stdClass();
       
   231       $row->nid = $node->nid;
       
   232       $row->changed = $node->changed;
       
   233       $row->previously_changed = $node->created;
       
   234       $row->priority_override = isset($node->priority_override) ? $node->priority_override : -2.0;
       
   235       drupal_write_record('xmlsitemap_node', $row);
       
   236       if ($node->status) {
       
   237         xmlsitemap_flag_sitemap();
       
   238       }
       
   239       break;
       
   240     case 'update':
       
   241       if (($result = db_fetch_object(db_query("SELECT nid, changed, previously_changed, comment_ratio, priority_override FROM {xmlsitemap_node} WHERE nid = %d", $node->nid))) === FALSE) {
       
   242         $row = new stdClass();
       
   243         $row->nid = $node->nid;
       
   244         $row->changed = $node->changed;
       
   245         $row->previously_changed =  $node->created;
       
   246         $row->priority_override = isset($node->priority_override) ? $node->priority_override : -2.0;
       
   247       }
       
   248       else {
       
   249         $row = $result;
       
   250         $row->previously_changed = $row->changed;
       
   251         $row->changed = $node->changed;
       
   252         if (isset($node->priority_override)) {
       
   253           $row->priority_override =  $node->priority_override;
       
   254         }
       
   255       }
       
   256       drupal_write_record('xmlsitemap_node', $row, $result === FALSE ? NULL : 'nid');
       
   257       xmlsitemap_flag_sitemap();
       
   258       break;
       
   259     case 'delete':
       
   260       db_query("DELETE FROM {xmlsitemap_node} WHERE nid = %d", $node->nid);
       
   261       db_query("DELETE FROM {xmlsitemap} WHERE type = 'node' AND id = %d", $node->nid);
       
   262       if ($node->status) {
       
   263         xmlsitemap_flag_sitemap();
       
   264       }
       
   265       break;
       
   266   }
       
   267 }
       
   268 
       
   269 /**
       
   270  * Implementation of hook_xmlsitemap_description().
       
   271  */
       
   272 function xmlsitemap_node_xmlsitemap_description() {
       
   273   return '<dt>'. t('XML sitemap node') .'</dt>'.
       
   274     '<dd>'. t('<em>XML sitemap node</em> adds nodes (content) to the sitemap. The default priority of a node is determined by a combination of its <a href="@content">content type</a> priority, whether it appears on the front page of your site, and the number of comments it has received. You can override the default priority for individual nodes when you add or edit a node.', array('@content' => url('admin/content/types'))) .'</dd>';
       
   275 }
       
   276 
       
   277 /**
       
   278  * Implementation of hook_xmlsitemap_link_status().
       
   279  */
       
   280 function xmlsitemap_node_xmlsitemap_link_status($type, $id, $sid) {
       
   281   if (!($node = node_load($id, NULL, TRUE))) {
       
   282     return XMLSITEMAP_LINK_DISABLED;
       
   283   }
       
   284   if ($node->status) {
       
   285     return 0;
       
   286   }
       
   287   return XMLSITEMAP_LINK_DISABLED;
       
   288 }
       
   289 
       
   290 /**
       
   291  * Implementation of hook_xmlsitemap_links().
       
   292  */
       
   293 function xmlsitemap_node_xmlsitemap_links() {
       
   294   $anon_account = drupal_anonymous_user();
       
   295   $query = "SELECT n.nid, n.vid, n.type, n.language, n.uid, n.created, n.promote, xn.changed, xn.previously_changed, xn.priority_override, xn.comment_ratio
       
   296     FROM {node} n
       
   297     INNER JOIN {xmlsitemap_node} xn ON n.nid = xn.nid
       
   298     WHERE n.status > 0";
       
   299   $result = db_query($query);
       
   300   $row = new stdClass();
       
   301   $row->module = 'xmlsitemap_node';
       
   302   $row->type = 'node';
       
   303   while ($node = db_fetch_object($result)) {
       
   304     $row->loc = 'node/'. $node->nid;
       
   305     $row->id = $node->nid;
       
   306     $row->sid = $node->vid;
       
   307     $row->language = $node->language;
       
   308     $row->changed = $node->changed;
       
   309     $row->changefreq = max(REQUEST_TIME - $node->changed, empty($node->previously_changed) ? $node->changed - $node->created : $node->changed - $node->previously_changed);
       
   310     $priority = xmlsitemap_node_get_priority($node);
       
   311     $row->priority = ($priority == -1.0) ? $priority : min(max(round($priority, 1), 0.0), 1.0);
       
   312     $old_row = db_fetch_object(db_query("SELECT lid, type, language, priority FROM {xmlsitemap} WHERE loc = '%s'", $row->loc));
       
   313     $node_access = node_access('view', node_load(array('nid' => $node->nid), NULL, TRUE), $anon_account);
       
   314     $row->priority = $node_access ? $row->priority : -1;
       
   315     if ($old_row === FALSE) {
       
   316       drupal_write_record('xmlsitemap', $row);
       
   317     }
       
   318     elseif ($old_row->type == 'node' && ($old_row->priority != $row->priority || $old_row->language != $row->language)) {
       
   319       $row->lid = $old_row->lid;
       
   320       drupal_write_record('xmlsitemap', $row, 'lid');
       
   321     }
       
   322   }
       
   323 }
       
   324 
       
   325 /*****************************************************************************
       
   326  * Menu callbacks / form builders, submit/validate functions.
       
   327  ****************************************************************************/
       
   328 
       
   329 /**
       
   330  * Add submit actions to forms.
       
   331  */
       
   332 function xmlsitemap_node_type_submit($form, &$form_state) {
       
   333   xmlsitemap_flag_sitemap();
       
   334 }
       
   335 
       
   336 /*****************************************************************************
       
   337  * Public functions.
       
   338  ****************************************************************************/
       
   339 
       
   340 /**
       
   341  * Get the node priority in the sitemap.
       
   342  * @param $node
       
   343  *   The node object.
       
   344  * @param $load
       
   345  *   TRUE if priority_override must be loaded from the module table.
       
   346  * @return
       
   347  *   The priority for the node.
       
   348  * @see xmlsitemap_node_set_priority()
       
   349  */
       
   350 function xmlsitemap_node_get_priority($node, $load = FALSE) {
       
   351   if (!isset($node->priority_override) && $load) {
       
   352     $priority_override = db_result(db_query("SELECT xn.priority_override FROM {xmlsitemap_node} xn ON WHERE xn.nid = %d", $node->nid));
       
   353     if ($priority_override !== FALSE) {
       
   354       $node->priority_override = $priority_override;
       
   355     }
       
   356   }
       
   357   if (isset($node->priority_override) && $node->priority_override != -2.0) {
       
   358     $priority = $node->priority_override;
       
   359   }
       
   360   elseif (($priority = variable_get('xmlsitemap_node_type_priority_'. $node->type, 0.5)) != -1.0) {
       
   361     if ($node->promote) {
       
   362       $priority += variable_get('xmlsitemap_node_promote_priority', 0.3);
       
   363     }
       
   364     $priority += $node->comment_ratio * variable_get('xmlsitemap_node_comment_priority', 0.2);
       
   365   }
       
   366   if (!isset($priority)) {
       
   367     $priority = -1.0;
       
   368   }
       
   369   return $priority;
       
   370 }
       
   371 
       
   372 /**
       
   373  * Set the node priority in the sitemap.
       
   374  * @param $node
       
   375  *   The node object, or the node ID.
       
   376  * @param $priority
       
   377  *   The priority for the node.
       
   378  * @return
       
   379  *   The node object, or FALSE.
       
   380  */
       
   381 function xmlsitemap_node_set_priority($node, $priority) {
       
   382   if (!is_numeric($node)) {
       
   383     $node = (object) $node;
       
   384     $nid = $node->nid;
       
   385   }
       
   386   else {
       
   387     $nid = $node;
       
   388     $node = node_load($nid);
       
   389   }
       
   390   if ($node) {
       
   391     $result = db_fetch_object(db_query("SELECT nid, changed, previously_changed, comment_ratio, priority_override
       
   392       FROM {xmlsitemap_node}
       
   393       WHERE nid = %d", $nid)
       
   394     );
       
   395     if ($result === FALSE) {
       
   396       $row = new stdClass();
       
   397       $row->nid = $nid;
       
   398       $row->changed = $node->changed;
       
   399       $row->previously_changed = $node->created;
       
   400     }
       
   401     else {
       
   402       $row = $result;
       
   403       if ($node->changed > $row->changed) {
       
   404         $row->previously_changed = $row->changed;
       
   405         $row->changed = $node->changed;
       
   406       }
       
   407     }
       
   408     $row->priority_override = $priority;
       
   409     drupal_write_record('xmlsitemap_node', $row, $result === FALSE ? NULL : 'nid');
       
   410     return $node;
       
   411   }
       
   412   return FALSE;
       
   413 }
       
   414 
       
   415 /*****************************************************************************
       
   416  * Private functions - node operation callbacks.
       
   417  ****************************************************************************/
       
   418 
       
   419 /**
       
   420  * Node operations callback.
       
   421  */
       
   422 function _xmlsitemap_node_priority_operations($nodes, $priority) {
       
   423   if (count($nodes)) {
       
   424     $batch = array(
       
   425       'operations' => array(
       
   426         array('_xmlsitemap_node_batch_process', array($nodes, $priority))
       
   427       ),
       
   428       'finished' => 'xmlsitemap_batch_operations_finished',
       
   429       'title' => t('Processing'),
       
   430       'progress_message' => '',
       
   431       'error_message' => t('The update has encountered an error.'),
       
   432     );
       
   433     batch_set($batch);
       
   434   }
       
   435 }
       
   436 
       
   437 /*****************************************************************************
       
   438  * Private functions - batch operation callbacks.
       
   439  ****************************************************************************/
       
   440 
       
   441 /**
       
   442  * Node operations batch process callback.
       
   443  */
       
   444 function _xmlsitemap_node_batch_process($nodes, $priority, &$context) {
       
   445   if (!isset($context['sandbox']['progress'])) {
       
   446     $context['sandbox']['progress'] = 0;
       
   447     $context['sandbox']['max'] = count($nodes);
       
   448     $context['sandbox']['nodes'] = $nodes;
       
   449     if (module_exists('comment')) {
       
   450       $context['sandbox']['maxcomments'] = (integer) db_result(db_query('SELECT MAX(comment_count) FROM {node_comment_statistics}'));
       
   451     }
       
   452   }
       
   453   $nid = array_shift($context['sandbox']['nodes']);
       
   454   if ($node = xmlsitemap_node_set_priority($nid, $priority)) {
       
   455     $context['results'][] = l($node->title, 'node/'. $nid);
       
   456     if (count($context['results']) > 6) {
       
   457       array_shift($context['results']);
       
   458     }
       
   459   }
       
   460   $context['sandbox']['progress']++;
       
   461   if ($context['sandbox']['progress'] != $context['sandbox']['max']) {
       
   462     $context['finished'] = $context['sandbox']['progress'] / $context['sandbox']['max'];
       
   463   }
       
   464   else {
       
   465     xmlsitemap_flag_sitemap();
       
   466   }
       
   467 }
       
   468 
       
   469 /**
       
   470  * @} End of "addtogroup xmlsitemap".
       
   471  */