Commit | Line | Data |
---|---|---|
28f672b2 | 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/>. | |
2a439ba7 | 17 | |
28f672b2 | 18 | /** |
702ab58c PS |
19 | * @package mod |
20 | * @subpackage resource | |
21 | * @copyright 2009 Petr Skoda {@link http://skodak.org} | |
22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later | |
28f672b2 | 23 | */ |
24 | ||
702ab58c PS |
25 | defined('MOODLE_INTERNAL') || die; |
26 | ||
aa54ed7b | 27 | /** |
28 | * List of features supported in Resource module | |
29 | * @param string $feature FEATURE_xx constant for requested feature | |
30 | * @return mixed True if module supports feature, false if not, null if doesn't know | |
31 | */ | |
32 | function resource_supports($feature) { | |
33 | switch($feature) { | |
34 | case FEATURE_MOD_ARCHETYPE: return MOD_ARCHETYPE_RESOURCE; | |
35 | case FEATURE_GROUPS: return false; | |
36 | case FEATURE_GROUPINGS: return false; | |
37 | case FEATURE_GROUPMEMBERSONLY: return true; | |
38 | case FEATURE_MOD_INTRO: return true; | |
39 | case FEATURE_COMPLETION_TRACKS_VIEWS: return true; | |
40 | case FEATURE_GRADE_HAS_GRADE: return false; | |
41 | case FEATURE_GRADE_OUTCOMES: return false; | |
a345de6e | 42 | case FEATURE_BACKUP_MOODLE2: return true; |
3e4c2435 | 43 | case FEATURE_SHOW_DESCRIPTION: return true; |
214b1cf7 | 44 | |
aa54ed7b | 45 | default: return null; |
46 | } | |
47 | } | |
713d78ea | 48 | |
28f672b2 | 49 | /** |
aa54ed7b | 50 | * Returns all other caps used in module |
51 | * @return array | |
28f672b2 | 52 | */ |
aa54ed7b | 53 | function resource_get_extra_capabilities() { |
54 | return array('moodle/site:accessallgroups'); | |
55 | } | |
3d30a455 | 56 | |
d18830fe | 57 | /** |
aa54ed7b | 58 | * This function is used by the reset_course_userdata function in moodlelib. |
59 | * @param $data the data submitted from the reset course. | |
60 | * @return array status array | |
28f672b2 | 61 | */ |
aa54ed7b | 62 | function resource_reset_userdata($data) { |
63 | return array(); | |
64 | } | |
65634a81 | 65 | |
aa54ed7b | 66 | /** |
67 | * List of view style log actions | |
68 | * @return array | |
69 | */ | |
70 | function resource_get_view_actions() { | |
71 | return array('view','view all'); | |
72 | } | |
65634a81 | 73 | |
aa54ed7b | 74 | /** |
75 | * List of update style log actions | |
76 | * @return array | |
77 | */ | |
78 | function resource_get_post_actions() { | |
79 | return array('update', 'add'); | |
80 | } | |
65634a81 | 81 | |
aa54ed7b | 82 | /** |
83 | * Add resource instance. | |
84 | * @param object $data | |
85 | * @param object $mform | |
c6c9a3bc | 86 | * @return int new resource instance id |
aa54ed7b | 87 | */ |
88 | function resource_add_instance($data, $mform) { | |
89 | global $CFG, $DB; | |
90 | require_once("$CFG->libdir/resourcelib.php"); | |
f79321f1 | 91 | $cmid = $data->coursemodule; |
aa54ed7b | 92 | $data->timemodified = time(); |
a2c57666 | 93 | |
94 | resource_set_display_options($data); | |
d18830fe | 95 | |
aa54ed7b | 96 | $data->id = $DB->insert_record('resource', $data); |
d18830fe | 97 | |
aa54ed7b | 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)); | |
f79321f1 | 100 | resource_set_mainfile($data); |
aa54ed7b | 101 | return $data->id; |
102 | } | |
cccb016a | 103 | |
aa54ed7b | 104 | /** |
105 | * Update resource instance. | |
106 | * @param object $data | |
107 | * @param object $mform | |
108 | * @return bool true | |
109 | */ | |
110 | function resource_update_instance($data, $mform) { | |
111 | global $CFG, $DB; | |
112 | require_once("$CFG->libdir/resourcelib.php"); | |
aa54ed7b | 113 | $data->timemodified = time(); |
114 | $data->id = $data->instance; | |
115 | $data->revision++; | |
2a439ba7 | 116 | |
a2c57666 | 117 | resource_set_display_options($data); |
118 | ||
119 | $DB->update_record('resource', $data); | |
120 | resource_set_mainfile($data); | |
121 | return true; | |
122 | } | |
123 | ||
124 | /** | |
125 | * Updates display options based on form input. | |
126 | * | |
127 | * Shared code used by resource_add_instance and resource_update_instance. | |
128 | * | |
129 | * @param object $data Data object | |
130 | */ | |
131 | function resource_set_display_options($data) { | |
aa54ed7b | 132 | $displayoptions = array(); |
133 | if ($data->display == RESOURCELIB_DISPLAY_POPUP) { | |
134 | $displayoptions['popupwidth'] = $data->popupwidth; | |
135 | $displayoptions['popupheight'] = $data->popupheight; | |
65634a81 | 136 | } |
aa54ed7b | 137 | if (in_array($data->display, array(RESOURCELIB_DISPLAY_AUTO, RESOURCELIB_DISPLAY_EMBED, RESOURCELIB_DISPLAY_FRAME))) { |
138 | $displayoptions['printheading'] = (int)!empty($data->printheading); | |
139 | $displayoptions['printintro'] = (int)!empty($data->printintro); | |
3efe78df | 140 | } |
a2c57666 | 141 | if (!empty($data->showsize)) { |
142 | $displayoptions['showsize'] = 1; | |
143 | } | |
144 | if (!empty($data->showtype)) { | |
145 | $displayoptions['showtype'] = 1; | |
146 | } | |
aa54ed7b | 147 | $data->displayoptions = serialize($displayoptions); |
d18830fe | 148 | } |
149 | ||
28f672b2 | 150 | /** |
aa54ed7b | 151 | * Delete resource instance. |
28f672b2 | 152 | * @param int $id |
aa54ed7b | 153 | * @return bool true |
28f672b2 | 154 | */ |
d18830fe | 155 | function resource_delete_instance($id) { |
aa54ed7b | 156 | global $DB; |
ec81373f | 157 | |
aa54ed7b | 158 | if (!$resource = $DB->get_record('resource', array('id'=>$id))) { |
d18830fe | 159 | return false; |
160 | } | |
79035d46 | 161 | |
aa54ed7b | 162 | // note: all context files are deleted automatically |
ec81373f | 163 | |
aa54ed7b | 164 | $DB->delete_records('resource', array('id'=>$resource->id)); |
d18830fe | 165 | |
aa54ed7b | 166 | return true; |
d18830fe | 167 | } |
168 | ||
28f672b2 | 169 | /** |
aa54ed7b | 170 | * Return use outline |
28f672b2 | 171 | * @param object $course |
172 | * @param object $user | |
173 | * @param object $mod | |
174 | * @param object $resource | |
175 | * @return object|null | |
176 | */ | |
2a439ba7 | 177 | function resource_user_outline($course, $user, $mod, $resource) { |
5f5cd33c | 178 | global $DB; |
179 | ||
aa54ed7b | 180 | if ($logs = $DB->get_records('log', array('userid'=>$user->id, 'module'=>'resource', |
181 | 'action'=>'view', 'info'=>$resource->id), 'time ASC')) { | |
2a439ba7 | 182 | |
183 | $numviews = count($logs); | |
184 | $lastlog = array_pop($logs); | |
185 | ||
39790bd8 | 186 | $result = new stdClass(); |
aa54ed7b | 187 | $result->info = get_string('numviews', '', $numviews); |
2a439ba7 | 188 | $result->time = $lastlog->time; |
189 | ||
190 | return $result; | |
191 | } | |
192 | return NULL; | |
193 | } | |
194 | ||
28f672b2 | 195 | /** |
aa54ed7b | 196 | * Return use complete |
28f672b2 | 197 | * @param object $course |
198 | * @param object $user | |
199 | * @param object $mod | |
200 | * @param object $resource | |
201 | */ | |
2a439ba7 | 202 | function resource_user_complete($course, $user, $mod, $resource) { |
5f5cd33c | 203 | global $CFG, $DB; |
2a439ba7 | 204 | |
aa54ed7b | 205 | if ($logs = $DB->get_records('log', array('userid'=>$user->id, 'module'=>'resource', |
206 | 'action'=>'view', 'info'=>$resource->id), 'time ASC')) { | |
2a439ba7 | 207 | $numviews = count($logs); |
208 | $lastlog = array_pop($logs); | |
209 | ||
aa54ed7b | 210 | $strmostrecently = get_string('mostrecently'); |
211 | $strnumviews = get_string('numviews', '', $numviews); | |
2a439ba7 | 212 | |
213 | echo "$strnumviews - $strmostrecently ".userdate($lastlog->time); | |
214 | ||
215 | } else { | |
aa54ed7b | 216 | print_string('neverseen', 'resource'); |
2a439ba7 | 217 | } |
218 | } | |
219 | ||
28f672b2 | 220 | /** |
221 | * Returns the users with data in one resource | |
28f672b2 | 222 | * |
2b04c41c SH |
223 | * @todo: deprecated - to be deleted in 2.2 |
224 | * | |
28f672b2 | 225 | * @param int $resourceid |
226 | * @return bool false | |
227 | */ | |
84caf038 | 228 | function resource_get_participants($resourceid) { |
84caf038 | 229 | return false; |
230 | } | |
2a439ba7 | 231 | |
28f672b2 | 232 | /** |
233 | * Given a course_module object, this function returns any | |
234 | * "extra" information that may be needed when printing | |
235 | * this activity in a course listing. | |
236 | * | |
237 | * See {@link get_array_of_activities()} in course/lib.php | |
238 | * | |
3e4c2435 | 239 | * @param cm_info $coursemodule |
240 | * @return cached_cm_info info | |
28f672b2 | 241 | */ |
8dddba42 | 242 | function resource_get_coursemodule_info($coursemodule) { |
aa54ed7b | 243 | global $CFG, $DB; |
244 | require_once("$CFG->libdir/filelib.php"); | |
245 | require_once("$CFG->dirroot/mod/resource/locallib.php"); | |
516c5eca PS |
246 | require_once($CFG->libdir.'/completionlib.php'); |
247 | ||
f79321f1 | 248 | $context = get_context_instance(CONTEXT_MODULE, $coursemodule->id); |
ec81373f | 249 | |
3e4c2435 | 250 | if (!$resource = $DB->get_record('resource', array('id'=>$coursemodule->instance), |
251 | 'id, name, display, displayoptions, tobemigrated, revision, intro, introformat')) { | |
aa54ed7b | 252 | return NULL; |
af65e103 | 253 | } |
ec81373f | 254 | |
3e4c2435 | 255 | $info = new cached_cm_info(); |
aa54ed7b | 256 | $info->name = $resource->name; |
3e4c2435 | 257 | if ($coursemodule->showdescription) { |
258 | // Convert intro to html. Do not filter cached version, filters run at display time. | |
259 | $info->content = format_module_intro('resource', $resource, $coursemodule->id, false); | |
260 | } | |
8dddba42 | 261 | |
aa54ed7b | 262 | if ($resource->tobemigrated) { |
263 | $info->icon ='i/cross_red_big'; | |
264 | return $info; | |
af65e103 | 265 | } |
f79321f1 | 266 | $fs = get_file_storage(); |
3d8f1d3a | 267 | $files = $fs->get_area_files($context->id, 'mod_resource', 'content', 0, 'sortorder DESC, id ASC', false); // TODO: this is not very efficient!! |
f79321f1 | 268 | if (count($files) >= 1) { |
020088d6 | 269 | $mainfile = reset($files); |
ede72522 | 270 | $info->icon = file_extension_icon($mainfile->get_filename()); |
f79321f1 DC |
271 | $resource->mainfile = $mainfile->get_filename(); |
272 | } | |
d18830fe | 273 | |
aa54ed7b | 274 | $display = resource_get_final_display_type($resource); |
9f741612 | 275 | |
aa54ed7b | 276 | if ($display == RESOURCELIB_DISPLAY_POPUP) { |
277 | $fullurl = "$CFG->wwwroot/mod/resource/view.php?id=$coursemodule->id&redirect=1"; | |
278 | $options = empty($resource->displayoptions) ? array() : unserialize($resource->displayoptions); | |
279 | $width = empty($options['popupwidth']) ? 620 : $options['popupwidth']; | |
280 | $height = empty($options['popupheight']) ? 450 : $options['popupheight']; | |
281 | $wh = "width=$width,height=$height,toolbar=no,location=no,menubar=no,copyhistory=no,status=no,directories=no,scrollbars=yes,resizable=yes"; | |
3e4c2435 | 282 | $info->onclick = "window.open('$fullurl', '', '$wh'); return false;"; |
6da4b261 | 283 | |
aa54ed7b | 284 | } else if ($display == RESOURCELIB_DISPLAY_NEW) { |
285 | $fullurl = "$CFG->wwwroot/mod/resource/view.php?id=$coursemodule->id&redirect=1"; | |
3e4c2435 | 286 | $info->onclick = "window.open('$fullurl'); return false;"; |
6da4b261 | 287 | |
6da4b261 | 288 | } |
89bfeee0 | 289 | |
a2c57666 | 290 | // If any optional extra details are turned on, store in custom data |
291 | $info->customdata = resource_get_optional_details($resource, $coursemodule); | |
292 | ||
aa54ed7b | 293 | return $info; |
6da4b261 | 294 | } |
f3221af9 | 295 | |
a2c57666 | 296 | /** |
297 | * Called when viewing course page. Shows extra details after the link if | |
298 | * enabled. | |
299 | * | |
300 | * @param cm_info $cm Course module information | |
301 | */ | |
302 | function resource_cm_info_view(cm_info $cm) { | |
303 | $details = $cm->get_custom_data(); | |
304 | if ($details) { | |
305 | $cm->set_after_link(' ' . html_writer::tag('span', $details, | |
306 | array('class' => 'resourcelinkdetails'))); | |
307 | } | |
308 | } | |
f3221af9 | 309 | |
28f672b2 | 310 | /** |
aa54ed7b | 311 | * Lists all browsable file areas |
d2b7803e DC |
312 | * |
313 | * @package mod_resource | |
314 | * @category files | |
315 | * @param stdClass $course course object | |
316 | * @param stdClass $cm course module object | |
317 | * @param stdClass $context context object | |
28f672b2 | 318 | * @return array |
319 | */ | |
aa54ed7b | 320 | function resource_get_file_areas($course, $cm, $context) { |
321 | $areas = array(); | |
64f93798 | 322 | $areas['content'] = get_string('resourcecontent', 'resource'); |
aa54ed7b | 323 | return $areas; |
f3221af9 | 324 | } |
325 | ||
28f672b2 | 326 | /** |
f1b8bcf7 | 327 | * File browsing support for resource module content area. |
d2b7803e DC |
328 | * |
329 | * @package mod_resource | |
330 | * @category files | |
331 | * @param stdClass $browser file browser instance | |
332 | * @param stdClass $areas file areas | |
333 | * @param stdClass $course course object | |
334 | * @param stdClass $cm course module object | |
335 | * @param stdClass $context context object | |
336 | * @param string $filearea file area | |
337 | * @param int $itemid item ID | |
338 | * @param string $filepath file path | |
339 | * @param string $filename file name | |
340 | * @return file_info instance or null if not found | |
28f672b2 | 341 | */ |
aa54ed7b | 342 | function resource_get_file_info($browser, $areas, $course, $cm, $context, $filearea, $itemid, $filepath, $filename) { |
343 | global $CFG; | |
a69be0d8 | 344 | |
64f93798 PS |
345 | if (!has_capability('moodle/course:managefiles', $context)) { |
346 | // students can not peak here! | |
347 | return null; | |
348 | } | |
a69be0d8 | 349 | |
aa54ed7b | 350 | $fs = get_file_storage(); |
a69be0d8 | 351 | |
64f93798 | 352 | if ($filearea === 'content') { |
aa54ed7b | 353 | $filepath = is_null($filepath) ? '/' : $filepath; |
354 | $filename = is_null($filename) ? '.' : $filename; | |
a69be0d8 | 355 | |
aa54ed7b | 356 | $urlbase = $CFG->wwwroot.'/pluginfile.php'; |
64f93798 | 357 | if (!$storedfile = $fs->get_file($context->id, 'mod_resource', 'content', 0, $filepath, $filename)) { |
aa54ed7b | 358 | if ($filepath === '/' and $filename === '.') { |
64f93798 | 359 | $storedfile = new virtual_root_file($context->id, 'mod_resource', 'content', 0); |
a69be0d8 | 360 | } else { |
aa54ed7b | 361 | // not found |
362 | return null; | |
a69be0d8 | 363 | } |
364 | } | |
aa54ed7b | 365 | require_once("$CFG->dirroot/mod/resource/locallib.php"); |
64f93798 | 366 | return new resource_content_file_info($browser, $context, $storedfile, $urlbase, $areas[$filearea], true, true, true, false); |
a69be0d8 | 367 | } |
368 | ||
aa54ed7b | 369 | // note: resource_intro handled in file_browser automatically |
a69be0d8 | 370 | |
aa54ed7b | 371 | return null; |
a69be0d8 | 372 | } |
373 | ||
0b5a80a1 | 374 | /** |
aa54ed7b | 375 | * Serves the resource files. |
d2b7803e DC |
376 | * |
377 | * @package mod_resource | |
378 | * @category files | |
379 | * @param stdClass $course course object | |
380 | * @param stdClass $cm course module object | |
381 | * @param stdClass $context context object | |
382 | * @param string $filearea file area | |
383 | * @param array $args extra arguments | |
384 | * @param bool $forcedownload whether or not force download | |
261cbbac | 385 | * @param array $options additional options affecting the file serving |
b4ff85aa | 386 | * @return bool false if file not found, does not return if found - just send the file |
28f672b2 | 387 | */ |
261cbbac | 388 | function resource_pluginfile($course, $cm, $context, $filearea, $args, $forcedownload, array $options=array()) { |
aa54ed7b | 389 | global $CFG, $DB; |
390 | require_once("$CFG->libdir/resourcelib.php"); | |
0d06b6fd | 391 | |
64f93798 | 392 | if ($context->contextlevel != CONTEXT_MODULE) { |
aa54ed7b | 393 | return false; |
3efe78df | 394 | } |
395 | ||
64f93798 | 396 | require_course_login($course, true, $cm); |
ce459060 PS |
397 | if (!has_capability('mod/resource:view', $context)) { |
398 | return false; | |
399 | } | |
3efe78df | 400 | |
64f93798 PS |
401 | if ($filearea !== 'content') { |
402 | // intro is handled automatically in pluginfile.php | |
aa54ed7b | 403 | return false; |
3efe78df | 404 | } |
405 | ||
aa54ed7b | 406 | array_shift($args); // ignore revision - designed to prevent caching problems only |
3efe78df | 407 | |
aa54ed7b | 408 | $fs = get_file_storage(); |
64f93798 | 409 | $relativepath = implode('/', $args); |
fe3c5dae PS |
410 | $fullpath = rtrim("/$context->id/mod_resource/$filearea/0/$relativepath", '/'); |
411 | do { | |
412 | if (!$file = $fs->get_file_by_hash(sha1($fullpath))) { | |
9815ccee | 413 | if ($fs->get_file_by_hash(sha1("$fullpath/."))) { |
fe3c5dae PS |
414 | if ($file = $fs->get_file_by_hash(sha1("$fullpath/index.htm"))) { |
415 | break; | |
416 | } | |
417 | if ($file = $fs->get_file_by_hash(sha1("$fullpath/index.html"))) { | |
418 | break; | |
419 | } | |
420 | if ($file = $fs->get_file_by_hash(sha1("$fullpath/Default.htm"))) { | |
421 | break; | |
422 | } | |
423 | } | |
424 | $resource = $DB->get_record('resource', array('id'=>$cm->instance), 'id, legacyfiles', MUST_EXIST); | |
425 | if ($resource->legacyfiles != RESOURCELIB_LEGACYFILES_ACTIVE) { | |
426 | return false; | |
427 | } | |
428 | if (!$file = resourcelib_try_file_migration('/'.$relativepath, $cm->id, $cm->course, 'mod_resource', 'content', 0)) { | |
429 | return false; | |
430 | } | |
431 | // file migrate - update flag | |
432 | $resource->legacyfileslast = time(); | |
433 | $DB->update_record('resource', $resource); | |
0d06b6fd | 434 | } |
fe3c5dae | 435 | } while (false); |
ffcfd8a7 | 436 | |
aa54ed7b | 437 | // should we apply filters? |
438 | $mimetype = $file->get_mimetype(); | |
b4ff85aa | 439 | if ($mimetype === 'text/html' or $mimetype === 'text/plain') { |
64f93798 | 440 | $filter = $DB->get_field('resource', 'filterfiles', array('id'=>$cm->instance)); |
4eaa964f | 441 | $CFG->embeddedsoforcelinktarget = true; |
aa54ed7b | 442 | } else { |
443 | $filter = 0; | |
18a2a0cb | 444 | } |
18a2a0cb | 445 | |
aa54ed7b | 446 | // finally send the file |
261cbbac | 447 | send_stored_file($file, 86400, $filter, $forcedownload, $options); |
13ca1e06 | 448 | } |
b1627a92 DC |
449 | |
450 | /** | |
451 | * Return a list of page types | |
452 | * @param string $pagetype current page type | |
453 | * @param stdClass $parentcontext Block's parent context | |
454 | * @param stdClass $currentcontext Current context of block | |
455 | */ | |
b38e2e28 | 456 | function resource_page_type_list($pagetype, $parentcontext, $currentcontext) { |
b1627a92 DC |
457 | $module_pagetype = array('mod-resource-*'=>get_string('page-mod-resource-x', 'resource')); |
458 | return $module_pagetype; | |
459 | } | |
ec0d6ea2 DC |
460 | |
461 | /** | |
462 | * Export file resource contents | |
463 | * | |
464 | * @return array of file content | |
465 | */ | |
466 | function resource_export_contents($cm, $baseurl) { | |
467 | global $CFG, $DB; | |
468 | $contents = array(); | |
469 | $context = get_context_instance(CONTEXT_MODULE, $cm->id); | |
470 | $resource = $DB->get_record('resource', array('id'=>$cm->instance), '*', MUST_EXIST); | |
471 | ||
472 | $fs = get_file_storage(); | |
473 | $files = $fs->get_area_files($context->id, 'mod_resource', 'content', 0, 'sortorder DESC, id ASC', false); | |
474 | ||
475 | foreach ($files as $fileinfo) { | |
476 | $file = array(); | |
477 | $file['type'] = 'file'; | |
478 | $file['filename'] = $fileinfo->get_filename(); | |
479 | $file['filepath'] = $fileinfo->get_filepath(); | |
480 | $file['filesize'] = $fileinfo->get_filesize(); | |
481 | $file['fileurl'] = file_encode_url("$CFG->wwwroot/" . $baseurl, '/'.$context->id.'/mod_resource/content/'.$resource->revision.$fileinfo->get_filepath().$fileinfo->get_filename(), true); | |
482 | $file['timecreated'] = $fileinfo->get_timecreated(); | |
483 | $file['timemodified'] = $fileinfo->get_timemodified(); | |
484 | $file['sortorder'] = $fileinfo->get_sortorder(); | |
485 | $file['userid'] = $fileinfo->get_userid(); | |
486 | $file['author'] = $fileinfo->get_author(); | |
487 | $file['license'] = $fileinfo->get_license(); | |
488 | $contents[] = $file; | |
489 | } | |
490 | ||
491 | return $contents; | |
492 | } |