taxonomy_wrangler.admin.inc 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291
  1. <?php
  2. /**
  3. * @file
  4. * Administrative page callbacks for the taxonomy ui tweaks module.
  5. */
  6. /**
  7. * Form builder for the taxonomy tweaks terms overview.
  8. *
  9. * Display a tree of all the terms in a vocabulary, with options to edit
  10. * each one. The form is made drag and drop by the theme function.
  11. *
  12. * @ingroup forms
  13. * @see taxonomy_overview_terms_submit()
  14. * @see theme_taxonomy_overview_terms()
  15. */
  16. function taxonomy_wrangler_overview_terms($form, &$form_state, $vocabulary) {
  17. global $pager_page_array, $pager_total, $pager_total_items;
  18. // Check for confirmation forms.
  19. if (isset($form_state['confirm_reset_alphabetical'])) {
  20. module_load_include('inc', 'taxonomy', 'taxonomy.admin');
  21. return taxonomy_vocabulary_confirm_reset_alphabetical($form, $form_state, $vocabulary->vid);
  22. }
  23. $form['#vocabulary'] = $vocabulary;
  24. $form['#tree'] = TRUE;
  25. $form['#parent_fields'] = FALSE;
  26. $form['header']['info'] = array(
  27. '#markup' => '<p>' . t('Drag and drop taxonomy terms below. Ctrl + click on an arrow will expand the term and all its children') . '</p>',
  28. );
  29. $form['header']['messages'] = array(
  30. '#markup' => '<div id="taxonomy-wrangler-messages"><div id="taxonomy-wrangler-messages-server"></div><div id="taxonomy-wrangler-messages-js"></div></div>',
  31. );
  32. $root_entries = 0; // Elements at the root level on this page.
  33. $delta = 0;
  34. $term_deltas = array();
  35. $tree = taxonomy_get_tree($vocabulary->vid);
  36. $form_state['storage']['tree'] = $tree;
  37. $term = current($tree);
  38. $form['taxonomy_wrangler_messages'] = array(
  39. '#type' => 'markup',
  40. '#markup' => '',
  41. );
  42. // The original form handled setting the order after a validation error.
  43. // Since we aren't supporting the non-ajax form, it has been removed.
  44. // Build the actual form.
  45. foreach ($tree as $orig_key => $term) {
  46. $term_deltas[$term->tid] = isset($term_deltas[$term->tid]) ? $term_deltas[$term->tid] + 1 : 0;
  47. $key = 'tid:' . $term->tid . ':' . $term_deltas[$term->tid];
  48. // Save the term for the current page so we don't have to load it a second time.
  49. $form[$key]['#term'] = (array) $term;
  50. if (isset($term->parents)) {
  51. $form[$key]['#term']['parent'] = $term->parent = $term->parents[0];
  52. unset($form[$key]['#term']['parents'], $term->parents);
  53. }
  54. $form[$key]['view'] = array('#type' => 'link', '#title' => $term->name, '#href' => "taxonomy/term/$term->tid");
  55. if ($vocabulary->hierarchy < 2 && count($tree) > 1) {
  56. $form['#parent_fields'] = TRUE;
  57. $form[$key]['view']['#options']['attributes']['data-tid'] = $term->tid;
  58. $form[$key]['view']['#options']['attributes']['data-parent'] = $term->tid;
  59. $form[$key]['view']['#options']['attributes']['data-depth'] = $term->depth;
  60. $form[$key]['view']['#options']['attributes']['data-weight'] = $term->weight;
  61. }
  62. $form[$key]['edit'] = array('#type' => 'link', '#title' => t('edit'), '#href' => 'taxonomy/term/' . $term->tid . '/edit', '#options' => array('query' => drupal_get_destination()));
  63. }
  64. $form['#empty_text'] = t('No terms available. <a href="@link">Add term</a>.', array('@link' => url('admin/structure/taxonomy/' . $vocabulary->machine_name . '/add')));
  65. // Hidden input field for ajax.
  66. $form['term_data'] = array(
  67. '#type' => 'hidden',
  68. '#default_value' => '{}',
  69. );
  70. if ($vocabulary->hierarchy < 2 && count($tree) > 1) {
  71. $form['actions'] = array('#type' => 'actions', '#tree' => FALSE);
  72. $form['actions']['submit'] = array(
  73. '#type' => 'submit',
  74. '#value' => t('Save'),
  75. '#ajax' => array(
  76. 'callback' => 'taxonomy_wrangler_terms_overview_ajax_handler',
  77. ),
  78. );
  79. $form['actions']['reset_alphabetical'] = array(
  80. '#type' => 'submit',
  81. '#value' => t('Reset to alphabetical'),
  82. );
  83. }
  84. $module_path = drupal_get_path('module', 'taxonomy_wrangler');
  85. $form['#attached']['css'][] = $module_path . '/css/taxonomy_wrangler.css';
  86. $form['#attached']['js'][] = $module_path . '/js/taxonomy_wrangler.js';
  87. return $form;
  88. }
  89. /**
  90. * Validate callback for taxonomy_wrangler_overview_terms.
  91. */
  92. function taxonomy_wrangler_overview_terms_validate($form, &$form_state) {
  93. if ($form_state['triggering_element']['#value'] != t('Reset to alphabetical')) {
  94. if (isset($form_state['values']['term_data'])) {
  95. $updated_terms_json = json_decode($form_state['values']['term_data']);
  96. if ($updated_terms_json == NULL) {
  97. drupal_set_message(t('an error occurred parsing submitted values.'), 'error');
  98. }
  99. else {
  100. $form_state['storage']['updated_terms'] = array();
  101. $values_to_update = array('parent', 'weight');
  102. if (!empty($updated_terms_json->termData)) {
  103. $form_state['storage']['raw_term_data'] = $updated_terms_json->termData;
  104. foreach ($updated_terms_json->termData as $updated_term) {
  105. $term = taxonomy_term_load($updated_term->tid);
  106. foreach ($values_to_update as $prop) {
  107. if (isset($updated_term->{$prop})) {
  108. $term->{$prop} = (int) $updated_term->{$prop};
  109. }
  110. }
  111. $form_state['storage']['updated_terms'][$term->tid] = $term;
  112. }
  113. }
  114. }
  115. }
  116. }
  117. }
  118. /**
  119. * Submit callback for taxonomy_wrangler_overview_terms.
  120. */
  121. function taxonomy_wrangler_overview_terms_submit($form, &$form_state) {
  122. if ($form_state['triggering_element']['#value'] == t('Reset to alphabetical')) {
  123. module_load_include('inc', 'taxonomy', 'taxonomy.admin');
  124. // Execute the reset action.
  125. if ($form_state['values']['reset_alphabetical'] === TRUE) {
  126. return taxonomy_vocabulary_confirm_reset_alphabetical_submit($form, $form_state);
  127. }
  128. // Rebuild the form to confirm the reset action.
  129. $form_state['rebuild'] = TRUE;
  130. $form_state['confirm_reset_alphabetical'] = TRUE;
  131. return;
  132. }
  133. else {
  134. if (!empty($form_state['storage']['updated_terms'])) {
  135. foreach ($form_state['storage']['updated_terms'] as $term) {
  136. taxonomy_term_save($term);
  137. }
  138. }
  139. }
  140. }
  141. /**
  142. * Ajax handler for taxonomy_wrangler_overview_terms.
  143. */
  144. function taxonomy_wrangler_terms_overview_ajax_handler($form, &$form_state) {
  145. $commands = array();
  146. $messages = '<div id="taxonomy-wrangler-messages-server">';
  147. $messages .= theme('status_messages');
  148. $messages .= '</div>';
  149. $commands[] = ajax_command_replace('#taxonomy-wrangler-messages-server', $messages);
  150. // Send timestamps back to browser so it can update the row status.
  151. $timestamps = array();
  152. if (!empty($form_state['storage']['raw_term_data'])) {
  153. foreach($form_state['storage']['raw_term_data'] as $term) {
  154. if (isset($term->updated)) {
  155. $timestamps[$term->tid] = (float) $term->updated;
  156. }
  157. }
  158. }
  159. $commands[] = ajax_command_settings(array(
  160. 'taxonomyWrangler' => array('updatedTimestamps' => $timestamps),
  161. ));
  162. return array('#type' => 'ajax', '#commands' => $commands);
  163. }
  164. /**
  165. * Returns HTML for a terms overview form as a sortable list of terms.
  166. *
  167. * @param $variables
  168. * An associative array containing:
  169. * - form: A render element representing the form.
  170. *
  171. * @see taxonomy_overview_terms()
  172. * @ingroup themeable
  173. */
  174. function theme_taxonomy_wrangler_overview_terms($variables) {
  175. $form = $variables['form'];
  176. // Add drag and drop if parent fields are present in the form.
  177. if ($form['#parent_fields']) {
  178. taxonomy_wrangler_add_tabledrag('taxonomy-wrangler', 'match', 'parent', 'parent', 'parent', 'tid', FALSE);
  179. taxonomy_wrangler_add_tabledrag('taxonomy-wrangler', 'depth', 'group', 'depth', NULL, NULL, FALSE);
  180. drupal_add_css(drupal_get_path('module', 'taxonomy') . '/taxonomy.css');
  181. }
  182. taxonomy_wrangler_add_tabledrag('taxonomy-wrangler', 'order', 'sibling', 'weight');
  183. $errors = form_get_errors() != FALSE ? form_get_errors() : array();
  184. $rows = array();
  185. $element_children = element_children($form);
  186. $is_root = TRUE;
  187. foreach ($element_children as $i => $key) {
  188. if (isset($form[$key]['#term'])) {
  189. $term = &$form[$key];
  190. $next_key = isset($element_children[$i + 1]) ? $element_children[$i + 1] : FALSE;
  191. $is_parent = FALSE;
  192. if (isset($form[$next_key]['#term']) && $form[$next_key]['#term']['depth'] > $term['#term']['depth'] && !$is_root) {
  193. $is_parent = TRUE;
  194. }
  195. $row = array();
  196. $row[] = (isset($term['#term']['depth']) && $term['#term']['depth'] > 0 ? theme('indentation', array('size' => $term['#term']['depth'])) : '');
  197. $accordion_classes = array('taxonomy-wrangler-accordion-item');
  198. if ($is_root) {
  199. $accordion_classes[] = 'taxonomy-wrangler-accordion-item--root';
  200. $is_root = FALSE;
  201. }
  202. elseif ($is_parent) {
  203. $accordion_classes[] = 'taxonomy-wrangler-accordion-item--parent';
  204. }
  205. else {
  206. $accordion_classes[] = 'taxonomy-wrangler-accordion-item--child';
  207. }
  208. $row[0] .= '<a href="#" class="' . implode(' ', $accordion_classes) . '"><span></span></a>';
  209. $row[0] .= drupal_render($term['view']);
  210. if ($form['#parent_fields']) {
  211. $term['tid']['#attributes']['class'] = array('term-id');
  212. $term['parent']['#attributes']['class'] = array('term-parent');
  213. $term['depth']['#attributes']['class'] = array('term-depth');
  214. $row[0] .= drupal_render($term['parent']) . drupal_render($term['tid']) . drupal_render($term['depth']);
  215. }
  216. $term['weight']['#attributes']['class'] = array('term-weight');
  217. $row[] = drupal_render($term['weight']);
  218. $row[] = drupal_render($term['edit']);
  219. $row = array(
  220. 'data' => $row,
  221. 'data-tid' => $term['#term']['tid'],
  222. 'data-parent' => $term['#term']['parent'],
  223. 'data-depth' => $term['#term']['depth'],
  224. 'data-weight' => $term['#term']['weight'],
  225. 'data-haschildren' => $is_parent,
  226. );
  227. $rows[$key] = $row;
  228. }
  229. }
  230. // Add necessary classes to rows.
  231. $row_position = 0;
  232. foreach ($rows as $key => $row) {
  233. $rows[$key]['class'] = array();
  234. if (isset($form['#parent_fields'])) {
  235. $rows[$key]['class'][] = 'draggable';
  236. }
  237. // Add an error class if this row contains a form error.
  238. foreach ($errors as $error_key => $error) {
  239. if (strpos($error_key, $key) === 0) {
  240. $rows[$key]['class'][] = 'error';
  241. }
  242. }
  243. $rows[$key]['class'][] = 'taxonomy-wrangler-term-row';
  244. $rows[$key]['class'][] = 'term-weight-row';
  245. $row_position++;
  246. }
  247. if (empty($rows)) {
  248. $rows[] = array(array('data' => $form['#empty_text'], 'colspan' => '3'));
  249. }
  250. $output = drupal_render($form['header']);
  251. //unset($form['header']);
  252. $header = array(t('Name'), t('Weight'), t('Operations'));
  253. $output .= theme('table', array(
  254. 'header' => $header,
  255. 'rows' => $rows,
  256. 'attributes' => array(
  257. 'id' => 'taxonomy-wrangler',
  258. 'class' => array('taxonomy-wrangler', 'taxonomy-wrangler-accordion'),
  259. ),
  260. ));
  261. $output .= drupal_render_children($form);
  262. return $output;
  263. }