f777ae1cfe4bd3da7875c51891bff396af239e23
[moodle.git] / mod / imscp / lib.php
1 <?php
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/>.
18 /**
19  * Mandatory public API of imscp module
20  *
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
25  */
27 defined('MOODLE_INTERNAL') || die();
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  */
34 function 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;
44         case FEATURE_BACKUP_MOODLE2:          return true;
46         default: return null;
47     }
48 }
50 /**
51  * Returns all other caps used in module
52  * @return array
53  */
54 function imscp_get_extra_capabilities() {
55     return array('moodle/site:accessallgroups');
56 }
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  */
63 function imscp_reset_userdata($data) {
64     return array();
65 }
67 /**
68  * List of view style log actions
69  * @return array
70  */
71 function imscp_get_view_actions() {
72     return array('view', 'view all');
73 }
75 /**
76  * List of update style log actions
77  * @return array
78  */
79 function imscp_get_post_actions() {
80     return array('update', 'add');
81 }
83 /**
84  * Add imscp instance.
85  * @param object $data
86  * @param object $mform
87  * @return int new imscp instance id
88  */
89 function imscp_add_instance($data, $mform) {
90     global $CFG, $DB;
91     require_once("$CFG->dirroot/mod/imscp/locallib.php");
93     $cmid = $data->coursemodule;
95     $data->timemodified = time();
96     $data->revision     = 1;
97     $data->structure    = null;
99     $data->id = $DB->insert_record('imscp', $data);
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);
106     if ($filename = $mform->get_new_filename('package')) {
107         if ($package = $mform->save_stored_file('package', $context->id, 'mod_imscp', 'backup', 1, '/', $filename)) {
108             // extract package content
109             $packer = get_file_packer('application/zip');
110             $package->extract_to_storage($packer, $context->id, 'mod_imscp', 'content', 1, '/');
111             $structure = imscp_parse_structure($imscp, $context);
112             $imscp->structure = is_array($structure) ? serialize($structure) : null;
113             $DB->update_record('imscp', $imscp);
114         }
115     }
117     return $data->id;
120 /**
121  * Update imscp instance.
122  * @param object $data
123  * @param object $mform
124  * @return bool true
125  */
126 function imscp_update_instance($data, $mform) {
127     global $CFG, $DB;
128     require_once("$CFG->dirroot/mod/imscp/locallib.php");
130     $cmid = $data->coursemodule;
132     $data->timemodified = time();
133     $data->id           = $data->instance;
134     $data->structure   = null; // better reparse structure after each update
136     $DB->update_record('imscp', $data);
138     $context = get_context_instance(CONTEXT_MODULE, $cmid);
139     $imscp = $DB->get_record('imscp', array('id'=>$data->id), '*', MUST_EXIST);
141     if ($filename = $mform->get_new_filename('package')) {
142         $fs = get_file_storage();
144         $imscp->revision++;
145         $DB->update_record('imscp', $imscp);
147         // get a list of existing packages before adding new package
148         if ($imscp->keepold > -1) {
149             $packages = $fs->get_area_files($context->id, 'mod_imscp', 'backup', false, "itemid ASC", false);
150         } else {
151             $packages = array();
152         }
154         $package = $mform->save_stored_file('package', $context->id, 'mod_imscp', 'backup', $imscp->revision, '/', $filename);
156         // purge all extracted content
157         $fs->delete_area_files($context->id, 'mod_imscp', 'content');
159         // extract package content
160         if ($package) {
161             $packer = get_file_packer('application/zip');
162             $package->extract_to_storage($packer, $context->id, 'mod_imscp', 'content', $imscp->revision, '/');
163         }
165         // cleanup old package files, keep current + keepold
166         while ($packages and (count($packages) > $imscp->keepold)) {
167             $package = array_shift($packages);
168             $fs->delete_area_files($context->id, 'mod_imscp', 'backup', $package->get_itemid());
169         }
170     }
172     $structure = imscp_parse_structure($imscp, $context);
173     $imscp->structure = is_array($structure) ? serialize($structure) : null;
174     $DB->update_record('imscp', $imscp);
176     return true;
179 /**
180  * Delete imscp instance.
181  * @param int $id
182  * @return bool true
183  */
184 function imscp_delete_instance($id) {
185     global $DB;
187     if (!$imscp = $DB->get_record('imscp', array('id'=>$id))) {
188         return false;
189     }
191     // note: all context files are deleted automatically
193     $DB->delete_records('imscp', array('id'=>$imscp->id));
195     return true;
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  */
206 function imscp_user_outline($course, $user, $mod, $imscp) {
207     global $DB;
209     if ($logs = $DB->get_records('log', array('userid'=>$user->id, 'module'=>'imscp',
210                                               'action'=>'view', 'info'=>$imscp->id), 'time ASC')) {
212         $numviews = count($logs);
213         $lastlog = array_pop($logs);
215         $result = new stdClass();
216         $result->info = get_string('numviews', '', $numviews);
217         $result->time = $lastlog->time;
219         return $result;
220     }
221     return NULL;
224 /**
225  * Return use complete
226  * @param object $course
227  * @param object $user
228  * @param object $mod
229  * @param object $imscp
230  */
231 function imscp_user_complete($course, $user, $mod, $imscp) {
232     global $CFG, $DB;
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);
239         $strmostrecently = get_string('mostrecently');
240         $strnumviews = get_string('numviews', '', $numviews);
242         echo "$strnumviews - $strmostrecently ".userdate($lastlog->time);
244     } else {
245         print_string('neverseen', 'imscp');
246     }
249 /**
250  * Returns the users with data in one imscp
251  *
252  * @param int $imscpid
253  * @return bool false
254  */
255 function imscp_get_participants($imscpid) {
256     return false;
259 /**
260  * Lists all browsable file areas
261  * @param object $course
262  * @param object $cm
263  * @param object $context
264  * @return array
265  */
266 function imscp_get_file_areas($course, $cm, $context) {
267     $areas = array();
269     $areas['content'] = get_string('areacontent', 'imscp');
270     $areas['backup']  = get_string('areabackup', 'imscp');
272     return $areas;
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  */
288 function imscp_get_file_info($browser, $areas, $course, $cm, $context, $filearea, $itemid, $filepath, $filename) {
289     global $CFG, $DB;
291     // note: imscp_intro handled in file_browser automatically
293     if (!has_capability('moodle/course:managefiles', $context)) {
294         // no peaking here for students!!
295         return null;
296     }
298     if ($filearea !== 'content' and $filearea !== 'backup') {
299         return null;
300     }
302     require_once("$CFG->dirroot/mod/imscp/locallib.php");
304     if (is_null($itemid)) {
305         return new imscp_file_info($browser, $course, $cm, $context, $areas, $filearea, $itemid);
306     }
308     $fs = get_file_storage();
309     $filepath = is_null($filepath) ? '/' : $filepath;
310     $filename = is_null($filename) ? '.' : $filename;
311     if (!$storedfile = $fs->get_file($context->id, 'mod_imscp', $filearea, $itemid, $filepath, $filename)) {
312         return null;
313     }
315     // do not allow manual modification of any files!
316     $urlbase = $CFG->wwwroot.'/pluginfile.php';
317     return new file_info_stored($browser, $context, $storedfile, $urlbase, $itemid, true, true, false, false); //no writing here!
320 /**
321  * Serves the imscp files.
322  *
323  * @param object $course
324  * @param object $cm
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  */
331 function imscp_pluginfile($course, $cm, $context, $filearea, $args, $forcedownload) {
332     global $CFG, $DB;
334     if ($context->contextlevel != CONTEXT_MODULE) {
335         return false;
336     }
338     require_login($course, true, $cm);
340     if ($filearea === 'content') {
341         $revision = array_shift($args);
342         $fs = get_file_storage();
343         $relativepath = implode('/', $args);
344         if ($relativepath === 'imsmanifest.xml') {
345             if (!has_capability('moodle/course:managefiles', $context)) {
346                 // no stealing of detailed package info ;-)
347                 return false;
348             }
349         }
350         $fullpath = "/$context->id/mod_imscp/$filearea/$revision/$relativepath";
351         if (!$file = $fs->get_file_by_hash(sha1($fullpath)) or $file->is_directory()) {
352             return false;
353         }
355         // finally send the file
356         send_stored_file($file, 86400, 0, $forcedownload);
358     } else if ($filearea === 'backup') {
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();
365         $relativepath = implode('/', $args);
366         $fullpath = "/$context->id/mod_imscp/$filearea/$revision/$relativepath";
367         if (!$file = $fs->get_file_by_hash(sha1($fullpath)) or $file->is_directory()) {
368             return false;
369         }
371         // finally send the file
372         send_stored_file($file, 86400, 0, $forcedownload);
374     } else {
375         return false;
376     }
379 /**
380  * This function extends the global navigation for the site.
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
388  * @param stdClass $cm The course module instance returned from the DB
389  */
390 function 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;