|
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 */ |