Code coverage for /20080809/modules/book/book.pages.inc

Line #Times calledCode
1
<?php
2
// $Id: book.pages.inc,v 1.7 2008/05/15 21:19:24 dries Exp $
3
4
/**
5
 * @file
6
 * User page callbacks for the book module.
7
 */
8
9
/**
10
 * Menu callback; prints a listing of all books.
11
 */
126
function book_render() {
130
  $book_list = array();
140
  foreach (book_get_books() as $book) {
150
    $book_list[] = l($book['title'], $book['href'], $book['options']);
160
  }
17
180
  return theme('item_list', $book_list);
190
}
20
21
/**
22
 * Menu callback; Generates various representation of a book page and its
children.
23
 *
24
 * The function delegates the generation of output to helper functions.
25
 * The function name is derived by prepending 'book_export_' to the
26
 * given output type. So, e.g., a type of 'html' results in a call to
27
 * the function book_export_html().
28
 *
29
 * @param $type
30
 *   A string encoding the type of output requested. The following
31
 *   types are currently supported in book module:
32
 *
33
 *   - html: HTML (printer friendly output)
34
 *
35
 *   Other types may be supported in contributed modules.
36
 * @param $nid
37
 *   An integer representing the node id (nid) of the node to export
38
 * @return
39
 *   A string representing the node and its children in the book hierarchy
40
 *   in a format determined by the $type parameter.
41
 */
426
function book_export($type, $nid) {
436
  $type = drupal_strtolower($type);
44
456
  $export_function = 'book_export_' . $type;
46
476
  if (function_exists($export_function)) {
486
    print call_user_func($export_function, $nid);
496
  }
50
  else {
510
    drupal_set_message(t('Unknown export format.'));
520
    drupal_not_found();
53
  }
546
}
55
56
/**
57
 * This function is called by book_export() to generate HTML for export.
58
 *
59
 * The given node is /embedded to its absolute depth in a top level
60
 * section/. For example, a child node with depth 2 in the hierarchy
61
 * is contained in (otherwise empty) &lt;div&gt; elements
62
 * corresponding to depth 0 and depth 1. This is intended to support
63
 * WYSIWYG output - e.g., level 3 sections always look like level 3
64
 * sections, no matter their depth relative to the node selected to be
65
 * exported as printer-friendly HTML.
66
 *
67
 * @param $nid
68
 *   An integer representing the node id (nid) of the node to export.
69
 * @return
70
 *   A string containing HTML representing the node and its children in
71
 *   the book hierarchy.
72
 */
736
function book_export_html($nid) {
746
  if (user_access('access printer-friendly version')) {
756
    $export_data = array();
766
    $node = node_load($nid);
776
    if (isset($node->book)) {
786
      $tree = book_menu_subtree_data($node->book);
796
      $contents = book_export_traverse($tree, 'book_node_export');
806
    }
81
826
    return theme('book_export_html', $node->title, $contents,
$node->book['depth']);
830
  }
84
  else {
850
    drupal_access_denied();
86
  }
870
}
88
89
/**
90
 * Menu callback; show the outline form for a single node.
91
 */
926
function book_outline($node) {
930
  drupal_set_title(check_plain($node->title));
940
  return drupal_get_form('book_outline_form', $node);
950
}
96
97
/**
98
 * Build the form to handle all book outline operations via the outline
tab.
99
 *
100
 * @see book_outline_form_submit()
101
 * @see book_remove_button_submit()
102
 *
103
 * @ingroup forms
104
 */
1056
function book_outline_form(&$form_state, $node) {
1060
  if (!isset($node->book)) {
107
    // The node is not part of any book yet - set default options.
1080
    $node->book = _book_link_defaults($node->nid);
1090
  }
110
  else {
1110
    $node->book['original_bid'] = $node->book['bid'];
112
  }
113
114
  // Find the depth limit for the parent select.
1150
  if (!isset($node->book['parent_depth_limit'])) {
1160
    $node->book['parent_depth_limit'] =
_book_parent_depth_limit($node->book);
1170
  }
1180
  $form['#node'] = $node;
1190
  $form['#id'] = 'book-outline';
1200
  _book_add_form_elements($form, $node);
121
1220
  $form['book']['#collapsible'] = FALSE;
123
1240
  $form['update'] = array(
1250
    '#type' => 'submit',
1260
    '#value' => $node->book['original_bid'] ? t('Update book outline') :
t('Add to book outline'),
1270
    '#weight' => 15,
128
  );
129
1300
  $form['remove'] = array(
1310
    '#type' => 'submit',
1320
    '#value' => t('Remove from book outline'),
1330
    '#access' => $node->nid != $node->book['bid'] && $node->book['bid'],
1340
    '#weight' => 20,
1350
    '#submit' => array('book_remove_button_submit'),
136
  );
137
1380
  return $form;
1390
}
140
141
/**
142
 * Button submit function to redirect to removal confirm form.
143
 *
144
 * @see book_outline_form()
145
 */
1466
function book_remove_button_submit($form, &$form_state) {
1470
  $form_state['redirect'] = 'node/' . $form['#node']->nid .
'/outline/remove';
1480
}
149
150
/**
151
 * Handles book outline form submissions from the outline tab.
152
 *
153
 * @see book_outline_form()
154
 */
1556
function book_outline_form_submit($form, &$form_state) {
1560
  $node = $form['#node'];
1570
  $form_state['redirect'] = "node/" . $node->nid;
1580
  $book_link = $form_state['values']['book'];
1590
  if (!$book_link['bid']) {
1600
    drupal_set_message(t('No changes were made'));
161
1620
    return;
1630
  }
164
1650
  $book_link['menu_name'] = book_menu_name($book_link['bid']);
1660
  $node->book = $book_link;
1670
  if (_book_update_outline($node)) {
1680
    if ($node->book['parent_mismatch']) {
169
      // This will usually only happen when JS is disabled.
1700
      drupal_set_message(t('The post has been added to the selected book.
You may now position it relative to other pages.'));
1710
      $form_state['redirect'] = "node/" . $node->nid . "/outline";
1720
    }
173
    else {
1740
      drupal_set_message(t('The book outline has been updated.'));
175
    }
1760
  }
177
  else {
1780
    drupal_set_message(t('There was an error adding the post to the
book.'), 'error');
179
  }
1800
}
181
182
/**
183
 * Menu callback; builds a form to confirm removal of a node from the
book.
184
 *
185
 * @see book_remove_form_submit()
186
 *
187
 * @ingroup forms
188
 */
1896
function book_remove_form(&$form_state, $node) {
1900
  $form['#node'] = $node;
1910
  $title = array('%title' => $node->title);
192
1930
  if ($node->book['has_children']) {
1940
    $description = t('%title has associated child pages, which will be
relocated automatically to maintain their connection to the book. To
recreate the hierarchy (as it was before removing this page), %title may be
added again using the Outline tab, and each of its former child pages will
need to be relocated manually.', $title);
1950
  }
196
  else {
1970
    $description = t('%title may be added to hierarchy again using the
Outline tab.', $title);
198
  }
199
2000
  return confirm_form($form, t('Are you sure you want to remove %title from
the book hierarchy?', $title), 'node/' . $node->nid, $description,
t('Remove'));
2010
}
202
203
/**
204
 * Confirm form submit function to remove a node from the book.
205
 *
206
 * @see book_remove_form()
207
 */
2086
function book_remove_form_submit($form, &$form_state) {
2090
  $node = $form['#node'];
2100
  if ($node->nid != $node->book['bid']) {
211
    // Only allowed when this is not a book (top-level page).
2120
    menu_link_delete($node->book['mlid']);
2130
    db_query('DELETE FROM {book} WHERE nid = %d', $node->nid);
2140
    drupal_set_message(t('The post has been removed from the book.'));
2150
  }
2160
  $form_state['redirect'] = 'node/' . $node->nid;
2170
}
218
219
/**
220
 * AJAX callback to replace the book parent select options.
221
 *
222
 * This function is called when the selected book is changed.  It updates
the
223
 * cached form (either the node form or the book outline form) and returns
224
 * rendered output to be used to replace the select containing the
possible
225
 * parent pages in the newly selected book.
226
 *
227
 * @param $build_id
228
 *   The form's build_id.
229
 * @param $bid
230
 *   A bid from from among those in the form's book select.
231
 * @return
232
 *   Prints the replacement HTML in JSON format.
233
 */
2346
function book_form_update() {
2350
  $cid = 'form_' . $_POST['form_build_id'];
2360
  $bid = $_POST['book']['bid'];
2370
  $cache = cache_get($cid, 'cache_form');
2380
  if ($cache) {
2390
    $form = $cache->data;
240
241
    // Validate the bid.
2420
    if (isset($form['book']['bid']['#options'][$bid])) {
2430
      $book_link = $form['#node']->book;
2440
      $book_link['bid'] = $bid;
245
      // Get the new options and update the cache.
2460
      $form['book']['plid'] = _book_parent_select($book_link);
2470
      cache_set($cid, $form, 'cache_form', $cache->expire);
248
      // Build and render the new select element, then return it in JSON
format.
2490
      $form_state = array();
2500
      $form['#post'] = array();
2510
      $form = form_builder($form['form_id']['#value'] , $form,
$form_state);
2520
      $output = drupal_render($form['book']['plid']);
2530
      drupal_json(array('status' => TRUE, 'data' => $output));
2540
    }
255
    else {
2560
      drupal_json(array('status' => FALSE, 'data' => ''));
257
    }
2580
  }
259
  else {
2600
    drupal_json(array('status' => FALSE, 'data' => ''));
261
  }
2620
  exit();
2630
}
2646