PageRenderTime 55ms CodeModel.GetById 27ms RepoModel.GetById 0ms app.codeStats 1ms

/generateimscp.php

https://github.com/mylescarrick/moodle-mod_book
PHP | 255 lines | 145 code | 38 blank | 72 comment | 14 complexity | 30ca690388e6414d5bbfc0057cfbae96 MD5 | raw file
  1. <?php
  2. ///////////////////////////////////////////////////////////////////////////
  3. // //
  4. // NOTICE OF COPYRIGHT //
  5. // //
  6. // Moodle - Modular Object-Oriented Dynamic Learning Environment //
  7. // http://moodle.com //
  8. // //
  9. // Copyright (C) 2001-3001 Antonio Vicent http://ludens.es //
  10. // (C) 2001-3001 Eloy Lafuente (stronk7) http://contiento.com //
  11. // //
  12. // This program is free software; you can redistribute it and/or modify //
  13. // it under the terms of the GNU General Public License as published by //
  14. // the Free Software Foundation; either version 2 of the License, or //
  15. // (at your option) any later version. //
  16. // //
  17. // This program is distributed in the hope that it will be useful, //
  18. // but WITHOUT ANY WARRANTY; without even the implied warranty of //
  19. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
  20. // GNU General Public License for more details: //
  21. // //
  22. // http://www.gnu.org/copyleft/gpl.html //
  23. // //
  24. ///////////////////////////////////////////////////////////////////////////
  25. require('../../config.php');
  26. require_once($CFG->dirroot.'/mod/book/locallib.php');
  27. require_once($CFG->dirroot.'/backup/lib.php');
  28. require_once($CFG->libdir.'/filelib.php');
  29. $id = required_param('id', PARAM_INT); // Course Module ID
  30. die('Not converted to 2.0 yet, sorry');
  31. if (!$cm = get_coursemodule_from_id('book', $id)) {
  32. error('Course Module ID was incorrect');
  33. }
  34. if (!$course = get_record('course', 'id', $cm->course)) {
  35. error('Course is misconfigured');
  36. }
  37. require_login($course, true, $cm);
  38. $context = get_context_instance(CONTEXT_MODULE, $cm->id);
  39. require_capability('mod/book:read', $context);
  40. require_capability('mod/book:exportimscp', $context);
  41. if (!$book = get_record('book', 'id', $cm->instance)) {
  42. error('Course module is incorrect');
  43. }
  44. $strbooks = get_string('modulenameplural', 'book');
  45. $strbook = get_string('modulename', 'book');
  46. $strtop = get_string('top', 'book');
  47. add_to_log($course->id, 'book', 'generateimscp', 'generateimscp.php?id='.$cm->id, $book->id, $cm->id);
  48. /// Get all the chapters
  49. $chapters = get_records('book_chapters', 'bookid', $book->id, 'pagenum');
  50. /// Generate the manifest and all the contents
  51. chapters2imsmanifest($chapters, $book, $cm);
  52. /// Now zip everything
  53. make_upload_directory('temp');
  54. $zipfile = $CFG->dataroot . "/temp/". time() . '.zip';
  55. $files = get_directory_list($CFG->dataroot . "/$cm->course/moddata/book/$book->id", basename($zipfile), false, true, true);
  56. foreach ($files as $key => $value) {
  57. $files[$key] = $CFG->dataroot . "/$cm->course/moddata/book/$book->id/" . $value;
  58. }
  59. zip_files($files, $zipfile);
  60. /// Now delete all the temp dirs
  61. delete_dir_contents($CFG->dataroot . "/$cm->course/moddata/book/$book->id");
  62. /// Now serve the file
  63. send_temp_file($zipfile, clean_filename($book->name) . '.zip');
  64. /**
  65. * This function will create the default imsmanifest plus contents for the book chapters passed as array
  66. * Everything will be created under the book moddata file area *
  67. */
  68. function chapters2imsmanifest ($chapters, $book, $cm) {
  69. global $CFG;
  70. /// Init imsmanifest and others
  71. $imsmanifest = '';
  72. $imsitems = '';
  73. $imsresources = '';
  74. /// Moodle and Book version
  75. $moodle_release = $CFG->release;
  76. $moodle_version = $CFG->version;
  77. $book_version = get_field('modules', 'version', 'name', 'book');
  78. /// Load manifest header
  79. $imsmanifest .= '<?xml version="1.0" encoding="UTF-8"?>
  80. <!-- This package has been created with Moodle ' . $moodle_release . ' (' . $moodle_version . '), Book module version ' . $book_version . ' - http://moodle.org -->
  81. <!-- One idea and implementation by Eloy Lafuente (stronk7) and Antonio Vicent (C) 2001-3001 -->
  82. <manifest xmlns="http://www.imsglobal.org/xsd/imscp_v1p1" xmlns:imsmd="http://www.imsglobal.org/xsd/imsmd_v1p2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" identifier="MANIFEST-' . md5($CFG->wwwroot . '-' . $book->course . '-' . $book->id) . '" xsi:schemaLocation="http://www.imsglobal.org/xsd/imscp_v1p1 imscp_v1p1.xsd http://www.imsglobal.org/xsd/imsmd_v1p2 imsmd_v1p2p2.xsd">
  83. <organizations default="MOODLE-' . $book->course . '-' . $book->id . '">
  84. <organization identifier="MOODLE-' . $book->course . '-' . $book->id . '" structure="hierarchical">
  85. <title>' . htmlspecialchars($book->name) . '</title>';
  86. /// Create the temp directory
  87. $moddir = "$cm->course/moddata/book/$book->id";
  88. make_upload_directory($moddir);
  89. /// For each chapter, create the corresponding directory and save contents there
  90. /// To store the prev level (book only have 0 and 1)
  91. $prevlevel = null;
  92. foreach ($chapters as $chapter) {
  93. /// Calculate current level ((book only have 0 and 1)
  94. $currlevel = empty($chapter->subchapter) ? 0 : 1;
  95. /// Based upon prevlevel and current one, decide what to close
  96. if ($prevlevel !== null) {
  97. /// Calculate the number of spaces (for visual xml-text formating)
  98. $prevspaces = substr(' ', 0, $currlevel * 2);
  99. /// Same level, simply close the item
  100. if ($prevlevel == $currlevel) {
  101. $imsitems .= $prevspaces . ' </item>' . "\n";
  102. }
  103. /// Bigger currlevel, nothing to close
  104. /// Smaller currlevel, close both the current item and the parent one
  105. if ($prevlevel > $currlevel) {
  106. $imsitems .= ' </item>' . "\n";
  107. $imsitems .= ' </item>' . "\n";
  108. }
  109. }
  110. /// Update prevlevel
  111. $prevlevel = $currlevel;
  112. /// Calculate the number of spaces (for visual xml-text formating)
  113. $currspaces = substr(' ', 0, $currlevel * 2);
  114. /// Create the static html file + local attachments (images...)
  115. $chapterdir = "$moddir/$chapter->pagenum";
  116. make_upload_directory($chapterdir);
  117. $chaptercontent = chapter2html($chapter, $book->course, $book->id);
  118. file_put_contents($CFG->dataroot . "/" . $chapterdir . "/index.html", $chaptercontent->content);
  119. /// Add the imsitems
  120. $imsitems .= $currspaces .' <item identifier="ITEM-' . $book->course . '-' . $book->id . '-' . $chapter->pagenum .'" isvisible="true" identifierref="RES-' . $book->course . '-' . $book->id . '-' . $chapter->pagenum . '">
  121. ' . $currspaces . ' <title>' . htmlspecialchars($chapter->title) . '</title>' . "\n";
  122. /// Add the imsresources
  123. /// First, check if we have localfiles
  124. $localfiles = '';
  125. if ($chaptercontent->localfiles) {
  126. foreach ($chaptercontent->localfiles as $localfile) {
  127. $localfiles .= "\n" . ' <file href="' . $chapter->pagenum . '/' . $localfile . '" />';
  128. }
  129. }
  130. /// Now add the dependency to css
  131. $cssdependency = "\n" . ' <dependency identifierref="RES-' . $book->course . '-' . $book->id . '-css" />';
  132. /// Now build the resources section
  133. $imsresources .= ' <resource identifier="RES-' . $book->course . '-' . $book->id . '-' . $chapter->pagenum . '" type="webcontent" xml:base="' . $chapter->pagenum . '/" href="index.html">
  134. <file href="' . $chapter->pagenum . '/index.html" />' . $localfiles . $cssdependency . '
  135. </resource>' . "\n";
  136. }
  137. /// Close items (the latest chapter)
  138. /// Level 1, close 1
  139. if ($currlevel == 0) {
  140. $imsitems .= ' </item>' . "\n";
  141. }
  142. /// Level 2, close 2
  143. if ($currlevel == 1) {
  144. $imsitems .= ' </item>' . "\n";
  145. $imsitems .= ' </item>' . "\n";
  146. }
  147. /// Define the css common resource
  148. $cssresource = ' <resource identifier="RES-' . $book->course . '-' . $book->id . '-css" type="webcontent" xml:base="css/" href="styles.css">
  149. <file href="css/styles.css" />
  150. </resource>' . "\n";
  151. /// Add imsitems to manifest
  152. $imsmanifest .= "\n" . $imsitems;
  153. /// Close the organization
  154. $imsmanifest .= " </organization>
  155. </organizations>";
  156. /// Add resources to manifest
  157. $imsmanifest .= "\n <resources>\n" . $imsresources . $cssresource . " </resources>";
  158. /// Close manifest
  159. $imsmanifest .= "\n</manifest>\n";
  160. file_put_contents($CFG->dataroot . "/" . $moddir . '/imsmanifest.xml', $imsmanifest );
  161. /// Now send the css resource
  162. make_upload_directory("$moddir/css");
  163. file_put_contents($CFG->dataroot . "/" . $moddir . "/css/styles.css", file_get_contents("$CFG->dirroot/mod/book/generateimscp.css"));
  164. }
  165. /**
  166. * This function will create one chaptercontent object, with the contents converted to html and
  167. * one array of local images to be included
  168. */
  169. function chapter2html($chapter, $courseid, $bookid) {
  170. global $CFG;
  171. $content = '';
  172. $content .= '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">' . "\n";
  173. $content .= '<html>' . "\n";
  174. $content .= '<head>' . "\n";
  175. $content .= '<meta http-equiv="content-type" content="text/html; charset=utf-8" />' . "\n";
  176. $content .= '<link rel="stylesheet" type="text/css" href="../css/styles.css" />' . "\n";
  177. $content .= '<title>' . $chapter->title . '</title>' . "\n";
  178. $content .= '</head>' . "\n";
  179. $content .= '<body>' . "\n";
  180. $content .= '<h1 id="header">' . $chapter->title . '</h1>' ."\n";
  181. $options = new object();
  182. $options->noclean = true;
  183. $content .= format_text($chapter->content, '', $options, $courseid) . "\n";
  184. $content .= '</body>' . "\n";
  185. $content .= '</html>' . "\n";
  186. /// Now look for course-files in contents
  187. $search = array($CFG->wwwroot.'/file.php/'.$courseid,
  188. $CFG->wwwroot.'/file.php?file=/'.$courseid);
  189. $replace = array('$@FILEPHP@$','$@FILEPHP@$');
  190. $content = str_replace($search, $replace, $content);
  191. $regexp = '/\$@FILEPHP@\$(.*?)"/is';
  192. $localfiles = array();
  193. $basefiles = array();
  194. preg_match_all($regexp, $content, $list);
  195. if ($list) {
  196. /// Build the array of local files
  197. foreach (array_unique($list[1]) as $key => $value) {
  198. $localfiles['<#'. $key . '#>'] = $value;
  199. $basefiles['<#'. $key . '#>'] = basename($value);
  200. /// Copy files to current chapter directory
  201. if (file_exists($CFG->dataroot . '/' . $courseid . '/' . $value)) {
  202. copy($CFG->dataroot . '/' . $courseid . '/' . $value, $CFG->dataroot . '/' . $courseid . '/moddata/book/' . $bookid . '/' . $chapter->pagenum . '/' . basename ($value));
  203. }
  204. }
  205. /// Replace contents by keys
  206. $content = str_replace($localfiles, array_keys($localfiles), $content);
  207. /// Replace keys by basefiles
  208. $content = str_replace(array_keys($basefiles), $basefiles, $content);
  209. /// Delete $@FILEPHP@$
  210. $content = str_replace('$@FILEPHP@$', '', $content);
  211. }
  212. /// Build the final object needed to have all the info in order to create the manifest
  213. $object = new object();
  214. $object->content = $content;
  215. $object->localfiles = $basefiles;
  216. return $object;
  217. }