book.module 11.6 KB
Newer Older
Dries's avatar
 
Dries committed
1
<?php
2
// $Id$
Dries's avatar
 
Dries committed
3

Dries's avatar
 
Dries committed
4 5 6
function book_node($field) {
  global $user;

Dries's avatar
 
Dries committed
7 8
  $info["name"] = t("book page");
  $info["description"] = t("A book is a collaborative effort on a certain subject. Users collaborate writing the pages of the book, positioning the pages in the right order, and reviewing or modifying pages previously written.  You can add a new book page or you can modify existing pages.");
Dries's avatar
 
Dries committed
9 10 11 12 13

  return $info[$field];
}

function book_access($op, $node) {
Dries's avatar
 
Dries committed
14
  global $user;
Dries's avatar
 
Dries committed
15 16

  if ($op == "view") {
Dries's avatar
 
Dries committed
17 18 19 20 21 22 23 24
    /*
    ** Everyone can access all published book pages whether these pages
    ** are still waiting for approval or not.  We might not always want
    ** to display pages that are waiting for approval, but we take care
    ** of that problem in the book_view() function.
    */

    return $node->status;
Dries's avatar
 
Dries committed
25 26 27 28 29 30 31 32
  }

  if  ($op == "create") {
    return 1;
  }

  if ($op == "update") {

Dries's avatar
 
Dries committed
33
    /*
Dries's avatar
 
Dries committed
34 35 36 37
    ** Everyone can upate a book page if there are no suggested updates
    ** of that page waiting for approval 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.
Dries's avatar
 
Dries committed
38 39
    */

Dries's avatar
 
Dries committed
40
    return !$node->moderate && $node->revision;
Dries's avatar
 
Dries committed
41
  }
Dries's avatar
 
Dries committed
42 43
}

Dries's avatar
 
Dries committed
44 45 46
function book_link($type) {
  if ($type == "page" && user_access("access content")) {
    $links[] = "<a href=\"module.php?mod=book\">". t("collaborative book") ."</a>";
Dries's avatar
 
Dries committed
47
  }
Dries's avatar
 
Dries committed
48 49

  return $links ? $links : array();
Dries's avatar
 
Dries committed
50 51
}

Dries's avatar
 
Dries committed
52
function book_load($node) {
Dries's avatar
 
Dries committed
53
  $book = db_fetch_object(db_query("SELECT parent, weight, revision FROM book WHERE nid = '$node->nid'"));
Dries's avatar
 
Dries committed
54
  return $book;
Dries's avatar
 
Dries committed
55 56
}

Dries's avatar
 
Dries committed
57
function book_insert($node) {
Dries's avatar
 
Dries committed
58
  db_query("INSERT INTO book (nid, parent, weight) VALUES ('$node->nid', '$node->parent', '$node->weight')");
Dries's avatar
 
Dries committed
59
}
Dries's avatar
 
Dries committed
60

Dries's avatar
 
Dries committed
61
function book_update($node) {
Dries's avatar
 
Dries committed
62
  db_query("UPDATE book SET parent = '$node->parent', weight = '$node->weight' WHERE nid = '$node->nid'");
Dries's avatar
 
Dries committed
63
}
Dries's avatar
 
Dries committed
64

Dries's avatar
 
Dries committed
65 66
function book_delete($node) {
  db_query("DELETE FROM book WHERE nid = '$node->nid'");
Dries's avatar
 
Dries committed
67 68
}

Dries's avatar
 
Dries committed
69
function book_save($node) {
Dries's avatar
 
Dries committed
70 71 72 73
  if ($node->nid) {
    if (user_access("administer nodes")) {
      /*
      ** If a node administrator updates a book page, we don't create a
Dries's avatar
 
Dries committed
74
      ** new revision unless we are explicitly instructed to.
Dries's avatar
 
Dries committed
75 76 77 78 79 80 81
      */

      return array("parent", "weight");
    }
    else {
      /*
      ** If a regular user updates a book page, we always create a new
Dries's avatar
 
Dries committed
82 83
      ** revision.  All new revisions have to be approved (moderation)
      ** and are not promoted by derault.
Dries's avatar
 
Dries committed
84 85 86 87
      */

      return array("created" => time(), "moderate" => 1, "parent", "promote" => 0, "score" => 0, "status" => 1, "users" => "", "revisions", "votes" => 0, "weight");
    }
Dries's avatar
 
Dries committed
88 89
  }
  else {
Dries's avatar
 
Dries committed
90
    return array("moderate" => 1, "parent", "promote" => 0, "status" => 1, "weight");
Dries's avatar
 
Dries committed
91
  }
Dries's avatar
 
Dries committed
92 93
}

Dries's avatar
 
Dries committed
94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118
function book_form($node, $help, $error) {
  global $user;

  $output .= form_select(t("Parent"), "parent", $node->parent, book_toc(), t("The parent subject or category the page belongs in."));
  $output .= form_textarea(t("Content"), "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 nodes will sink and the lighter nodes will be positioned nearer the top."));
  }
  else {

    /*
    ** Carry out some explanation or submission guidelines:
    */

    $help = t("\"update book page\"-help: to be written!  It should explain the basic idea behind our collaborative book and how their update helps to improve the quality of the book.  Also mention that all updates are subject to moderation or review.  Any who can put this into a fluent English help text?");

    /*
    ** If a regular user updates a book page, we create a new revision
    ** authored by that user:
    */

    $output .= form_hidden("revision", 1);

Dries's avatar
 
Dries committed
119
    $node->uid = $user->uid;    // $node is passed by reference
Dries's avatar
 
Dries committed
120 121 122 123 124 125 126
    $node->name = $user->name;

  }

  return $output;
}

Dries's avatar
 
Dries committed
127
function book_location($node, $nodes = array()) {
Dries's avatar
 
Dries committed
128
  $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'"));
Dries's avatar
 
Dries committed
129 130 131 132 133 134 135
  if ($parent->title) {
    $nodes = book_location($parent, $nodes);
    array_push($nodes, $parent);
  }
  return $nodes;
}

Dries's avatar
 
Dries committed
136
function book_view($node, $main = 0) {
Dries's avatar
 
Dries committed
137 138 139 140 141 142 143 144 145
  global $theme, $mod;

  /*
  ** Always display the most recently approved revision of a node
  ** unless we have to display it in the context of the moderation
  ** queue.
  */

  if ($node->moderate && $mod != "queue") {
Dries's avatar
 
Dries committed
146
    $node = node_revision_load($node, end(node_revision_list($node)));
Dries's avatar
 
Dries committed
147 148 149 150 151 152 153
  }

  /*
  ** 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.
  */
Dries's avatar
 
Dries committed
154

Dries's avatar
 
Dries committed
155 156
  if ($main) {
    $theme->node($node, $main);
Dries's avatar
 
Dries committed
157
  }
Dries's avatar
 
Dries committed
158 159
  else {
    if ($node->nid && $node->parent) {
Dries's avatar
 
Dries committed
160 161
      $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) ."')) 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) ."')) ORDER BY b.weight DESC, n.title DESC"));
Dries's avatar
 
Dries committed
162
    }
Dries's avatar
 
Dries committed
163

Dries's avatar
 
Dries committed
164
    $output .= "<table border=\"0\" cellpadding=\"0\" cellspacing=\"0\" width=\"100%\">\n";
Dries's avatar
 
Dries committed
165

Dries's avatar
 
Dries committed
166 167
    if ($node->title) {
      foreach (book_location($node) as $level) {
Dries's avatar
 
Dries committed
168
        $location .= "$indent <a href=\"node.php?id=$level->nid\">$level->title</a><br />";
Dries's avatar
 
Dries committed
169 170
        $indent .= "-";
      }
Dries's avatar
 
Dries committed
171

Dries's avatar
 
Dries committed
172 173 174
      $output .= " <tr><td colspan=\"2\">$location</td><td align=\"right\"><a href=\"module.php?mod=node&op=edit&id=$node->nid\">". t("update this book page") ."</a></td></tr>";
      $output .= " <tr><td colspan=\"3\"><hr /></td></tr>";
      $output .= " <tr><td colspan=\"3\"><b><big>". check_output($node->title) ."</big></b>". ($node->body ? "<br /><small><i>". sprintf(t("Last updated by %s on %s"), format_name($node), format_date($node->created)) ."</i></small> " : "") ."</td></tr>";
Dries's avatar
 
Dries committed
175
    }
Dries's avatar
 
Dries committed
176

Dries's avatar
 
Dries committed
177
    if ($node->body) {
Dries's avatar
 
Dries committed
178
      $output .= " <tr><td colspan=\"3\"><br />". check_output($node->body, 1) ."</td></tr>";
Dries's avatar
 
Dries committed
179
    }
Dries's avatar
 
Dries committed
180

Dries's avatar
 
Dries committed
181
    if ($node->nid) {
Dries's avatar
 
Dries committed
182
      $output .= " <tr><td colspan=\"3\"><br />". book_tree($node->nid) ."</td></tr>";
Dries's avatar
 
Dries committed
183
    }
Dries's avatar
 
Dries committed
184

Dries's avatar
 
Dries committed
185 186 187 188
    $output .= " <tr><td colspan=\"3\"><hr /></td></tr>";
    $output .= " <tr><td align=\"left\" width=\"33%\">". ($prev ? "<a href=\"node.php?id=$prev->nid\">". t("previous") ."</a>" : t("previous")) ."</td><td align=\"center\" width=\"34%\"><a href=\"module.php?mod=book\">index</a></td><td align=\"right\" width=\"33%\">". ($next ? "<a href=\"node.php?id=$next->nid\">". t("next") ."</a>" : t("next")) ."</td></tr>";
    $output .= " <tr><td align=\"left\" width=\"33%\">". ($prev ? "<small>". check_output($prev->title) ."</small>" : "&nbsp;") ."</td><td align=\"center\" width=\"34%\">". ($node->parent ? "<a href=\"node.php?id=$node->parent\">". t("up") ."</a>" : t("up")) ."</td><td align=\"right\" width=\"33%\">". ($next ? "<small>". check_output($next->title) ."</small>" : "&nbsp;") ."</td></tr>";
    $output .= "</table>";
Dries's avatar
 
Dries committed
189

Dries's avatar
 
Dries committed
190 191
    $theme->box(t("Handbook"), $output);
  }
Dries's avatar
 
Dries committed
192 193
}

Dries's avatar
 
Dries committed
194
function book_toc($parent = "", $indent = "", $toc = array()) {
Dries's avatar
 
Dries committed
195

Dries's avatar
 
Dries committed
196 197 198 199 200 201 202 203 204
  /*
  ** Select all child nodes:
  */

  $result = db_query("SELECT n.nid, n.title FROM node n LEFT JOIN book b ON n.nid = b.nid WHERE n.type = 'book' AND n.status = 1 AND b.parent = '$parent' ORDER BY b.weight");

  /*
  ** Add the root node:
  */
Dries's avatar
 
Dries committed
205

Dries's avatar
 
Dries committed
206
  if (user_access("administer nodes")) {
Dries's avatar
 
Dries committed
207
    $toc[0] = "<root>";
Dries's avatar
 
Dries committed
208 209
  }

Dries's avatar
 
Dries committed
210 211 212 213
  /*
  ** Build the table of contents:
  */

Dries's avatar
 
Dries committed
214
  while ($node = db_fetch_object($result)) {
Dries's avatar
 
Dries committed
215 216
    $toc[$node->nid] = "$indent $node->title";
    $toc = book_toc($node->nid, "$indent-", $toc);
Dries's avatar
 
Dries committed
217
  }
Dries's avatar
 
Dries committed
218

Dries's avatar
 
Dries committed
219 220 221
  return $toc;
}

Dries's avatar
Dries committed
222
function book_tree($parent = "", $depth = 0) {
Dries's avatar
 
Dries committed
223

Dries's avatar
 
Dries committed
224
  if ($depth < 3) {
Dries's avatar
 
Dries committed
225 226 227 228 229
    /*
    ** Select all child nodes and render them into a table of contents:
    */

    $result = db_query("SELECT n.nid FROM node n LEFT JOIN book b ON n.nid = b.nid WHERE n.type = 'book' AND b.parent = '$parent' ORDER BY b.weight, n.title");
Dries's avatar
 
Dries committed
230

Dries's avatar
 
Dries committed
231 232 233 234 235 236
    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) {
Dries's avatar
 
Dries committed
237
        $node = node_revision_load($node, end(node_revision_list($node)));
Dries's avatar
 
Dries committed
238 239 240
      }

      // output the content:
Dries's avatar
 
Dries committed
241
      $output .= "<li><a href=\"node.php?id=$node->nid\">". check_output($node->title) ."</a></li>";
Dries's avatar
 
Dries committed
242 243

      // build the sub-tree of each child:
Dries's avatar
 
Dries committed
244 245
      $output .= book_tree($node->nid, $depth + 1);
    }
Dries's avatar
 
Dries committed
246

Dries's avatar
 
Dries committed
247
    $output = "<ul>$output</ul>";
Dries's avatar
 
Dries committed
248
  }
Dries's avatar
 
Dries committed
249

Dries's avatar
 
Dries committed
250 251 252
  return $output;
}

Dries's avatar
 
Dries committed
253
function book_render() {
Dries's avatar
 
Dries committed
254
  global $theme;
Dries's avatar
Dries committed
255

Dries's avatar
 
Dries committed
256
  $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 ORDER BY b.weight");
Dries's avatar
 
Dries committed
257

Dries's avatar
 
Dries committed
258 259 260 261 262 263
  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) {
Dries's avatar
 
Dries committed
264
      $node = node_revision_load($node, end(node_revision_list($node)));
Dries's avatar
 
Dries committed
265 266 267
    }

    // output the content:
Dries's avatar
 
Dries committed
268
    $output .= "<dt><a href=\"node.php?id=$node->nid\">". check_output($node->title) ."</a></dt><dd>". check_output($node->body, 1) ."<br /><br /></dd>";
Dries's avatar
 
Dries committed
269 270 271
  }

  $theme->header();
Dries's avatar
 
Dries committed
272
  $theme->box(t("Handbook"), "<dl>$output</dl>");
Dries's avatar
 
Dries committed
273 274 275 276 277 278
  $theme->footer();
}

function book_page() {
  global $op, $id, $theme;

Dries's avatar
 
Dries committed
279
  if (user_access("access content")) {
Dries's avatar
 
Dries committed
280 281
    switch ($op) {
      case "feed":
Dries's avatar
 
Dries committed
282
        print book_export_html($id, $depth = 1);
Dries's avatar
 
Dries committed
283 284 285
        break;
      default:
        book_render();
Dries's avatar
 
Dries committed
286 287 288 289 290 291 292
    }
  }
  else {
    $theme->header();
    $theme->box(t("Access denied"), message_access());
    $theme->footer();
  }
Dries's avatar
 
Dries committed
293 294
}

Dries's avatar
 
Dries committed
295
function book_export_html($id = "", $depth = 1) {
Dries's avatar
 
Dries committed
296
  $result = db_query("SELECT n.nid FROM node n LEFT JOIN book b ON n.nid = b.nid WHERE n.type = 'book' AND n.status = 1 AND n.nid = '". check_input($id) ."'");
Dries's avatar
 
Dries committed
297

Dries's avatar
 
Dries committed
298 299 300
  while ($page = db_fetch_object($result)) {
    // load the node:
    $node = node_load(array("nid" => $page->nid));
Dries's avatar
 
Dries committed
301

Dries's avatar
 
Dries committed
302 303
    // take the most recent approved revision:
    if ($node->moderate) {
Dries's avatar
 
Dries committed
304
      $node = node_revision_load($node, end(node_revision_list($node)));
Dries's avatar
 
Dries committed
305 306 307
    }

    // output the content:
Dries's avatar
 
Dries committed
308
    $output .= "<h$depth>". check_output($node->title) ."</h$depth>";
Dries's avatar
 
Dries committed
309 310 311 312

    if ($node->body) {
      $output .= "<blockquote>". check_output($node->body, 1) ."</blockquote>";
    }
Dries's avatar
 
Dries committed
313
  }
Dries's avatar
 
Dries committed
314

Dries's avatar
 
Dries committed
315 316 317 318 319 320
  $output .= book_export_html_recursive($id, $depth);

  return $output;
}

function book_export_html_recursive($parent = "", $depth = 1) {
Dries's avatar
 
Dries committed
321
  $result = db_query("SELECT n.nid FROM node n LEFT JOIN book b ON n.nid = b.nid WHERE n.type = 'book' AND n.status = 1 AND b.parent = '$parent' ORDER BY b.weight");
Dries's avatar
 
Dries committed
322

Dries's avatar
 
Dries committed
323 324 325 326 327 328
  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) {
Dries's avatar
 
Dries committed
329
      $node = node_revision_load($node, end(node_revision_list($node)));
Dries's avatar
 
Dries committed
330 331 332
    }

    // output the content:
Dries's avatar
 
Dries committed
333
    $output .= "<h$depth>". check_output($node->title) ."</h$depth>";
Dries's avatar
 
Dries committed
334 335 336 337 338

    if ($node->body) {
      $output .= "<blockquote>". check_output($node->body, 1) ."</blockquote>";
    }

Dries's avatar
 
Dries committed
339
    $output .= book_export_html_recursive($node->nid, $depth + 1);
Dries's avatar
 
Dries committed
340
  }
Dries's avatar
 
Dries committed
341

Dries's avatar
 
Dries committed
342 343
  return $output;
}
Dries's avatar
 
Dries committed
344

Dries's avatar
 
Dries committed
345
?>