refactor chapter title proccessing
[moodle.git] / 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 *
20 * @package mod
21 * @subpackage book
ad1c11bd 22 * @copyright 2010-2011 Petr Skoda {@link http://skodak.org}
e355240d
PS
23 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
24 */
25
26defined('MOODLE_INTERNAL') || die;
27
f6ca19ae
PS
28require_once($CFG->dirroot.'/mod/book/lib.php');
29require_once($CFG->libdir.'/filelib.php');
30
2c1e98e6 31/**
ad1c11bd
PS
32 * Preload book chapters and fix toc structure if necessary.
33 *
34 * Returns array of chapters with standard 'pagenum', 'id, pagenum, subchapter, title, hidden'
35 * and extra 'parent, number, subchapters, prev, next'.
36 * Please note the content/text of chapters is not included.
37 *
38 * @param $book
39 * @param $cm
40 * @return array of id=>chapter
2c1e98e6 41 */
b1a9b01e 42function book_preload_chapters($book) {
2c1e98e6 43 global $DB;
b1a9b01e 44 $chapters = $DB->get_records('book_chapters', array('bookid'=>$book->id), 'pagenum', 'id, pagenum, subchapter, title, hidden');
ad1c11bd
PS
45 if (!$chapters) {
46 return array();
47 }
48
49 $prev = null;
50 $prevsub = null;
2c1e98e6 51
ad1c11bd
PS
52 $first = true;
53 $hidesub = true;
54 $parent = null;
55 $pagenum = 0; // chapter sort
56 $i = 0; // main chapter num
57 $j = 0; // subchapter num
58 foreach($chapters as $id=>$ch) {
59 $oldch = clone($ch);
60 $pagenum++;
61 $ch->pagenum = $pagenum;
62 if ($first) {
63 // book can not start with a subchapter
64 $ch->subchapter = 0;
65 $first = false;
66 }
67 if (!$ch->subchapter) {
68 $ch->prev = $prev;
69 $ch->next = null;
70 if ($prev) {
71 $chapters[$prev]->next = $ch->id;
72 }
73 if ($ch->hidden) {
b1a9b01e
PS
74 if ($book->numbering == BOOK_NUM_NUMBERS) {
75 $ch->number = 'x';
76 } else {
77 $ch->number = null;
78 }
ad1c11bd
PS
79 } else {
80 $i++;
81 $ch->number = $i;
82 }
83 $j = 0;
84 $prevsub = null;
85 $hidesub = $ch->hidden;
86 $parent = $ch->id;
87 $ch->parent = null;
88 $ch->subchpaters = array();
89 } else {
90 $ch->prev = $prevsub;
91 $ch->next = null;
92 if ($prevsub) {
93 $chapters[$prevsub]->next = $ch->id;
e355240d 94 }
ad1c11bd
PS
95 $ch->parent = $parent;
96 $ch->subchpaters = null;
97 $chapters[$parent]->subchapters[$ch->id] = $ch->id;
98 if ($hidesub) {
99 // all subchapters in hidden chapter must be hidden too
bc953600 100 $ch->hidden = 1;
e355240d 101 }
ad1c11bd 102 if ($ch->hidden) {
b1a9b01e
PS
103 if ($book->numbering == BOOK_NUM_NUMBERS) {
104 $ch->number = 'x';
105 } else {
106 $ch->number = null;
107 }
ad1c11bd
PS
108 } else {
109 $j++;
110 $ch->number = $j;
23b02c4f 111 }
e355240d 112 }
ad1c11bd
PS
113 if ($oldch->subchapter != $ch->subchapter or $oldch->pagenum != $ch->pagenum or $oldch->hidden != $ch->hidden) {
114 // update only if something changed
115 $DB->update_record('book_chapters', $ch);
116 }
117 $chapters[$id] = $ch;
e355240d 118 }
ad1c11bd
PS
119
120 return $chapters;
e355240d
PS
121}
122
b1a9b01e
PS
123function book_get_chapter_title($chid, $chapters, $book, $context) {
124 $ch = $chapters[$chid];
125 $title = trim(format_string($ch->title, true, array('context'=>$context)));
126 $numbers = array();
127 if ($book->numbering == BOOK_NUM_NUMBERS) {
128 if ($ch->parent and $chapters[$ch->parent]->number) {
129 $numbers[] = $chapters[$ch->parent]->number;
130 }
131 if ($ch->number) {
132 $numbers[] = $ch->number;
133 }
134 }
135
136 if ($numbers) {
137 $title = implode('.', $numbers).' '.$title;
138 }
139
140 return $title;
141}
142
f6ca19ae
PS
143/**
144 * General logging to table
145 * @param string $str1
146 * @param string $str2
147 * @param int $level
148 * @return void
149 */
e355240d
PS
150function book_log($str1, $str2, $level = 0) {
151 switch ($level) {
152 case 1:
153 echo '<tr><td><span class="dimmed_text">'.$str1.'</span></td><td><span class="dimmed_text">'.$str2.'</span></td></tr>';
154 break;
155 case 2:
156 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>';
157 break;
158 default:
159 echo '<tr><td>'.$str1.'</class></td><td>'.$str2.'</td></tr>';
160 break;
161 }
162}
163
ad1c11bd
PS
164function book_add_fake_block($chapters, $chapter, $book, $cm, $edit) {
165 global $OUTPUT, $PAGE;
166
167 list($toc, $currtitle, $currsubtitle, $titles) = book_get_toc($chapters, $chapter, $book, $cm, $edit, 0);
168
169 if ($edit) {
170 $toc .= '<div class="faq">';
171 $toc .= $OUTPUT->help_icon('faq', 'mod_book', get_string('faq', 'mod_book'));
172 $toc .= '</div>';
173 }
174
175 $bc = new block_contents();
176 $bc->title = get_string('toc', 'mod_book');
177 $bc->attributes['class'] = 'block';
178 $bc->content = $toc;
179
180 $regions = $PAGE->blocks->get_regions();
181 $firstregion = reset($regions);
182 $PAGE->blocks->add_fake_block($bc, $firstregion);
183}
184
f6ca19ae
PS
185/**
186 * Generate toc structure and titles
187 *
188 * @param array $chapters
189 * @param stdClass $chapter
190 * @param stdClass $book
191 * @param stdClass $cm
192 * @param bool $edit
193 * @param bool $print
194 * @return array
195 */
196function book_get_toc($chapters, $chapter, $book, $cm, $edit, $print) {
197 global $USER, $OUTPUT;
198
199 $currtitle = ''; //active chapter title (plain text)
200 $currsubtitle = ''; //active subchapter if any
201 $prevtitle = '&nbsp;';
202 $toc = ''; //representation of toc (HTML)
203
204 $nch = 0; //chapter number
205 $ns = 0; //subchapter number
206 $first = 1;
207 $titles = array();
208
dc888a31
PS
209 $context = get_context_instance(CONTEXT_MODULE, $cm->id);
210
f6ca19ae
PS
211 switch ($book->numbering) {
212 case BOOK_NUM_NONE:
213 $toc .= '<div class="book_toc_none">';
214 break;
215 case BOOK_NUM_NUMBERS:
216 $toc .= '<div class="book_toc_numbered">';
217 break;
218 case BOOK_NUM_BULLETS:
219 $toc .= '<div class="book_toc_bullets">';
220 break;
221 case BOOK_NUM_INDENTED:
222 $toc .= '<div class="book_toc_indented">';
223 break;
224 }
225
226
227 if ($print) { ///TOC for printing
228 $toc .= '<a name="toc"></a>';
229 if ($book->customtitles) {
230 $toc .= '<h1>'.get_string('toc', 'book').'</h1>';
231 } else {
232 $toc .= '<p class="book_chapter_title">'.get_string('toc', 'book').'</p>';
233 }
234 $toc .= '<ul>';
235 foreach($chapters as $ch) {
dc888a31 236 $title = trim(format_string($ch->title, true, array('context'=>$context)));
f6ca19ae
PS
237 if (!$ch->hidden) {
238 if (!$ch->subchapter) {
239 $nch++;
240 $ns = 0;
241 $toc .= ($first) ? '<li>' : '</ul></li><li>';
242 if ($book->numbering == BOOK_NUM_NUMBERS) {
243 $title = "$nch $title";
244 }
245 } else {
246 $ns++;
247 $toc .= ($first) ? '<li><ul><li>' : '<li>';
248 if ($book->numbering == BOOK_NUM_NUMBERS) {
249 $title = "$nch.$ns $title";
250 }
251 }
252 $titles[$ch->id] = $title;
253 $toc .= '<a title="'.s($title).'" href="#ch'.$ch->id.'">'.$title.'</a>';
254 $toc .= (!$ch->subchapter) ? '<ul>' : '</li>';
255 $first = 0;
256 }
257 }
258 $toc .= '</ul></li></ul>';
259 } else if ($edit) { ///teacher's TOC
260 $toc .= '<ul>';
261 $i = 0;
262 foreach($chapters as $ch) {
263 $i++;
dc888a31 264 $title = trim(format_string($ch->title, true, array('context'=>$context)));
f6ca19ae
PS
265 if (!$ch->subchapter) {
266 $toc .= ($first) ? '<li>' : '</ul></li><li>';
267 if (!$ch->hidden) {
268 $nch++;
269 $ns = 0;
270 if ($book->numbering == BOOK_NUM_NUMBERS) {
271 $title = "$nch $title";
272 }
273 } else {
274 if ($book->numbering == BOOK_NUM_NUMBERS) {
275 $title = "x $title";
276 }
277 $title = '<span class="dimmed_text">'.$title.'</span>';
278 }
279 $prevtitle = $title;
280 } else {
281 $toc .= ($first) ? '<li><ul><li>' : '<li>';
282 if (!$ch->hidden) {
283 $ns++;
284 if ($book->numbering == BOOK_NUM_NUMBERS) {
285 $title = "$nch.$ns $title";
286 }
287 } else {
288 if ($book->numbering == BOOK_NUM_NUMBERS) {
289 $title = "x.x $title";
290 }
291 $title = '<span class="dimmed_text">'.$title.'</span>';
292 }
293 }
294
295 if ($ch->id == $chapter->id) {
296 $toc .= '<strong>'.$title.'</strong>';
297 if ($ch->subchapter) {
298 $currtitle = $prevtitle;
299 $currsubtitle = $title;
300 } else {
301 $currtitle = $title;
302 $currsubtitle = '&nbsp;';
303 }
304 } else {
305 $toc .= '<a title="'.s($title).'" href="view.php?id='.$cm->id.'&amp;chapterid='.$ch->id.'">'.$title.'</a>';
306 }
307 $toc .= '&nbsp;&nbsp;';
308 if ($i != 1) {
309 $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>';
310 }
311 if ($i != count($chapters)) {
312 $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>';
313 }
314 $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>';
315 $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>';
316 if ($ch->hidden) {
317 $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>';
318 } else {
319 $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>';
320 }
321 $toc .= ' <a title="'.get_string('addafter', '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', 'book').'" /></a>';
322
323 $toc .= (!$ch->subchapter) ? '<ul>' : '</li>';
324 $first = 0;
325 }
326 $toc .= '</ul></li></ul>';
327 } else { //normal students view
328 $toc .= '<ul>';
329 foreach($chapters as $ch) {
dc888a31 330 $title = trim(format_string($ch->title, true, array('context'=>$context)));
f6ca19ae
PS
331 if (!$ch->hidden) {
332 if (!$ch->subchapter) {
333 $nch++;
334 $ns = 0;
335 $toc .= ($first) ? '<li>' : '</ul></li><li>';
336 if ($book->numbering == BOOK_NUM_NUMBERS) {
337 $title = "$nch $title";
338 }
339 $prevtitle = $title;
340 } else {
341 $ns++;
342 $toc .= ($first) ? '<li><ul><li>' : '<li>';
343 if ($book->numbering == BOOK_NUM_NUMBERS) {
344 $title = "$nch.$ns $title";
345 }
346 }
347 if ($ch->id == $chapter->id) {
348 $toc .= '<strong>'.$title.'</strong>';
349 if ($ch->subchapter) {
350 $currtitle = $prevtitle;
351 $currsubtitle = $title;
352 } else {
353 $currtitle = $title;
354 $currsubtitle = '&nbsp;';
355 }
356 } else {
357 $toc .= '<a title="'.s($title).'" href="view.php?id='.$cm->id.'&amp;chapterid='.$ch->id.'">'.$title.'</a>';
358 }
359 $toc .= (!$ch->subchapter) ? '<ul>' : '</li>';
360 $first = 0;
361 }
362 }
363 $toc .= '</ul></li></ul>';
364 }
365
366 $toc .= '</div>';
367
368 $toc = str_replace('<ul></ul>', '', $toc); //cleanup of invalid structures
369
370 return array($toc, $currtitle, $currsubtitle, $titles);
371}
372
373
e355240d 374//=================================================
f6ca19ae 375// import functions - not converted yet!
e355240d
PS
376//=================================================
377
378/// normalize relative links (= remove ..)
379function book_prepare_link($ref) {
380 if ($ref == '') {
381 return '';
382 }
383 $ref = str_replace('\\','/',$ref); //anti MS hack
384 $cnt = substr_count($ref, '..');
385 for($i=0; $i<$cnt; $i++) {
386 $ref = ereg_replace('[^/]+/\.\./', '', $ref);
387 }
388 //still any '..' left?? == error! error!
389 if (substr_count($ref, '..') > 0) {
390 return '';
391 }
392 if (ereg('[\|\`]', $ref)) { // check for other bad characters
393 return '';
394 }
395 return $ref;
396}
397
398/// read chapter content from file
399function book_read_chapter($base, $ref) {
400 $file = $base.'/'.$ref;
401 if (filesize($file) <= 0 or !is_readable($file)) {
402 book_log($ref, get_string('error'), 2);
403 return;
404 }
405 //first read data
406 $handle = fopen($file, "rb");
407 $contents = fread($handle, filesize($file));
408 fclose($handle);
409 //extract title
410 $chapter = new object();
411 if (preg_match('/<title>([^<]+)<\/title>/i', $contents, $matches)) {
412 $chapter->title = $matches[1];
413 } else {
414 $chapter->title = $ref;
415 }
416 //extract page body
417 if (preg_match('/<body[^>]*>(.+)<\/body>/is', $contents, $matches)) {
418 $chapter->content = $matches[1];
419 } else {
420 book_log($ref, get_string('error'), 2);
421 return;
422 }
423 book_log($ref, get_string('ok'));
424 $chapter->importsrc = $ref;
425 //extract page head
426 if (preg_match('/<head[^>]*>(.+)<\/head>/is', $contents, $matches)) {
427 $head = $matches[1];
428 if (preg_match('/charset=([^"]+)/is', $head, $matches)) {
429 $enc = $matches[1];
430 $textlib = textlib_get_instance();
32230603
PS
431 $chapter->content = $textlib->convert($chapter->content, $enc, 'utf-8');
432 $chapter->title = $textlib->convert($chapter->title, $enc, 'utf-8');
e355240d
PS
433 }
434 if (preg_match_all('/<link[^>]+rel="stylesheet"[^>]*>/i', $head, $matches)) { //dlnsk extract links to css
435 for($i=0; $i<count($matches[0]); $i++){
436 $chapter->content = $matches[0][$i]."\n".$chapter->content;
437 }
438 }
439 }
440 return $chapter;
441}
442
443///relink images and relative links
444function book_relink($id, $bookid, $courseid) {
2c1e98e6
PS
445 global $CFG, $DB;
446
e355240d
PS
447 if ($CFG->slasharguments) {
448 $coursebase = $CFG->wwwroot.'/file.php/'.$courseid;
449 } else {
450 $coursebase = $CFG->wwwroot.'/file.php?file=/'.$courseid;
451 }
2c1e98e6 452 $chapters = $DB->get_records('book_chapters', array('bookid'=>$bookid), 'pagenum', 'id, pagenum, title, content, importsrc');
e355240d
PS
453 $originals = array();
454 foreach($chapters as $ch) {
455 $originals[$ch->importsrc] = $ch;
456 }
457 foreach($chapters as $ch) {
458 $rel = substr($ch->importsrc, 0, strrpos($ch->importsrc, '/')+1);
459 $base = $coursebase.strtr(urlencode($rel), array("%2F" => "/")); //for better internationalization (dlnsk)
460 $modified = false;
461 //image relinking
462 if ($ch->importsrc && preg_match_all('/(<img[^>]+src=")([^"]+)("[^>]*>)/i', $ch->content, $images)) {
463 for($i = 0; $i<count($images[0]); $i++) {
464 if (!preg_match('/[a-z]+:/i', $images[2][$i])) { // not absolute link
465 $link = book_prepare_link($base.$images[2][$i]);
466 if ($link == '') {
467 continue;
468 }
469 $origtag = $images[0][$i];
470 $newtag = $images[1][$i].$link.$images[3][$i];
471 $ch->content = str_replace($origtag, $newtag, $ch->content);
472 $modified = true;
473 book_log($ch->title, $images[2][$i].' --> '.$link);
474 }
475 }
476 }
477 //css relinking (dlnsk)
478 if ($ch->importsrc && preg_match_all('/(<link[^>]+href=")([^"]+)("[^>]*>)/i', $ch->content, $csslinks)) {
479 for($i = 0; $i<count($csslinks[0]); $i++) {
480 if (!preg_match('/[a-z]+:/i', $csslinks[2][$i])) { // not absolute link
481 $link = book_prepare_link($base.$csslinks[2][$i]);
482 if ($link == '') {
483 continue;
484 }
485 $origtag = $csslinks[0][$i];
486 $newtag = $csslinks[1][$i].$link.$csslinks[3][$i];
487 $ch->content = str_replace($origtag, $newtag, $ch->content);
488 $modified = true;
489 book_log($ch->title, $csslinks[2][$i].' --> '.$link);
490 }
491 }
492 }
493 //general embed relinking - flash and others??
494 if ($ch->importsrc && preg_match_all('/(<embed[^>]+src=")([^"]+)("[^>]*>)/i', $ch->content, $embeds)) {
495 for($i = 0; $i<count($embeds[0]); $i++) {
496 if (!preg_match('/[a-z]+:/i', $embeds[2][$i])) { // not absolute link
497 $link = book_prepare_link($base.$embeds[2][$i]);
498 if ($link == '') {
499 continue;
500 }
501 $origtag = $embeds[0][$i];
502 $newtag = $embeds[1][$i].$link.$embeds[3][$i];
503 $ch->content = str_replace($origtag, $newtag, $ch->content);
504 $modified = true;
505 book_log($ch->title, $embeds[2][$i].' --> '.$link);
506 }
507 }
508 }
509 //flash in IE <param name=movie value="something" - I do hate IE!
510 if ($ch->importsrc && preg_match_all('/<param[^>]+name\s*=\s*"?movie"?[^>]*>/i', $ch->content, $params)) {
511 for($i = 0; $i<count($params[0]); $i++) {
512 if (preg_match('/(value=\s*")([^"]+)(")/i', $params[0][$i], $values)) {
513 if (!preg_match('/[a-z]+:/i', $values[2])) { // not absolute link
514 $link = book_prepare_link($base.$values[2]);
515 if ($link == '') {
516 continue;
517 }
518 $newvalue = $values[1].$link.$values[3];
519 $newparam = str_replace($values[0], $newvalue, $params[0][$i]);
520 $ch->content = str_replace($params[0][$i], $newparam, $ch->content);
521 $modified = true;
522 book_log($ch->title, $values[2].' --> '.$link);
523 }
524 }
525 }
526 }
527 //java applet - add code bases if not present!!!!
528 if ($ch->importsrc && preg_match_all('/<applet[^>]*>/i', $ch->content, $applets)) {
529 for($i = 0; $i<count($applets[0]); $i++) {
530 if (!stripos($applets[0][$i], 'codebase')) {
531 $newapplet = str_ireplace('<applet', '<applet codebase="."', $applets[0][$i]);
532 $ch->content = str_replace($applets[0][$i], $newapplet, $ch->content);
533 $modified = true;
534 }
535 }
536 }
537 //relink java applet code bases
538 if ($ch->importsrc && preg_match_all('/(<applet[^>]+codebase=")([^"]+)("[^>]*>)/i', $ch->content, $codebases)) {
539 for($i = 0; $i<count($codebases[0]); $i++) {
540 if (!preg_match('/[a-z]+:/i', $codebases[2][$i])) { // not absolute link
541 $link = book_prepare_link($base.$codebases[2][$i]);
542 if ($link == '') {
543 continue;
544 }
545 $origtag = $codebases[0][$i];
546 $newtag = $codebases[1][$i].$link.$codebases[3][$i];
547 $ch->content = str_replace($origtag, $newtag, $ch->content);
548 $modified = true;
549 book_log($ch->title, $codebases[2][$i].' --> '.$link);
550 }
551 }
552 }
553 //relative link conversion
554 if ($ch->importsrc && preg_match_all('/(<a\s[^>]*href=")([^"^#]*)(#[^"]*)?("[^>]*>)/i', $ch->content, $links)) {
555 for($i = 0; $i<count($links[0]); $i++) {
556 if ($links[2][$i] != '' //check for inner anchor links
557 && !preg_match('/[a-z]+:/i', $links[2][$i])) { //not absolute link
558 $origtag = $links[0][$i];
559 $target = book_prepare_link($rel.$links[2][$i]); //target chapter
560 if ($target != '' && array_key_exists($target, $originals)) {
561 $o = $originals[$target];
562 $newtag = $links[1][$i].$CFG->wwwroot.'/mod/book/view.php?id='.$id.'&chapterid='.$o->id.$links[3][$i].$links[4][$i];
563 $newtag = preg_replace('/target=[^\s>]/i','', $newtag);
564 $ch->content = str_replace($origtag, $newtag, $ch->content);
565 $modified = true;
566 book_log($ch->title, $links[2][$i].$links[3][$i].' --> '.$CFG->wwwroot.'/mod/book/view.php?id='.$id.'&chapterid='.$o->id.$links[3][$i]);
567 } else if ($target!='' && (!preg_match('/\.html$|\.htm$/i', $links[2][$i]))) { // other relative non html links converted to download links
568 $target = book_prepare_link($base.$links[2][$i]);
569 $origtag = $links[0][$i];
570 $newtag = $links[1][$i].$target.$links[4][$i];
571 $ch->content = str_replace($origtag, $newtag, $ch->content);
572 $modified = true;
573 book_log($ch->title, $links[2][$i].' --> '.$target);
574 }
575 }
576 }
577 }
578 if ($modified) {
2c1e98e6 579 $DB->update_record('book_chapters', $ch);
e355240d
PS
580 }
581 }
582}