fixed log action inserts
[moodle.git] / lib.php
1 <?PHP // $Id: lib.php,v 1.1 2006/03/12 18:39:59 skodak Exp $
3 define('NUM_NONE',     '0');
4 define('NUM_NUMBERS',  '1');
5 define('NUM_BULLETS',  '2');
6 define('NUM_INDENTED', '3');
8 $NUMBERING_TYPE = array (NUM_NONE       => get_string('numbering0', 'book'),
9                          NUM_NUMBERS    => get_string('numbering1', 'book'),
10                          NUM_BULLETS    => get_string('numbering2', 'book'),
11                          NUM_INDENTED   => get_string('numbering3', 'book') );
13 if (!isset($CFG->book_tocwidth)) {
14     set_config("book_tocwidth", 180);  // default toc width
15 }
18 /// Library of functions and constants for module 'book'
20 function book_add_instance($book) {
21 /// Given an object containing all the necessary data,
22 /// (defined by the form in mod.html) this function
23 /// will create a new instance and return the id number
24 /// of the new instance.
26     $book->timecreated = time();
27     $book->timemodified = $book->timecreated;
29     return insert_record('book', $book);
30 }
33 function book_update_instance($book) {
34 /// Given an object containing all the necessary data,
35 /// (defined by the form in mod.html) this function
36 /// will update an existing instance with new data.
38     $book->timemodified = time();
39     $book->id = $book->instance;
41     # May have to add extra stuff in here #
43     return update_record('book', $book);
44 }
47 function book_delete_instance($id) {
48 /// Given an ID of an instance of this module,
49 /// this function will permanently delete the instance
50 /// and any data that depends on it.
52     if (! $book = get_record('book', 'id', $id)) {
53         return false;
54     }
56     $result = true;
58     delete_records('book_chapters', 'bookid', $book->id);
60     if (! delete_records('book', 'id', $book->id)) {
61         $result = false;
62     }
64     return $result;
65 }
67 function book_user_outline($course, $user, $mod, $book) {
68 /// Return a small object with summary information about what a
69 /// user has done with a given particular instance of this module
70 /// Used for user activity reports.
71 /// $return->time = the time they did it
72 /// $return->info = a short text description
74     $return = null;
75     return $return;
76 }
78 function book_user_complete($course, $user, $mod, $book) {
79 /// Print a detailed representation of what a  user has done with
80 /// a given particular instance of this module, for user activity reports.
82     return true;
83 }
85 function book_print_recent_activity($course, $isteacher, $timestart) {
86 /// Given a course and a time, this module should find recent activity
87 /// that has occurred in book activities and print it out.
88 /// Return true if there was output, or false is there was none.
90     global $CFG;
92     return false;  //  True if anything was printed, otherwise false
93 }
95 function book_cron () {
96 /// Function to be run periodically according to the moodle cron
97 /// This function searches for things that need to be done, such
98 /// as sending out mail, toggling flags etc ...
100     global $CFG;
102     return true;
105 function book_grades($bookid) {
106 /// Must return an array of grades for a given instance of this module,
107 /// indexed by user.  It also returns a maximum allowed grade.
109     return NULL;
112 function book_get_participants($bookid) {
113 //Must return an array of user records (all data) who are participants
114 //for a given instance of book. Must include every user involved
115 //in the instance, independient of his role (student, teacher, admin...)
116 //See other modules as example.
118     return false;
121 function book_scale_used ($bookid,$scaleid) {
122 //This function returns if a scale is being used by one book
123 //it it has support for grading and scales. Commented code should be
124 //modified if necessary. See forum, glossary or journal modules
125 //as reference.
127     $return = false;
129     //$rec = get_record('book','id',$bookid,'scale',"-$scaleid");
130     //
131     //if (!empty($rec)  && !empty($scaleid)) {
132     //    $return = true;
133     //}
135     return $return;
138 //////////////////////////////////////////////////////////////////////////////////////
139 /// Any other book functions go here.  Each of them must have a name that
140 /// starts with book_
142 //check chapter ordering and
143 //make sure subchapter is not first in book
144 //hidden chapter must have all subchapters hidden too
145 function book_check_structure($bookid) {
146     if ($chapters = get_records('book_chapters', 'bookid', $bookid, 'pagenum', 'id, pagenum, subchapter, hidden')) {
147         $first = true;
148         $hidesub = true;
149         $i = 1;
150         foreach($chapters as $ch) {
151             if ($first and $ch->subchapter) {
152                 $ch->subchapter = 0;
153             }
154             $first = false;
155             if (!$ch->subchapter) {
156                 $hidesub = $ch->hidden;
157             } else {
158                 $ch->hidden = $hidesub ? true : $ch->hidden;
159             }
160             $ch->pagenum = $i;
161             update_record('book_chapters', $ch);
162             $i++;
163         }
164     }
168 /// prepare button to turn chapter editing on - connected with course editing
169 function book_edit_button($id, $courseid, $chapterid) {
170     global $CFG, $USER;
173     if (isteacheredit($courseid)) {
174         if (!empty($USER->editing)) {
175             $string = get_string("turneditingoff");
176             $edit = '0';
177         } else {
178             $string = get_string("turneditingon");
179             $edit = '1';
180         }
181         return '<form target="'.$CFG->framename.'" method="get" action="'.$CFG->wwwroot.'/mod/book/view.php">'.
182                '<input type="hidden" name="id" value="'.$id.'" />'.
183                '<input type="hidden" name="chapterid" value="'.$chapterid.'" />'.
184                '<input type="hidden" name="edit" value="'.$edit.'" />'.
185                '<input type="submit" value="'.$string.'" /></form>';
186     } else {
187         return '';
188     }
191 /// general function for logging to table
192 function book_log($str1, $str2, $level = 0) {
193     switch ($level) {
194         case 1:
195             echo '<tr><td><span class="dimmed_text">'.$str1.'</span></td><td><span class="dimmed_text">'.$str2.'</span></td></tr>';
196             break;
197         case 2:
198             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>';
199             break;
200         default:
201             echo '<tr><td>'.$str1.'</class></td><td>'.$str2.'</td></tr>';
202             break;
203     }
206 //=================================================
207 // import functions
208 //=================================================
210 /// normalize relative links (= remove ..)
211 function book_prepare_link($ref) {
212     if ($ref == '') {
213         return '';
214     }
215     $ref = str_replace('\\','/',$ref); //anti MS hack
216     $cnt = substr_count($ref, '..');
217     for($i=0; $i<$cnt; $i++) {
218         $ref = ereg_replace('[^/]+/\.\./', '', $ref);
219     }
220     //still any '..' left?? == error! error!
221     if (substr_count($ref, '..') > 0) {
222         return '';
223     }
224     if (ereg('[\|\`]', $ref)) {  // check for other bad characters
225         return '';
226     }
227     return $ref;
230 /// read chapter content from file
231 function book_read_chapter($base, $ref) {
232     $file = $base.'/'.$ref;
233     if (filesize($file) <= 0 or !is_readable($file)) {
234         book_log($ref, get_string('error'), 2);
235         return;
236     }
237     //first read data
238     $handle = fopen($file, "rb");
239     $contents = fread($handle, filesize($file));
240     fclose($handle);
241     //extract title
242     if (preg_match('/<title>([^<]+)<\/title>/i', $contents, $matches)) {
243         $chapter->title = $matches[1];
244     } else {
245         $chapter->title = $ref;
246     }
247     //extract page body
248     if (preg_match('/<body[^>]*>(.+)<\/body>/is', $contents, $matches)) {
249         $chapter->content = $matches[1];
250     } else {
251         book_log($ref, get_string('error'), 2);
252         return;
253     }
254     book_log($ref, get_string('ok'));
255     $chapter->importsrc = $ref;
256     //extract page head
257     if (preg_match('/<head[^>]*>(.+)<\/head>/is', $contents, $matches)) {
258         $head = $matches[1];
259         if (preg_match('/charset=([^"]+)/is', $head, $matches)) {
260             $enc = $matches[1];
261             $textlib = textlib_get_instance();
262             $chapter->content = $textlib->convert($chapter->content, $enc, current_charset());
263             $chapter->title = $textlib->convert($chapter->title, $enc, current_charset());
264         }
265         if (preg_match_all('/<link[^>]+rel="stylesheet"[^>]*>/i', $head, $matches)) { //dlnsk extract links to css
266             for($i=0; $i<count($matches[0]); $i++){
267                 $chapter->content = $matches[0][$i]."\n".$chapter->content;
268             }
269         }
270     }
271     return $chapter;
274 ///relink images and relative links
275 function book_relink($id, $bookid, $courseid) {
276     global $CFG;
277     if ($CFG->slasharguments) {
278         $coursebase = $CFG->wwwroot.'/file.php/'.$courseid;
279     } else {
280         $coursebase = $CFG->wwwroot.'/file.php?file=/'.$courseid;
281     }
282     $chapters = get_records('book_chapters', 'bookid', $bookid, 'pagenum', 'id, pagenum, title, content, importsrc');
283     $originals = array();
284     foreach($chapters as $ch) {
285         $originals[$ch->importsrc] = $ch;
286     }
287     foreach($chapters as $ch) {
288         $rel = substr($ch->importsrc, 0, strrpos($ch->importsrc, '/')+1);
289         $base = $coursebase.strtr(urlencode($rel), array("%2F" => "/"));  //for better internationalization (dlnsk) 
290         $modified = false;
291         //image relinking
292         if ($ch->importsrc && preg_match_all('/(<img[^>]+src=")([^"]+)("[^>]*>)/i', $ch->content, $images)) {
293             for($i = 0; $i<count($images[0]); $i++) {
294                 if (!preg_match('/[a-z]+:/i', $images[2][$i])) { // not absolute link
295                     $link = book_prepare_link($base.$images[2][$i]);
296                     if ($link == '') {
297                         continue;
298                     }
299                     $origtag = $images[0][$i];
300                     $newtag = $images[1][$i].$link.$images[3][$i];
301                     $ch->content = str_replace($origtag, $newtag, $ch->content);
302                     $modified = true;
303                     book_log($ch->title, $images[2][$i].' --> '.$link);
304                 }
305             }
306         }
307         //css relinking (dlnsk)
308         if ($ch->importsrc && preg_match_all('/(<link[^>]+href=")([^"]+)("[^>]*>)/i', $ch->content, $csslinks)) {
309             for($i = 0; $i<count($csslinks[0]); $i++) {
310                 if (!preg_match('/[a-z]+:/i', $csslinks[2][$i])) { // not absolute link
311                     $link = book_prepare_link($base.$csslinks[2][$i]);
312                     if ($link == '') {
313                         continue;
314                     }
315                     $origtag = $csslinks[0][$i];
316                     $newtag = $csslinks[1][$i].$link.$csslinks[3][$i];
317                     $ch->content = str_replace($origtag, $newtag, $ch->content);
318                     $modified = true;
319                     book_log($ch->title, $csslinks[2][$i].' --> '.$link);
320                 }
321             }
322         }
323         //general embed relinking - flash and others??
324         if ($ch->importsrc && preg_match_all('/(<embed[^>]+src=")([^"]+)("[^>]*>)/i', $ch->content, $embeds)) {
325             for($i = 0; $i<count($embeds[0]); $i++) {
326                 if (!preg_match('/[a-z]+:/i', $embeds[2][$i])) { // not absolute link
327                     $link = book_prepare_link($base.$embeds[2][$i]);
328                     if ($link == '') {
329                         continue;
330                     }
331                     $origtag = $embeds[0][$i];
332                     $newtag = $embeds[1][$i].$link.$embeds[3][$i];
333                     $ch->content = str_replace($origtag, $newtag, $ch->content);
334                     $modified = true;
335                     book_log($ch->title, $embeds[2][$i].' --> '.$link);
336                 }
337             }
338         }
339         //flash in IE <param name=movie value="something" - I do hate IE!
340         if ($ch->importsrc && preg_match_all('/<param[^>]+name\s*=\s*"?movie"?[^>]*>/i', $ch->content, $params)) {
341             for($i = 0; $i<count($params[0]); $i++) {
342                 if (preg_match('/(value=\s*")([^"]+)(")/i', $params[0][$i], $values)) {
343                     if (!preg_match('/[a-z]+:/i', $values[2])) { // not absolute link
344                         $link = book_prepare_link($base.$values[2]);
345                         if ($link == '') {
346                             continue;
347                         }
348                         $newvalue = $values[1].$link.$values[3];
349                         $newparam = str_replace($values[0], $newvalue, $params[0][$i]);
350                         $ch->content = str_replace($params[0][$i], $newparam, $ch->content);
351                         $modified = true;
352                         book_log($ch->title, $values[2].' --> '.$link);
353                     }
354                 }
355             }
356         }
357         //java applet - add code bases if not present!!!!
358         if ($ch->importsrc && preg_match_all('/<applet[^>]*>/i', $ch->content, $applets)) {
359             for($i = 0; $i<count($applets[0]); $i++) {
360                 if (!stripos($applets[0][$i], 'codebase')) {
361                     $newapplet = str_ireplace('<applet', '<applet codebase="."', $applets[0][$i]);
362                     $ch->content = str_replace($applets[0][$i], $newapplet, $ch->content);
363                     $modified = true;
364                 }
365             }
366         }
367         //relink java applet code bases
368         if ($ch->importsrc && preg_match_all('/(<applet[^>]+codebase=")([^"]+)("[^>]*>)/i', $ch->content, $codebases)) {
369             for($i = 0; $i<count($codebases[0]); $i++) {
370                 if (!preg_match('/[a-z]+:/i', $codebases[2][$i])) { // not absolute link
371                     $link = book_prepare_link($base.$codebases[2][$i]);
372                     if ($link == '') {
373                         continue;
374                     }
375                     $origtag = $codebases[0][$i];
376                     $newtag = $codebases[1][$i].$link.$codebases[3][$i];
377                     $ch->content = str_replace($origtag, $newtag, $ch->content);
378                     $modified = true;
379                     book_log($ch->title, $codebases[2][$i].' --> '.$link);
380                 }
381             }
382         }
383         //relative link conversion
384         if ($ch->importsrc && preg_match_all('/(<a[^>]+href=")([^"^#]*)(#[^"]*)?("[^>]*>)/i', $ch->content, $links)) {
385             for($i = 0; $i<count($links[0]); $i++) {
386                 if ($links[2][$i] != ''                         //check for inner anchor links
387                 && !preg_match('/[a-z]+:/i', $links[2][$i])) { //not absolute link
388                     $origtag = $links[0][$i];
389                     $target = book_prepare_link($rel.$links[2][$i]); //target chapter
390                     if ($target != '' && array_key_exists($target, $originals)) {
391                         $o = $originals[$target];
392                         $newtag = $links[1][$i].$CFG->wwwroot.'/mod/book/view.php?id='.$id.'&chapterid='.$o->id.$links[3][$i].$links[4][$i];
393                         $newtag = preg_replace('/target=[^\s>]/i','', $newtag);
394                         $ch->content = str_replace($origtag, $newtag, $ch->content);
395                         $modified = true;
396                         book_log($ch->title, $links[2][$i].$links[3][$i].' --> '.$CFG->wwwroot.'/mod/book/view.php?id='.$id.'&chapterid='.$o->id.$links[3][$i]);
397                     } else if ($target!='' && (!preg_match('/\.html$|\.htm$/i', $links[2][$i]))) { // other relative non html links converted to download links
398                         $target = book_prepare_link($base.$links[2][$i]);
399                         $origtag = $links[0][$i];
400                         $newtag = $links[1][$i].$target.$links[4][$i];
401                         $ch->content = str_replace($origtag, $newtag, $ch->content);
402                         $modified = true;
403                         book_log($ch->title, $links[2][$i].' --> '.$target);
404                     }
405                 }
406             }
407         }
408         if ($modified) {
409             $ch->title = addslashes($ch->title);
410             $ch->content = addslashes($ch->content);
411             $ch->importsrc = addslashes($ch->importsrc);
412             if (!update_record('book_chapters', $ch)) {
413                 error('Could not update your book');
414             }
415         }
416     }
419 ?>