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