fixed forced reparsing after update
[moodle.git] / mod / imscp / lib.php
CommitLineData
2ff648fb 1<?php
2
3// This file is part of Moodle - http://moodle.org/
4//
5// Moodle is free software: you can redistribute it and/or modify
6// it under the terms of the GNU General Public License as published by
7// the Free Software Foundation, either version 3 of the License, or
8// (at your option) any later version.
9//
10// Moodle is distributed in the hope that it will be useful,
11// but WITHOUT ANY WARRANTY; without even the implied warranty of
12// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13// GNU General Public License for more details.
14//
15// You should have received a copy of the GNU General Public License
16// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
17
18/**
19 * Mandatory public API of imscp module
20 *
3b43615f
PS
21 * @package mod
22 * @subpackage imscp
23 * @copyright 2009 Petr Skoda {@link http://skodak.org}
24 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
2ff648fb 25 */
26
3b43615f
PS
27defined('MOODLE_INTERNAL') || die();
28
2ff648fb 29/**
30 * List of features supported in IMS CP module
31 * @param string $feature FEATURE_xx constant for requested feature
32 * @return mixed True if module supports feature, false if not, null if doesn't know
33 */
34function imscp_supports($feature) {
35 switch($feature) {
36 case FEATURE_MOD_ARCHETYPE: return MOD_ARCHETYPE_RESOURCE;
37 case FEATURE_GROUPS: return false;
38 case FEATURE_GROUPINGS: return false;
39 case FEATURE_GROUPMEMBERSONLY: return true;
40 case FEATURE_MOD_INTRO: return true;
41 case FEATURE_COMPLETION_TRACKS_VIEWS: return true;
42 case FEATURE_GRADE_HAS_GRADE: return false;
43 case FEATURE_GRADE_OUTCOMES: return false;
5a06da3c 44 case FEATURE_BACKUP_MOODLE2: return true;
2ff648fb 45
46 default: return null;
47 }
48}
49
50/**
51 * Returns all other caps used in module
52 * @return array
53 */
54function imscp_get_extra_capabilities() {
55 return array('moodle/site:accessallgroups');
56}
57
58/**
59 * This function is used by the reset_course_userdata function in moodlelib.
60 * @param $data the data submitted from the reset course.
61 * @return array status array
62 */
63function imscp_reset_userdata($data) {
64 return array();
65}
66
67/**
68 * List of view style log actions
69 * @return array
70 */
71function imscp_get_view_actions() {
72 return array('view', 'view all');
73}
74
75/**
76 * List of update style log actions
77 * @return array
78 */
79function imscp_get_post_actions() {
80 return array('update', 'add');
81}
82
83/**
84 * Add imscp instance.
85 * @param object $data
86 * @param object $mform
87 * @return int new imscp instance id
88 */
89function imscp_add_instance($data, $mform) {
90 global $CFG, $DB;
91 require_once("$CFG->dirroot/mod/imscp/locallib.php");
92
93 $cmid = $data->coursemodule;
94
95 $data->timemodified = time();
96 $data->revision = 1;
97 $data->structure = null;
98
99 $data->id = $DB->insert_record('imscp', $data);
100
101 // we need to use context now, so we need to make sure all needed info is already in db
102 $DB->set_field('course_modules', 'instance', $data->id, array('id'=>$cmid));
103 $context = get_context_instance(CONTEXT_MODULE, $cmid);
104 $imscp = $DB->get_record('imscp', array('id'=>$data->id), '*', MUST_EXIST);
105
106 if ($filename = $mform->get_new_filename('package')) {
64f93798 107 if ($package = $mform->save_stored_file('package', $context->id, 'mod_imscp', 'backup', 1, '/', $filename)) {
2ff648fb 108 // extract package content
109 $packer = get_file_packer('application/zip');
64f93798 110 $package->extract_to_storage($packer, $context->id, 'mod_imscp', 'content', 1, '/');
2ff648fb 111 $structure = imscp_parse_structure($imscp, $context);
112 $imscp->structure = is_array($structure) ? serialize($structure) : null;
113 $DB->update_record('imscp', $imscp);
114 }
115 }
116
117 return $data->id;
118}
119
120/**
121 * Update imscp instance.
122 * @param object $data
123 * @param object $mform
124 * @return bool true
125 */
126function imscp_update_instance($data, $mform) {
127 global $CFG, $DB;
128 require_once("$CFG->dirroot/mod/imscp/locallib.php");
129
130 $cmid = $data->coursemodule;
131
132 $data->timemodified = time();
133 $data->id = $data->instance;
a873afc1 134 $data->structure = null; // better reparse structure after each update
2ff648fb 135
136 $DB->update_record('imscp', $data);
137
138 $context = get_context_instance(CONTEXT_MODULE, $cmid);
139 $imscp = $DB->get_record('imscp', array('id'=>$data->id), '*', MUST_EXIST);
140
141 if ($filename = $mform->get_new_filename('package')) {
142 $fs = get_file_storage();
143
144 $imscp->revision++;
145 $DB->update_record('imscp', $imscp);
146
147 // get a list of existing packages before adding new package
148 if ($imscp->keepold > -1) {
64f93798 149 $packages = $fs->get_area_files($context->id, 'mod_imscp', 'backup', false, "itemid ASC", false);
2ff648fb 150 } else {
151 $packages = array();
152 }
153
64f93798 154 $package = $mform->save_stored_file('package', $context->id, 'mod_imscp', 'backup', $imscp->revision, '/', $filename);
2ff648fb 155
156 // purge all extracted content
64f93798 157 $fs->delete_area_files($context->id, 'mod_imscp', 'content');
2ff648fb 158
159 // extract package content
160 if ($package) {
161 $packer = get_file_packer('application/zip');
64f93798 162 $package->extract_to_storage($packer, $context->id, 'mod_imscp', 'content', $imscp->revision, '/');
2ff648fb 163 }
164
165 // cleanup old package files, keep current + keepold
166 while ($packages and (count($packages) > $imscp->keepold)) {
167 $package = array_shift($packages);
64f93798 168 $fs->delete_area_files($context->id, 'mod_imscp', 'backup', $package->get_itemid());
2ff648fb 169 }
170 }
171
172 $structure = imscp_parse_structure($imscp, $context);
173 $imscp->structure = is_array($structure) ? serialize($structure) : null;
174 $DB->update_record('imscp', $imscp);
175
176 return true;
177}
178
179/**
180 * Delete imscp instance.
181 * @param int $id
182 * @return bool true
183 */
184function imscp_delete_instance($id) {
185 global $DB;
186
187 if (!$imscp = $DB->get_record('imscp', array('id'=>$id))) {
188 return false;
189 }
190
191 // note: all context files are deleted automatically
192
193 $DB->delete_records('imscp', array('id'=>$imscp->id));
194
195 return true;
196}
197
198/**
199 * Return use outline
200 * @param object $course
201 * @param object $user
202 * @param object $mod
203 * @param object $imscp
204 * @return object|null
205 */
206function imscp_user_outline($course, $user, $mod, $imscp) {
207 global $DB;
208
209 if ($logs = $DB->get_records('log', array('userid'=>$user->id, 'module'=>'imscp',
210 'action'=>'view', 'info'=>$imscp->id), 'time ASC')) {
211
212 $numviews = count($logs);
213 $lastlog = array_pop($logs);
214
215 $result = new object();
216 $result->info = get_string('numviews', '', $numviews);
217 $result->time = $lastlog->time;
218
219 return $result;
220 }
221 return NULL;
222}
223
224/**
225 * Return use complete
226 * @param object $course
227 * @param object $user
228 * @param object $mod
229 * @param object $imscp
230 */
231function imscp_user_complete($course, $user, $mod, $imscp) {
232 global $CFG, $DB;
233
234 if ($logs = $DB->get_records('log', array('userid'=>$user->id, 'module'=>'imscp',
235 'action'=>'view', 'info'=>$imscp->id), 'time ASC')) {
236 $numviews = count($logs);
237 $lastlog = array_pop($logs);
238
239 $strmostrecently = get_string('mostrecently');
240 $strnumviews = get_string('numviews', '', $numviews);
241
242 echo "$strnumviews - $strmostrecently ".userdate($lastlog->time);
243
244 } else {
245 print_string('neverseen', 'imscp');
246 }
247}
248
249/**
250 * Returns the users with data in one imscp
251 *
252 * @param int $imscpid
253 * @return bool false
254 */
255function imscp_get_participants($imscpid) {
256 return false;
257}
258
259/**
260 * Lists all browsable file areas
261 * @param object $course
262 * @param object $cm
263 * @param object $context
264 * @return array
265 */
266function imscp_get_file_areas($course, $cm, $context) {
267 $areas = array();
64f93798
PS
268
269 $areas['content'] = get_string('areacontent', 'imscp');
270 $areas['backup'] = get_string('areabackup', 'imscp');
271
2ff648fb 272 return $areas;
273}
274
275/**
276 * File browsing support for imscp module ontent area.
277 * @param object $browser
278 * @param object $areas
279 * @param object $course
280 * @param object $cm
281 * @param object $context
282 * @param string $filearea
283 * @param int $itemid
284 * @param string $filepath
285 * @param string $filename
286 * @return object file_info instance or null if not found
287 */
288function imscp_get_file_info($browser, $areas, $course, $cm, $context, $filearea, $itemid, $filepath, $filename) {
289 global $CFG, $DB;
2ff648fb 290
291 // note: imscp_intro handled in file_browser automatically
292
293 if (!has_capability('moodle/course:managefiles', $context)) {
64f93798 294 // no peaking here for students!!
2ff648fb 295 return null;
296 }
297
64f93798 298 if ($filearea !== 'content' and $filearea !== 'backup') {
2ff648fb 299 return null;
300 }
64f93798
PS
301
302 require_once("$CFG->dirroot/mod/imscp/locallib.php");
303
2ff648fb 304 if (is_null($itemid)) {
305 return new imscp_file_info($browser, $course, $cm, $context, $areas, $filearea, $itemid);
306 }
307
308 $fs = get_file_storage();
309 $filepath = is_null($filepath) ? '/' : $filepath;
310 $filename = is_null($filename) ? '.' : $filename;
64f93798 311 if (!$storedfile = $fs->get_file($context->id, 'mod_imscp', $filearea, $itemid, $filepath, $filename)) {
2ff648fb 312 return null;
313 }
314
315 // do not allow manual modification of any files!
316 $urlbase = $CFG->wwwroot.'/pluginfile.php';
64f93798 317 return new file_info_stored($browser, $context, $storedfile, $urlbase, $itemid, true, true, false, false); //no writing here!
2ff648fb 318}
319
320/**
321 * Serves the imscp files.
322 *
323 * @param object $course
64f93798 324 * @param object $cm
2ff648fb 325 * @param object $context
326 * @param string $filearea
327 * @param array $args
328 * @param bool $forcedownload
329 * @return bool false if file not found, does not return if found - justsend the file
330 */
64f93798 331function imscp_pluginfile($course, $cm, $context, $filearea, $args, $forcedownload) {
2ff648fb 332 global $CFG, $DB;
333
64f93798 334 if ($context->contextlevel != CONTEXT_MODULE) {
2ff648fb 335 return false;
336 }
337
64f93798 338 require_login($course, true, $cm);
2ff648fb 339
64f93798 340 if ($filearea === 'content') {
2ff648fb 341 $revision = array_shift($args);
342 $fs = get_file_storage();
64f93798
PS
343 $relativepath = implode('/', $args);
344 if ($relativepath === 'imsmanifest.xml') {
2ff648fb 345 if (!has_capability('moodle/course:managefiles', $context)) {
346 // no stealing of detailed package info ;-)
347 return false;
348 }
349 }
64f93798 350 $fullpath = "/$context->id/mod_imscp/$filearea/$revision/$relativepath";
2ff648fb 351 if (!$file = $fs->get_file_by_hash(sha1($fullpath)) or $file->is_directory()) {
352 return false;
353 }
354
355 // finally send the file
356 send_stored_file($file, 86400, 0, $forcedownload);
357
64f93798 358 } else if ($filearea === 'backup') {
2ff648fb 359 if (!has_capability('moodle/course:managefiles', $context)) {
360 // no stealing of package backups
361 return false;
362 }
363 $revision = array_shift($args);
364 $fs = get_file_storage();
64f93798
PS
365 $relativepath = implode('/', $args);
366 $fullpath = "/$context->id/mod_imscp/$filearea/$revision/$relativepath";
2ff648fb 367 if (!$file = $fs->get_file_by_hash(sha1($fullpath)) or $file->is_directory()) {
368 return false;
369 }
370
371 // finally send the file
372 send_stored_file($file, 86400, 0, $forcedownload);
373
374 } else {
375 return false;
376 }
377}
92059c7e
SH
378
379/**
792881f0 380 * This function extends the global navigation for the site.
92059c7e
SH
381 * It is important to note that you should not rely on PAGE objects within this
382 * body of code as there is no guarantee that during an AJAX request they are
383 * available
384 *
385 * @param navigation_node $navigation The imscp node within the global navigation
386 * @param stdClass $course The course object returned from the DB
387 * @param stdClass $module The module object returned from the DB
792881f0 388 * @param stdClass $cm The course module instance returned from the DB
92059c7e
SH
389 */
390function imscp_extend_navigation($navigation, $course, $module, $cm) {
391 /**
392 * This is currently just a stub so that it can be easily expanded upon.
393 * When expanding just remove this comment and the line below and then add
394 * you content.
395 */
396 $navigation->nodetype = navigation_node::NODETYPE_LEAF;
5a06da3c 397}