book.module 11.5 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
  $info["name"] = t("book page");
Dries's avatar
 
Dries committed
8
  $info["description"] = t("A book is a collaborative writing effort: users can collaborate writing the pages of the book, positioning the pages in the right order, and reviewing or modifying pages previously written.  So when you have some information to share or when you read a page of the book and you didn't like it, or if you think a certain page could have been written better, you can do something about it.");
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
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:
    */

Dries's avatar
 
Dries committed
110 111
    $help = book_node("description");

Dries's avatar
 
Dries committed
112 113 114 115 116 117 118 119

    /*
    ** 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
120
    $node->uid = $user->uid;    // $node is passed by reference
Dries's avatar
 
Dries committed
121 122 123 124 125 126 127
    $node->name = $user->name;

  }

  return $output;
}

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

Dries's avatar
 
Dries committed
137
function book_view($node, $main = 0) {
Dries's avatar
 
Dries committed
138 139 140 141 142 143 144 145 146
  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
147
    $node = node_revision_load($node, end(node_revision_list($node)));
Dries's avatar
 
Dries committed
148 149 150 151 152 153 154
  }

  /*
  ** 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
155

Dries's avatar
 
Dries committed
156 157
  if ($main) {
    $theme->node($node, $main);
Dries's avatar
 
Dries committed
158
  }
Dries's avatar
 
Dries committed
159 160
  else {
    if ($node->nid && $node->parent) {
Dries's avatar
 
Dries committed
161 162
      $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
163
    }
Dries's avatar
 
Dries committed
164

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

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

Dries's avatar
 
Dries committed
173 174 175
      $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
176
    }
Dries's avatar
 
Dries committed
177

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

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

Dries's avatar
 
Dries committed
186 187 188 189
    $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
190

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

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

Dries's avatar
 
Dries committed
197 198 199 200 201 202 203 204 205
  /*
  ** 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
206

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

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

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

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

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

Dries's avatar
 
Dries committed
225
  if ($depth < 3) {
Dries's avatar
 
Dries committed
226 227 228 229 230
    /*
    ** 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
231

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

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

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

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

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

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

Dries's avatar
 
Dries committed
257
  $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
258

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

    // output the content:
Dries's avatar
 
Dries committed
269
    $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
270 271 272
  }

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

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

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

Dries's avatar
 
Dries committed
296
function book_export_html($id = "", $depth = 1) {
Dries's avatar
 
Dries committed
297
  $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
298

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

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

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

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

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

  return $output;
}

function book_export_html_recursive($parent = "", $depth = 1) {
Dries's avatar
 
Dries committed
322
  $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
323

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

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

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

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

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

Dries's avatar
 
Dries committed
346
?>