Index: book.module =================================================================== RCS file: /cvs/drupal/drupal/modules/book.module,v retrieving revision 1.350 diff -u -F^f -r1.350 book.module --- book.module 21 Feb 2006 18:46:54 -0000 1.350 +++ book.module 22 Feb 2006 09:41:01 -0000 @@ -134,7 +134,6 @@ function book_menu($may_cache) { } } } - return $items; } @@ -246,12 +245,26 @@ function book_validate($node) { * Implementation of hook_form(). */ function book_form(&$node) { + if (user_access('create new books')) { + $toc = book_toc($node->nid); + } + else { + if (!$node->parent) { + // this is a top level page + $toc = array('<'. t('top-level') .'>'); + } + else { + $path_to_root = book_location($node); + $root = (object) $path_to_root[0]; + $toc = book_toc($node->nid, $root->nid); + } + } $form['parent'] = array( '#type' => 'select', '#title' => t('Parent'), '#default_value' => ($node->parent ? $node->parent : arg(4)), - '#options' => book_toc($node->nid), + '#options' => $toc, '#weight' => -4, '#description' => user_access('create new books') ? @@ -348,9 +361,28 @@ function book_outline() { } /** + * Given a node, this function returns an array of 'book node' objects + * representing the path in the book tree from the root to the + * parent of the given node. + * + * @param node + * - either a node, or a numerical node id (nid) of a node for which + * to compute path + * @return + * - an array of book node objects representing the path of nodes + * root to parent of the given node. + * - Returns an empty array if the node does not exist or is not + * part of a book hierarchy. + */ + + +/** * Return the path (call stack) to a certain book page. */ function book_location($node, $nodes = array()) { + if (is_numeric($node)) { + $node = node_load($node); + } $parent = db_fetch_object(db_query(db_rewrite_sql('SELECT n.nid, n.title, b.parent, b.weight FROM {node} n INNER JOIN {book} b ON n.vid = b.vid WHERE n.nid = %d'), $node->parent)); if ($parent->title) { $nodes = book_location($parent, $nodes); @@ -385,7 +417,6 @@ function book_prev($node) { if ($direct_above) { // Get last leaf of $above. $path = book_location_down($direct_above); - return $path ? (count($path) > 0 ? array_pop($path) : NULL) : $direct_above; } else { @@ -479,7 +510,7 @@ function book_nodeapi(&$node, $op, $teas } /** - * Prepares both the custom breadcrumb trail and the forward/backward + * Prepares the links to children (TOC) and forward/backward * navigation for a node presented as a book page. * * @ingroup themeable @@ -530,16 +561,18 @@ function book_toc_recurse($nid, $indent, } } } - return $toc; } /** - * Returns an array of titles and nid entries of book pages in table of contents order. + * Returns a table of contents (TOC), i.e., an array of titles and nid + * entries of book pages in table of contents order. This is used for example + * to generate the list of potential parents for a page to be inserted under. + * @param exclude - the subtree rooted at this nid is excluded from the TOC + * @param root - create the TOC for the subtree rooted at this nid */ -function book_toc($exclude = 0) { +function book_toc($exclude = 0, $root = NULL) { $result = db_query(db_rewrite_sql('SELECT n.nid, n.title, b.parent, b.weight FROM {node} n INNER JOIN {book} b ON n.vid = b.vid WHERE n.status = 1 ORDER BY b.weight, n.title')); - while ($node = db_fetch_object($result)) { if (!$children[$node->parent]) { $children[$node->parent] = array(); @@ -551,10 +584,15 @@ function book_toc($exclude = 0) { // If the user has permission to create new books, add the top-level book page to the menu; if (user_access('create new books')) { $toc[0] = '<'. t('top-level') .'>'; + $toc = book_toc_recurse(0, '', $toc, $children, $exclude); + } + else { + // $children = $children[$root]; + // $toc[0] = array($root => $children[$root]['title']); + // $toc[0] = array($root => . ' '. $children[$root]->title); + $toc[0] = '<'. t('current-book') .'>'; + $toc = book_toc_recurse($root, '--', $toc, $children, $exclude); } - - $toc = book_toc_recurse(0, '', $toc, $children, $exclude); - return $toc; } @@ -564,6 +602,7 @@ function book_toc($exclude = 0) { function book_tree_recurse($nid, $depth, $children, $unfold = array()) { if ($depth > 0) { if ($children[$nid]) { + $output = ''; foreach ($children[$nid] as $foo => $node) { if (in_array($node->nid, $unfold)) { if ($tree = book_tree_recurse($node->nid, $depth - 1, $children, $unfold)) { @@ -587,7 +626,6 @@ function book_tree_recurse($nid, $depth, } } } - return $output; } @@ -596,14 +634,18 @@ function book_tree_recurse($nid, $depth, * as a tree. */ function book_tree($parent = 0, $depth = 3, $unfold = array()) { - $result = db_query(db_rewrite_sql('SELECT n.nid, n.title, b.parent, b.weight FROM {node} n INNER JOIN {book} b ON n.vid = b.vid WHERE n.status = 1 AND n.moderate = 0 ORDER BY b.weight, n.title')); + static $children; - while ($node = db_fetch_object($result)) { - $list = $children[$node->parent] ? $children[$node->parent] : array(); - array_push($list, $node); - $children[$node->parent] = $list; + // Only perform this query if the result is not cached + if (!isset($children)) { + $result = db_query(db_rewrite_sql('SELECT n.nid, n.title, b.parent, b.weight FROM {node} n INNER JOIN {book} b ON n.vid = b.vid WHERE n.status = 1 AND n.moderate = 0 ORDER BY b.weight, n.title')); + + while ($node = db_fetch_object($result)) { + $list = $children[$node->parent] ? $children[$node->parent] : array(); + array_push($list, $node); + $children[$node->parent] = $list; + } } - if ($tree = book_tree_recurse($parent, $depth, $children, $unfold)) { return '
'; } @@ -643,7 +685,7 @@ function book_render() { */ function book_export($type = 'html', $nid = 0) { $type = drupal_strtolower($type); - $depth = _book_get_depth($nid); + $depth = count(book_location($nid)) + 1; $export_function = 'book_export_' . $type; if (function_exists($export_function)) { @@ -658,7 +700,7 @@ function book_export($type = 'html', $ni /** * This function is called by book_export() to generate HTML for export. * - * The given node is /embedded to its absolute depth in a top level + * The given node is /embedded to its absolute depth in a top-level * section/. For example, a child node with depth 2 in the hierarchy * is contained in (otherwise empty) <div> elements * corresponding to depth 0 and depth 1. This is intended to support @@ -678,6 +720,7 @@ function book_export($type = 'html', $ni function book_export_html($nid, $depth) { if (user_access('see printer-friendly version')) { global $base_url; + $output = ''; for ($i = 1; $i < $depth; $i++) { $output .= "