fde1587f5162d976619e7c7ebcb4bb2988f8d2ad
[moodle.git] / mod / folder / 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 folder module
20  *
21  * @package    mod
22  * @subpackage folder
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 Folder 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 folder_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;
45         case FEATURE_SHOW_DESCRIPTION:        return true;
47         default: return null;
48     }
49 }
51 /**
52  * Returns all other caps used in module
53  * @return array
54  */
55 function folder_get_extra_capabilities() {
56     return array('moodle/site:accessallgroups');
57 }
59 /**
60  * This function is used by the reset_course_userdata function in moodlelib.
61  * @param $data the data submitted from the reset course.
62  * @return array status array
63  */
64 function folder_reset_userdata($data) {
65     return array();
66 }
68 /**
69  * List of view style log actions
70  * @return array
71  */
72 function folder_get_view_actions() {
73     return array('view', 'view all');
74 }
76 /**
77  * List of update style log actions
78  * @return array
79  */
80 function folder_get_post_actions() {
81     return array('update', 'add');
82 }
84 /**
85  * Add folder instance.
86  * @param object $data
87  * @param object $mform
88  * @return int new folder instance id
89  */
90 function folder_add_instance($data, $mform) {
91     global $DB;
93     $cmid        = $data->coursemodule;
94     $draftitemid = $data->files;
96     $data->timemodified = time();
97     $data->id = $DB->insert_record('folder', $data);
99     // we need to use context now, so we need to make sure all needed info is already in db
100     $DB->set_field('course_modules', 'instance', $data->id, array('id'=>$cmid));
101     $context = get_context_instance(CONTEXT_MODULE, $cmid);
103     if ($draftitemid) {
104         file_save_draft_area_files($draftitemid, $context->id, 'mod_folder', 'content', 0, array('subdirs'=>true));
105     }
107     return $data->id;
110 /**
111  * Update folder instance.
112  * @param object $data
113  * @param object $mform
114  * @return bool true
115  */
116 function folder_update_instance($data, $mform) {
117     global $CFG, $DB;
119     $cmid        = $data->coursemodule;
120     $draftitemid = $data->files;
122     $data->timemodified = time();
123     $data->id           = $data->instance;
124     $data->revision++;
126     $DB->update_record('folder', $data);
128     $context = get_context_instance(CONTEXT_MODULE, $cmid);
129     if ($draftitemid = file_get_submitted_draft_itemid('files')) {
130         file_save_draft_area_files($draftitemid, $context->id, 'mod_folder', 'content', 0, array('subdirs'=>true));
131     }
133     return true;
136 /**
137  * Delete folder instance.
138  * @param int $id
139  * @return bool true
140  */
141 function folder_delete_instance($id) {
142     global $DB;
144     if (!$folder = $DB->get_record('folder', array('id'=>$id))) {
145         return false;
146     }
148     // note: all context files are deleted automatically
150     $DB->delete_records('folder', array('id'=>$folder->id));
152     return true;
155 /**
156  * Return use outline
157  * @param object $course
158  * @param object $user
159  * @param object $mod
160  * @param object $folder
161  * @return object|null
162  */
163 function folder_user_outline($course, $user, $mod, $folder) {
164     global $DB;
166     if ($logs = $DB->get_records('log', array('userid'=>$user->id, 'module'=>'folder',
167                                               'action'=>'view', 'info'=>$folder->id), 'time ASC')) {
169         $numviews = count($logs);
170         $lastlog = array_pop($logs);
172         $result = new stdClass();
173         $result->info = get_string('numviews', '', $numviews);
174         $result->time = $lastlog->time;
176         return $result;
177     }
178     return NULL;
181 /**
182  * Return use complete
183  * @param object $course
184  * @param object $user
185  * @param object $mod
186  * @param object $folder
187  */
188 function folder_user_complete($course, $user, $mod, $folder) {
189     global $CFG, $DB;
191     if ($logs = $DB->get_records('log', array('userid'=>$user->id, 'module'=>'folder',
192                                               'action'=>'view', 'info'=>$folder->id), 'time ASC')) {
193         $numviews = count($logs);
194         $lastlog = array_pop($logs);
196         $strmostrecently = get_string('mostrecently');
197         $strnumviews = get_string('numviews', '', $numviews);
199         echo "$strnumviews - $strmostrecently ".userdate($lastlog->time);
201     } else {
202         print_string('neverseen', 'folder');
203     }
206 /**
207  * Lists all browsable file areas
208  *
209  * @package  mod_folder
210  * @category files
211  * @param stdClass $course course object
212  * @param stdClass $cm course module object
213  * @param stdClass $context context object
214  * @return array
215  */
216 function folder_get_file_areas($course, $cm, $context) {
217     $areas = array();
218     $areas['content'] = get_string('foldercontent', 'folder');
220     return $areas;
223 /**
224  * File browsing support for folder module content area.
225  *
226  * @package  mod_folder
227  * @category files
228  * @param file_browser $browser file browser instance
229  * @param array $areas file areas
230  * @param stdClass $course course object
231  * @param stdClass $cm course module object
232  * @param stdClass $context context object
233  * @param string $filearea file area
234  * @param int $itemid item ID
235  * @param string $filepath file path
236  * @param string $filename file name
237  * @return file_info instance or null if not found
238  */
239 function folder_get_file_info($browser, $areas, $course, $cm, $context, $filearea, $itemid, $filepath, $filename) {
240     global $CFG;
243     if ($filearea === 'content') {
244         if (!has_capability('mod/folder:view', $context)) {
245             return NULL;
246         }
247         $fs = get_file_storage();
249         $filepath = is_null($filepath) ? '/' : $filepath;
250         $filename = is_null($filename) ? '.' : $filename;
251         if (!$storedfile = $fs->get_file($context->id, 'mod_folder', 'content', 0, $filepath, $filename)) {
252             if ($filepath === '/' and $filename === '.') {
253                 $storedfile = new virtual_root_file($context->id, 'mod_folder', 'content', 0);
254             } else {
255                 // not found
256                 return null;
257             }
258         }
260         require_once("$CFG->dirroot/mod/folder/locallib.php");
261         $urlbase = $CFG->wwwroot.'/pluginfile.php';
263         // students may read files here
264         $canwrite = has_capability('mod/folder:managefiles', $context);
265         return new folder_content_file_info($browser, $context, $storedfile, $urlbase, $areas[$filearea], true, true, $canwrite, false);
266     }
268     // note: folder_intro handled in file_browser automatically
270     return null;
273 /**
274  * Serves the folder files.
275  *
276  * @package  mod_folder
277  * @category files
278  * @param stdClass $course course object
279  * @param stdClass $cm course module
280  * @param stdClass $context context object
281  * @param string $filearea file area
282  * @param array $args extra arguments
283  * @param bool $forcedownload whether or not force download
284  * @param array $options additional options affecting the file serving
285  * @return bool false if file not found, does not return if found - just send the file
286  */
287 function folder_pluginfile($course, $cm, $context, $filearea, $args, $forcedownload, array $options=array()) {
288     global $CFG, $DB;
290     if ($context->contextlevel != CONTEXT_MODULE) {
291         return false;
292     }
294     require_course_login($course, true, $cm);
295     if (!has_capability('mod/folder:view', $context)) {
296         return false;
297     }
299     if ($filearea !== 'content') {
300         // intro is handled automatically in pluginfile.php
301         return false;
302     }
304     array_shift($args); // ignore revision - designed to prevent caching problems only
306     $fs = get_file_storage();
307     $relativepath = implode('/', $args);
308     $fullpath = "/$context->id/mod_folder/content/0/$relativepath";
309     if (!$file = $fs->get_file_by_hash(sha1($fullpath)) or $file->is_directory()) {
310         return false;
311     }
313     // finally send the file
314     // for folder module, we force download file all the time
315     send_stored_file($file, 86400, 0, true, $options);
318 /**
319  * Return a list of page types
320  * @param string $pagetype current page type
321  * @param stdClass $parentcontext Block's parent context
322  * @param stdClass $currentcontext Current context of block
323  */
324 function folder_page_type_list($pagetype, $parentcontext, $currentcontext) {
325     $module_pagetype = array('mod-folder-*'=>get_string('page-mod-folder-x', 'folder'));
326     return $module_pagetype;
329 /**
330  * Export folder resource contents
331  *
332  * @return array of file content
333  */
334 function folder_export_contents($cm, $baseurl) {
335     global $CFG, $DB;
336     $contents = array();
337     $context = get_context_instance(CONTEXT_MODULE, $cm->id);
338     $folder = $DB->get_record('folder', array('id'=>$cm->instance), '*', MUST_EXIST);
340     $fs = get_file_storage();
341     $files = $fs->get_area_files($context->id, 'mod_folder', 'content', 0, 'sortorder DESC, id ASC', false);
343     foreach ($files as $fileinfo) {
344         $file = array();
345         $file['type'] = 'file';
346         $file['filename']     = $fileinfo->get_filename();
347         $file['filepath']     = $fileinfo->get_filepath();
348         $file['filesize']     = $fileinfo->get_filesize();
349         $file['fileurl']      = file_encode_url("$CFG->wwwroot/" . $baseurl, '/'.$context->id.'/mod_folder/content/'.$folder->revision.$fileinfo->get_filepath().$fileinfo->get_filename(), true);
350         $file['timecreated']  = $fileinfo->get_timecreated();
351         $file['timemodified'] = $fileinfo->get_timemodified();
352         $file['sortorder']    = $fileinfo->get_sortorder();
353         $file['userid']       = $fileinfo->get_userid();
354         $file['author']       = $fileinfo->get_author();
355         $file['license']      = $fileinfo->get_license();
356         $contents[] = $file;
357     }
359     return $contents;
362 /**
363  * Register the ability to handle drag and drop file uploads
364  * @return array containing details of the files / types the mod can handle
365  */
366 function folder_dndupload_register() {
367     return array('files' => array(
368                      array('extension' => 'zip', 'message' => get_string('dnduploadmakefolder', 'mod_folder'))
369                  ));
372 /**
373  * Handle a file that has been uploaded
374  * @param object $uploadinfo details of the file / content that has been uploaded
375  * @return int instance id of the newly created mod
376  */
377 function folder_dndupload_handle($uploadinfo) {
378     global $DB, $USER;
380     // Gather the required info.
381     $data = new stdClass();
382     $data->course = $uploadinfo->course->id;
383     $data->name = $uploadinfo->displayname;
384     $data->intro = '<p>'.$uploadinfo->displayname.'</p>';
385     $data->introformat = FORMAT_HTML;
386     $data->coursemodule = $uploadinfo->coursemodule;
387     $data->files = null; // We will unzip the file and sort out the contents below.
389     $data->id = folder_add_instance($data, null);
391     // Retrieve the file from the draft file area.
392     $context = context_module::instance($uploadinfo->coursemodule);
393     file_save_draft_area_files($uploadinfo->draftitemid, $context->id, 'mod_folder', 'temp', 0, array('subdirs'=>true));
394     $fs = get_file_storage();
395     $files = $fs->get_area_files($context->id, 'mod_folder', 'temp', 0, 'sortorder', false);
396     // Only ever one file - extract the contents.
397     $file = reset($files);
399     $success = $file->extract_to_storage(new zip_packer(), $context->id, 'mod_folder', 'content', 0, '/', $USER->id);
400     $fs->delete_area_files($context->id, 'mod_folder', 'temp', 0);
402     if ($success) {
403         return $data->id;
404     }
406     $DB->delete_records('folder', array('id' => $data->id));
407     return false;