MDL-50015 mod_imscp: New WS mod_imscp_view_imscp
[moodle.git] / mod / book / tool / exportimscp / locallib.php
CommitLineData
f3d91d52 1<?php
b15ef0b0 2// This file is part of Moodle - http://moodle.org/
f3d91d52
PS
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 imscp export lib
19 *
3542c4f4 20 * @package booktool_exportimscp
f3d91d52 21 * @copyright 2001-3001 Antonio Vicent {@link http://ludens.es}
3542c4f4 22 * @copyright 2001-3001 Eloy Lafuente (stronk7) {@link http://stronk7.com}
f3d91d52
PS
23 * @copyright 2011 Petr Skoda {@link http://skodak.org}
24 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
25 */
26
27defined('MOODLE_INTERNAL') || die;
28
29require_once(dirname(__FILE__).'/lib.php');
30require_once($CFG->dirroot.'/mod/book/locallib.php');
31
3542c4f4
EL
32/**
33 * Export one book as IMSCP package
34 *
35 * @param stdClass $book book instance
36 * @param context_module $context
37 * @return bool|stored_file
38 */
f3d91d52
PS
39function booktool_exportimscp_build_package($book, $context) {
40 global $DB;
41
42 $fs = get_file_storage();
43
44 if ($packagefile = $fs->get_file($context->id, 'booktool_exportimscp', 'package', $book->revision, '/', 'imscp.zip')) {
45 return $packagefile;
46 }
47
26c6ba6c
PS
48 // fix structure and test if chapters present
49 if (!book_preload_chapters($book)) {
50 print_error('nochapters', 'booktool_exportimscp');
51 }
f3d91d52
PS
52
53 // prepare temp area with package contents
54 booktool_exportimscp_prepare_files($book, $context);
55
56 $packer = get_file_packer('application/zip');
57 $areafiles = $fs->get_area_files($context->id, 'booktool_exportimscp', 'temp', $book->revision, "sortorder, itemid, filepath, filename", false);
58 $files = array();
59 foreach ($areafiles as $file) {
60 $path = $file->get_filepath().$file->get_filename();
61 $path = ltrim($path, '/');
62 $files[$path] = $file;
63 }
64 unset($areafiles);
65 $packagefile = $packer->archive_to_storage($files, $context->id, 'booktool_exportimscp', 'package', $book->revision, '/', 'imscp.zip');
66
67 // drop temp area
68 $fs->delete_area_files($context->id, 'booktool_exportimscp', 'temp', $book->revision);
69
70 // delete older versions
71 $sql = "SELECT DISTINCT itemid
72 FROM {files}
73 WHERE contextid = :contextid AND component = 'booktool_exportimscp' AND itemid < :revision";
74 $params = array('contextid'=>$context->id, 'revision'=>$book->revision);
75 $revisions = $DB->get_records_sql($sql, $params);
079be74d 76 foreach ($revisions as $rev => $unused) {
f3d91d52
PS
77 $fs->delete_area_files($context->id, 'booktool_exportimscp', 'temp', $rev);
78 $fs->delete_area_files($context->id, 'booktool_exportimscp', 'package', $rev);
79 }
80
81 return $packagefile;
82}
83
3542c4f4
EL
84/**
85 * Prepare temp area with the files used by book html contents
86 *
87 * @param stdClass $book book instance
88 * @param context_module $context
89 */
f3d91d52
PS
90function booktool_exportimscp_prepare_files($book, $context) {
91 global $CFG, $DB;
92
93 $fs = get_file_storage();
94
95 $temp_file_record = array('contextid'=>$context->id, 'component'=>'booktool_exportimscp', 'filearea'=>'temp', 'itemid'=>$book->revision);
96 $chapters = $DB->get_records('book_chapters', array('bookid'=>$book->id), 'pagenum');
97 $chapterresources = array();
98 foreach ($chapters as $chapter) {
99 $chapterresources[$chapter->id] = array();
100 $files = $fs->get_area_files($context->id, 'mod_book', 'chapter', $chapter->id, "sortorder, itemid, filepath, filename", false);
101 foreach ($files as $file) {
102 $temp_file_record['filepath'] = '/'.$chapter->pagenum.$file->get_filepath();
103 $fs->create_file_from_storedfile($temp_file_record, $file);
104 $chapterresources[$chapter->id][] = $chapter->pagenum.$file->get_filepath().$file->get_filename();
105 }
106 if ($file = $fs->get_file($context->id, 'booktool_exportimscp', 'temp', $book->revision, "/$chapter->pagenum/", 'index.html')) {
107 // this should not exist
108 $file->delete();
109 }
110 $content = booktool_exportimscp_chapter_content($chapter, $context);
079be74d
EL
111 $index_file_record = array('contextid'=>$context->id, 'component'=>'booktool_exportimscp', 'filearea'=>'temp',
112 'itemid'=>$book->revision, 'filepath'=>"/$chapter->pagenum/", 'filename'=>'index.html');
f3d91d52
PS
113 $fs->create_file_from_string($index_file_record, $content);
114 }
115
079be74d
EL
116 $css_file_record = array('contextid'=>$context->id, 'component'=>'booktool_exportimscp', 'filearea'=>'temp',
117 'itemid'=>$book->revision, 'filepath'=>"/css/", 'filename'=>'styles.css');
f3d91d52
PS
118 $fs->create_file_from_pathname($css_file_record, dirname(__FILE__).'/imscp.css');
119
120 // Init imsmanifest and others
121 $imsmanifest = '';
122 $imsitems = '';
123 $imsresources = '';
124
125 // Moodle and Book version
126 $moodle_release = $CFG->release;
127 $moodle_version = $CFG->version;
5f8012d4 128 $book_version = get_config('mod_book', 'version');
f3d91d52
PS
129 $bookname = format_string($book->name, true, array('context'=>$context));
130
131 // Load manifest header
132 $imsmanifest .= '<?xml version="1.0" encoding="UTF-8"?>
133<!-- This package has been created with Moodle ' . $moodle_release . ' (' . $moodle_version . ') http://moodle.org/, Book module version ' . $book_version . ' - https://github.com/skodak/moodle-mod_book -->
134<!-- One idea and implementation by Eloy Lafuente (stronk7) and Antonio Vicent (C) 2001-3001 -->
135<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">
136 <organizations default="MOODLE-' . $book->course . '-' . $book->id . '">
137 <organization identifier="MOODLE-' . $book->course . '-' . $book->id . '" structure="hierarchical">
138 <title>' . htmlspecialchars($bookname) . '</title>';
139
140 // To store the prev level (book only have 0 and 1)
141 $prevlevel = null;
079be74d 142 $currlevel = 0;
f3d91d52
PS
143 foreach ($chapters as $chapter) {
144 // Calculate current level ((book only have 0 and 1)
145 $currlevel = empty($chapter->subchapter) ? 0 : 1;
146 // Based upon prevlevel and current one, decide what to close
147 if ($prevlevel !== null) {
148 // Calculate the number of spaces (for visual xml-text formating)
149 $prevspaces = substr(' ', 0, $currlevel * 2);
150
151 // Same level, simply close the item
152 if ($prevlevel == $currlevel) {
153 $imsitems .= $prevspaces . ' </item>' . "\n";
154 }
155 // Bigger currlevel, nothing to close
156 // Smaller currlevel, close both the current item and the parent one
157 if ($prevlevel > $currlevel) {
158 $imsitems .= ' </item>' . "\n";
159 $imsitems .= ' </item>' . "\n";
160 }
161 }
162 // Update prevlevel
163 $prevlevel = $currlevel;
164
1fc9e895 165 // Calculate the number of spaces (for visual xml-text formatting)
f3d91d52
PS
166 $currspaces = substr(' ', 0, $currlevel * 2);
167
168 $chaptertitle = format_string($chapter->title, true, array('context'=>$context));
169
079be74d
EL
170 // Add the imsitems
171 $imsitems .= $currspaces .' <item identifier="ITEM-' . $book->course . '-' . $book->id . '-' . $chapter->pagenum .'" isvisible="true" identifierref="RES-' .
172 $book->course . '-' . $book->id . '-' . $chapter->pagenum . "\">\n" .
173 $currspaces . ' <title>' . htmlspecialchars($chaptertitle) . '</title>' . "\n";
f3d91d52
PS
174
175 // Add the imsresources
176 // First, check if we have localfiles
177 $localfiles = array();
178 foreach ($chapterresources[$chapter->id] as $localfile) {
179 $localfiles[] = "\n" . ' <file href="' . $localfile . '" />';
180 }
181 // Now add the dependency to css
182 $cssdependency = "\n" . ' <dependency identifierref="RES-' . $book->course . '-' . $book->id . '-css" />';
183 // Now build the resources section
079be74d
EL
184 $imsresources .= ' <resource identifier="RES-' . $book->course . '-' . $book->id . '-' . $chapter->pagenum . '" type="webcontent" xml:base="' .
185 $chapter->pagenum . '/" href="index.html">' . "\n" .
186 ' <file href="' . $chapter->pagenum . '/index.html" />' . implode($localfiles) . $cssdependency . "\n".
187 ' </resource>' . "\n";
f3d91d52
PS
188 }
189
190 // Close items (the latest chapter)
191 // Level 1, close 1
192 if ($currlevel == 0) {
193 $imsitems .= ' </item>' . "\n";
194 }
195 // Level 2, close 2
196 if ($currlevel == 1) {
197 $imsitems .= ' </item>' . "\n";
198 $imsitems .= ' </item>' . "\n";
199 }
200
201 // Define the css common resource
202 $cssresource = ' <resource identifier="RES-' . $book->course . '-' . $book->id . '-css" type="webcontent" xml:base="css/" href="styles.css">
203 <file href="css/styles.css" />
204 </resource>' . "\n";
205
206 // Add imsitems to manifest
207 $imsmanifest .= "\n" . $imsitems;
208 // Close the organization
209 $imsmanifest .= " </organization>
210 </organizations>";
211 // Add resources to manifest
212 $imsmanifest .= "\n <resources>\n" . $imsresources . $cssresource . " </resources>";
213 // Close manifest
214 $imsmanifest .= "\n</manifest>\n";
215
079be74d
EL
216 $manifest_file_record = array('contextid'=>$context->id, 'component'=>'booktool_exportimscp', 'filearea'=>'temp',
217 'itemid'=>$book->revision, 'filepath'=>"/", 'filename'=>'imsmanifest.xml');
f3d91d52
PS
218 $fs->create_file_from_string($manifest_file_record, $imsmanifest);
219}
220
3542c4f4
EL
221/**
222 * Returns the html contents of one book's chapter to be exported as IMSCP
223 *
224 * @param stdClass $chapter the chapter to be exported
225 * @param context_module $context context the chapter belongs to
226 * @return string the contents of the chapter
227 */
f3d91d52
PS
228function booktool_exportimscp_chapter_content($chapter, $context) {
229
dcb83c34 230 $options = new stdClass();
f3d91d52
PS
231 $options->noclean = true;
232 $options->context = $context;
233
234 $chaptercontent = str_replace('@@PLUGINFILE@@/', '', $chapter->content);
235 $chaptercontent = format_text($chaptercontent, $chapter->contentformat, $options);
236
237 $chaptertitle = format_string($chapter->title, true, array('context'=>$context));
238
239 $content = '';
240 $content .= '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">' . "\n";
241 $content .= '<html>' . "\n";
242 $content .= '<head>' . "\n";
243 $content .= '<meta http-equiv="content-type" content="text/html; charset=utf-8" />' . "\n";
244 $content .= '<link rel="stylesheet" type="text/css" href="../css/styles.css" />' . "\n";
245 $content .= '<title>' . $chaptertitle . '</title>' . "\n";
246 $content .= '</head>' . "\n";
247 $content .= '<body>' . "\n";
248 $content .= '<h1 id="header">' . $chaptertitle . '</h1>' ."\n";
249 $content .= $chaptercontent . "\n";
250 $content .= '</body>' . "\n";
251 $content .= '</html>' . "\n";
252
253 return $content;
254}