mirror of
https://github.com/moodle/moodle.git
synced 2025-01-18 05:58:34 +01:00
af164ce9c7
One of the resource settings, the file type, has been moved to the activity badge near the activity name. The rest of the information will be displayed using the afterlink feature. However, for now, the activity page still displays all the information together (that's why resource_get_optional_details() supports now one new parameter, $showtype, to define whether the file type should be displayed or not).
556 lines
20 KiB
PHP
556 lines
20 KiB
PHP
<?php
|
|
|
|
// This file is part of Moodle - http://moodle.org/
|
|
//
|
|
// Moodle is free software: you can redistribute it and/or modify
|
|
// it under the terms of the GNU General Public License as published by
|
|
// the Free Software Foundation, either version 3 of the License, or
|
|
// (at your option) any later version.
|
|
//
|
|
// Moodle is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU General Public License
|
|
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
/**
|
|
* Private resource module utility functions
|
|
*
|
|
* @package mod_resource
|
|
* @copyright 2009 Petr Skoda {@link http://skodak.org}
|
|
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
|
*/
|
|
|
|
defined('MOODLE_INTERNAL') || die;
|
|
|
|
require_once("$CFG->libdir/filelib.php");
|
|
require_once("$CFG->libdir/resourcelib.php");
|
|
require_once("$CFG->dirroot/mod/resource/lib.php");
|
|
|
|
/**
|
|
* Redirected to migrated resource if needed,
|
|
* return if incorrect parameters specified
|
|
* @param int $oldid
|
|
* @param int $cmid
|
|
* @return void
|
|
*/
|
|
function resource_redirect_if_migrated($oldid, $cmid) {
|
|
global $DB, $CFG;
|
|
|
|
if ($oldid) {
|
|
$old = $DB->get_record('resource_old', array('oldid'=>$oldid));
|
|
} else {
|
|
$old = $DB->get_record('resource_old', array('cmid'=>$cmid));
|
|
}
|
|
|
|
if (!$old) {
|
|
return;
|
|
}
|
|
|
|
redirect("$CFG->wwwroot/mod/$old->newmodule/view.php?id=".$old->cmid);
|
|
}
|
|
|
|
/**
|
|
* Display embedded resource file.
|
|
* @param object $resource
|
|
* @param object $cm
|
|
* @param object $course
|
|
* @param stored_file $file main file
|
|
* @return does not return
|
|
*/
|
|
function resource_display_embed($resource, $cm, $course, $file) {
|
|
global $PAGE, $OUTPUT;
|
|
|
|
$clicktoopen = resource_get_clicktoopen($file, $resource->revision);
|
|
|
|
$context = context_module::instance($cm->id);
|
|
$moodleurl = moodle_url::make_pluginfile_url($context->id, 'mod_resource', 'content', $resource->revision,
|
|
$file->get_filepath(), $file->get_filename());
|
|
|
|
$mimetype = $file->get_mimetype();
|
|
$title = $resource->name;
|
|
|
|
$extension = resourcelib_get_extension($file->get_filename());
|
|
|
|
$mediamanager = core_media_manager::instance($PAGE);
|
|
$embedoptions = array(
|
|
core_media_manager::OPTION_TRUSTED => true,
|
|
core_media_manager::OPTION_BLOCK => true,
|
|
);
|
|
|
|
if (file_mimetype_in_typegroup($mimetype, 'web_image')) { // It's an image
|
|
$code = resourcelib_embed_image($moodleurl->out(), $title);
|
|
|
|
} else if ($mimetype === 'application/pdf') {
|
|
// PDF document
|
|
$code = resourcelib_embed_pdf($moodleurl->out(), $title, $clicktoopen);
|
|
|
|
} else if ($mediamanager->can_embed_url($moodleurl, $embedoptions)) {
|
|
// Media (audio/video) file.
|
|
$code = $mediamanager->embed_url($moodleurl, $title, 0, 0, $embedoptions);
|
|
|
|
} else {
|
|
// We need a way to discover if we are loading remote docs inside an iframe.
|
|
$moodleurl->param('embed', 1);
|
|
|
|
// anything else - just try object tag enlarged as much as possible
|
|
$code = resourcelib_embed_general($moodleurl, $title, $clicktoopen, $mimetype);
|
|
}
|
|
|
|
// Let the module handle the display.
|
|
$PAGE->activityheader->set_description(resource_get_intro($resource, $cm));
|
|
|
|
resource_print_header($resource, $cm, $course);
|
|
|
|
echo format_text($code, FORMAT_HTML, ['noclean' => true]);
|
|
|
|
echo $OUTPUT->footer();
|
|
die;
|
|
}
|
|
|
|
/**
|
|
* Display resource frames.
|
|
* @param object $resource
|
|
* @param object $cm
|
|
* @param object $course
|
|
* @param stored_file $file main file
|
|
* @return does not return
|
|
*/
|
|
function resource_display_frame($resource, $cm, $course, $file) {
|
|
global $PAGE, $OUTPUT, $CFG;
|
|
|
|
$frame = optional_param('frameset', 'main', PARAM_ALPHA);
|
|
|
|
if ($frame === 'top') {
|
|
$PAGE->set_pagelayout('frametop');
|
|
$PAGE->activityheader->set_description(resource_get_intro($resource, $cm, true));
|
|
resource_print_header($resource, $cm, $course);
|
|
echo $OUTPUT->footer();
|
|
die;
|
|
|
|
} else {
|
|
$config = get_config('resource');
|
|
$context = context_module::instance($cm->id);
|
|
$path = '/'.$context->id.'/mod_resource/content/'.$resource->revision.$file->get_filepath().$file->get_filename();
|
|
$fileurl = file_encode_url($CFG->wwwroot.'/pluginfile.php', $path, false);
|
|
$navurl = "$CFG->wwwroot/mod/resource/view.php?id=$cm->id&frameset=top";
|
|
$title = strip_tags(format_string($course->shortname.': '.$resource->name));
|
|
$framesize = $config->framesize;
|
|
$contentframetitle = s(format_string($resource->name));
|
|
$modulename = s(get_string('modulename','resource'));
|
|
$dir = get_string('thisdirection', 'langconfig');
|
|
|
|
$file = <<<EOF
|
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">
|
|
<html dir="$dir">
|
|
<head>
|
|
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
|
|
<title>$title</title>
|
|
</head>
|
|
<frameset rows="$framesize,*">
|
|
<frame src="$navurl" title="$modulename" />
|
|
<frame src="$fileurl" title="$contentframetitle" />
|
|
</frameset>
|
|
</html>
|
|
EOF;
|
|
|
|
@header('Content-Type: text/html; charset=utf-8');
|
|
echo $file;
|
|
die;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Internal function - create click to open text with link.
|
|
*/
|
|
function resource_get_clicktoopen($file, $revision, $extra='') {
|
|
global $CFG;
|
|
|
|
$filename = $file->get_filename();
|
|
$path = '/'.$file->get_contextid().'/mod_resource/content/'.$revision.$file->get_filepath().$file->get_filename();
|
|
$fullurl = file_encode_url($CFG->wwwroot.'/pluginfile.php', $path, false);
|
|
|
|
$string = get_string('clicktoopen2', 'resource', "<a href=\"$fullurl\" $extra>$filename</a>");
|
|
|
|
return $string;
|
|
}
|
|
|
|
/**
|
|
* Internal function - create click to open text with link.
|
|
*/
|
|
function resource_get_clicktodownload($file, $revision) {
|
|
global $CFG;
|
|
|
|
$filename = $file->get_filename();
|
|
$path = '/'.$file->get_contextid().'/mod_resource/content/'.$revision.$file->get_filepath().$file->get_filename();
|
|
$fullurl = file_encode_url($CFG->wwwroot.'/pluginfile.php', $path, true);
|
|
|
|
$string = get_string('clicktodownload', 'resource', "<a href=\"$fullurl\">$filename</a>");
|
|
|
|
return $string;
|
|
}
|
|
|
|
/**
|
|
* Print resource info and workaround link when JS not available.
|
|
* @param object $resource
|
|
* @param object $cm
|
|
* @param object $course
|
|
* @param stored_file $file main file
|
|
* @return does not return
|
|
*/
|
|
function resource_print_workaround($resource, $cm, $course, $file) {
|
|
global $CFG, $OUTPUT, $PAGE;
|
|
|
|
// Let the module handle the display.
|
|
$PAGE->activityheader->set_description(resource_get_intro($resource, $cm, true));
|
|
|
|
resource_print_header($resource, $cm, $course);
|
|
|
|
$resource->mainfile = $file->get_filename();
|
|
echo '<div class="resourceworkaround">';
|
|
switch (resource_get_final_display_type($resource)) {
|
|
case RESOURCELIB_DISPLAY_POPUP:
|
|
$path = '/'.$file->get_contextid().'/mod_resource/content/'.$resource->revision.$file->get_filepath().$file->get_filename();
|
|
$fullurl = file_encode_url($CFG->wwwroot.'/pluginfile.php', $path, false);
|
|
$options = empty($resource->displayoptions) ? [] : (array) unserialize_array($resource->displayoptions);
|
|
$width = empty($options['popupwidth']) ? 620 : $options['popupwidth'];
|
|
$height = empty($options['popupheight']) ? 450 : $options['popupheight'];
|
|
$wh = "width=$width,height=$height,toolbar=no,location=no,menubar=no,copyhistory=no,status=no,directories=no,scrollbars=yes,resizable=yes";
|
|
$extra = "onclick=\"window.open('$fullurl', '', '$wh'); return false;\"";
|
|
echo resource_get_clicktoopen($file, $resource->revision, $extra);
|
|
break;
|
|
|
|
case RESOURCELIB_DISPLAY_NEW:
|
|
$extra = 'onclick="this.target=\'_blank\'"';
|
|
echo resource_get_clicktoopen($file, $resource->revision, $extra);
|
|
break;
|
|
|
|
case RESOURCELIB_DISPLAY_DOWNLOAD:
|
|
echo resource_get_clicktodownload($file, $resource->revision);
|
|
break;
|
|
|
|
case RESOURCELIB_DISPLAY_OPEN:
|
|
default:
|
|
echo resource_get_clicktoopen($file, $resource->revision);
|
|
break;
|
|
}
|
|
echo '</div>';
|
|
|
|
echo $OUTPUT->footer();
|
|
die;
|
|
}
|
|
|
|
/**
|
|
* Print resource header.
|
|
* @param object $resource
|
|
* @param object $cm
|
|
* @param object $course
|
|
* @return void
|
|
*/
|
|
function resource_print_header($resource, $cm, $course) {
|
|
global $PAGE, $OUTPUT;
|
|
|
|
$PAGE->set_title($course->shortname.': '.$resource->name);
|
|
$PAGE->set_heading($course->fullname);
|
|
$PAGE->set_activity_record($resource);
|
|
echo $OUTPUT->header();
|
|
}
|
|
|
|
/**
|
|
* Gets details of the file to cache in course cache to be displayed using {@link resource_get_optional_details()}
|
|
*
|
|
* @param object $resource Resource table row (only property 'displayoptions' is used here)
|
|
* @param object $cm Course-module table row
|
|
* @return string Size and type or empty string if show options are not enabled
|
|
*/
|
|
function resource_get_file_details($resource, $cm) {
|
|
$options = empty($resource->displayoptions) ? [] : (array) unserialize_array($resource->displayoptions);
|
|
$filedetails = array();
|
|
if (!empty($options['showsize']) || !empty($options['showtype']) || !empty($options['showdate'])) {
|
|
$context = context_module::instance($cm->id);
|
|
$fs = get_file_storage();
|
|
$files = $fs->get_area_files($context->id, 'mod_resource', 'content', 0, 'sortorder DESC, id ASC', false);
|
|
// For a typical file resource, the sortorder is 1 for the main file
|
|
// and 0 for all other files. This sort approach is used just in case
|
|
// there are situations where the file has a different sort order.
|
|
$mainfile = $files ? reset($files) : null;
|
|
if (!empty($options['showsize'])) {
|
|
$filedetails['size'] = 0;
|
|
foreach ($files as $file) {
|
|
// This will also synchronize the file size for external files if needed.
|
|
$filedetails['size'] += $file->get_filesize();
|
|
if ($file->get_repository_id()) {
|
|
// If file is a reference the 'size' attribute can not be cached.
|
|
$filedetails['isref'] = true;
|
|
}
|
|
}
|
|
}
|
|
if (!empty($options['showtype'])) {
|
|
if ($mainfile) {
|
|
$filedetails['type'] = get_mimetype_description($mainfile);
|
|
$filedetails['mimetype'] = $mainfile->get_mimetype();
|
|
$filedetails['extension'] = strtoupper(resourcelib_get_extension($mainfile->get_filename()));
|
|
// Only show type if it is not unknown.
|
|
if ($filedetails['type'] === get_mimetype_description('document/unknown')) {
|
|
$filedetails['type'] = '';
|
|
}
|
|
} else {
|
|
$filedetails['type'] = '';
|
|
}
|
|
}
|
|
if (!empty($options['showdate'])) {
|
|
if ($mainfile) {
|
|
// Modified date may be up to several minutes later than uploaded date just because
|
|
// teacher did not submit the form promptly. Give teacher up to 5 minutes to do it.
|
|
if ($mainfile->get_timemodified() > $mainfile->get_timecreated() + 5 * MINSECS) {
|
|
$filedetails['modifieddate'] = $mainfile->get_timemodified();
|
|
} else {
|
|
$filedetails['uploadeddate'] = $mainfile->get_timecreated();
|
|
}
|
|
if ($mainfile->get_repository_id()) {
|
|
// If main file is a reference the 'date' attribute can not be cached.
|
|
$filedetails['isref'] = true;
|
|
}
|
|
} else {
|
|
$filedetails['uploadeddate'] = '';
|
|
}
|
|
}
|
|
}
|
|
return $filedetails;
|
|
}
|
|
|
|
/**
|
|
* Gets optional details for a resource, depending on resource settings.
|
|
*
|
|
* Result may include the file size and type if those settings are chosen,
|
|
* or blank if none.
|
|
*
|
|
* @param object $resource Resource table row (only property 'displayoptions' is used here)
|
|
* @param object $cm Course-module table row
|
|
* @param bool $showtype Whether the file type should be displayed or not (regardless the display option is enabled).
|
|
* @return string Size and type or empty string if show options are not enabled
|
|
*/
|
|
function resource_get_optional_details($resource, $cm, bool $showtype = true) {
|
|
global $DB;
|
|
|
|
$details = '';
|
|
|
|
$options = empty($resource->displayoptions) ? [] : (array) unserialize_array($resource->displayoptions);
|
|
if (!empty($options['showsize']) || ($showtype && !empty($options['showtype'])) || !empty($options['showdate'])) {
|
|
if (!array_key_exists('filedetails', $options)) {
|
|
$filedetails = resource_get_file_details($resource, $cm);
|
|
} else {
|
|
$filedetails = $options['filedetails'];
|
|
}
|
|
$size = '';
|
|
$type = '';
|
|
$date = '';
|
|
$langstring = '';
|
|
$infodisplayed = 0;
|
|
if (!empty($options['showsize'])) {
|
|
if (!empty($filedetails['size'])) {
|
|
$size = display_size($filedetails['size']);
|
|
$langstring .= 'size';
|
|
$infodisplayed += 1;
|
|
}
|
|
}
|
|
if ($showtype && !empty($options['showtype'])) {
|
|
if (!empty($filedetails['type'])) {
|
|
$type = $filedetails['extension'];
|
|
$langstring .= 'type';
|
|
$infodisplayed += 1;
|
|
}
|
|
}
|
|
if (!empty($options['showdate']) && (!empty($filedetails['modifieddate']) || !empty($filedetails['uploadeddate']))) {
|
|
if (!empty($filedetails['modifieddate'])) {
|
|
$date = get_string('modifieddate', 'mod_resource', userdate($filedetails['modifieddate'],
|
|
get_string('strftimedatetimeshort', 'langconfig')));
|
|
} else if (!empty($filedetails['uploadeddate'])) {
|
|
$date = get_string('uploadeddate', 'mod_resource', userdate($filedetails['uploadeddate'],
|
|
get_string('strftimedatetimeshort', 'langconfig')));
|
|
}
|
|
$langstring .= 'date';
|
|
$infodisplayed += 1;
|
|
}
|
|
|
|
if ($infodisplayed > 1) {
|
|
$details = get_string("resourcedetails_{$langstring}", 'resource',
|
|
(object)array('size' => $size, 'type' => $type, 'date' => $date));
|
|
} else {
|
|
// Only one of size, type and date is set, so just append.
|
|
$details = $size . $type . $date;
|
|
}
|
|
}
|
|
|
|
return $details;
|
|
}
|
|
|
|
/**
|
|
* Gets optional file type extension for a resource, depending on resource settings.
|
|
*
|
|
* @param object $resource Resource table row (only property 'displayoptions' is used here)
|
|
* @param object $cm Course-module table row
|
|
* @return string File extension or null if showtype option is not enabled
|
|
*/
|
|
function resource_get_optional_filetype($resource, $cm): ?string {
|
|
$filetype = null;
|
|
|
|
$options = empty($resource->displayoptions) ? [] : (array) unserialize_array($resource->displayoptions);
|
|
if (empty($options['showtype'])) {
|
|
// Show type option is disabled; early return null filetype.
|
|
return $filetype;
|
|
}
|
|
|
|
if (!array_key_exists('filedetails', $options)) {
|
|
$filedetails = resource_get_file_details($resource, $cm);
|
|
} else {
|
|
$filedetails = $options['filedetails'];
|
|
}
|
|
if (!empty($filedetails['type'])) {
|
|
$filetype = $filedetails['extension'];
|
|
}
|
|
|
|
return $filetype;
|
|
}
|
|
|
|
/**
|
|
* Get resource introduction.
|
|
*
|
|
* @param object $resource
|
|
* @param object $cm
|
|
* @param bool $ignoresettings print even if not specified in modedit
|
|
* @return string
|
|
*/
|
|
function resource_get_intro(object $resource, object $cm, bool $ignoresettings = false): string {
|
|
$options = empty($resource->displayoptions) ? [] : (array) unserialize_array($resource->displayoptions);
|
|
|
|
$extraintro = resource_get_optional_details($resource, $cm);
|
|
if ($extraintro) {
|
|
// Put a paragaph tag around the details
|
|
$extraintro = html_writer::tag('p', $extraintro, array('class' => 'resourcedetails'));
|
|
}
|
|
|
|
$content = "";
|
|
if ($ignoresettings || !empty($options['printintro']) || $extraintro) {
|
|
$gotintro = !html_is_blank($resource->intro);
|
|
if ($gotintro || $extraintro) {
|
|
if ($gotintro) {
|
|
$content = format_module_intro('resource', $resource, $cm->id);
|
|
}
|
|
$content .= $extraintro;
|
|
}
|
|
}
|
|
|
|
return $content;
|
|
}
|
|
|
|
/**
|
|
* Print warning that instance not migrated yet.
|
|
* @param object $resource
|
|
* @param object $cm
|
|
* @param object $course
|
|
* @return void, does not return
|
|
*/
|
|
function resource_print_tobemigrated($resource, $cm, $course) {
|
|
global $DB, $OUTPUT, $PAGE;
|
|
$PAGE->activityheader->set_description(resource_get_intro($resource, $cm));
|
|
$resource_old = $DB->get_record('resource_old', array('oldid'=>$resource->id));
|
|
resource_print_header($resource, $cm, $course);
|
|
echo $OUTPUT->notification(get_string('notmigrated', 'resource', $resource_old->type));
|
|
echo $OUTPUT->footer();
|
|
die;
|
|
}
|
|
|
|
/**
|
|
* Print warning that file can not be found.
|
|
* @param object $resource
|
|
* @param object $cm
|
|
* @param object $course
|
|
* @return void, does not return
|
|
*/
|
|
function resource_print_filenotfound($resource, $cm, $course) {
|
|
global $DB, $OUTPUT, $PAGE;
|
|
|
|
$resource_old = $DB->get_record('resource_old', array('oldid'=>$resource->id));
|
|
$PAGE->activityheader->set_description(resource_get_intro($resource, $cm));
|
|
resource_print_header($resource, $cm, $course);
|
|
if ($resource_old) {
|
|
echo $OUTPUT->notification(get_string('notmigrated', 'resource', $resource_old->type));
|
|
} else {
|
|
echo $OUTPUT->notification(get_string('filenotfound', 'resource'));
|
|
}
|
|
echo $OUTPUT->footer();
|
|
die;
|
|
}
|
|
|
|
/**
|
|
* Decide the best display format.
|
|
* @param object $resource
|
|
* @return int display type constant
|
|
*/
|
|
function resource_get_final_display_type($resource) {
|
|
global $CFG, $PAGE;
|
|
|
|
if ($resource->display != RESOURCELIB_DISPLAY_AUTO) {
|
|
return $resource->display;
|
|
}
|
|
|
|
if (empty($resource->mainfile)) {
|
|
return RESOURCELIB_DISPLAY_DOWNLOAD;
|
|
} else {
|
|
$mimetype = mimeinfo('type', $resource->mainfile);
|
|
}
|
|
|
|
if (file_mimetype_in_typegroup($mimetype, 'archive')) {
|
|
return RESOURCELIB_DISPLAY_DOWNLOAD;
|
|
}
|
|
if (file_mimetype_in_typegroup($mimetype, array('web_image', '.htm', 'web_video', 'web_audio'))) {
|
|
return RESOURCELIB_DISPLAY_EMBED;
|
|
}
|
|
|
|
// let the browser deal with it somehow
|
|
return RESOURCELIB_DISPLAY_OPEN;
|
|
}
|
|
|
|
/**
|
|
* File browsing support class
|
|
*/
|
|
class resource_content_file_info extends file_info_stored {
|
|
public function get_parent() {
|
|
if ($this->lf->get_filepath() === '/' and $this->lf->get_filename() === '.') {
|
|
return $this->browser->get_file_info($this->context);
|
|
}
|
|
return parent::get_parent();
|
|
}
|
|
public function get_visible_name() {
|
|
if ($this->lf->get_filepath() === '/' and $this->lf->get_filename() === '.') {
|
|
return $this->topvisiblename;
|
|
}
|
|
return parent::get_visible_name();
|
|
}
|
|
}
|
|
|
|
function resource_set_mainfile($data) {
|
|
global $DB;
|
|
$fs = get_file_storage();
|
|
$cmid = $data->coursemodule;
|
|
$draftitemid = $data->files;
|
|
|
|
$context = context_module::instance($cmid);
|
|
if ($draftitemid) {
|
|
$options = array('subdirs' => true, 'embed' => false);
|
|
if ($data->display == RESOURCELIB_DISPLAY_EMBED) {
|
|
$options['embed'] = true;
|
|
}
|
|
file_save_draft_area_files($draftitemid, $context->id, 'mod_resource', 'content', 0, $options);
|
|
}
|
|
$files = $fs->get_area_files($context->id, 'mod_resource', 'content', 0, 'sortorder', false);
|
|
if (count($files) == 1) {
|
|
// only one file attached, set it as main file automatically
|
|
$file = reset($files);
|
|
file_set_sortorder($context->id, 'mod_resource', 'content', 0, $file->get_filepath(), $file->get_filename(), 1);
|
|
}
|
|
}
|