xmlsitemap_taxonomy.module 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366
  1. <?php
  2. // $Id: xmlsitemap_taxonomy.module,v 1.9 2010/01/20 03:34:29 davereid Exp $
  3. /**
  4. * Implements hook_cron().
  5. *
  6. * Process old taxonomy terms not found in the {xmlsitemap} table.
  7. */
  8. function xmlsitemap_taxonomy_cron() {
  9. xmlsitemap_taxonomy_xmlsitemap_index_links(xmlsitemap_var('batch_limit'));
  10. }
  11. /**
  12. * Implements hook_xmlsitemap_index_links().
  13. */
  14. function xmlsitemap_taxonomy_xmlsitemap_index_links($limit) {
  15. if ($vids = xmlsitemap_taxonomy_get_vids()) {
  16. $tids = db_query_range("SELECT t.tid FROM {term_data} t LEFT JOIN {xmlsitemap} x ON x.type = 'taxonomy_term' AND t.tid = x.id WHERE x.id IS NULL AND t.vid IN (:vids) ORDER BY t.tid DESC", 0, $limit, array(':vids' => $vids));
  17. foreach ($tids as $tid) {
  18. $term = xmlsitemap_taxonomy_taxonomy_term_load($tid);
  19. $link = xmlsitemap_taxonomy_create_link($term);
  20. xmlsitemap_save_link($link);
  21. }
  22. }
  23. }
  24. /**
  25. * Implements hook_xmlsitemap_links().
  26. */
  27. function xmlsitemap_taxonomy_xmlsitemap_links($offset = 0, $limit = 0) {
  28. $links = array();
  29. if ($vids = xmlsitemap_taxonomy_get_vids()) {
  30. $sql = "SELECT t.tid FROM {term_data} t WHERE t.tid > :tid AND t.vid IN (:vids) ORDER BY t.tid";
  31. $args = array(':tid' => $offset, ':vids' => $vids);
  32. $tids = ($limit ? db_query_range($sql, 0, $limit, $args) : db_query($sql, $args));
  33. foreach ($tids as $tid) {
  34. $term = xmlsitemap_taxonomy_taxonomy_term_load($tid);
  35. $links[] = xmlsitemap_taxonomy_create_link($term);
  36. }
  37. }
  38. return $links;
  39. }
  40. /**
  41. * Implements hook_xmlsitemap_links_batch_info().
  42. */
  43. function xmlsitemap_taxonomy_xmlsitemap_links_batch_info() {
  44. $vids = xmlsitemap_taxonomy_get_vids();
  45. return array(
  46. 'max' => $vids ? db_query("SELECT COUNT(t.tid) FROM {term_data} t WHERE t.vid IN (:vids)", array(':vids' => $vids))->fetchField() : 0,
  47. );
  48. }
  49. /**
  50. * Implements hook_xmlsitemap_link_info().
  51. */
  52. function xmlsitemap_taxonomy_xmlsitemap_link_info() {
  53. return array(
  54. 'taxononomy' => array(
  55. 'purge' => TRUE,
  56. 'table' => 'term_data',
  57. 'id' => 'tid',
  58. 'subtype' => 'vid',
  59. 'subtypes' => xmlsitemap_taxonomy_get_vids(),
  60. ),
  61. );
  62. }
  63. /**
  64. * Load a taxonomy term and its associated sitemap link data.
  65. *
  66. * Use this instead of taxonomy_get_term().
  67. *
  68. * @todo Convert this to hook_taxonomy_term_load() in Drupal 7.
  69. */
  70. function xmlsitemap_taxonomy_taxonomy_term_load($tid) {
  71. $term = taxonomy_get_term($tid);
  72. if ($data = xmlsitemap_load_link(array('type' => 'taxonomy_term', 'id' => $tid))) {
  73. $term->xmlsitemap = $data;
  74. }
  75. return $term;
  76. }
  77. /**
  78. * Implements hook_form_FORM_ID_alter().
  79. *
  80. * Show a summary of vocabularies on the XML sitemap settings page.
  81. */
  82. function xmlsitemap_taxonomy_form_xmlsitemap_settings_form_alter(&$form, $form_state) {
  83. $type = array(
  84. 'type' => 'taxonomy_term',
  85. 'title' => t('Taxonomy'),
  86. 'item_title' => t('Vocabulary'),
  87. 'access' => user_access('administer taxonomy'),
  88. );
  89. $vocabularies = taxonomy_get_vocabularies();
  90. foreach ($vocabularies as $vid => $vocabulary) {
  91. $vocabularies[$vid] = array(
  92. 'name' => $vocabulary->name,
  93. 'link' => 'admin/content/taxonomy/edit/vocabulary/' . $vid,
  94. 'status' => xmlsitemap_taxonomy_var('status_' . $vid),
  95. 'priority' => xmlsitemap_taxonomy_var('priority_' . $vid),
  96. );
  97. }
  98. xmlsitemap_add_form_type_summary($form, $type, $vocabularies);
  99. $form['taxonomy_term']['#weight'] = 40;
  100. }
  101. /**
  102. * Implements hook_form_FORM_ID_alter().
  103. *
  104. * @see taxonomy_form_vocabulary()
  105. * @see xmlsitemap_add_form_type_options()
  106. */
  107. function xmlsitemap_taxonomy_form_taxonomy_form_vocabulary_alter(&$form, $form_state) {
  108. $vid = isset($form['vid']['#value']) ? $form['vid']['#value'] : 0;
  109. module_load_include('inc', 'xmlsitemap', 'xmlsitemap.admin');
  110. $options = array(
  111. 'status' => variable_get('xmlsitemap_taxonomy_status_' . $vid, 0),
  112. 'priority' => variable_get('xmlsitemap_taxonomy_priority_' . $vid, 0.5),
  113. );
  114. xmlsitemap_add_form_type_options($form, 'taxonomy', $options);
  115. // @todo Enable these features:
  116. //$form['xmlsitemap']['xmlsitemap_taxonomy_calculate_priority'] = array(
  117. // '#type' => 'checkbox',
  118. // '#title' => t('Calculate priority based on term depth and weight.'),
  119. // '#default_value' => xmlsitemap_taxonomy_var('calculate_priority_' . $vid),
  120. //);
  121. //$form['xmlsitemap']['xmlsitemap_taxonomy_include_empty_terms'] = array(
  122. // '#type' => 'checkbox',
  123. // '#title' => t('Include terms that do not have any associated content.'),
  124. // '#default_value' => xmlsitemap_taxonomy_var('include_empty_terms_' . $vid),
  125. //);
  126. // The submit and delete buttons need to be weighted down.
  127. $form['submit'] += array('#weight' => 50);
  128. if (isset($form['delete'])) {
  129. $form['delete'] += array('#weight' => 51);
  130. }
  131. $form['#submit'][] = 'xmlsitemap_taxonomy_taxonomy_form_vocabulary_submit';
  132. }
  133. /**
  134. * Form submit handler; update settings when a taxonomy vocabulary is saved.
  135. */
  136. function xmlsitemap_taxonomy_taxonomy_form_vocabulary_submit($form, $form_state) {
  137. $vid = $form_state['values']['vid'];
  138. $new_status = $form_state['values']['xmlsitemap_taxonomy_status'];
  139. $new_priority = $form_state['values']['xmlsitemap_taxonomy_priority'];
  140. if ($new_status != variable_get('xmlsitemap_taxonomy_status_' . $vid, 0)) {
  141. xmlsitemap_update_links(array('status' => $new_status), array('type' => 'taxonomy_term', 'subtype' => $vid, 'status_override' => 0));
  142. }
  143. if ($new_priority != variable_get('xmlsitemap_taxonomy_priority_' . $vid, 0.5)) {
  144. xmlsitemap_update_links(array('priority' => $new_priority), array('type' => 'taxonomy_term', 'subtype' => $vid, 'priority_override' => 0));
  145. }
  146. variable_set('xmlsitemap_taxonomy_status_' . $vid, $new_status);
  147. variable_set('xmlsitemap_taxonomy_priority_' . $vid, $new_priority);
  148. }
  149. /**
  150. * Implements hook_form_FORM_ID_alter().
  151. */
  152. function xmlsitemap_taxonomy_form_taxonomy_form_term_alter(&$form, $form_state) {
  153. // Because the same form is used for deletion in confirm_form, we must check
  154. // if the normal editing form elements are present. Hopefully this is fixed
  155. // in Drupal 7.
  156. if (isset($form['identification'])) {
  157. if ($form['#term']['tid']) {
  158. $term = xmlsitemap_taxonomy_taxonomy_term_load($form['#term']['tid']);
  159. }
  160. else {
  161. $term = (object) $form['#term'];
  162. }
  163. $term->vid = $form['vid']['#value'];
  164. $link = xmlsitemap_taxonomy_create_link($term);
  165. // Add the link options.
  166. module_load_include('inc', 'xmlsitemap', 'xmlsitemap.admin');
  167. xmlsitemap_add_form_link_options($form, $link);
  168. $form['xmlsitemap']['#access'] |= user_access('administer taxonomy');
  169. if (user_access('administer taxonomy')) {
  170. $form['xmlsitemap']['#description'] = t('The default priority for this vocabulary can be changed <a href="@link-type">here</a>.', array('@link-type' => url('admin/content/taxonomy/edit/vocabulary/' . $term->vid, array('query' => drupal_get_destination()))));
  171. }
  172. // The submit and delete buttons need to be weighted down.
  173. $form['submit'] += array('#weight' => 50);
  174. if (isset($form['delete'])) {
  175. $form['delete'] += array('#weight' => 51);
  176. }
  177. }
  178. }
  179. /**
  180. * Implements hook_taxonomy().
  181. */
  182. function xmlsitemap_taxonomy_taxonomy($op, $type, $array = NULL) {
  183. if ($type == 'vocabulary') {
  184. $vid = $array['vid'];
  185. // Insert and update actions handled by xmlsitemap_taxonomy_taxonomy_form_vocabulary_submit().
  186. if ($op == 'delete') {
  187. xmlsitemap_delete_link(array('type' => 'taxonomy_term', 'subtype' => $vid));
  188. variable_del('xmlsitemap_taxonomy_status_' . $vid);
  189. variable_del('xmlsitemap_taxonomy_priority_' . $vid);
  190. }
  191. }
  192. if ($type == 'term') {
  193. $tid = $array['tid'];
  194. if ($op == 'insert' || $op == 'update') {
  195. $link = xmlsitemap_taxonomy_create_link((object) $array);
  196. xmlsitemap_save_link($link);
  197. }
  198. elseif ($op == 'delete') {
  199. xmlsitemap_delete_link(array('type' => 'taxonomy_term', 'id' => $tid));
  200. }
  201. }
  202. }
  203. /**
  204. * Create a sitemap link from a taxonomy term.
  205. *
  206. * @param $term
  207. * A taxonomy term object.
  208. * @return
  209. * An array representing a sitemap link.
  210. */
  211. function xmlsitemap_taxonomy_create_link(stdClass $term) {
  212. if (!isset($term->xmlsitemap)) {
  213. $term->xmlsitemap = array();
  214. }
  215. $term->xmlsitemap += array(
  216. 'id' => $term->tid,
  217. 'type' => 'taxonomy_term',
  218. 'subtype' => $term->vid,
  219. 'loc' => taxonomy_term_path($term),
  220. 'status' => variable_get('xmlsitemap_taxonomy_status_' . $term->vid, 0),
  221. 'status_default' => variable_get('xmlsitemap_taxonomy_status_' . $term->vid, 0),
  222. 'status_override' => 0,
  223. 'priority' => variable_get('xmlsitemap_taxonomy_priority_' . $term->vid, 0.5),
  224. 'priority_default' => variable_get('xmlsitemap_taxonomy_priority_' . $term->vid, 0.5),
  225. 'priority_override' => 0,
  226. );
  227. // The following values must always be checked because they are volatile.
  228. // @todo How can/should we check taxonomy term access?
  229. $term->xmlsitemap['access'] = 1;
  230. $term->xmlsitemap['language'] = isset($term->language) ? $term->language : LANGUAGE_NONE;
  231. return $term->xmlsitemap;
  232. }
  233. /**
  234. * Calculate the priority of a taxonomy term based on depth and weight.
  235. */
  236. function xmlsitemap_taxonomy_calculate_term_priority($term) {
  237. // Calculate priority.
  238. // Min weight = -128
  239. // Max weight = 127
  240. // Max depth = ?
  241. return NULL;
  242. }
  243. /**
  244. * Find the tree depth of a taxonomy term.
  245. *
  246. * @param $tid
  247. * A term ID.
  248. * @return
  249. * The tree depth of the term.
  250. */
  251. function xmlsitemap_taxonomy_get_term_depth($tid) {
  252. static $depths = array();
  253. if (!isset($depths[$tid])) {
  254. if ($parent = db_query("SELECT parent FROM {term_hierarchy} WHERE tid = %d", $tid)->fetchField()) {
  255. // If the term has a parent, the term's depth is the parent's depth + 1.
  256. if (!isset($depths[$parent])) {
  257. $depths[$parent] = xmlsitemap_taxonomy_get_term_depth($parent);
  258. }
  259. $depths[$tid] = $depths[$parent] + 1;
  260. }
  261. else {
  262. // Term has no parents, so depth is 0.
  263. $depths[$tid] = 0;
  264. }
  265. }
  266. return $depths[$tid];
  267. }
  268. function xmlsitemap_taxonomy_get_node_count($term) {
  269. // @todo Use db_rewrite_sql() w/ switch user.
  270. return db_query_range("SELECT COUNT(tn.nid) FROM {term_node} tn LEFT JOIN {node n} USING (nid) WHERE tn.tid = :tid AND n.status = 1", 0, 1, array(':tid' => $term->tid))->fetchField();
  271. }
  272. /**
  273. * Fetch an array of vocabulary IDs to be included in the sitemap.
  274. */
  275. function xmlsitemap_taxonomy_get_vids() {
  276. $vids = array_keys(taxonomy_get_vocabularies());
  277. foreach ($vids as $index => $vid) {
  278. if (!variable_get('xmlsitemap_taxonomy_status_' . $vid, 0)) {
  279. unset($vids[$index]);
  280. }
  281. }
  282. return $vids;
  283. }
  284. /**
  285. * Internal default variables for template_var().
  286. */
  287. function xmlsitemap_taxonomy_variables() {
  288. $defaults = array(
  289. // Removed variables set to NULL.
  290. 'xmlsitemap_taxonomy_include_empty_terms' => NULL,
  291. 'xmlsitemap_taxonomy_calculate_priority' => NULL,
  292. );
  293. $vids = array_keys(taxonomy_get_vocabularies());
  294. foreach ($vids as $vid) {
  295. $defaults['xmlsitemap_taxonomy_status_' . $vid] = 0;
  296. $defaults['xmlsitemap_taxonomy_priority_' . $vid] = '0.5';
  297. $defaults['xmlsitemap_taxonomy_calculate_priority_' . $vid] = FALSE;
  298. $defaults['xmlsitemap_taxonomy_include_empty_terms_' . $vid] = FALSE;
  299. //$defaults += _xmlsitemap_taxonomy_variables_vid($vid);
  300. }
  301. return $defaults;
  302. }
  303. //function _xmlsitemap_taxonomy_variables_vid($vid) {
  304. // $defaults = array();
  305. // $defaults['xmlsitemap_taxonomy_status_' . $vid] = 0;
  306. // $defaults['xmlsitemap_taxonomy_priority_' . $vid] = 0.5;
  307. // $defaults['xmlsitemap_taxonomy_calculate_priority_' . $vid] = FALSE;
  308. // $defaults['xmlsitemap_taxonomy_include_empty_terms_' . $vid] = TRUE;
  309. // return $defaults;
  310. //}
  311. /**
  312. * Internal implementation of variable_get().
  313. */
  314. function xmlsitemap_taxonomy_var($name, $default = NULL) {
  315. static $defaults = NULL;
  316. if (!isset($defaults)) {
  317. $defaults = xmlsitemap_taxonomy_variables();
  318. }
  319. $name = 'xmlsitemap_taxonomy_' . $name;
  320. // @todo Remove when stable.
  321. if (!isset($defaults[$name])) {
  322. trigger_error(t('Default variable for %variable not found.', array('%variable' => $name)));
  323. }
  324. return variable_get($name, isset($default) || !isset($defaults[$name]) ? $default : $defaults[$name]);
  325. }