Merge branch 'MDL-22504_drag_and_drop_upload_final' of https://github.com/davosmith...
[moodle.git] / mod / folder / lib.php
blob607e78fb8f63a35deac45e8546295b63e4338757
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.
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
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
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
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;
51 /**
52 * Returns all other caps used in module
53 * @return array
55 function folder_get_extra_capabilities() {
56 return array('moodle/site:accessallgroups');
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
64 function folder_reset_userdata($data) {
65 return array();
68 /**
69 * List of view style log actions
70 * @return array
72 function folder_get_view_actions() {
73 return array('view', 'view all');
76 /**
77 * List of update style log actions
78 * @return array
80 function folder_get_post_actions() {
81 return array('update', 'add');
84 /**
85 * Add folder instance.
86 * @param object $data
87 * @param object $mform
88 * @return int new folder instance id
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));
107 return $data->id;
111 * Update folder instance.
112 * @param object $data
113 * @param object $mform
114 * @return bool true
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));
133 return true;
137 * Delete folder instance.
138 * @param int $id
139 * @return bool true
141 function folder_delete_instance($id) {
142 global $DB;
144 if (!$folder = $DB->get_record('folder', array('id'=>$id))) {
145 return false;
148 // note: all context files are deleted automatically
150 $DB->delete_records('folder', array('id'=>$folder->id));
152 return true;
156 * Return use outline
157 * @param object $course
158 * @param object $user
159 * @param object $mod
160 * @param object $folder
161 * @return object|null
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;
178 return NULL;
182 * Return use complete
183 * @param object $course
184 * @param object $user
185 * @param object $mod
186 * @param object $folder
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');
207 * Lists all browsable file areas
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
216 function folder_get_file_areas($course, $cm, $context) {
217 $areas = array();
218 $areas['content'] = get_string('foldercontent', 'folder');
220 return $areas;
224 * File browsing support for folder module content area.
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
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;
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;
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);
268 // note: folder_intro handled in file_browser automatically
270 return null;
274 * Serves the folder files.
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
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;
294 require_course_login($course, true, $cm);
295 if (!has_capability('mod/folder:view', $context)) {
296 return false;
299 if ($filearea !== 'content') {
300 // intro is handled automatically in pluginfile.php
301 return false;
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;
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);
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
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;
330 * Export folder resource contents
332 * @return array of file content
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;
359 return $contents;
363 * Register the ability to handle drag and drop file uploads
364 * @return array containing details of the files / types the mod can handle
366 function mod_folder_dndupload_register() {
367 return array('files' => array(
368 array('extension' => 'zip', 'message' => get_string('dnduploadmakefolder', 'mod_folder'))
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
377 function mod_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;
406 $DB->delete_records('folder', array('id' => $data->id));
407 return false;