PageRenderTime 49ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/mod/book/lib.php

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