| 1 | | <?php |
| 2 | | // $Id: book.pages.inc,v 1.11 2008/10/13 00:33:01 webchick 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 | | */ |
| 12 | 6 | function book_render() { |
| 13 | 0 | $book_list = array(); |
| 14 | 0 | foreach (book_get_books() as $book) { |
| 15 | 0 | $book_list[] = l($book['title'], $book['href'], $book['options']); |
| 16 | 0 | } |
| 17 | | |
| 18 | 0 | return theme('item_list', $book_list); |
| 19 | 0 | } |
| 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 | | */ |
| 42 | 6 | function book_export($type, $nid) { |
| 43 | 6 | $type = drupal_strtolower($type); |
| 44 | | |
| 45 | 6 | $export_function = 'book_export_' . $type; |
| 46 | | |
| 47 | 6 | if (function_exists($export_function)) { |
| 48 | 6 | print call_user_func($export_function, $nid); |
| 49 | 6 | } |
| 50 | | else { |
| 51 | 0 | drupal_set_message(t('Unknown export format.')); |
| 52 | 0 | drupal_not_found(); |
| 53 | | } |
| 54 | 6 | } |
| 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) <div> 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 | | */ |
| 73 | 6 | function book_export_html($nid) { |
| 74 | 6 | if (user_access('access printer-friendly version')) { |
| 75 | 6 | $export_data = array(); |
| 76 | 6 | $node = node_load($nid); |
| 77 | 6 | if (isset($node->book)) { |
| 78 | 6 | $tree = book_menu_subtree_data($node->book); |
| 79 | 6 | $contents = book_export_traverse($tree, 'book_node_export'); |
| 80 | 6 | } |
| 81 | | |
| 82 | 6 | return theme('book_export_html', $node->title, $contents,
$node->book['depth']); |
| 83 | 0 | } |
| 84 | | else { |
| 85 | 0 | drupal_access_denied(); |
| 86 | | } |
| 87 | 0 | } |
| 88 | | |
| 89 | | /** |
| 90 | | * Menu callback; show the outline form for a single node. |
| 91 | | */ |
| 92 | 6 | function book_outline($node) { |
| 93 | 0 | drupal_set_title($node->title); |
| 94 | 0 | return drupal_get_form('book_outline_form', $node); |
| 95 | 0 | } |
| 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 | | */ |
| 105 | 6 | function book_outline_form(&$form_state, $node) { |
| 106 | 0 | if (!isset($node->book)) { |
| 107 | | // The node is not part of any book yet - set default options. |
| 108 | 0 | $node->book = _book_link_defaults($node->nid); |
| 109 | 0 | } |
| 110 | | else { |
| 111 | 0 | $node->book['original_bid'] = $node->book['bid']; |
| 112 | | } |
| 113 | | |
| 114 | | // Find the depth limit for the parent select. |
| 115 | 0 | if (!isset($node->book['parent_depth_limit'])) { |
| 116 | 0 | $node->book['parent_depth_limit'] =
_book_parent_depth_limit($node->book); |
| 117 | 0 | } |
| 118 | 0 | $form['#node'] = $node; |
| 119 | 0 | $form['#id'] = 'book-outline'; |
| 120 | 0 | _book_add_form_elements($form, $node); |
| 121 | | |
| 122 | 0 | $form['book']['#collapsible'] = FALSE; |
| 123 | | |
| 124 | 0 | $form['update'] = array( |
| 125 | 0 | '#type' => 'submit', |
| 126 | 0 | '#value' => $node->book['original_bid'] ? t('Update book outline') :
t('Add to book outline'), |
| 127 | 0 | '#weight' => 15, |
| 128 | | ); |
| 129 | | |
| 130 | 0 | $form['remove'] = array( |
| 131 | 0 | '#type' => 'submit', |
| 132 | 0 | '#value' => t('Remove from book outline'), |
| 133 | 0 | '#access' => $node->nid != $node->book['bid'] && $node->book['bid'], |
| 134 | 0 | '#weight' => 20, |
| 135 | 0 | '#submit' => array('book_remove_button_submit'), |
| 136 | | ); |
| 137 | | |
| 138 | 0 | return $form; |
| 139 | 0 | } |
| 140 | | |
| 141 | | /** |
| 142 | | * Button submit function to redirect to removal confirm form. |
| 143 | | * |
| 144 | | * @see book_outline_form() |
| 145 | | */ |
| 146 | 6 | function book_remove_button_submit($form, &$form_state) { |
| 147 | 0 | $form_state['redirect'] = 'node/' . $form['#node']->nid .
'/outline/remove'; |
| 148 | 0 | } |
| 149 | | |
| 150 | | /** |
| 151 | | * Handles book outline form submissions from the outline tab. |
| 152 | | * |
| 153 | | * @see book_outline_form() |
| 154 | | */ |
| 155 | 6 | function book_outline_form_submit($form, &$form_state) { |
| 156 | 0 | $node = $form['#node']; |
| 157 | 0 | $form_state['redirect'] = "node/" . $node->nid; |
| 158 | 0 | $book_link = $form_state['values']['book']; |
| 159 | 0 | if (!$book_link['bid']) { |
| 160 | 0 | drupal_set_message(t('No changes were made')); |
| 161 | | |
| 162 | 0 | return; |
| 163 | 0 | } |
| 164 | | |
| 165 | 0 | $book_link['menu_name'] = book_menu_name($book_link['bid']); |
| 166 | 0 | $node->book = $book_link; |
| 167 | 0 | if (_book_update_outline($node)) { |
| 168 | 0 | if ($node->book['parent_mismatch']) { |
| 169 | | // This will usually only happen when JS is disabled. |
| 170 | 0 | drupal_set_message(t('The post has been added to the selected book.
You may now position it relative to other pages.')); |
| 171 | 0 | $form_state['redirect'] = "node/" . $node->nid . "/outline"; |
| 172 | 0 | } |
| 173 | | else { |
| 174 | 0 | drupal_set_message(t('The book outline has been updated.')); |
| 175 | | } |
| 176 | 0 | } |
| 177 | | else { |
| 178 | 0 | drupal_set_message(t('There was an error adding the post to the
book.'), 'error'); |
| 179 | | } |
| 180 | 0 | } |
| 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 | | */ |
| 189 | 6 | function book_remove_form(&$form_state, $node) { |
| 190 | 0 | $form['#node'] = $node; |
| 191 | 0 | $title = array('%title' => $node->title); |
| 192 | | |
| 193 | 0 | if ($node->book['has_children']) { |
| 194 | 0 | $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); |
| 195 | 0 | } |
| 196 | | else { |
| 197 | 0 | $description = t('%title may be added to hierarchy again using the
Outline tab.', $title); |
| 198 | | } |
| 199 | | |
| 200 | 0 | return confirm_form($form, t('Are you sure you want to remove %title from
the book hierarchy?', $title), 'node/' . $node->nid, $description,
t('Remove')); |
| 201 | 0 | } |
| 202 | | |
| 203 | | /** |
| 204 | | * Confirm form submit function to remove a node from the book. |
| 205 | | * |
| 206 | | * @see book_remove_form() |
| 207 | | */ |
| 208 | 6 | function book_remove_form_submit($form, &$form_state) { |
| 209 | 0 | $node = $form['#node']; |
| 210 | 0 | if ($node->nid != $node->book['bid']) { |
| 211 | | // Only allowed when this is not a book (top-level page). |
| 212 | 0 | menu_link_delete($node->book['mlid']); |
| 213 | 0 | db_query('DELETE FROM {book} WHERE nid = %d', $node->nid); |
| 214 | 0 | drupal_set_message(t('The post has been removed from the book.')); |
| 215 | 0 | } |
| 216 | 0 | $form_state['redirect'] = 'node/' . $node->nid; |
| 217 | 0 | } |
| 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 | | */ |
| 234 | 6 | function book_form_update() { |
| 235 | 0 | $cached_form_state = array(); |
| 236 | 0 | $bid = $_POST['book']['bid']; |
| 237 | 0 | if ($form = form_get_cache($_POST['form_build_id'], $cached_form_state))
{ |
| 238 | | // Validate the bid. |
| 239 | 0 | if (isset($form['book']['bid']['#options'][$bid])) { |
| 240 | 0 | $book_link = $form['#node']->book; |
| 241 | 0 | $book_link['bid'] = $bid; |
| 242 | | // Get the new options and update the cache. |
| 243 | 0 | $form['book']['plid'] = _book_parent_select($book_link); |
| 244 | 0 | form_set_cache($_POST['form_build_id'], $form, $cached_form_state); |
| 245 | | // Build and render the new select element, then return it in JSON
format. |
| 246 | 0 | $form_state = array(); |
| 247 | 0 | $form['#post'] = array(); |
| 248 | 0 | $form = form_builder($form['form_id']['#value'] , $form,
$form_state); |
| 249 | 0 | $output = drupal_render($form['book']['plid']); |
| 250 | 0 | drupal_json(array('status' => TRUE, 'data' => $output)); |
| 251 | 0 | } |
| 252 | | else { |
| 253 | 0 | drupal_json(array('status' => FALSE, 'data' => '')); |
| 254 | | } |
| 255 | 0 | } |
| 256 | | else { |
| 257 | 0 | drupal_json(array('status' => FALSE, 'data' => '')); |
| 258 | | } |
| 259 | 0 | exit(); |
| 260 | 0 | } |
| 261 | 6 | |