Merge commit 'catalyst/MOODLE_19_STABLE' into mdl19-linuxchix
[moodle-linuxchix.git] / mod / resource / lib.php
blob7deec4be1cccb8318eba1b878d27a087c2db9256
1 <?php // $Id$
3 define('RESOURCE_LOCALPATH', 'LOCALPATH');
5 global $RESOURCE_WINDOW_OPTIONS; // must be global because it might be included from a function!
6 $RESOURCE_WINDOW_OPTIONS = array('resizable', 'scrollbars', 'directories', 'location',
7 'menubar', 'toolbar', 'status', 'width', 'height');
9 if (!isset($CFG->resource_hide_repository)) {
10 set_config("resource_hide_repository", "1");
13 /**
14 * resource_base is the base class for resource types
16 * This class provides all the functionality for a resource
19 class resource_base {
21 var $cm;
22 var $course;
23 var $resource;
24 var $navlinks;
26 /**
27 * Constructor for the base resource class
29 * Constructor for the base resource class.
30 * If cmid is set create the cm, course, resource objects.
31 * and do some checks to make sure people can be here, and so on.
33 * @param cmid integer, the current course module id - not set for new resources
35 function resource_base($cmid=0) {
37 global $CFG, $COURSE;
38 $this->navlinks = array();
40 if ($cmid) {
41 if (! $this->cm = get_coursemodule_from_id('resource', $cmid)) {
42 error("Course Module ID was incorrect");
45 if (! $this->course = get_record("course", "id", $this->cm->course)) {
46 error("Course is misconfigured");
49 if (! $this->resource = get_record("resource", "id", $this->cm->instance)) {
50 error("Resource ID was incorrect");
53 $this->strresource = get_string("modulename", "resource");
54 $this->strresources = get_string("modulenameplural", "resource");
56 if (!$this->cm->visible and !has_capability('moodle/course:viewhiddenactivities', get_context_instance(CONTEXT_MODULE, $this->cm->id))) {
57 $pagetitle = strip_tags($this->course->shortname.': '.$this->strresource);
58 $navigation = build_navigation($this->navlinks, $this->cm);
60 print_header($pagetitle, $this->course->fullname, $navigation, "", "", true, '', navmenu($this->course, $this->cm));
61 notice(get_string("activityiscurrentlyhidden"), "$CFG->wwwroot/course/view.php?id={$this->course->id}");
64 } else {
65 $this->course = $COURSE;
70 /**
71 * Display function does nothing in the base class
73 function display() {
78 /**
79 * Display the resource with the course blocks.
81 function display_course_blocks_start() {
83 global $CFG;
84 global $USER;
85 global $THEME;
87 require_once($CFG->libdir.'/blocklib.php');
88 require_once($CFG->libdir.'/pagelib.php');
89 require_once($CFG->dirroot.'/course/lib.php'); //required by some blocks
91 $PAGE = page_create_object(PAGE_COURSE_VIEW, $this->course->id);
92 $this->PAGE = $PAGE;
93 $pageblocks = blocks_setup($PAGE);
95 $blocks_preferred_width = bounded_number(180, blocks_preferred_width($pageblocks[BLOCK_POS_LEFT]), 210);
97 /// Print the page header
99 $edit = optional_param('edit', -1, PARAM_BOOL);
101 if (($edit != -1) and $PAGE->user_allowed_editing()) {
102 $USER->editing = $edit;
105 $morenavlinks = array($this->strresources => 'index.php?id='.$this->course->id,
106 $this->resource->name => '');
108 $PAGE->print_header($this->course->shortname.': %fullname%', $morenavlinks, "", "",
109 update_module_button($this->cm->id, $this->course->id, $this->strresource));
111 echo '<table id="layout-table"><tr>';
113 $lt = (empty($THEME->layouttable)) ? array('left', 'middle', 'right') : $THEME->layouttable;
114 foreach ($lt as $column) {
115 $lt1[] = $column;
116 if ($column == 'middle') break;
118 foreach ($lt1 as $column) {
119 switch ($column) {
120 case 'left':
121 if((blocks_have_content($pageblocks, BLOCK_POS_LEFT) || $PAGE->user_is_editing())) {
122 echo '<td style="width: '.$blocks_preferred_width.'px;" id="left-column">';
123 print_container_start();
124 blocks_print_group($PAGE, $pageblocks, BLOCK_POS_LEFT);
125 print_container_end();
126 echo '</td>';
128 break;
130 case 'middle':
131 echo '<td id="middle-column">';
132 print_container_start(false, 'middle-column-wrap');
133 echo '<div id="resource">';
134 break;
136 case 'right':
137 if((blocks_have_content($pageblocks, BLOCK_POS_RIGHT) || $PAGE->user_is_editing())) {
138 echo '<td style="width: '.$blocks_preferred_width.'px;" id="right-column">';
139 print_container_start();
140 blocks_print_group($PAGE, $pageblocks, BLOCK_POS_RIGHT);
141 print_container_end();
142 echo '</td>';
144 break;
151 * Finish displaying the resource with the course blocks
153 function display_course_blocks_end() {
155 global $CFG;
156 global $THEME;
158 $PAGE = $this->PAGE;
159 $pageblocks = blocks_setup($PAGE);
160 $blocks_preferred_width = bounded_number(180, blocks_preferred_width($pageblocks[BLOCK_POS_RIGHT]), 210);
162 $lt = (empty($THEME->layouttable)) ? array('left', 'middle', 'right') : $THEME->layouttable;
163 foreach ($lt as $column) {
164 if ($column != 'middle') {
165 array_shift($lt);
166 } else if ($column == 'middle') {
167 break;
170 foreach ($lt as $column) {
171 switch ($column) {
172 case 'left':
173 if((blocks_have_content($pageblocks, BLOCK_POS_LEFT) || $PAGE->user_is_editing())) {
174 echo '<td style="width: '.$blocks_preferred_width.'px;" id="left-column">';
175 print_container_start();
176 blocks_print_group($PAGE, $pageblocks, BLOCK_POS_LEFT);
177 print_container_end();
178 echo '</td>';
180 break;
182 case 'middle':
183 echo '</div>';
184 print_container_end();
185 echo '</td>';
186 break;
188 case 'right':
189 if((blocks_have_content($pageblocks, BLOCK_POS_RIGHT) || $PAGE->user_is_editing())) {
190 echo '<td style="width: '.$blocks_preferred_width.'px;" id="right-column">';
191 print_container_start();
192 blocks_print_group($PAGE, $pageblocks, BLOCK_POS_RIGHT);
193 print_container_end();
194 echo '</td>';
196 break;
200 echo '</tr></table>';
202 print_footer($this->course);
207 function add_instance($resource) {
208 // Given an object containing all the necessary data,
209 // (defined by the form in mod.html) this function
210 // will create a new instance and return the id number
211 // of the new instance.
213 $resource->timemodified = time();
215 return insert_record("resource", $resource);
219 function update_instance($resource) {
220 // Given an object containing all the necessary data,
221 // (defined by the form in mod.html) this function
222 // will update an existing instance with new data.
224 $resource->id = $resource->instance;
225 $resource->timemodified = time();
227 return update_record("resource", $resource);
231 function delete_instance($resource) {
232 // Given an object containing the resource data
233 // this function will permanently delete the instance
234 // and any data that depends on it.
236 $result = true;
238 if (! delete_records("resource", "id", "$resource->id")) {
239 $result = false;
242 return $result;
245 function setup_elements(&$mform) {
246 //override to add your own options
249 function setup_preprocessing(&$default_values){
250 //override to add your own options
253 } /// end of class definition
257 function resource_add_instance($resource) {
258 global $CFG;
260 $resource->type = clean_param($resource->type, PARAM_SAFEDIR); // Just to be safe
262 require_once("$CFG->dirroot/mod/resource/type/$resource->type/resource.class.php");
263 $resourceclass = "resource_$resource->type";
264 $res = new $resourceclass();
266 return $res->add_instance($resource);
269 function resource_update_instance($resource) {
270 global $CFG;
272 $resource->type = clean_param($resource->type, PARAM_SAFEDIR); // Just to be safe
274 require_once("$CFG->dirroot/mod/resource/type/$resource->type/resource.class.php");
275 $resourceclass = "resource_$resource->type";
276 $res = new $resourceclass();
278 return $res->update_instance($resource);
281 function resource_delete_instance($id) {
282 global $CFG;
284 if (! $resource = get_record("resource", "id", "$id")) {
285 return false;
288 $resource->type = clean_param($resource->type, PARAM_SAFEDIR); // Just to be safe
290 require_once("$CFG->dirroot/mod/resource/type/$resource->type/resource.class.php");
291 $resourceclass = "resource_$resource->type";
292 $res = new $resourceclass();
294 return $res->delete_instance($resource);
298 function resource_user_outline($course, $user, $mod, $resource) {
299 if ($logs = get_records_select("log", "userid='$user->id' AND module='resource'
300 AND action='view' AND info='$resource->id'", "time ASC")) {
302 $numviews = count($logs);
303 $lastlog = array_pop($logs);
305 $result = new object();
306 $result->info = get_string("numviews", "", $numviews);
307 $result->time = $lastlog->time;
309 return $result;
311 return NULL;
315 function resource_user_complete($course, $user, $mod, $resource) {
316 global $CFG;
318 if ($logs = get_records_select("log", "userid='$user->id' AND module='resource'
319 AND action='view' AND info='$resource->id'", "time ASC")) {
320 $numviews = count($logs);
321 $lastlog = array_pop($logs);
323 $strmostrecently = get_string("mostrecently");
324 $strnumviews = get_string("numviews", "", $numviews);
326 echo "$strnumviews - $strmostrecently ".userdate($lastlog->time);
328 } else {
329 print_string("neverseen", "resource");
333 function resource_get_participants($resourceid) {
334 //Returns the users with data in one resource
335 //(NONE, byt must exists on EVERY mod !!)
337 return false;
340 function resource_get_coursemodule_info($coursemodule) {
341 /// Given a course_module object, this function returns any
342 /// "extra" information that may be needed when printing
343 /// this activity in a course listing.
345 /// See get_array_of_activities() in course/lib.php
348 global $CFG;
350 $info = NULL;
352 if ($resource = get_record("resource", "id", $coursemodule->instance, '', '', '', '', 'id, popup, reference, type, name')) {
353 $info = new object();
354 $info->name = $resource->name;
355 if (!empty($resource->popup)) {
356 $info->extra = urlencode("onclick=\"this.target='resource$resource->id'; return ".
357 "openpopup('/mod/resource/view.php?inpopup=true&amp;id=".
358 $coursemodule->id.
359 "','resource$resource->id','$resource->popup');\"");
362 require_once($CFG->libdir.'/filelib.php');
364 if ($resource->type == 'file') {
365 $icon = mimeinfo("icon", $resource->reference);
366 if ($icon != 'unknown.gif') {
367 $info->icon ="f/$icon";
368 } else {
369 $info->icon ="f/web.gif";
371 } else if ($resource->type == 'directory') {
372 $info->icon ="f/folder.gif";
376 return $info;
379 function resource_fetch_remote_file ($cm, $url, $headers = "" ) {
380 /// Snoopy is an HTTP client in PHP
382 global $CFG;
384 require_once("$CFG->libdir/snoopy/Snoopy.class.inc");
386 $client = new Snoopy();
387 $ua = 'Moodle/'. $CFG->release . ' (+http://moodle.org';
388 if ( $CFG->resource_usecache ) {
389 $ua = $ua . ')';
390 } else {
391 $ua = $ua . '; No cache)';
393 $client->agent = $ua;
394 $client->read_timeout = 5;
395 $client->use_gzip = true;
396 if (is_array($headers) ) {
397 $client->rawheaders = $headers;
400 @$client->fetch($url);
401 if ( $client->status >= 200 && $client->status < 300 ) {
402 $tags = array("A" => "href=",
403 "IMG" => "src=",
404 "LINK" => "href=",
405 "AREA" => "href=",
406 "FRAME" => "src=",
407 "IFRAME" => "src=",
408 "FORM" => "action=");
410 foreach ($tags as $tag => $key) {
411 $prefix = "fetch.php?id=$cm->id&amp;url=";
412 if ( $tag == "IMG" or $tag == "LINK" or $tag == "FORM") {
413 $prefix = "";
415 $client->results = resource_redirect_tags($client->results, $url, $tag, $key,$prefix);
417 } else {
418 if ( $client->status >= 400 && $client->status < 500) {
419 $client->results = get_string("fetchclienterror","resource"); // Client error
420 } elseif ( $client->status >= 500 && $client->status < 600) {
421 $client->results = get_string("fetchservererror","resource"); // Server error
422 } else {
423 $client->results = get_string("fetcherror","resource"); // Redirection? HEAD? Unknown error.
426 return $client;
429 function resource_redirect_tags($text, $url, $tagtoparse, $keytoparse,$prefix = "" ) {
430 $valid = 1;
431 if ( strpos($url,"?") == FALSE ) {
432 $valid = 1;
434 if ( $valid ) {
435 $lastpoint = strrpos($url,".");
436 $lastslash = strrpos($url,"/");
437 if ( $lastpoint > $lastslash ) {
438 $root = substr($url,0,$lastslash+1);
439 } else {
440 $root = $url;
442 if ( $root == "http://" or
443 $root == "https://") {
444 $root = $url;
446 if ( substr($root,strlen($root)-1) == '/' ) {
447 $root = substr($root,0,-1);
450 $mainroot = $root;
451 $lastslash = strrpos($mainroot,"/");
452 while ( $lastslash > 9) {
453 $mainroot = substr($mainroot,0,$lastslash);
455 $lastslash = strrpos($mainroot,"/");
458 $regex = "/<$tagtoparse (.+?)>/is";
459 $count = preg_match_all($regex, $text, $hrefs);
460 for ( $i = 0; $i < $count; $i++) {
461 $tag = $hrefs[1][$i];
463 $poshref = strpos(strtolower($tag),strtolower($keytoparse));
464 $start = $poshref + strlen($keytoparse);
465 $left = substr($tag,0,$start);
466 if ( $tag[$start] == '"' ) {
467 $left .= '"';
468 $start++;
470 $posspace = strpos($tag," ", $start+1);
471 $right = "";
472 if ( $posspace != FALSE) {
473 $right = substr($tag, $posspace);
475 $end = strlen($tag)-1;
476 if ( $tag[$end] == '"' ) {
477 $right = '"' . $right;
479 $finalurl = substr($tag,$start,$end-$start+$diff);
480 // Here, we could have these possible values for $finalurl:
481 // file.ext Add current root dir
482 // http://(domain) don't care
483 // http://(domain)/ don't care
484 // http://(domain)/folder don't care
485 // http://(domain)/folder/ don't care
486 // http://(domain)/folder/file.ext don't care
487 // folder/ Add current root dir
488 // folder/file.ext Add current root dir
489 // /folder/ Add main root dir
490 // /folder/file.ext Add main root dir
492 // Special case: If finalurl contains a ?, it won't be parsed
493 $valid = 1;
495 if ( strpos($finalurl,"?") == FALSE ) {
496 $valid = 1;
498 if ( $valid ) {
499 if ( $finalurl[0] == "/" ) {
500 $finalurl = $mainroot . $finalurl;
501 } elseif ( strtolower(substr($finalurl,0,7)) != "http://" and
502 strtolower(substr($finalurl,0,8)) != "https://") {
503 if ( $finalurl[0] == "/") {
504 $finalurl = $mainroot . $finalurl;
505 } else {
506 $finalurl = "$root/$finalurl";
510 $text = str_replace($tag,"$left$prefix$finalurl$right",$text);
514 return $text;
517 function resource_is_url($path) {
518 if (strpos($path, '://')) { // eg http:// https:// ftp:// etc
519 return true;
521 if (strpos($path, '/') === 0) { // Starts with slash
522 return true;
524 return false;
527 function resource_get_types() {
528 global $CFG;
530 $types = array();
532 $standardresources = array('text','html','file','directory');
533 foreach ($standardresources as $resourcetype) {
534 $type = new object();
535 $type->modclass = MOD_CLASS_RESOURCE;
536 $type->name = $resourcetype;
537 $type->type = "resource&amp;type=$resourcetype";
538 $type->typestr = get_string("resourcetype$resourcetype", 'resource');
539 $types[] = $type;
542 /// Drop-in extra resource types
543 $resourcetypes = get_list_of_plugins('mod/resource/type');
544 foreach ($resourcetypes as $resourcetype) {
545 if (!empty($CFG->{'resource_hide_'.$resourcetype})) { // Not wanted
546 continue;
548 if (!in_array($resourcetype, $standardresources)) {
549 $type = new object();
550 $type->modclass = MOD_CLASS_RESOURCE;
551 $type->name = $resourcetype;
552 $type->type = "resource&amp;type=$resourcetype";
553 $type->typestr = get_string("resourcetype$resourcetype", 'resource');
554 $types[] = $type;
558 return $types;
561 function resource_get_view_actions() {
562 return array('view','view all');
565 function resource_get_post_actions() {
566 return array();
569 function resource_renamefiles($course, $wdir, $oldname, $name) {
570 global $CFG;
572 $status = '<p align=\"center\"><strong>'.get_string('affectedresources', 'resource').':</strong><ul>';
573 $updates = false;
575 $old = trim($wdir.'/'.$oldname, '/');
576 $new = trim($wdir.'/'.$name, '/');
578 $sql = "SELECT r.id, r.reference, r.name, cm.id AS cmid
579 FROM {$CFG->prefix}resource r,
580 {$CFG->prefix}course_modules cm,
581 {$CFG->prefix}modules m
582 WHERE r.course = '{$course->id}'
583 AND m.name = 'resource'
584 AND cm.module = m.id
585 AND cm.instance = r.id
586 AND (r.type = 'file' OR r.type = 'directory')
587 AND (r.reference LIKE '{$old}/%' OR r.reference = '{$old}')";
588 if ($resources = get_records_sql($sql)) {
589 foreach ($resources as $resource) {
590 $r = new object();
591 $r->id = $resource->id;
592 $r->reference = '';
593 if ($resource->reference == $old) {
594 $r->reference = addslashes($new);
595 } else {
596 $r->reference = addslashes(preg_replace('|^'.preg_quote($old, '|').'/|', $new.'/', $resource->reference));
598 if ($r->reference !== '') {
599 $updates = true;
600 $status .= "<li><a href=\"$CFG->wwwroot/mod/resource/view.php?id=$resource->cmid\" target=\"_blank\">$resource->name</a>: $resource->reference ==> $r->reference</li>";
601 if (!empty($CFG->resource_autofilerename)) {
602 if (!update_record('resource', $r)) {
603 error("Error updating resource with ID $r->id.");
609 $status .= '</ul></p>';
611 if ($updates) {
612 echo $status;
613 if (empty($CFG->resource_autofilerename)) {
614 notify(get_string('warningdisabledrename', 'resource'));
619 function resource_delete_warning($course, $files) {
620 global $CFG;
622 $found = array();
624 foreach($files as $key=>$file) {
625 $files[$key] = trim($file, '/');
627 $sql = "SELECT r.id, r.reference, r.name, cm.id AS cmid
628 FROM {$CFG->prefix}resource r,
629 {$CFG->prefix}course_modules cm,
630 {$CFG->prefix}modules m
631 WHERE r.course = '{$course->id}'
632 AND m.name = 'resource'
633 AND cm.module = m.id
634 AND cm.instance = r.id
635 AND (r.type = 'file' OR r.type = 'directory')";
636 if ($resources = get_records_sql($sql)) {
637 foreach ($resources as $resource) {
638 if ($resource->reference == '') {
639 continue; // top shared directory does not prevent anything
641 if (in_array($resource->reference, $files)) {
642 $found[$resource->id] = $resource;
643 } else {
644 foreach($files as $file) {
645 if (preg_match('|^'.preg_quote($file, '|').'/|', $resource->reference)) {
646 $found[$resource->id] = $resource;
653 if (!empty($found)) {
655 print_simple_box_start("center");
656 echo '<p><strong>'.get_string('affectedresources', 'resource').':</strong><ul>';
657 foreach($found as $resource) {
658 echo "<li><a href=\"$CFG->wwwroot/mod/resource/view.php?id=$resource->cmid\" target=\"_blank\">$resource->name</a>: $resource->reference</li>";
660 echo '</ul></p>';
661 print_simple_box_end();
663 return true;
664 } else {
665 return false;
670 * This function is used by the reset_course_userdata function in moodlelib.
671 * @param $data the data submitted from the reset course.
672 * @return array status array
674 function resource_reset_userdata($data) {
675 return array();
679 * Returns all other caps used in module
681 function resource_get_extra_capabilities() {
682 return array('moodle/site:accessallgroups');