xmlsitemap.admin.inc 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913
  1. <?php
  2. /**
  3. * @file
  4. * Administrative page callbacks for the xmlsitemap module.
  5. *
  6. * @ingroup xmlsitemap
  7. */
  8. /**
  9. * Render a tableselect list of XML sitemaps for the main admin page.
  10. */
  11. function xmlsitemap_sitemap_list_form() {
  12. $destination = drupal_get_destination();
  13. // Build the 'Update options' form.
  14. $form['#operations'] = module_invoke_all('xmlsitemap_sitemap_operations');
  15. $operations = array();
  16. foreach ($form['#operations'] as $operation => $operation_info) {
  17. $operations[$operation] = $operation_info['label'];
  18. }
  19. asort($operations);
  20. $form['operations'] = array(
  21. '#type' => 'fieldset',
  22. '#title' => t('Update options'),
  23. '#prefix' => '<div class="container-inline">',
  24. '#suffix' => '</div>',
  25. );
  26. $form['operations']['operation'] = array(
  27. '#type' => 'select',
  28. '#options' => $operations,
  29. '#default_value' => 'update',
  30. );
  31. $form['operations']['submit'] = array(
  32. '#type' => 'submit',
  33. '#value' => t('Update'),
  34. );
  35. $contexts = xmlsitemap_get_context_info();
  36. $header = array();
  37. $header['url'] = array('data' => t('URL'));
  38. foreach ($contexts as $context_key => $context_info) {
  39. if (!empty($context_info['summary callback'])) {
  40. $header['context_' . $context_key] = $context_info['label'];
  41. }
  42. }
  43. $header['updated'] = array(
  44. 'data' => t('Last updated'),
  45. 'field' => 'updated',
  46. 'sort' => 'asc',
  47. );
  48. $header['links'] = array('data' => t('Links'), 'field' => 'links');
  49. $header['chunks'] = array('data' => t('Pages'), 'field' => 'chunks');
  50. $header['operations'] = array('data' => t('Operations'));
  51. $query = db_select('xmlsitemap_sitemap');
  52. $query->fields('xmlsitemap_sitemap', array('smid'));
  53. $query->extend('TableSort')->orderByHeader($header);
  54. $smids = $query->execute()->fetchCol();
  55. $sitemaps = $smids ? xmlsitemap_sitemap_load_multiple($smids) : array();
  56. $options = array();
  57. foreach ($sitemaps as $smid => $sitemap) {
  58. $sitemap->url = url($sitemap->uri['path'], $sitemap->uri['options']);
  59. $options[$smid]['url'] = array(
  60. 'data' => array(
  61. '#type' => 'link',
  62. '#title' => $sitemap->url,
  63. '#href' => $sitemap->url,
  64. ),
  65. );
  66. foreach ($contexts as $context_key => $context_info) {
  67. if (!empty($context_info['summary callback'])) {
  68. $options[$smid]['context_' . $context_key] = _xmlsitemap_sitemap_context_summary($sitemap, $context_key, $context_info);
  69. }
  70. }
  71. $options[$smid]['updated'] = $sitemap->updated ? format_date($sitemap->updated, 'short') : t('Never');
  72. $options[$smid]['links'] = $sitemap->updated ? $sitemap->links : '-';
  73. $options[$smid]['chunks'] = $sitemap->updated ? $sitemap->chunks : '-';
  74. // @todo Highlight sitemaps that need updating.
  75. // $options[$smid]['#attributes']['class'][] = 'warning';
  76. $operations = array();
  77. $operations['edit'] = xmlsitemap_get_operation_link('admin/config/search/xmlsitemap/edit/' . $smid, array('title' => t('Edit'), 'modal' => TRUE));
  78. $operations['delete'] = xmlsitemap_get_operation_link('admin/config/search/xmlsitemap/delete/' . $smid, array('title' => t('Delete'), 'modal' => TRUE));
  79. if ($operations) {
  80. $options[$smid]['operations'] = array(
  81. 'data' => array(
  82. '#theme' => 'links',
  83. '#links' => $operations,
  84. '#attributes' => array('class' => array('links', 'inline')),
  85. ),
  86. );
  87. }
  88. else {
  89. $options[$smid]['operations'] = t('None (sitemap locked)');
  90. }
  91. }
  92. $form['sitemaps'] = array(
  93. '#type' => 'tableselect',
  94. '#header' => $header,
  95. '#options' => $options,
  96. '#empty' => t('No XML sitemaps available.') . ' ' . l(t('Add a new XML sitemap'), 'admin/config/search/xmlsitemap/add'),
  97. );
  98. return $form;
  99. }
  100. /**
  101. * Validate xmlsitemap_sitemap_list_form submissions.
  102. */
  103. function xmlsitemap_sitemap_list_form_validate($form, &$form_state) {
  104. $form_state['values']['sitemaps'] = array_filter($form_state['values']['sitemaps']);
  105. // Error if there are no items to select.
  106. if (!count($form_state['values']['sitemaps'])) {
  107. form_set_error('', t('No sitemaps selected.'));
  108. }
  109. }
  110. /**
  111. * Process xmlsitemap_sitemap_list_form submissions.
  112. *
  113. * Execute the chosen 'Update option' on the selected sitemaps.
  114. */
  115. function xmlsitemap_sitemap_list_form_submit($form, &$form_state) {
  116. $operation = $form['#operations'][$form_state['values']['operation']];
  117. // Filter out unchecked sitemaps.
  118. $sitemaps = array_filter($form_state['values']['sitemaps']);
  119. if (!empty($operation['confirm']) && empty($form_state['values']['confirm'])) {
  120. // We need to rebuild the form to go to a second step. For example, to
  121. // show the confirmation form for the deletion of redirects.
  122. $form_state['rebuild'] = TRUE;
  123. }
  124. else {
  125. $function = $operation['callback'];
  126. // Add in callback arguments if present.
  127. if (isset($operation['callback arguments'])) {
  128. $args = array_merge(array($sitemaps), $operation['callback arguments']);
  129. }
  130. else {
  131. $args = array($sitemaps);
  132. }
  133. call_user_func_array($function, $args);
  134. $count = count($form_state['values']['sitemaps']);
  135. drupal_set_message(
  136. format_plural(
  137. count($sitemaps), '@action @count XML sitemap.', '@action @count XML sitemaps.',
  138. array('@action' => $operation['action past'], '@count' => $count)
  139. )
  140. );
  141. }
  142. }
  143. /**
  144. * Edit Form.
  145. */
  146. function xmlsitemap_sitemap_edit_form(array $form, array &$form_state, stdClass $sitemap = NULL) {
  147. _xmlsitemap_set_breadcrumb();
  148. if (!isset($sitemap)) {
  149. $sitemap = new stdClass();
  150. $sitemap->smid = NULL;
  151. $sitemap->context = array();
  152. }
  153. $form['#sitemap'] = $sitemap;
  154. $form['smid'] = array(
  155. '#type' => 'value',
  156. '#value' => $sitemap->smid,
  157. );
  158. // The context settings should be form_alter'ed by the context modules.
  159. $form['context'] = array(
  160. '#tree' => TRUE,
  161. );
  162. $form['actions'] = array(
  163. '#type' => 'actions',
  164. );
  165. $form['actions']['save'] = array(
  166. '#type' => 'submit',
  167. '#value' => t('Save'),
  168. );
  169. $form['actions']['cancel'] = array(
  170. '#type' => 'link',
  171. '#href' => isset($_GET['destination']) ? $_GET['destination'] : 'admin/config/search/xmlsitemap',
  172. '#title' => t('Cancel'),
  173. );
  174. // Let other modules alter this form with their context settings.
  175. $form['#pre_render'][] = 'xmlsitemap_sitemap_edit_form_pre_render';
  176. return $form;
  177. }
  178. /**
  179. * Edit Form Pre Render.
  180. */
  181. function xmlsitemap_sitemap_edit_form_pre_render($form) {
  182. $visible_children = element_get_visible_children($form['context']);
  183. if (empty($visible_children)) {
  184. $form['context']['empty'] = array(
  185. '#type' => 'markup',
  186. '#markup' => '<p>' . t('There are currently no XML sitemap contexts available.') . '</p>',
  187. );
  188. }
  189. return $form;
  190. }
  191. /**
  192. * Edit form validate.
  193. */
  194. function xmlsitemap_sitemap_edit_form_validate($form, &$form_state) {
  195. // If there are no context options, the $form_state['values']['context']
  196. // disappears.
  197. $form_state['values'] += array('context' => array());
  198. $existing = xmlsitemap_sitemap_load_by_context($form_state['values']['context']);
  199. if ($existing && $existing->smid != $form_state['values']['smid']) {
  200. form_set_error('context', t('A sitemap with the same context already exists.'));
  201. }
  202. }
  203. /**
  204. * Edit Form Submit.
  205. */
  206. function xmlsitemap_sitemap_edit_form_submit($form, &$form_state) {
  207. form_state_values_clean($form_state);
  208. $sitemap = (object) $form_state['values'];
  209. xmlsitemap_sitemap_save($sitemap);
  210. drupal_set_message(t('The sitemap has been saved.'));
  211. $form_state['redirect'] = 'admin/config/search/xmlsitemap';
  212. }
  213. /**
  214. * Delete form.
  215. */
  216. function xmlsitemap_sitemap_delete_form(array $form, array &$form_state, stdClass $sitemap) {
  217. _xmlsitemap_set_breadcrumb();
  218. $count = (int) db_query("SELECT COUNT(smid) FROM {xmlsitemap_sitemap}")->fetchField();
  219. if ($count === 1 && empty($_POST)) {
  220. drupal_set_message(t('It is not recommended to delete the only XML sitemap.'), 'error');
  221. }
  222. $form['#sitemap'] = $sitemap;
  223. $form['smid'] = array(
  224. '#type' => 'value',
  225. '#value' => $sitemap->smid,
  226. );
  227. return confirm_form(
  228. $form,
  229. t('Are you sure you want to delete the XML sitemap?'),
  230. 'admin/config/search/xmlsitemap',
  231. '',
  232. t('Delete'),
  233. t('Cancel')
  234. );
  235. }
  236. /**
  237. * Delete form submit.
  238. */
  239. function xmlsitemap_sitemap_delete_form_submit($form, $form_state) {
  240. xmlsitemap_sitemap_delete($form_state['values']['smid']);
  241. drupal_set_message(t('The sitemap has been deleted.'));
  242. $form_state['redirect'] = 'admin/config/search/xmlsitemap';
  243. }
  244. /**
  245. * Form builder; Administration settings form.
  246. *
  247. * @see system_settings_form()
  248. * @see xmlsitemap_settings_form_validate()
  249. */
  250. function xmlsitemap_settings_form($form, &$form_state) {
  251. global $base_url;
  252. $form['xmlsitemap_minimum_lifetime'] = array(
  253. '#type' => 'select',
  254. '#title' => t('Minimum sitemap lifetime'),
  255. '#options' => array(0 => t('No minimum')) + drupal_map_assoc(array(300,
  256. 900,
  257. 1800,
  258. 3600,
  259. 10800,
  260. 21600,
  261. 43200,
  262. 86400,
  263. 172800,
  264. 259200,
  265. 604800,
  266. ), 'format_interval'),
  267. '#description' => t('The minimum amount of time that will elapse before the sitemaps are regenerated. The sitemaps will also only be regenerated on cron if any links have been added, updated, or deleted.') . '<br />' . t('Recommended value: %value.', array('%value' => t('1 day'))),
  268. '#default_value' => variable_get('xmlsitemap_minimum_lifetime', 0),
  269. );
  270. $form['xmlsitemap_xsl'] = array(
  271. '#type' => 'checkbox',
  272. '#title' => t('Include a stylesheet in the sitemaps for humans.'),
  273. '#description' => t('When enabled, this will add formatting and tables with sorting to make it easier to view the XML sitemap data instead of viewing raw XML output. Search engines will ignore this.'),
  274. '#default_value' => variable_get('xmlsitemap_xsl', 1),
  275. );
  276. $form['xmlsitemap_prefetch_aliases'] = array(
  277. '#type' => 'checkbox',
  278. '#title' => t('Prefetch URL aliases during sitemap generation.'),
  279. '#description' => t('When enabled, this will fetch all URL aliases at once instead of one at a time during sitemap generation. For medium or large sites, it is recommended to disable this feature as it uses a lot of memory.'),
  280. '#default_value' => variable_get('xmlsitemap_prefetch_aliases', 1),
  281. );
  282. $form['advanced'] = array(
  283. '#type' => 'fieldset',
  284. '#title' => t('Advanced settings'),
  285. '#collapsible' => TRUE,
  286. '#collapsed' => !variable_get('xmlsitemap_developer_mode', 0),
  287. '#weight' => 10,
  288. );
  289. $form['advanced']['xmlsitemap_chunk_size'] = array(
  290. '#type' => 'select',
  291. '#title' => t('Number of links in each sitemap page'),
  292. '#options' => array('auto' => t('Automatic (recommended)')) + drupal_map_assoc(array(
  293. 100,
  294. 500,
  295. 1000,
  296. 2500,
  297. 5000,
  298. 10000,
  299. 25000,
  300. XMLSITEMAP_MAX_SITEMAP_LINKS,
  301. )),
  302. '#default_value' => xmlsitemap_var('chunk_size'),
  303. // @todo This description is not clear.
  304. '#description' => t('If there are problems with rebuilding the sitemap, you may want to manually set this value. If you have more than @max links, an index with multiple sitemap pages will be generated. There is a maximum of @max sitemap pages.', array('@max' => XMLSITEMAP_MAX_SITEMAP_LINKS)),
  305. );
  306. $form['advanced']['xmlsitemap_batch_limit'] = array(
  307. '#type' => 'select',
  308. '#title' => t('Maximum number of sitemap links to process at once'),
  309. '#options' => drupal_map_assoc(array(
  310. 5,
  311. 10,
  312. 25,
  313. 50,
  314. 100,
  315. 250,
  316. 500,
  317. 1000,
  318. 2500,
  319. 5000,
  320. )),
  321. '#default_value' => xmlsitemap_var('batch_limit'),
  322. '#description' => t('If you have problems running cron or rebuilding the sitemap, you may want to lower this value.'),
  323. );
  324. if (!xmlsitemap_check_directory()) {
  325. form_set_error('xmlsitemap_path', t('The directory %directory does not exist or is not writable.', array('%directory' => xmlsitemap_get_directory())));
  326. }
  327. $form['advanced']['xmlsitemap_path'] = array(
  328. '#type' => 'textfield',
  329. '#title' => t('Sitemap cache directory'),
  330. '#default_value' => variable_get('xmlsitemap_path', 'xmlsitemap'),
  331. '#size' => 30,
  332. '#maxlength' => 255,
  333. '#description' => t('Subdirectory where the sitemap data will be stored. This folder <strong>must not be shared</strong> with any other Drupal site or install using XML sitemap.'),
  334. '#field_prefix' => file_build_uri(''),
  335. '#required' => TRUE,
  336. );
  337. $form['advanced']['xmlsitemap_base_url'] = array(
  338. '#type' => 'textfield',
  339. '#title' => t('Default base URL'),
  340. '#default_value' => variable_get('xmlsitemap_base_url', $base_url),
  341. '#size' => 30,
  342. '#description' => t('This is the default base URL used for sitemaps and sitemap links.'),
  343. '#required' => TRUE,
  344. );
  345. $form['advanced']['xmlsitemap_lastmod_format'] = array(
  346. '#type' => 'select',
  347. '#title' => t('Last modification date format'),
  348. '#options' => array(
  349. XMLSITEMAP_LASTMOD_SHORT => t('Short'),
  350. XMLSITEMAP_LASTMOD_MEDIUM => t('Medium'),
  351. XMLSITEMAP_LASTMOD_LONG => t('Long'),
  352. ),
  353. '#default_value' => variable_get('xmlsitemap_lastmod_format', XMLSITEMAP_LASTMOD_MEDIUM),
  354. );
  355. foreach ($form['advanced']['xmlsitemap_lastmod_format']['#options'] as $key => &$label) {
  356. $label .= ' (' . gmdate($key, REQUEST_TIME) . ')';
  357. }
  358. $form['advanced']['xmlsitemap_developer_mode'] = array(
  359. '#type' => 'checkbox',
  360. '#title' => t('Enable developer mode to expose additional settings.'),
  361. '#default_value' => variable_get('xmlsitemap_developer_mode', 0),
  362. );
  363. $form['advanced']['xmlsitemap_disable_cron_regeneration'] = array(
  364. '#type' => 'checkbox',
  365. '#title' => t('Disable cron generation of sitemap files.'),
  366. '#default_value' => variable_get('xmlsitemap_disable_cron_regeneration', 0),
  367. '#description' => t('This can be disabled if other methods are being used to generate the sitemap files, like <em>drush xmlsitemap-regenerate</em>.'),
  368. );
  369. $form['advanced']['xmlsitemap_output_elements'] = array(
  370. '#type' => 'checkboxes',
  371. '#title' => t('Enable or disable the individual @loc elements from output', array('@loc' => '<loc>')),
  372. '#options' => array(
  373. 'lastmod' => t('Last modification date: @lastmod', array('@lastmod' => '<lastmod>')),
  374. 'changefreq' => t('Change frequency: @changfreq', array('@changfreq' => '<changefreq>')),
  375. 'priority' => t('Priority: @priority', array('@priority' => '<priority>')),
  376. ),
  377. '#default_value' => drupal_map_assoc(variable_get('xmlsitemap_output_elements', array(
  378. 'lastmod',
  379. 'changefreq',
  380. 'priority',
  381. ))),
  382. );
  383. $form['xmlsitemap_settings'] = array(
  384. '#type' => 'vertical_tabs',
  385. '#weight' => 20,
  386. );
  387. $entities = xmlsitemap_get_link_info(NULL, TRUE);
  388. module_load_all_includes('xmlsitemap.inc');
  389. foreach ($entities as $entity => $entity_info) {
  390. $form[$entity] = array(
  391. '#type' => 'fieldset',
  392. '#title' => $entity_info['label'],
  393. '#collapsible' => TRUE,
  394. '#collapsed' => TRUE,
  395. '#group' => 'xmlsitemap_settings',
  396. );
  397. if (!empty($entity_info['bundles'])) {
  398. // If this entity has bundles, show a bundle setting summary.
  399. xmlsitemap_add_form_entity_summary($form[$entity], $entity, $entity_info);
  400. }
  401. if (!empty($entity_info['xmlsitemap']['settings callback'])) {
  402. // Add any entity-specific settings.
  403. $entity_info['xmlsitemap']['settings callback']($form[$entity]);
  404. }
  405. // Ensure that the entity fieldset is not shown if there are no accessible
  406. // sub-elements.
  407. $form[$entity]['#access'] = (bool) element_get_visible_children($form[$entity]);
  408. }
  409. $form['#validate'][] = 'xmlsitemap_settings_form_validate';
  410. $form['#submit'][] = 'xmlsitemap_settings_form_submit';
  411. array_unshift($form['#submit'], 'xmlsitemap_form_submit_flag_regenerate');
  412. $form['array_filter'] = array('#type' => 'value', '#value' => TRUE);
  413. $form = system_settings_form($form);
  414. return $form;
  415. }
  416. /**
  417. * Form validator; Check the sitemap files directory.
  418. *
  419. * @see xmlsitemap_settings_form()
  420. */
  421. function xmlsitemap_settings_form_validate($form, &$form_state) {
  422. // Check that the chunk size will not create more than 1000 chunks.
  423. $chunk_size = $form_state['values']['xmlsitemap_chunk_size'];
  424. if ($chunk_size != 'auto' && $chunk_size != 50000 && (xmlsitemap_get_link_count() / $chunk_size) > 1000) {
  425. form_set_error('xmlsitemap_chunk_size', t('The sitemap page link count of @size will create more than 1,000 sitemap pages. Please increase the link count.', array('@size' => $chunk_size)));
  426. }
  427. $base_url = &$form_state['values']['xmlsitemap_base_url'];
  428. $base_url = rtrim($base_url, '/');
  429. if ($base_url != '' && !valid_url($base_url, TRUE)) {
  430. form_set_error('xmlsitemap_base_url', t('Invalid base URL.'));
  431. }
  432. }
  433. /**
  434. * Submit handler;.
  435. *
  436. * @see xmlsitemap_settings_form()
  437. */
  438. function xmlsitemap_settings_form_submit($form, $form_state) {
  439. // Save any changes to the frontpage link.
  440. xmlsitemap_link_save(array('type' => 'frontpage', 'id' => 0, 'loc' => ''));
  441. }
  442. /**
  443. * Menu callback; Confirm rebuilding of the sitemap.
  444. *
  445. * @see xmlsitemap_rebuild_form_submit()
  446. */
  447. function xmlsitemap_rebuild_form() {
  448. if (!$_POST && !variable_get('xmlsitemap_rebuild_needed', FALSE)) {
  449. if (!variable_get('xmlsitemap_regenerate_needed', FALSE)) {
  450. drupal_set_message(t('Your sitemap is up to date and does not need to be rebuilt.'), 'error');
  451. }
  452. else {
  453. $_REQUEST += array('destination' => 'admin/config/search/xmlsitemap');
  454. drupal_set_message(t('A rebuild is not necessary. If you are just wanting to regenerate the XML sitemap files, you can <a href="@link-cron">run cron manually</a>.', array('@link-cron' => url('admin/reports/status/run-cron', array('query' => drupal_get_destination())))), 'warning');
  455. }
  456. }
  457. // Build a list of rebuildable link types.
  458. module_load_include('generate.inc', 'xmlsitemap');
  459. $rebuild_types = xmlsitemap_get_rebuildable_link_types();
  460. $form['entities'] = array(
  461. '#type' => 'select',
  462. '#title' => t("Select which link types you would like to rebuild"),
  463. '#description' => t('If no link types are selected, the sitemap files will just be regenerated.'),
  464. '#multiple' => TRUE,
  465. '#options' => drupal_map_assoc($rebuild_types),
  466. '#default_value' => variable_get('xmlsitemap_rebuild_needed', FALSE) || !variable_get('xmlsitemap_developer_mode', 0) ? $rebuild_types : array(),
  467. '#access' => variable_get('xmlsitemap_developer_mode', 0),
  468. );
  469. $form['save_custom'] = array(
  470. '#type' => 'checkbox',
  471. '#title' => t('Save and restore any custom inclusion and priority links.'),
  472. '#default_value' => TRUE,
  473. );
  474. return confirm_form(
  475. $form,
  476. t('Are you sure you want to rebuild the XML sitemap?'),
  477. 'admin/config/search/xmlsitemap',
  478. '',
  479. t('Rebuild sitemap'),
  480. t('Cancel')
  481. );
  482. }
  483. /**
  484. * Submit handler; Starts the sitemap rebuild batch.
  485. *
  486. * @see xmlsitemap_rebuild_form()
  487. * @see xmlsitemap_rebuild_batch()
  488. */
  489. function xmlsitemap_rebuild_form_submit($form, &$form_state) {
  490. module_load_include('generate.inc', 'xmlsitemap');
  491. $batch = xmlsitemap_rebuild_batch($form_state['values']['entities'], $form_state['values']['save_custom']);
  492. batch_set($batch);
  493. $form_state['redirect'] = 'admin/config/search/xmlsitemap';
  494. }
  495. /**
  496. * Add a table summary for an entity and its bundles.
  497. */
  498. function xmlsitemap_add_form_entity_summary(&$form, $entity, array $entity_info) {
  499. $priorities = xmlsitemap_get_priority_options(NULL, FALSE);
  500. $statuses = xmlsitemap_get_status_options(NULL);
  501. $destination = drupal_get_destination();
  502. $rows = array();
  503. $totals = array('total' => 0, 'indexed' => 0, 'visible' => 0);
  504. foreach ($entity_info['bundles'] as $bundle => $bundle_info) {
  505. // Fetch current per-bundle link total and indexed counts.
  506. $status = xmlsitemap_get_link_type_indexed_status($entity, $bundle);
  507. $totals['total'] += $status['total'];
  508. $totals['indexed'] += $status['indexed'];
  509. $totals['visible'] += $status['visible'];
  510. $row = array();
  511. if (drupal_valid_path("admin/config/search/xmlsitemap/settings/$entity/$bundle")) {
  512. $edit_link = xmlsitemap_get_operation_link("admin/config/search/xmlsitemap/settings/$entity/$bundle", array('title' => $bundle_info['label'], 'modal' => TRUE));
  513. $row[] = l($edit_link['title'], $edit_link['href'], $edit_link);
  514. }
  515. else {
  516. // Bundle labels are assumed to be un-escaped input.
  517. $row[] = check_plain($bundle_info['label']);
  518. }
  519. $row[] = $statuses[$bundle_info['xmlsitemap']['status'] ? 1 : 0];
  520. $row[] = $priorities[number_format($bundle_info['xmlsitemap']['priority'], 1)];
  521. $row[] = $status['total'];
  522. $row[] = $status['indexed'];
  523. $row[] = $status['visible'];
  524. $rows[] = $row;
  525. }
  526. if ($rows) {
  527. $header = array(
  528. isset($entity_info['bundle label']) ? $entity_info['bundle label'] : '',
  529. t('Inclusion'),
  530. t('Priority'),
  531. t('Available'),
  532. t('Indexed'),
  533. t('Visible'),
  534. );
  535. $rows[] = array(
  536. array(
  537. 'data' => t('Totals'),
  538. 'colspan' => 3,
  539. 'header' => TRUE,
  540. ),
  541. array(
  542. 'data' => $totals['total'],
  543. 'header' => TRUE,
  544. ),
  545. array(
  546. 'data' => $totals['indexed'],
  547. 'header' => TRUE,
  548. ),
  549. array(
  550. 'data' => $totals['visible'],
  551. 'header' => TRUE,
  552. ),
  553. );
  554. $form['summary'] = array(
  555. '#theme' => 'table',
  556. '#header' => $header,
  557. '#rows' => $rows,
  558. );
  559. }
  560. }
  561. /**
  562. * Add the link type XML sitemap options to the link type's form.
  563. *
  564. * Caller is responsible for ensuring xmlsitemap_link_bundle_settings_save()
  565. * is called during submission.
  566. */
  567. function xmlsitemap_add_link_bundle_settings(array &$form, array &$form_state, $entity, $bundle) {
  568. $entity_info = xmlsitemap_get_link_info($entity);
  569. $bundle_info = xmlsitemap_link_bundle_load($entity, $bundle);
  570. $form['xmlsitemap'] = array(
  571. '#type' => 'fieldset',
  572. '#title' => t('XML sitemap'),
  573. '#collapsible' => TRUE,
  574. '#collapsed' => TRUE,
  575. '#access' => user_access('administer xmlsitemap'),
  576. '#group' => 'additional_settings',
  577. '#attached' => array(
  578. 'js' => array(
  579. 'vertical-tabs' => drupal_get_path('module', 'xmlsitemap') . '/xmlsitemap.js',
  580. ),
  581. ),
  582. '#tree' => TRUE,
  583. '#entity' => $entity,
  584. '#bundle' => $bundle,
  585. '#entity_info' => $entity_info,
  586. '#bundle_info' => $bundle_info,
  587. );
  588. // Hack to remove fieldset summary if Vertical tabs is not enabled.
  589. if (!isset($form['additional_settings'])) {
  590. unset($form['xmlsitemap']['#attached']['js']['vertical-tabs']);
  591. }
  592. $form['xmlsitemap']['description'] = array(
  593. '#prefix' => '<div class="description">',
  594. '#suffix' => '</div>',
  595. '#markup' => t('Changing these type settings will affect any items of this type that have either inclusion or priority set to default.'),
  596. );
  597. $form['xmlsitemap']['status'] = array(
  598. '#type' => 'select',
  599. '#title' => t('Inclusion'),
  600. '#options' => xmlsitemap_get_status_options(),
  601. '#default_value' => $bundle_info['status'],
  602. );
  603. $form['xmlsitemap']['priority'] = array(
  604. '#type' => 'select',
  605. '#title' => t('Default priority'),
  606. '#options' => xmlsitemap_get_priority_options(),
  607. '#default_value' => $bundle_info['priority'],
  608. '#states' => array(
  609. 'invisible' => array(
  610. 'select[name="xmlsitemap[status]"]' => array('value' => '0'),
  611. ),
  612. ),
  613. );
  614. $form += array('#submit' => array());
  615. array_unshift($form['#submit'], 'xmlsitemap_link_bundle_settings_form_submit');
  616. if (isset($form['submit'])) {
  617. $form['submit'] += array('#weight' => 40);
  618. }
  619. if (isset($form['delete'])) {
  620. $form['delete'] += array('#weight' => 50);
  621. }
  622. }
  623. /**
  624. * Link bundle settings form.
  625. */
  626. function xmlsitemap_link_bundle_settings_form(array $form, array &$form_state, array $bundle) {
  627. if (empty($form_state['ajax']) && $admin_path = xmlsitemap_get_bundle_path($bundle['entity'], $bundle['bundle'])) {
  628. // If this is a non-ajax form, redirect to the bundle administration page.
  629. $destination = drupal_get_destination();
  630. unset($_GET['destination']);
  631. drupal_goto($admin_path, array('query' => $destination));
  632. }
  633. else {
  634. drupal_set_title(t('@bundle XML sitemap settings', array('@bundle' => $bundle['info']['label'])));
  635. }
  636. $form = array();
  637. xmlsitemap_add_link_bundle_settings($form, $form_state, $bundle['entity'], $bundle['bundle']);
  638. $form['xmlsitemap']['#type'] = 'markup';
  639. $form['xmlsitemap']['#value'] = '';
  640. $form['xmlsitemap']['#access'] = TRUE;
  641. $form['xmlsitemap']['#show_message'] = TRUE;
  642. $form['actions'] = array(
  643. '#type' => 'actions',
  644. );
  645. $form['actions']['save'] = array(
  646. '#type' => 'submit',
  647. '#value' => t('Save'),
  648. );
  649. $form['actions']['cancel'] = array(
  650. '#value' => l(t('Cancel'), isset($_GET['destination']) ? $_GET['destination'] : 'admin/config/search/xmlsitemap/settings'),
  651. '#weight' => 10,
  652. );
  653. return $form;
  654. }
  655. /**
  656. * Add a link's XML sitemap options to the link's form.
  657. *
  658. * @todo Add changefreq overridability.
  659. */
  660. function xmlsitemap_add_form_link_options(array &$form, $entity, $bundle, $id) {
  661. $info = xmlsitemap_get_link_info($entity);
  662. if (!$info || empty($info['bundles'][$bundle])) {
  663. return;
  664. }
  665. if (!$link = xmlsitemap_link_load($entity, $id)) {
  666. $link = array();
  667. }
  668. $bundle_info = xmlsitemap_link_bundle_load($entity, $bundle);
  669. $link += array(
  670. 'access' => 1,
  671. 'status' => $bundle_info['status'],
  672. 'status_default' => $bundle_info['status'],
  673. 'status_override' => 0,
  674. 'priority' => $bundle_info['priority'],
  675. 'priority_default' => $bundle_info['priority'],
  676. 'priority_override' => 0,
  677. );
  678. $form['xmlsitemap'] = array(
  679. '#type' => 'fieldset',
  680. '#tree' => TRUE,
  681. '#title' => t('XML sitemap'),
  682. '#collapsible' => TRUE,
  683. '#collapsed' => !$link['status_override'] && !$link['priority_override'],
  684. '#access' => user_access('administer xmlsitemap') || user_access('use xmlsitemap') || xmlsitemap_link_bundle_access($bundle_info),
  685. '#group' => 'additional_settings',
  686. '#attached' => array(
  687. 'js' => array(
  688. 'vertical-tabs' => drupal_get_path('module', 'xmlsitemap') . '/xmlsitemap.js',
  689. ),
  690. ),
  691. );
  692. // Hack to remove fieldset summary if Vertical tabs is not enabled.
  693. if (!isset($form['additional_settings'])) {
  694. unset($form['xmlsitemap']['#attached']['js']['vertical-tabs']);
  695. }
  696. if (xmlsitemap_link_bundle_access($bundle_info) && $path = xmlsitemap_get_bundle_path($entity, $bundle)) {
  697. $form['xmlsitemap']['description'] = array(
  698. '#prefix' => '<div class="description">',
  699. '#suffix' => '</div>',
  700. '#markup' => t('The default XML sitemap settings for this @bundle can be changed <a href="@link-type">here</a>.', array(
  701. '@bundle' => drupal_strtolower($info['bundle label']),
  702. '@link-type' => url($path, array(
  703. 'query' => drupal_get_destination(),
  704. )),
  705. )),
  706. );
  707. }
  708. // Show a warning if the link is not accessible and will not be included in
  709. // the sitemap.
  710. if ($id && !$link['access']) {
  711. $form['xmlsitemap']['warning'] = array(
  712. '#type' => 'markup',
  713. '#prefix' => '<p><strong>',
  714. '#suffix' => '</strong></p>',
  715. '#value' => ('This item is not currently visible to anonymous users, so it will not be included in the sitemap.'),
  716. );
  717. }
  718. // Status field (inclusion/exclusion)
  719. $form['xmlsitemap']['status'] = array(
  720. '#type' => 'select',
  721. '#title' => t('Inclusion'),
  722. '#options' => xmlsitemap_get_status_options($link['status_default']),
  723. '#default_value' => $link['status_override'] ? $link['status'] : 'default',
  724. );
  725. $form['xmlsitemap']['status_default'] = array(
  726. '#type' => 'value',
  727. '#value' => $link['status_default'],
  728. );
  729. $form['xmlsitemap']['status_override'] = array(
  730. '#type' => 'value',
  731. '#value' => $link['status_override'],
  732. );
  733. // Priority field.
  734. $form['xmlsitemap']['priority'] = array(
  735. '#type' => 'select',
  736. '#title' => t('Priority'),
  737. '#options' => xmlsitemap_get_priority_options($link['priority_default']),
  738. '#default_value' => $link['priority_override'] ? number_format($link['priority'], 1) : 'default',
  739. '#description' => t('The priority of this URL relative to other URLs on your site.'),
  740. '#states' => array(
  741. 'invisible' => array(
  742. 'select[name="xmlsitemap[status]"]' => array('value' => '0'),
  743. ),
  744. ),
  745. );
  746. if (!$link['status_default']) {
  747. // If the default status is excluded, add a visible state on the include
  748. // override option.
  749. $form['xmlsitemap']['priority']['#states']['visible'] = array(
  750. 'select[name="xmlsitemap[status]"]' => array('value' => '1'),
  751. );
  752. }
  753. $form['xmlsitemap']['priority_default'] = array(
  754. '#type' => 'value',
  755. '#value' => $link['priority_default'],
  756. );
  757. $form['xmlsitemap']['priority_override'] = array(
  758. '#type' => 'value',
  759. '#value' => $link['priority_override'],
  760. );
  761. // Add the submit handler to adjust the default values if selected.
  762. $form += array('#submit' => array());
  763. if (!in_array('xmlsitemap_process_form_link_options', $form['#submit'])) {
  764. array_unshift($form['#submit'], 'xmlsitemap_process_form_link_options');
  765. }
  766. }
  767. /**
  768. * Get a list of priority options.
  769. *
  770. * @param string $default
  771. * Include a 'default' option.
  772. * @param string $guides
  773. * Add helpful indicators for the highest, middle and lowest values.
  774. *
  775. * @return array
  776. * An array of options.
  777. */
  778. function xmlsitemap_get_priority_options($default = NULL, $guides = TRUE) {
  779. $options = array();
  780. $priorities = array(
  781. '1.0' => t('1.0'),
  782. '0.9' => t('0.9'),
  783. '0.8' => t('0.8'),
  784. '0.7' => t('0.7'),
  785. '0.6' => t('0.6'),
  786. '0.5' => t('0.5'),
  787. '0.4' => t('0.4'),
  788. '0.3' => t('0.3'),
  789. '0.2' => t('0.2'),
  790. '0.1' => t('0.1'),
  791. '0.0' => t('0.0'),
  792. );
  793. if (isset($default)) {
  794. $default = number_format($default, 1);
  795. $options['default'] = t('Default (@value)', array('@value' => $priorities[$default]));
  796. }
  797. // Add the rest of the options.
  798. $options += $priorities;
  799. if ($guides) {
  800. $options['1.0'] .= ' ' . t('(highest)');
  801. $options['0.5'] .= ' ' . t('(normal)');
  802. $options['0.0'] .= ' ' . t('(lowest)');
  803. }
  804. return $options;
  805. }
  806. /**
  807. * Get a list of priority options.
  808. *
  809. * @param string $default
  810. * Include a 'default' option.
  811. *
  812. * @return array
  813. * An array of options.
  814. *
  815. * @see _xmlsitemap_translation_strings()
  816. */
  817. function xmlsitemap_get_status_options($default = NULL) {
  818. $options = array();
  819. $statuses = array(
  820. 1 => t('Included'),
  821. 0 => t('Excluded'),
  822. );
  823. if (isset($default)) {
  824. $default = $default ? 1 : 0;
  825. $options['default'] = t('Default (@value)', array('@value' => drupal_strtolower($statuses[$default])));
  826. }
  827. $options += $statuses;
  828. return $options;
  829. }