book.module 11.7 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
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
function book_save($op, $node) {

  if ($op == "approve") {
    return array("status" => 1);
  }

  if ($op == "create") {
    return array("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("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 derault.
      */

      return array("created" => time(), "moderate" => 1, "parent", "promote" => 0, "score" => 0, "status" => 1, "users" => "", "revisions", "votes" => 0, "weight");
    }
  }

}

Dries's avatar
   
Dries committed
80
81
82
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
83
  }
Dries's avatar
   
Dries committed
84
85

  return $links ? $links : array();
Dries's avatar
   
Dries committed
86
87
}

Dries's avatar
   
Dries committed
88
function book_load($node) {
Dries's avatar
   
Dries committed
89
  $book = db_fetch_object(db_query("SELECT parent, weight, revision FROM book WHERE nid = '$node->nid'"));
Dries's avatar
   
Dries committed
90
  return $book;
Dries's avatar
   
Dries committed
91
92
}

Dries's avatar
   
Dries committed
93
function book_insert($node) {
Dries's avatar
   
Dries committed
94
  db_query("INSERT INTO book (nid, parent, weight) VALUES ('$node->nid', '$node->parent', '$node->weight')");
Dries's avatar
   
Dries committed
95
}
Dries's avatar
   
Dries committed
96

Dries's avatar
   
Dries committed
97
function book_update($node) {
Dries's avatar
   
Dries committed
98
  db_query("UPDATE book SET parent = '$node->parent', weight = '$node->weight' WHERE nid = '$node->nid'");
Dries's avatar
   
Dries committed
99
}
Dries's avatar
   
Dries committed
100

Dries's avatar
   
Dries committed
101
102
function book_delete($node) {
  db_query("DELETE FROM book WHERE nid = '$node->nid'");
Dries's avatar
   
Dries committed
103
104
}

Dries's avatar
   
Dries committed
105

Dries's avatar
   
Dries committed
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
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
122
123
    $help = book_node("description");

Dries's avatar
   
Dries committed
124
125
126
127
128
129
130
131

    /*
    ** 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
132
    $node->uid = $user->uid;    // $node is passed by reference
Dries's avatar
   
Dries committed
133
134
135
136
137
138
139
    $node->name = $user->name;

  }

  return $output;
}

Dries's avatar
   
Dries committed
140
function book_location($node, $nodes = array()) {
Dries's avatar
   
Dries committed
141
  $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
142
143
144
145
146
147
148
  if ($parent->title) {
    $nodes = book_location($parent, $nodes);
    array_push($nodes, $parent);
  }
  return $nodes;
}

Dries's avatar
   
Dries committed
149
function book_view($node, $main = 0) {
Dries's avatar
   
Dries committed
150
151
152
153
154
155
156
157
158
  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
159
    $node = node_revision_load($node, end(node_revision_list($node)));
Dries's avatar
   
Dries committed
160
161
162
163
164
165
166
  }

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

Dries's avatar
   
Dries committed
168
169
  if ($main) {
    $theme->node($node, $main);
Dries's avatar
   
Dries committed
170
  }
Dries's avatar
   
Dries committed
171
172
  else {
    if ($node->nid && $node->parent) {
Dries's avatar
   
Dries committed
173
174
      $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
175
    }
Dries's avatar
   
Dries committed
176

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

Dries's avatar
   
Dries committed
179
180
    if ($node->title) {
      foreach (book_location($node) as $level) {
Dries's avatar
   
Dries committed
181
        $location .= "$indent <a href=\"node.php?id=$level->nid\">$level->title</a><br />";
Dries's avatar
   
Dries committed
182
183
        $indent .= "-";
      }
Dries's avatar
   
Dries committed
184

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

Dries's avatar
   
Dries committed
190
    if ($node->body) {
Dries's avatar
   
Dries committed
191
      $output .= " <tr><td colspan=\"3\"><br />". check_output($node->body, 1) ."</td></tr>";
Dries's avatar
   
Dries committed
192
    }
Dries's avatar
 
Dries committed
193

Dries's avatar
   
Dries committed
194
    if ($node->nid) {
Dries's avatar
   
Dries committed
195
      $output .= " <tr><td colspan=\"3\"><br />". book_tree($node->nid) ."</td></tr>";
Dries's avatar
   
Dries committed
196
    }
Dries's avatar
   
Dries committed
197

Dries's avatar
   
Dries committed
198
199
200
201
    $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
202

Dries's avatar
   
Dries committed
203
204
    $theme->box(t("Handbook"), $output);
  }
Dries's avatar
 
Dries committed
205
206
}

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

Dries's avatar
   
Dries committed
209
210
211
212
213
214
215
216
217
  /*
  ** 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
218

Dries's avatar
   
Dries committed
219
  if (user_access("administer nodes")) {
Dries's avatar
   
Dries committed
220
    $toc[0] = "<root>";
Dries's avatar
   
Dries committed
221
222
  }

Dries's avatar
   
Dries committed
223
224
225
226
  /*
  ** Build the table of contents:
  */

Dries's avatar
   
Dries committed
227
  while ($node = db_fetch_object($result)) {
Dries's avatar
   
Dries committed
228
229
    $toc[$node->nid] = "$indent $node->title";
    $toc = book_toc($node->nid, "$indent-", $toc);
Dries's avatar
   
Dries committed
230
  }
Dries's avatar
   
Dries committed
231

Dries's avatar
   
Dries committed
232
233
234
  return $toc;
}

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

Dries's avatar
   
Dries committed
237
  if ($depth < 3) {
Dries's avatar
   
Dries committed
238
239
240
241
242
    /*
    ** 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
243

Dries's avatar
   
Dries committed
244
245
246
247
248
249
    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
250
        $node = node_revision_load($node, end(node_revision_list($node)));
Dries's avatar
   
Dries committed
251
252
253
      }

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

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

Dries's avatar
   
Dries committed
260
    $output = "<ul>$output</ul>";
Dries's avatar
   
Dries committed
261
  }
Dries's avatar
   
Dries committed
262

Dries's avatar
   
Dries committed
263
264
265
  return $output;
}

Dries's avatar
   
Dries committed
266
function book_render() {
Dries's avatar
   
Dries committed
267
  global $theme;
Dries's avatar
Dries committed
268

Dries's avatar
   
Dries committed
269
  $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
270

Dries's avatar
   
Dries committed
271
272
273
274
275
276
  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
277
      $node = node_revision_load($node, end(node_revision_list($node)));
Dries's avatar
   
Dries committed
278
279
280
    }

    // output the content:
Dries's avatar
   
Dries committed
281
    $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
282
283
284
  }

  $theme->header();
Dries's avatar
   
Dries committed
285
  $theme->box(t("Handbook"), "<dl>$output</dl>");
Dries's avatar
   
Dries committed
286
287
288
289
290
291
  $theme->footer();
}

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

Dries's avatar
   
Dries committed
292
  if (user_access("access content")) {
Dries's avatar
   
Dries committed
293
294
    switch ($op) {
      case "feed":
Dries's avatar
   
Dries committed
295
        print book_export_html($id, $depth = 1);
Dries's avatar
   
Dries committed
296
297
298
        break;
      default:
        book_render();
Dries's avatar
   
Dries committed
299
300
301
302
303
304
305
    }
  }
  else {
    $theme->header();
    $theme->box(t("Access denied"), message_access());
    $theme->footer();
  }
Dries's avatar
 
Dries committed
306
307
}

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

Dries's avatar
   
Dries committed
311
312
313
  while ($page = db_fetch_object($result)) {
    // load the node:
    $node = node_load(array("nid" => $page->nid));
Dries's avatar
   
Dries committed
314

Dries's avatar
   
Dries committed
315
316
    // take the most recent approved revision:
    if ($node->moderate) {
Dries's avatar
   
Dries committed
317
      $node = node_revision_load($node, end(node_revision_list($node)));
Dries's avatar
   
Dries committed
318
319
320
    }

    // output the content:
Dries's avatar
   
Dries committed
321
    $output .= "<h$depth>". check_output($node->title) ."</h$depth>";
Dries's avatar
   
Dries committed
322
323
324
325

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

Dries's avatar
   
Dries committed
328
329
330
331
332
333
  $output .= book_export_html_recursive($id, $depth);

  return $output;
}

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

Dries's avatar
   
Dries committed
336
337
338
339
340
341
  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
342
      $node = node_revision_load($node, end(node_revision_list($node)));
Dries's avatar
   
Dries committed
343
344
345
    }

    // output the content:
Dries's avatar
   
Dries committed
346
    $output .= "<h$depth>". check_output($node->title) ."</h$depth>";
Dries's avatar
   
Dries committed
347
348
349
350
351

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

Dries's avatar
   
Dries committed
352
    $output .= book_export_html_recursive($node->nid, $depth + 1);
Dries's avatar
   
Dries committed
353
  }
Dries's avatar
   
Dries committed
354

Dries's avatar
   
Dries committed
355
356
  return $output;
}
Dries's avatar
   
Dries committed
357

Dries's avatar
 
Dries committed
358
?>