MDL-32709 book: replace some deprecated stuff. Some pending yet, blame $PAGE
[moodle.git] / mod / book / locallib.php
CommitLineData
e355240d
PS
1<?php
2// This file is part of Book module for Moodle - http://moodle.org/
3//
4// Moodle is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8//
9// Moodle is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12// GNU General Public License for more details.
13//
14// You should have received a copy of the GNU General Public License
15// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
16
17/**
18 * Book module local lib functions
19 *
3542c4f4
EL
20 * @package mod_book
21 * @copyright 2010-2011 Petr Skoda {@link http://skodak.org}
e355240d
PS
22 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
23 */
24
25defined('MOODLE_INTERNAL') || die;
26
f6ca19ae
PS
27require_once($CFG->dirroot.'/mod/book/lib.php');
28require_once($CFG->libdir.'/filelib.php');
29
45573d5a
PS
30define('BOOK_NUM_NONE', '0');
31define('BOOK_NUM_NUMBERS', '1');
32define('BOOK_NUM_BULLETS', '2');
33define('BOOK_NUM_INDENTED', '3');
34
2c1e98e6 35/**
ad1c11bd
PS
36 * Preload book chapters and fix toc structure if necessary.
37 *
38 * Returns array of chapters with standard 'pagenum', 'id, pagenum, subchapter, title, hidden'
39 * and extra 'parent, number, subchapters, prev, next'.
40 * Please note the content/text of chapters is not included.
41 *
b962f030 42 * @param stdClass $book
ad1c11bd 43 * @return array of id=>chapter
2c1e98e6 44 */
b1a9b01e 45function book_preload_chapters($book) {
2c1e98e6 46 global $DB;
b1a9b01e 47 $chapters = $DB->get_records('book_chapters', array('bookid'=>$book->id), 'pagenum', 'id, pagenum, subchapter, title, hidden');
ad1c11bd
PS
48 if (!$chapters) {
49 return array();
50 }
51
52 $prev = null;
53 $prevsub = null;
2c1e98e6 54
ad1c11bd
PS
55 $first = true;
56 $hidesub = true;
57 $parent = null;
58 $pagenum = 0; // chapter sort
59 $i = 0; // main chapter num
60 $j = 0; // subchapter num
61 foreach($chapters as $id=>$ch) {
62 $oldch = clone($ch);
63 $pagenum++;
64 $ch->pagenum = $pagenum;
65 if ($first) {
66 // book can not start with a subchapter
67 $ch->subchapter = 0;
68 $first = false;
69 }
70 if (!$ch->subchapter) {
71 $ch->prev = $prev;
72 $ch->next = null;
73 if ($prev) {
74 $chapters[$prev]->next = $ch->id;
75 }
76 if ($ch->hidden) {
b1a9b01e
PS
77 if ($book->numbering == BOOK_NUM_NUMBERS) {
78 $ch->number = 'x';
79 } else {
80 $ch->number = null;
81 }
ad1c11bd
PS
82 } else {
83 $i++;
84 $ch->number = $i;
85 }
86 $j = 0;
87 $prevsub = null;
88 $hidesub = $ch->hidden;
89 $parent = $ch->id;
90 $ch->parent = null;
91 $ch->subchpaters = array();
92 } else {
93 $ch->prev = $prevsub;
94 $ch->next = null;
95 if ($prevsub) {
96 $chapters[$prevsub]->next = $ch->id;
e355240d 97 }
ad1c11bd
PS
98 $ch->parent = $parent;
99 $ch->subchpaters = null;
100 $chapters[$parent]->subchapters[$ch->id] = $ch->id;
101 if ($hidesub) {
102 // all subchapters in hidden chapter must be hidden too
bc953600 103 $ch->hidden = 1;
e355240d 104 }
ad1c11bd 105 if ($ch->hidden) {
b1a9b01e
PS
106 if ($book->numbering == BOOK_NUM_NUMBERS) {
107 $ch->number = 'x';
108 } else {
109 $ch->number = null;
110 }
ad1c11bd
PS
111 } else {
112 $j++;
113 $ch->number = $j;
23b02c4f 114 }
e355240d 115 }
ad1c11bd
PS
116 if ($oldch->subchapter != $ch->subchapter or $oldch->pagenum != $ch->pagenum or $oldch->hidden != $ch->hidden) {
117 // update only if something changed
118 $DB->update_record('book_chapters', $ch);
119 }
120 $chapters[$id] = $ch;
e355240d 121 }
ad1c11bd
PS
122
123 return $chapters;
e355240d
PS
124}
125
3542c4f4
EL
126/**
127 * Returns the title for a given chapter
128 *
129 * @param int $chid
130 * @param array $chapters
131 * @param stdClass $book
132 * @param context_module $context
133 * @return string
134 */
b1a9b01e
PS
135function book_get_chapter_title($chid, $chapters, $book, $context) {
136 $ch = $chapters[$chid];
137 $title = trim(format_string($ch->title, true, array('context'=>$context)));
138 $numbers = array();
139 if ($book->numbering == BOOK_NUM_NUMBERS) {
140 if ($ch->parent and $chapters[$ch->parent]->number) {
141 $numbers[] = $chapters[$ch->parent]->number;
142 }
143 if ($ch->number) {
144 $numbers[] = $ch->number;
145 }
146 }
147
148 if ($numbers) {
149 $title = implode('.', $numbers).' '.$title;
150 }
151
152 return $title;
153}
154
f6ca19ae
PS
155/**
156 * General logging to table
157 * @param string $str1
158 * @param string $str2
159 * @param int $level
160 * @return void
161 */
e355240d
PS
162function book_log($str1, $str2, $level = 0) {
163 switch ($level) {
164 case 1:
165 echo '<tr><td><span class="dimmed_text">'.$str1.'</span></td><td><span class="dimmed_text">'.$str2.'</span></td></tr>';
166 break;
167 case 2:
168 echo '<tr><td><span style="color: rgb(255, 0, 0);">'.$str1.'</span></td><td><span style="color: rgb(255, 0, 0);">'.$str2.'</span></td></tr>';
169 break;
170 default:
171 echo '<tr><td>'.$str1.'</class></td><td>'.$str2.'</td></tr>';
172 break;
173 }
174}
175
3542c4f4
EL
176/**
177 * Add the book TOC sticky block to the 1st region available
178 *
179 * @param array $chapters
180 * @param stdClass $chapter
181 * @param stdClass $book
182 * @param stdClass $cm
183 * @param bool $edit
184 */
ad1c11bd
PS
185function book_add_fake_block($chapters, $chapter, $book, $cm, $edit) {
186 global $OUTPUT, $PAGE;
187
8cb50b2a 188 $toc = book_get_toc($chapters, $chapter, $book, $cm, $edit, 0);
ad1c11bd
PS
189
190 if ($edit) {
8cb50b2a 191 $toc .= '<div class="book_faq">';
ad1c11bd
PS
192 $toc .= $OUTPUT->help_icon('faq', 'mod_book', get_string('faq', 'mod_book'));
193 $toc .= '</div>';
194 }
195
196 $bc = new block_contents();
197 $bc->title = get_string('toc', 'mod_book');
198 $bc->attributes['class'] = 'block';
199 $bc->content = $toc;
200
201 $regions = $PAGE->blocks->get_regions();
202 $firstregion = reset($regions);
203 $PAGE->blocks->add_fake_block($bc, $firstregion);
204}
205
ee952cbb
PS
206/**
207 * Generate toc structure
208 *
209 * @param array $chapters
210 * @param stdClass $chapter
211 * @param stdClass $book
212 * @param stdClass $cm
213 * @param bool $edit
ee952cbb
PS
214 * @return string
215 */
216function book_get_toc($chapters, $chapter, $book, $cm, $edit) {
217 global $USER, $OUTPUT;
218
3542c4f4
EL
219 $toc = ''; // Representation of toc (HTML)
220 $nch = 0; // Chapter number
221 $ns = 0; // Subchapter number
ee952cbb
PS
222 $first = 1;
223
1fc9e895 224 $context = context_module::instance($cm->id);
ee952cbb
PS
225
226 switch ($book->numbering) {
227 case BOOK_NUM_NONE:
228 $toc .= '<div class="book_toc_none">';
229 break;
230 case BOOK_NUM_NUMBERS:
231 $toc .= '<div class="book_toc_numbered">';
232 break;
233 case BOOK_NUM_BULLETS:
234 $toc .= '<div class="book_toc_bullets">';
235 break;
236 case BOOK_NUM_INDENTED:
237 $toc .= '<div class="book_toc_indented">';
238 break;
239 }
240
241
3542c4f4 242 if ($edit) { // Teacher's TOC
f6ca19ae
PS
243 $toc .= '<ul>';
244 $i = 0;
245 foreach($chapters as $ch) {
246 $i++;
dc888a31 247 $title = trim(format_string($ch->title, true, array('context'=>$context)));
f6ca19ae
PS
248 if (!$ch->subchapter) {
249 $toc .= ($first) ? '<li>' : '</ul></li><li>';
250 if (!$ch->hidden) {
251 $nch++;
252 $ns = 0;
253 if ($book->numbering == BOOK_NUM_NUMBERS) {
254 $title = "$nch $title";
255 }
256 } else {
257 if ($book->numbering == BOOK_NUM_NUMBERS) {
258 $title = "x $title";
259 }
260 $title = '<span class="dimmed_text">'.$title.'</span>';
261 }
f6ca19ae
PS
262 } else {
263 $toc .= ($first) ? '<li><ul><li>' : '<li>';
264 if (!$ch->hidden) {
265 $ns++;
266 if ($book->numbering == BOOK_NUM_NUMBERS) {
267 $title = "$nch.$ns $title";
268 }
269 } else {
270 if ($book->numbering == BOOK_NUM_NUMBERS) {
271 $title = "x.x $title";
272 }
273 $title = '<span class="dimmed_text">'.$title.'</span>';
274 }
275 }
276
277 if ($ch->id == $chapter->id) {
278 $toc .= '<strong>'.$title.'</strong>';
f6ca19ae
PS
279 } else {
280 $toc .= '<a title="'.s($title).'" href="view.php?id='.$cm->id.'&amp;chapterid='.$ch->id.'">'.$title.'</a>';
281 }
282 $toc .= '&nbsp;&nbsp;';
283 if ($i != 1) {
284 $toc .= ' <a title="'.get_string('up').'" href="move.php?id='.$cm->id.'&amp;chapterid='.$ch->id.'&amp;up=1&amp;sesskey='.$USER->sesskey.'"><img src="'.$OUTPUT->pix_url('t/up').'" class="iconsmall" alt="'.get_string('up').'" /></a>';
285 }
286 if ($i != count($chapters)) {
287 $toc .= ' <a title="'.get_string('down').'" href="move.php?id='.$cm->id.'&amp;chapterid='.$ch->id.'&amp;up=0&amp;sesskey='.$USER->sesskey.'"><img src="'.$OUTPUT->pix_url('t/down').'" class="iconsmall" alt="'.get_string('down').'" /></a>';
288 }
289 $toc .= ' <a title="'.get_string('edit').'" href="edit.php?cmid='.$cm->id.'&amp;id='.$ch->id.'"><img src="'.$OUTPUT->pix_url('t/edit').'" class="iconsmall" alt="'.get_string('edit').'" /></a>';
290 $toc .= ' <a title="'.get_string('delete').'" href="delete.php?id='.$cm->id.'&amp;chapterid='.$ch->id.'&amp;sesskey='.$USER->sesskey.'"><img src="'.$OUTPUT->pix_url('t/delete').'" class="iconsmall" alt="'.get_string('delete').'" /></a>';
291 if ($ch->hidden) {
292 $toc .= ' <a title="'.get_string('show').'" href="show.php?id='.$cm->id.'&amp;chapterid='.$ch->id.'&amp;sesskey='.$USER->sesskey.'"><img src="'.$OUTPUT->pix_url('t/show').'" class="iconsmall" alt="'.get_string('show').'" /></a>';
293 } else {
294 $toc .= ' <a title="'.get_string('hide').'" href="show.php?id='.$cm->id.'&amp;chapterid='.$ch->id.'&amp;sesskey='.$USER->sesskey.'"><img src="'.$OUTPUT->pix_url('t/hide').'" class="iconsmall" alt="'.get_string('hide').'" /></a>';
295 }
4cd51b08 296 $toc .= ' <a title="'.get_string('addafter', 'mod_book').'" href="edit.php?cmid='.$cm->id.'&amp;pagenum='.$ch->pagenum.'&amp;subchapter='.$ch->subchapter.'"><img src="'.$OUTPUT->pix_url('add', 'mod_book').'" class="iconsmall" alt="'.get_string('addafter', 'mod_book').'" /></a>';
f6ca19ae
PS
297
298 $toc .= (!$ch->subchapter) ? '<ul>' : '</li>';
299 $first = 0;
300 }
301 $toc .= '</ul></li></ul>';
3542c4f4 302 } else { // Normal students view
f6ca19ae
PS
303 $toc .= '<ul>';
304 foreach($chapters as $ch) {
dc888a31 305 $title = trim(format_string($ch->title, true, array('context'=>$context)));
f6ca19ae
PS
306 if (!$ch->hidden) {
307 if (!$ch->subchapter) {
308 $nch++;
309 $ns = 0;
310 $toc .= ($first) ? '<li>' : '</ul></li><li>';
311 if ($book->numbering == BOOK_NUM_NUMBERS) {
312 $title = "$nch $title";
313 }
f6ca19ae
PS
314 } else {
315 $ns++;
316 $toc .= ($first) ? '<li><ul><li>' : '<li>';
317 if ($book->numbering == BOOK_NUM_NUMBERS) {
318 $title = "$nch.$ns $title";
319 }
320 }
321 if ($ch->id == $chapter->id) {
322 $toc .= '<strong>'.$title.'</strong>';
f6ca19ae
PS
323 } else {
324 $toc .= '<a title="'.s($title).'" href="view.php?id='.$cm->id.'&amp;chapterid='.$ch->id.'">'.$title.'</a>';
325 }
326 $toc .= (!$ch->subchapter) ? '<ul>' : '</li>';
327 $first = 0;
328 }
329 }
330 $toc .= '</ul></li></ul>';
331 }
332
333 $toc .= '</div>';
334
3542c4f4 335 $toc = str_replace('<ul></ul>', '', $toc); // Cleanup of invalid structures.
f6ca19ae 336
ee952cbb 337 return $toc;
f6ca19ae 338}
dd9b772b
PS
339
340
341/**
342 * File browsing support class
3542c4f4
EL
343 *
344 * @copyright 2010-2011 Petr Skoda {@link http://skodak.org}
345 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
dd9b772b
PS
346 */
347class book_file_info extends file_info {
3542c4f4 348 /** @var stdClass Course object */
dd9b772b 349 protected $course;
3542c4f4 350 /** @var stdClass Course module object */
dd9b772b 351 protected $cm;
3542c4f4 352 /** @var array Available file areas */
dd9b772b 353 protected $areas;
3542c4f4 354 /** @var string File area to browse */
dd9b772b
PS
355 protected $filearea;
356
3542c4f4
EL
357 /**
358 * Constructor
359 *
360 * @param file_browser $browser file_browser instance
361 * @param stdClass $course course object
362 * @param stdClass $cm course module object
363 * @param stdClass $context module context
364 * @param array $areas available file areas
365 * @param string $filearea file area to browse
366 */
dd9b772b
PS
367 public function __construct($browser, $course, $cm, $context, $areas, $filearea) {
368 parent::__construct($browser, $context);
369 $this->course = $course;
370 $this->cm = $cm;
371 $this->areas = $areas;
372 $this->filearea = $filearea;
373 }
374
375 /**
376 * Returns list of standard virtual file/directory identification.
377 * The difference from stored_file parameters is that null values
378 * are allowed in all fields
379 * @return array with keys contextid, filearea, itemid, filepath and filename
380 */
381 public function get_params() {
382 return array('contextid'=>$this->context->id,
383 'component'=>'mod_book',
384 'filearea' =>$this->filearea,
385 'itemid' =>null,
386 'filepath' =>null,
387 'filename' =>null);
388 }
389
390 /**
391 * Returns localised visible name.
392 * @return string
393 */
394 public function get_visible_name() {
395 return $this->areas[$this->filearea];
396 }
397
398 /**
399 * Can I add new files or directories?
400 * @return bool
401 */
402 public function is_writable() {
403 return false;
404 }
405
406 /**
407 * Is directory?
408 * @return bool
409 */
410 public function is_directory() {
411 return true;
412 }
413
414 /**
415 * Returns list of children.
416 * @return array of file_info instances
417 */
418 public function get_children() {
419 global $DB;
420
421 $children = array();
422 $chapters = $DB->get_records('book_chapters', array('bookid'=>$this->cm->instance), 'pagenum', 'id, pagenum');
423 foreach ($chapters as $itemid=>$unused) {
424 if ($child = $this->browser->get_file_info($this->context, 'mod_book', $this->filearea, $itemid)) {
425 $children[] = $child;
426 }
427 }
428 return $children;
429 }
430
431 /**
432 * Returns parent file_info instance
433 * @return file_info or null for root
434 */
435 public function get_parent() {
436 return $this->browser->get_file_info($this->context);
437 }
438}