status; } if ($op == "create") { /* ** Only registered users can create book pages. Given the nature ** of the book module this is considered to be a good/safe idea. */ return $user->uid; } if ($op == "update") { /* ** Only registered users can update book pages. Given the nature ** of the book module this is considered to be a good/safe idea. ** One can only upate a book page if there are no suggested updates ** of that page waiting for approval, when it is not a PHP-page and ** as long as the "create new revision"-bit is set. That is, only ** updates that don't overwrite the current or pending information ** are allowed. */ return $user->uid && !$node->moderate && !$node->format && $node->revision; } } function book_save($op, $node) { global $user; if ($op == "approve") { return array("status" => 1); } if ($op == "create") { if (user_access("administer nodes")) { return array("format", "parent", "weight"); } else { return array("format", "moderate" => 1, "parent", "promote" => 0, "status" => 1, "weight"); } } if ($op == "decline") { return array("status" => 0); } if ($op == "update") { if (user_access("administer nodes")) { /* ** If a node administrator updates a book page, we don't create a ** new revision unless we are explicitly instructed to. */ return array("format", "parent", "weight"); } else { /* ** If a regular user updates a book page, we always create a new ** revision. All new revisions have to be approved (moderation) ** and are not promoted by default. See also: book_load(). */ return array("created" => time(), "format", "moderate" => 1, "parent", "promote" => 0, "score" => 0, "status" => 1, "users" => "", "revisions", "votes" => 0, "weight"); } } } function book_link($type, $node = 0, $main = 0) { if ($type == "page" && user_access("access content")) { $links[] = "". t("collaborative book") .""; } if ($type == "menu.create" && user_access("administer nodes")) { $links[] = "". t("create book page") .""; } if ($type == "admin" && user_access("administer nodes")) { $links[] = "". t("collaborative book") .""; } if ($type == "node" && $node->type == "book" && book_access("update", $node)) { $links[] = "nid\" title=\"". t("Suggest an update for this book page.") ."\">". t("edit this page") .""; } return $links ? $links : array(); } function book_load($node) { global $user, $REQUEST_URI; $book = db_fetch_object(db_query("SELECT format, parent, weight FROM book WHERE nid = '$node->nid'")); if (strstr($REQUEST_URI, "module.php?mod=node&op=edit")) { /* ** If a user is about to update a book page, we overload some ** fields to reflect the changes. We use the $REQUEST_URI to ** dectect this as we don't want to interfer with updating a ** book page through the admin pages. See also: book_save(). */ if ($user->uid) { $book->uid = $user->uid; $book->name = $user->name; } else { $book->uid = 0; $book->name = ""; } } /* ** We set the revision field to indicate that we have to create ** a new revision when updating this book page. We enable this ** always such that the "edit this page"-links appear. */ $book->revision = 1; return $book; } function book_insert($node) { if (!user_access("administer nodes")) { $node->format = 0; $node->weight = 0; } db_query("INSERT INTO book (nid, format, parent, weight) VALUES ('$node->nid', '$node->format', '$node->parent', '$node->weight')"); } function book_update($node) { if (!user_access("administer nodes")) { $node->format = 0; $node->weight = 0; } db_query("UPDATE book SET format = '$node->format', parent = '$node->parent', weight = '$node->weight' WHERE nid = '$node->nid'"); } function book_delete(&$node) { db_query("DELETE FROM book WHERE nid = '$node->nid'"); } function book_form(&$node, &$help, &$error) { global $user, $op; $output .= form_select(t("Parent"), "parent", $node->parent, book_toc(), t("The parent subject or category the page belongs in.")); if ($node->format) { if ($op != t("Preview")) { $node->body = addslashes($node->body); } } else { if ($node->teaser) { $output .= form_textarea(t("Teaser"), "teaser", $node->teaser, 60, 5, $error["teaser"]); } } $output .= form_textarea(t("Body"), "body", $node->body, 60, 20, t("Allowed HTML tags") .": ". htmlspecialchars(variable_get("allowed_html", ""))); $output .= form_textarea(t("Log message"), "history", $node->history, 60, 5, t("An explanation of the additions or updates being made to help the group understand your motivations.")); if (user_access("administer nodes")) { $output .= form_select(t("Weight"), "weight", $node->weight, array(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30), t("The heavier pages will sink and the lighter pages will be positioned nearer the top.")); $output .= form_select("Type", "format", $node->format, array(0 => "HTML / text", 1 => "PHP")); } else { /* ** Carry out some explanation or submission guidelines: */ $help = book_node("description"); /* ** If a regular user updates a book page, we create a new revision ** authored by that user: */ $output .= form_hidden("revision", 1); } return $output; } function book_node_link($node = 0) { global $user, $op, $edit; if ($node->type != "book") { if ($edit["nid"]) { $node = node_load(array("nid" => $edit["nid"])); } if ($op == t("Add to book outline")) { db_query("INSERT INTO book (nid, parent, weight) VALUES ('$node->nid', '". check_query($edit["parent"]) ."', '". check_query($edit["weight"]) ."')"); $output .= status(t("added the node to the book.")); } if ($op == t("Update book outline")) { db_query("UPDATE book SET parent = '". check_query($edit["parent"]) ."', weight = '". check_query($edit["weight"]) ."' WHERE nid = '$node->nid'"); $output .= status(t("updated the book outline.")); } if ($op == t("Remove from book outline")) { db_query("DELETE FROM book WHERE nid = '$node->nid'"); $output .= status(t("removed the node form the book.")); } $output .= "

". t("Edit book outline") ."

"; if ($edit["nid"]) { $page = db_fetch_object(db_query("SELECT * FROM book WHERE nid = '$node->nid'")); $output .= form_select(t("Parent"), "parent", $page->parent, book_toc(), t("The parent subject or category the page belongs in.")); $output .= form_select(t("Weight"), "weight", $page->weight, array(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30), t("The heavier pages will sink and the lighter pages will be positioned nearer the top.")); if ($page->nid) { $output .= form_submit(t("Update book outline")); $output .= form_submit(t("Remove from book outline")); } else { $output .= form_submit(t("Add to book outline")); } } else { $output .= form_submit(t("Edit book outline")); } $output .= form_hidden("nid", $node->nid); return form($output, "post", "admin.php?mod=book&op=outline"); } } /* ** Return the the most recent revision that matches the specified ** conditions. */ function book_revision_load($page, $conditions = array()) { $revisions = array_reverse(node_revision_list($page)); foreach ($revisions as $revision) { /* ** Extract the specified revision: */ $node = node_revision_load($page, $revision); /* ** Check to see if the conditions are met: */ $status = 1; foreach ($conditions as $key => $value) { if ($node->$key != $value) { $status = 0; } } if ($status) { return $node; } } } /* ** Return the path (call stack) to a certain book page. */ function book_location($node, $nodes = array()) { $parent = db_fetch_object(db_query("SELECT n.nid, n.title, b.parent FROM node n LEFT JOIN book b ON n.nid = b.nid WHERE n.nid = '$node->parent'")); if ($parent->title) { $nodes = book_location($parent, $nodes); array_push($nodes, $parent); } return $nodes; } function book_body($node) { global $theme, $op; if ($node->format == 1) { /* ** Make sure only authorized users can preview PHP pages. */ if ($op == t("Preview")) { if (user_access("administer nodes")) { $node->body = stripslashes($node->body); // see also book_form() } else { return; } } ob_start(); eval($node->body); $output = ob_get_contents(); ob_end_clean(); } else { $output = check_output(filter($node->body), 1); } return $output; } function book_view($node, $main = 0) { global $theme, $mod; /* ** Always display the most recently approved revision of a node ** (if any) unless we have to display this page in the context of ** the moderation queue. */ if ($node->moderate && $mod != "queue") { $revision = book_revision_load($node, array("moderate" => 0, "status" => 1)); if ($revision) { $node = $revision; } } /* ** Extract the page body. If body is dynamic (using PHP code), the body ** will be generated. */ $node->body = book_body($node); /* ** Display the node. If not displayed on the main page, we render ** the node as a page in the book with extra links to the previous ** and the next page. */ if ($main) { $theme->node($node, $main); } else { /* ** Construct the "next" and "previous" links: */ if ($node->nid && $node->parent) { $next = db_fetch_object(db_query("SELECT n.nid, n.title FROM node n LEFT JOIN book b ON n.nid = b.nid WHERE n.status = 1 AND b.parent = '$node->parent' AND (b.weight > '$node->weight' OR (b.weight = '$node->weight' AND n.title > '". check_query($node->title) ."')) AND (n.moderate = 0 OR n.revisions != '') ORDER BY b.weight ASC, n.title ASC")); $prev = db_fetch_object(db_query("SELECT n.nid, n.title FROM node n LEFT JOIN book b ON n.nid = b.nid WHERE n.status = 1 AND b.parent = '$node->parent' AND (b.weight < '$node->weight' OR (b.weight = '$node->weight' AND n.title < '". check_query($node->title) ."')) AND (n.moderate = 0 OR n.revisions != '') ORDER BY b.weight DESC, n.title DESC")); } $output .= ""; if ($node->title) { foreach (book_location($node) as $level) { $location .= "$indent nid\">$level->title
"; $indent .= "-"; } $output .= " "; $output .= " "; $output .= " "; } if ($node->body) { $output .= " "; } if ($node->nid) { $output .= " "; } $output .= " "; $output .= " "; $output .= " "; $output .= " "; $output .= " "; $output .= "
$location

". check_output($node->title) ."". ($node->body ? "
". sprintf(t("Last updated by %s on %s"), format_name($node), format_date($node->created)) ." " : "") ."

$node->body

". book_tree($node->nid) ."

". ($prev ? "nid\" title=\"". t("View the previous page in this book.") ."\">". t("previous") ."" : t("previous")) ."index". ($next ? "nid\" title=\"". t("View the next page in this book.") ."\">". t("next") ."" : t("next")) ."
". ($prev ? "". check_output($prev->title) ."" : " ") ."". ($node->parent ? "parent\" title=\"". t("View this page's parent section.") ."\">". t("up") ."" : t("up")) ."". ($next ? "". check_output($next->title) ."" : " ") ."

". $theme->links(link_node($node, $main)) ."
"; $theme->box(t("Handbook"), $output); } } function book_toc_recurse($nid, $indent, $toc, $children) { if ($children[$nid]) { foreach ($children[$nid] as $foo => $node) { $toc[$node->nid] = "$indent $node->title"; $toc = book_toc_recurse($node->nid, "$indent--", $toc, $children); } } return $toc; } function book_toc($parent = 0, $indent = "", $toc = array()) { $result = db_query("SELECT n.nid, n.title, b.parent FROM node n LEFT JOIN book b ON n.nid = b.nid WHERE n.type = 'book' AND n.status = '1' 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 the user is an administrator, add the root node; only ** administrators can start new books. */ if (user_access("administer nodes")) { $toc[0] = ""; } /* ** Iterate root book nodes: */ $toc = book_toc_recurse($parent, $indent, $toc, $children); return $toc; } function book_tree_recurse($nid, $depth, $children) { if ($depth > 0) { if ($children[$nid]) { foreach ($children[$nid] as $foo => $node) { $output .= "
  • nid\">". check_output($node->title) ."
  • "; if ($tree = book_tree_recurse($node->nid, $depth - 1, $children)) { $output .= ""; } } } } return $output; } function book_tree($parent = 0, $depth = 3) { $result = db_query("SELECT n.nid, n.title, b.parent FROM node n LEFT JOIN book b ON n.nid = b.nid WHERE n.type = 'book' AND n.status = '1' 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; } $output = book_tree_recurse($parent, $depth, $children); $output = ""; return $output; } function book_render() { global $theme; $result = db_query("SELECT n.nid FROM node n LEFT JOIN book b ON n.nid = b.nid WHERE b.parent = 0 AND n.status = 1 AND (n.moderate = 0 OR n.revisions != '') ORDER BY b.weight"); while ($page = db_fetch_object($result)) { // load the node: $node = node_load(array("nid" => $page->nid)); // take the most recent approved revision: if ($node->moderate) { $node = book_revision_load($node, array("moderate" => 0, "status" => 1)); } if ($node) { // output the content: $output .= "
    nid\">". check_output($node->title) ."
    ". book_body($node) ."

    "; } } $theme->header(); $theme->box(t("Handbook"), "
    $output
    "); $theme->footer(); } function book_page() { global $op, $id, $theme; if (user_access("access content")) { switch ($op) { case "feed": print book_export_html($id, $depth = 1); break; default: book_render(); } } else { $theme->header(); $theme->box(t("Access denied"), message_access()); $theme->footer(); } } function book_export_html($id = "", $depth = 1) { $result = db_query("SELECT n.nid FROM node n LEFT JOIN book b ON n.nid = b.nid WHERE n.status = 1 AND n.nid = '". check_input($id) ." AND (n.moderate = 0 OR n.revisions != '')'"); while ($page = db_fetch_object($result)) { // load the node: $node = node_load(array("nid" => $page->nid)); // take the most recent approved revision: if ($node->moderate) { $node = book_revision_load($node, array("moderate" => 0, "status" => 1)); } if ($node) { // output the content: $output .= "". check_output($node->title) .""; if ($node->body) { $output .= ""; } } } $output .= book_export_html_recurse($id, $depth); return $output; } function book_export_html_recurse($parent = "", $depth = 1) { $result = db_query("SELECT n.nid FROM node n LEFT JOIN book b ON n.nid = b.nid WHERE n.status = 1 AND b.parent = '$parent' AND (n.moderate = 0 OR n.revisions != '') ORDER BY b.weight"); while ($page = db_fetch_object($result)) { // load the node: $node = node_load(array("nid" => $page->nid)); // take the most recent approved revision: if ($node->moderate) { $node = book_revision_load($node, array("moderate" => 0, "status" => 1)); } if ($node) { // output the content: $output .= "". check_output($node->title) .""; if ($node->body) { $output .= ""; } $output .= book_export_html_recurse($node->nid, $depth + 1); } } return $output; } function book_admin_view_line($node, $depth = 0) { /* ** Extract the revision number: */ if ($list = node_revision_list($node)) { $revision = end($list); } else { $revision = 0; } /* ** Diplay the book page: */ $output .= ""; $output .= "
    nid\">". check_output($node->title) ."
    "; $output .= " $revision"; $output .= " nid\">". t("edit page") .""; $output .= " nid\">". t("delete page") .""; $output .= ""; return $output; } function book_admin_view_book($nid, $depth = 1) { $weight = array(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30); $result = db_query("SELECT n.nid FROM node n LEFT JOIN book b ON n.nid = b.nid WHERE b.parent = '$nid' ORDER BY b.weight, n.title"); while ($node = db_fetch_object($result)) { $node = node_load(array("nid" => $node->nid)); $output .= book_admin_view_line($node, $depth); $output .= book_admin_view_book($node->nid, $depth + 1); } return $output; } function book_admin_view($nid, $depth = 0) { $node = node_load(array("nid" => $nid)); $output .= "

    ". check_output($node->title) ."

    "; $output .= ""; $output .= " "; $output .= book_admin_view_line($node); $output .= book_admin_view_book($nid); $output .= "
    titlerevoperations
    "; return $output; } function book_admin_orphan() { $result = db_query("SELECT n.nid, n.title, b.parent FROM node n LEFT JOIN book b ON n.nid = b.nid WHERE n.type = 'book'"); while ($page = db_fetch_object($result)) { $pages[$page->nid] = $page; } $output .= ""; $output .= " "; foreach ($pages as $nid => $node) { if ($node->parent && empty($pages[$node->parent])) { $output .= ""; } } $output .= "
    titleoperations
    nid\">". check_output($node->title) ."nid\">". t("edit page") ."nid\">". t("delete page") ."
    "; return $output; } function book_admin_links() { $result = db_query("SELECT n.nid, n.title FROM node n LEFT JOIN book b ON n.nid = b.nid WHERE b.parent = 0 ORDER BY b.weight, n.title"); while ($book = db_fetch_object($result)) { $links[] = "
    nid\">". t("book") .": ". check_output($book->title) .""; } return $links; } function book_admin() { global $id, $op; if (user_access("administer nodes")) { /* ** Compile a list of the administrative links: */ $links = book_admin_links(); $links[] = "". t("orphan pages") .""; print "". implode(" · ", $links) ."
    "; switch ($op) { case t("Edit book outline"): case t("Add to book outline"): case t("Remove from book outline"): case t("Update book outline"): print book_node_link(); break; case "orphan": print book_admin_orphan(); break; case "view": print book_admin_view($id); break; default: } } } ?>