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
?>