book.admin.inc 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289
  1. <?php
  2. /**
  3. * @file
  4. * Administration page callbacks for the Book module.
  5. */
  6. /**
  7. * Returns an administrative overview of all books.
  8. *
  9. * @return string
  10. * A HTML-formatted string with the administrative page content.
  11. *
  12. * @see book_menu()
  13. */
  14. function book_admin_overview() {
  15. $rows = array();
  16. $headers = array(t('Book'), t('Operations'));
  17. // Add any recognized books to the table list.
  18. foreach (book_get_books() as $book) {
  19. $rows[] = array(l($book['title'], $book['href'], $book['options']), l(t('edit order and titles'), 'admin/content/book/' . $book['nid']));
  20. }
  21. return theme('table', array('header' => $headers, 'rows' => $rows, 'empty' => t('No books available.')));
  22. }
  23. /**
  24. * Form constructor for the book settings form.
  25. *
  26. * @see book_admin_settings_validate()
  27. *
  28. * @ingroup forms
  29. */
  30. function book_admin_settings() {
  31. $types = node_type_get_names();
  32. $form['book_allowed_types'] = array(
  33. '#type' => 'checkboxes',
  34. '#title' => t('Content types allowed in book outlines'),
  35. '#default_value' => variable_get('book_allowed_types', array('book')),
  36. '#options' => $types,
  37. '#description' => t('Users with the %outline-perm permission can add all content types.', array('%outline-perm' => t('Administer book outlines'))),
  38. '#required' => TRUE,
  39. );
  40. $form['book_child_type'] = array(
  41. '#type' => 'radios',
  42. '#title' => t('Content type for child pages'),
  43. '#default_value' => variable_get('book_child_type', 'book'),
  44. '#options' => $types,
  45. '#required' => TRUE,
  46. );
  47. $form['array_filter'] = array('#type' => 'value', '#value' => TRUE);
  48. $form['#validate'][] = 'book_admin_settings_validate';
  49. return system_settings_form($form);
  50. }
  51. /**
  52. * Form validation handler for book_admin_settings().
  53. *
  54. * @see book_admin_settings_submit()
  55. */
  56. function book_admin_settings_validate($form, &$form_state) {
  57. $child_type = $form_state['values']['book_child_type'];
  58. if (empty($form_state['values']['book_allowed_types'][$child_type])) {
  59. form_set_error('book_child_type', t('The content type for the %add-child link must be one of those selected as an allowed book outline type.', array('%add-child' => t('Add child page'))));
  60. }
  61. }
  62. /**
  63. * Form constructor for administering a single book's hierarchy.
  64. *
  65. * @see book_admin_edit_submit()
  66. *
  67. * @param $node
  68. * The node of the top-level page in the book.
  69. *
  70. * @see book_admin_edit_validate()
  71. * @see book_admin_edit_submit()
  72. * @ingroup forms
  73. */
  74. function book_admin_edit($form, $form_state, $node) {
  75. drupal_set_title($node->title);
  76. $form['#node'] = $node;
  77. _book_admin_table($node, $form);
  78. $form['save'] = array(
  79. '#type' => 'submit',
  80. '#value' => t('Save book pages'),
  81. );
  82. return $form;
  83. }
  84. /**
  85. * Form validation handler for book_admin_edit().
  86. *
  87. * Checks that the book has not been changed while using the form.
  88. *
  89. * @see book_admin_edit_submit()
  90. */
  91. function book_admin_edit_validate($form, &$form_state) {
  92. if ($form_state['values']['tree_hash'] != $form_state['values']['tree_current_hash']) {
  93. form_set_error('', t('This book has been modified by another user, the changes could not be saved.'));
  94. }
  95. }
  96. /**
  97. * Form submission handler for book_admin_edit().
  98. *
  99. * This function takes care to save parent menu items before their children.
  100. * Saving menu items in the incorrect order can break the menu tree.
  101. *
  102. * @see book_admin_edit_validate()
  103. * @see menu_overview_form_submit()
  104. */
  105. function book_admin_edit_submit($form, &$form_state) {
  106. // Save elements in the same order as defined in post rather than the form.
  107. // This ensures parents are updated before their children, preventing orphans.
  108. $order = array_flip(array_keys($form_state['input']['table']));
  109. $form['table'] = array_merge($order, $form['table']);
  110. foreach (element_children($form['table']) as $key) {
  111. if ($form['table'][$key]['#item']) {
  112. $row = $form['table'][$key];
  113. $values = $form_state['values']['table'][$key];
  114. // Update menu item if moved.
  115. if ($row['plid']['#default_value'] != $values['plid'] || $row['weight']['#default_value'] != $values['weight']) {
  116. $row['#item']['plid'] = $values['plid'];
  117. $row['#item']['weight'] = $values['weight'];
  118. menu_link_save($row['#item']);
  119. }
  120. // Update the title if changed.
  121. if ($row['title']['#default_value'] != $values['title']) {
  122. $node = node_load($values['nid']);
  123. $langcode = LANGUAGE_NONE;
  124. $node->title = $values['title'];
  125. $node->book['link_title'] = $values['title'];
  126. $node->revision = 1;
  127. $node->log = t('Title changed from %original to %current.', array('%original' => $node->title, '%current' => $values['title']));
  128. node_save($node);
  129. watchdog('content', 'book: updated %title.', array('%title' => $node->title), WATCHDOG_NOTICE, l(t('view'), 'node/' . $node->nid));
  130. }
  131. }
  132. }
  133. drupal_set_message(t('Updated book %title.', array('%title' => $form['#node']->title)));
  134. }
  135. /**
  136. * Builds the table portion of the form for the book administration page.
  137. *
  138. * @param $node
  139. * The node of the top-level page in the book.
  140. * @param $form
  141. * The form that is being modified, passed by reference.
  142. *
  143. * @see book_admin_edit()
  144. */
  145. function _book_admin_table($node, &$form) {
  146. $form['table'] = array(
  147. '#theme' => 'book_admin_table',
  148. '#tree' => TRUE,
  149. );
  150. $tree = book_menu_subtree_data($node->book);
  151. $tree = array_shift($tree); // Do not include the book item itself.
  152. if ($tree['below']) {
  153. $hash = drupal_hash_base64(serialize($tree['below']));
  154. // Store the hash value as a hidden form element so that we can detect
  155. // if another user changed the book hierarchy.
  156. $form['tree_hash'] = array(
  157. '#type' => 'hidden',
  158. '#default_value' => $hash,
  159. );
  160. $form['tree_current_hash'] = array(
  161. '#type' => 'value',
  162. '#value' => $hash,
  163. );
  164. _book_admin_table_tree($tree['below'], $form['table']);
  165. }
  166. }
  167. /**
  168. * Helps build the main table in the book administration page form.
  169. *
  170. * @param $tree
  171. * A subtree of the book menu hierarchy.
  172. * @param $form
  173. * The form that is being modified, passed by reference.
  174. *
  175. * @return
  176. * The modified form array.
  177. *
  178. * @see book_admin_edit()
  179. */
  180. function _book_admin_table_tree($tree, &$form) {
  181. // The delta must be big enough to give each node a distinct value.
  182. $count = count($tree);
  183. $delta = ($count < 30) ? 15 : intval($count / 2) + 1;
  184. foreach ($tree as $data) {
  185. $form['book-admin-' . $data['link']['nid']] = array(
  186. '#item' => $data['link'],
  187. 'nid' => array('#type' => 'value', '#value' => $data['link']['nid']),
  188. 'depth' => array('#type' => 'value', '#value' => $data['link']['depth']),
  189. 'href' => array('#type' => 'value', '#value' => $data['link']['href']),
  190. 'title' => array(
  191. '#type' => 'textfield',
  192. '#default_value' => $data['link']['link_title'],
  193. '#maxlength' => 255,
  194. '#size' => 40,
  195. ),
  196. 'weight' => array(
  197. '#type' => 'weight',
  198. '#default_value' => $data['link']['weight'],
  199. '#delta' => max($delta, abs($data['link']['weight'])),
  200. '#title' => t('Weight for @title', array('@title' => $data['link']['title'])),
  201. '#title_display' => 'invisible',
  202. ),
  203. 'plid' => array(
  204. '#type' => 'hidden',
  205. '#default_value' => $data['link']['plid'],
  206. ),
  207. 'mlid' => array(
  208. '#type' => 'hidden',
  209. '#default_value' => $data['link']['mlid'],
  210. ),
  211. );
  212. if ($data['below']) {
  213. _book_admin_table_tree($data['below'], $form);
  214. }
  215. }
  216. return $form;
  217. }
  218. /**
  219. * Returns HTML for a book administration form.
  220. *
  221. * @param $variables
  222. * An associative array containing:
  223. * - form: A render element representing the form.
  224. *
  225. * @see book_admin_table()
  226. * @ingroup themeable
  227. */
  228. function theme_book_admin_table($variables) {
  229. $form = $variables['form'];
  230. drupal_add_tabledrag('book-outline', 'match', 'parent', 'book-plid', 'book-plid', 'book-mlid', TRUE, MENU_MAX_DEPTH - 2);
  231. drupal_add_tabledrag('book-outline', 'order', 'sibling', 'book-weight');
  232. $header = array(t('Title'), t('Weight'), t('Parent'), array('data' => t('Operations'), 'colspan' => '3'));
  233. $rows = array();
  234. $destination = drupal_get_destination();
  235. $access = user_access('administer nodes');
  236. foreach (element_children($form) as $key) {
  237. $nid = $form[$key]['nid']['#value'];
  238. $href = $form[$key]['href']['#value'];
  239. // Add special classes to be used with tabledrag.js.
  240. $form[$key]['plid']['#attributes']['class'] = array('book-plid');
  241. $form[$key]['mlid']['#attributes']['class'] = array('book-mlid');
  242. $form[$key]['weight']['#attributes']['class'] = array('book-weight');
  243. $data = array(
  244. theme('indentation', array('size' => $form[$key]['depth']['#value'] - 2)) . drupal_render($form[$key]['title']),
  245. drupal_render($form[$key]['weight']),
  246. drupal_render($form[$key]['plid']) . drupal_render($form[$key]['mlid']),
  247. l(t('view'), $href),
  248. $access ? l(t('edit'), 'node/' . $nid . '/edit', array('query' => $destination)) : '&nbsp;',
  249. $access ? l(t('delete'), 'node/' . $nid . '/delete', array('query' => $destination) ) : '&nbsp;',
  250. );
  251. $row = array('data' => $data);
  252. if (isset($form[$key]['#attributes'])) {
  253. $row = array_merge($row, $form[$key]['#attributes']);
  254. }
  255. $row['class'][] = 'draggable';
  256. $rows[] = $row;
  257. }
  258. return theme('table', array('header' => $header, 'rows' => $rows, 'attributes' => array('id' => 'book-outline'), 'empty' => t('No book content available.')));
  259. }