MDL-14627 fixed file_browser access control
[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;
46         default: return null;
47     }
48 }
50 /**
51  * Returns all other caps used in module
52  * @return array
53  */
54 function folder_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 folder_reset_userdata($data) {
64     return array();
65 }
67 /**
68  * List of view style log actions
69  * @return array
70  */
71 function folder_get_view_actions() {
72     return array('view', 'view all');
73 }
75 /**
76  * List of update style log actions
77  * @return array
78  */
79 function folder_get_post_actions() {
80     return array('update', 'add');
81 }
83 /**
84  * Add folder instance.
85  * @param object $data
86  * @param object $mform
87  * @return int new folder instance id
88  */
89 function folder_add_instance($data, $mform) {
90     global $DB;
92     $cmid        = $data->coursemodule;
93     $draftitemid = $data->files;
95     $data->timemodified = time();
96     $data->id = $DB->insert_record('folder', $data);
98     // we need to use context now, so we need to make sure all needed info is already in db
99     $DB->set_field('course_modules', 'instance', $data->id, array('id'=>$cmid));
100     $context = get_context_instance(CONTEXT_MODULE, $cmid);
102     if ($draftitemid) {
103         file_save_draft_area_files($draftitemid, $context->id, 'mod_folder', 'content', 0, array('subdirs'=>true));
104     }
106     return $data->id;
109 /**
110  * Update folder instance.
111  * @param object $data
112  * @param object $mform
113  * @return bool true
114  */
115 function folder_update_instance($data, $mform) {
116     global $CFG, $DB;
118     $cmid        = $data->coursemodule;
119     $draftitemid = $data->files;
121     $data->timemodified = time();
122     $data->id           = $data->instance;
123     $data->revision++;
125     $DB->update_record('folder', $data);
127     $context = get_context_instance(CONTEXT_MODULE, $cmid);
128     if ($draftitemid = file_get_submitted_draft_itemid('files')) {
129         file_save_draft_area_files($draftitemid, $context->id, 'mod_folder', 'content', 0, array('subdirs'=>true));
130     }
132     return true;
135 /**
136  * Delete folder instance.
137  * @param int $id
138  * @return bool true
139  */
140 function folder_delete_instance($id) {
141     global $DB;
143     if (!$folder = $DB->get_record('folder', array('id'=>$id))) {
144         return false;
145     }
147     // note: all context files are deleted automatically
149     $DB->delete_records('folder', array('id'=>$folder->id));
151     return true;
154 /**
155  * Return use outline
156  * @param object $course
157  * @param object $user
158  * @param object $mod
159  * @param object $folder
160  * @return object|null
161  */
162 function folder_user_outline($course, $user, $mod, $folder) {
163     global $DB;
165     if ($logs = $DB->get_records('log', array('userid'=>$user->id, 'module'=>'folder',
166                                               'action'=>'view', 'info'=>$folder->id), 'time ASC')) {
168         $numviews = count($logs);
169         $lastlog = array_pop($logs);
171         $result = new stdClass();
172         $result->info = get_string('numviews', '', $numviews);
173         $result->time = $lastlog->time;
175         return $result;
176     }
177     return NULL;
180 /**
181  * Return use complete
182  * @param object $course
183  * @param object $user
184  * @param object $mod
185  * @param object $folder
186  */
187 function folder_user_complete($course, $user, $mod, $folder) {
188     global $CFG, $DB;
190     if ($logs = $DB->get_records('log', array('userid'=>$user->id, 'module'=>'folder',
191                                               'action'=>'view', 'info'=>$folder->id), 'time ASC')) {
192         $numviews = count($logs);
193         $lastlog = array_pop($logs);
195         $strmostrecently = get_string('mostrecently');
196         $strnumviews = get_string('numviews', '', $numviews);
198         echo "$strnumviews - $strmostrecently ".userdate($lastlog->time);
200     } else {
201         print_string('neverseen', 'folder');
202     }
205 /**
206  * Returns the users with data in one folder
207  *
208  * @param int $folderid
209  * @return bool false
210  */
211 function folder_get_participants($folderid) {
212     return false;
215 /**
216  * Lists all browsable file areas
217  * @param object $course
218  * @param object $cm
219  * @param object $context
220  * @return array
221  */
222 function folder_get_file_areas($course, $cm, $context) {
223     $areas = array();
224     $areas['content'] = get_string('foldercontent', 'folder');
226     return $areas;
229 /**
230  * File browsing support for folder module content area.
231  * @param object $browser
232  * @param object $areas
233  * @param object $course
234  * @param object $cm
235  * @param object $context
236  * @param string $filearea
237  * @param int $itemid
238  * @param string $filepath
239  * @param string $filename
240  * @return object file_info instance or null if not found
241  */
242 function folder_get_file_info($browser, $areas, $course, $cm, $context, $filearea, $itemid, $filepath, $filename) {
243     global $CFG;
246     if ($filearea === 'content') {
247         if (!has_capability('mod/folder:view', $context)) {
248             return NULL;
249         }
250         $fs = get_file_storage();
252         $filepath = is_null($filepath) ? '/' : $filepath;
253         $filename = is_null($filename) ? '.' : $filename;
254         if (!$storedfile = $fs->get_file($context->id, 'mod_folder', 'content', 0, $filepath, $filename)) {
255             if ($filepath === '/' and $filename === '.') {
256                 $storedfile = new virtual_root_file($context->id, 'mod_folder', 'content', 0);
257             } else {
258                 // not found
259                 return null;
260             }
261         }
263         require_once("$CFG->dirroot/mod/folder/locallib.php");
264         $urlbase = $CFG->wwwroot.'/pluginfile.php';
266         // students may read files here
267         $canwrite = has_capability('mod/folder:managefiles', $context);
268         return new folder_content_file_info($browser, $context, $storedfile, $urlbase, $areas[$filearea], true, true, $canwrite, false);
269     }
271     // note: folder_intro handled in file_browser automatically
273     return null;
276 /**
277  * Serves the folder files.
278  *
279  * @param object $course
280  * @param object $cm
281  * @param object $context
282  * @param string $filearea
283  * @param array $args
284  * @param bool $forcedownload
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) {
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);
318 /**
319  * This function extends the global navigation for the site.
320  * It is important to note that you should not rely on PAGE objects within this
321  * body of code as there is no guarantee that during an AJAX request they are
322  * available
323  *
324  * @param navigation_node $navigation The folder node within the global navigation
325  * @param stdClass $course The course object returned from the DB
326  * @param stdClass $module The module object returned from the DB
327  * @param stdClass $cm The course module instance returned from the DB
328  */
329 function folder_extend_navigation($navigation, $course, $module, $cm) {
330     /**
331      * This is currently just a stub so that it can be easily expanded upon.
332      * When expanding just remove this comment and the line below and then add
333      * you content.
334      */
335     $navigation->nodetype = navigation_node::NODETYPE_LEAF;