first commit

This commit is contained in:
CHIEFSOFT\ameye
2024-09-30 18:11:26 -04:00
commit e592ca6823
27270 changed files with 5002257 additions and 0 deletions
+306
View File
@@ -0,0 +1,306 @@
<?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/>.
/**
* Provides support for the conversion of moodle1 backup to the moodle2 format
*
* @package mod_resource
* @copyright 2011 Andrew Davis <andrew@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
/**
* Resource conversion handler
*/
class moodle1_mod_resource_handler extends moodle1_mod_handler {
/** @var moodle1_file_manager instance */
protected $fileman = null;
/** @var array of resource successors handlers */
private $successors = array();
/**
* Declare the paths in moodle.xml we are able to convert
*
* The method returns list of {@link convert_path} instances.
* For each path returned, the corresponding conversion method must be
* defined.
*
* Note that the paths /MOODLE_BACKUP/COURSE/MODULES/MOD/RESOURCE do not
* actually exist in the file. The last element with the module name was
* appended by the moodle1_converter class.
*
* @return array of {@link convert_path} instances
*/
public function get_paths() {
return array(
new convert_path(
'resource', '/MOODLE_BACKUP/COURSE/MODULES/MOD/RESOURCE',
array(
'renamefields' => array(
'summary' => 'intro',
),
'newfields' => array(
'introformat' => 0,
),
'dropfields' => array(
'modtype',
),
)
)
);
}
/**
* Converts /MOODLE_BACKUP/COURSE/MODULES/MOD/RESOURCE data
*
* This methods detects the resource type and eventually re-dispatches it to the
* corresponding resource successor (url, forum, page, imscp).
*/
public function process_resource(array $data, array $raw) {
global $CFG;
require_once("$CFG->libdir/resourcelib.php");
// replay the upgrade step 2009042001
if ($CFG->texteditors !== 'textarea') {
$data['intro'] = text_to_html($data['intro'], false, false, true);
$data['introformat'] = FORMAT_HTML;
}
// fix invalid null popup and options data
if (!array_key_exists('popup', $data) or is_null($data['popup'])) {
$data['popup'] = '';
}
if (!array_key_exists ('options', $data) or is_null($data['options'])) {
$data['options'] = '';
}
// decide if the legacy resource should be handled by a successor module
if ($successor = $this->get_successor($data['type'], $data['reference'])) {
// the instance id will be kept
$instanceid = $data['id'];
// move the instance from the resource's modinfo stash to the successor's
// modinfo stash
$resourcemodinfo = $this->converter->get_stash('modinfo_resource');
$successormodinfo = $this->converter->get_stash('modinfo_'.$successor->get_modname());
$successormodinfo['instances'][$instanceid] = $resourcemodinfo['instances'][$instanceid];
unset($resourcemodinfo['instances'][$instanceid]);
$this->converter->set_stash('modinfo_resource', $resourcemodinfo);
$this->converter->set_stash('modinfo_'.$successor->get_modname(), $successormodinfo);
// get the course module information for the legacy resource module
$cminfo = $this->get_cminfo($instanceid);
// use the version of the successor instead of the current mod/resource
// beware - the version.php declares info via $module object, do not use
// a variable of such name here
$plugin = new stdClass();
$plugin->version = null;
$module = $plugin;
include $CFG->dirroot.'/mod/'.$successor->get_modname().'/version.php';
$cminfo['version'] = $plugin->version;
// stash the new course module information for this successor
$cminfo['modulename'] = $successor->get_modname();
$this->converter->set_stash('cminfo_'.$cminfo['modulename'], $cminfo, $instanceid);
// rewrite the coursecontents stash
$coursecontents = $this->converter->get_stash('coursecontents');
$coursecontents[$cminfo['id']]['modulename'] = $successor->get_modname();
$this->converter->set_stash('coursecontents', $coursecontents);
// delegate the processing to the successor handler
return $successor->process_legacy_resource($data, $raw);
}
// no successor is interested in this record, convert it to the new mod_resource (aka File module)
$resource = array();
$resource['id'] = $data['id'];
$resource['name'] = $data['name'];
$resource['intro'] = $data['intro'];
$resource['introformat'] = $data['introformat'];
$resource['tobemigrated'] = 0;
$resource['legacyfiles'] = RESOURCELIB_LEGACYFILES_ACTIVE;
$resource['legacyfileslast'] = null;
$resource['filterfiles'] = 0;
$resource['revision'] = 1;
$resource['timemodified'] = $data['timemodified'];
// populate display and displayoptions fields
$options = array('printintro' => 1);
if ($data['options'] == 'frame') {
$resource['display'] = RESOURCELIB_DISPLAY_FRAME;
} else if ($data['options'] == 'objectframe') {
$resource['display'] = RESOURCELIB_DISPLAY_EMBED;
} else if ($data['options'] == 'forcedownload') {
$resource['display'] = RESOURCELIB_DISPLAY_DOWNLOAD;
} else if ($data['popup']) {
$resource['display'] = RESOURCELIB_DISPLAY_POPUP;
$rawoptions = explode(',', $data['popup']);
foreach ($rawoptions as $rawoption) {
list($name, $value) = explode('=', trim($rawoption), 2);
if ($value > 0 and ($name == 'width' or $name == 'height')) {
$options['popup'.$name] = $value;
continue;
}
}
} else {
$resource['display'] = RESOURCELIB_DISPLAY_AUTO;
}
$resource['displayoptions'] = serialize($options);
// get the course module id and context id
$instanceid = $resource['id'];
$currentcminfo = $this->get_cminfo($instanceid);
$moduleid = $currentcminfo['id'];
$contextid = $this->converter->get_contextid(CONTEXT_MODULE, $moduleid);
// get a fresh new file manager for this instance
$this->fileman = $this->converter->get_file_manager($contextid, 'mod_resource');
// convert course files embedded into the intro
$this->fileman->filearea = 'intro';
$this->fileman->itemid = 0;
$resource['intro'] = moodle1_converter::migrate_referenced_files($resource['intro'], $this->fileman);
// convert the referenced file itself as a main file in the content area
$reference = $data['reference'];
if (strpos($reference, '$@FILEPHP@$') === 0) {
$reference = str_replace(array('$@FILEPHP@$', '$@SLASH@$', '$@FORCEDOWNLOAD@$'), array('', '/', ''), $reference);
}
$this->fileman->filearea = 'content';
$this->fileman->itemid = 0;
// Rebuild the file path.
$curfilepath = '/';
if ($reference) {
$curfilepath = pathinfo('/'.$reference, PATHINFO_DIRNAME);
if ($curfilepath != '/') {
$curfilepath .= '/';
}
}
try {
$this->fileman->migrate_file('course_files/'.$reference, $curfilepath, null, 1);
} catch (moodle1_convert_exception $e) {
// the file probably does not exist
$this->log('error migrating the resource main file', backup::LOG_WARNING, 'course_files/'.$reference);
}
// write resource.xml
$this->open_xml_writer("activities/resource_{$moduleid}/resource.xml");
$this->xmlwriter->begin_tag('activity', array('id' => $instanceid, 'moduleid' => $moduleid,
'modulename' => 'resource', 'contextid' => $contextid));
$this->write_xml('resource', $resource, array('/resource/id'));
$this->xmlwriter->end_tag('activity');
$this->close_xml_writer();
// write inforef.xml
$this->open_xml_writer("activities/resource_{$currentcminfo['id']}/inforef.xml");
$this->xmlwriter->begin_tag('inforef');
$this->xmlwriter->begin_tag('fileref');
foreach ($this->fileman->get_fileids() as $fileid) {
$this->write_xml('file', array('id' => $fileid));
}
$this->xmlwriter->end_tag('fileref');
$this->xmlwriter->end_tag('inforef');
$this->close_xml_writer();
}
/**
* Give succesors a chance to finish their job
*/
public function on_resource_end(array $data) {
if ($successor = $this->get_successor($data['type'], $data['reference'])) {
$successor->on_legacy_resource_end($data);
}
}
/// internal implementation details follow /////////////////////////////////
/**
* Returns the handler of the new 2.0 mod type according the given type of the legacy 1.9 resource
*
* @param string $type the value of the 'type' field in 1.9 resource
* @param string $reference a file path. Necessary to differentiate files from web URLs
* @throws moodle1_convert_exception for the unknown types
* @return null|moodle1_mod_handler the instance of the handler, or null if the type does not have a successor
*/
protected function get_successor($type, $reference) {
switch ($type) {
case 'text':
case 'html':
$name = 'page';
break;
case 'directory':
$name = 'folder';
break;
case 'ims':
$name = 'imscp';
break;
case 'file':
// if starts with $@FILEPHP@$ then it is URL link to a local course file
// to be migrated to the new resource module
if (strpos($reference, '$@FILEPHP@$') === 0) {
$name = null;
break;
}
// if http:// https:// ftp:// OR starts with slash need to be converted to URL
if (strpos($reference, '://') or strpos($reference, '/') === 0) {
$name = 'url';
} else {
$name = null;
}
break;
default:
throw new moodle1_convert_exception('unknown_resource_successor', $type);
}
if (is_null($name)) {
return null;
}
if (!isset($this->successors[$name])) {
$this->log('preparing resource successor handler', backup::LOG_DEBUG, $name);
$class = 'moodle1_mod_'.$name.'_handler';
$this->successors[$name] = new $class($this->converter, 'mod', $name);
// add the successor into the modlist stash
$modnames = $this->converter->get_stash('modnameslist');
$modnames[] = $name;
$modnames = array_unique($modnames); // should not be needed but just in case
$this->converter->set_stash('modnameslist', $modnames);
// add the successor's modinfo stash
$modinfo = $this->converter->get_stash('modinfo_resource');
$modinfo['name'] = $name;
$modinfo['instances'] = array();
$this->converter->set_stash('modinfo_'.$name, $modinfo);
}
return $this->successors[$name];
}
}
@@ -0,0 +1,127 @@
<?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/>.
/**
* Defines backup_resource_activity_task class
*
* @package mod_resource
* @category backup
* @copyright 2010 onwards Eloy Lafuente (stronk7) {@link http://stronk7.com}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die;
require_once($CFG->dirroot . '/mod/resource/backup/moodle2/backup_resource_stepslib.php');
/**
* Provides the steps to perform one complete backup of the Resource instance
*/
class backup_resource_activity_task extends backup_activity_task {
/**
* @param bool $resourceoldexists True if there are records in the resource_old table.
*/
protected static $resourceoldexists = null;
/**
* No specific settings for this activity
*/
protected function define_my_settings() {
}
/**
* Defines a backup step to store the instance data in the resource.xml file
*/
protected function define_my_steps() {
$this->add_step(new backup_resource_activity_structure_step('resource_structure', 'resource.xml'));
}
/**
* Encodes URLs to the index.php and view.php scripts
*
* @param string $content some HTML text that eventually contains URLs to the activity instance scripts
* @return string the content with the URLs encoded
*/
public static function encode_content_links($content) {
global $CFG, $DB;
$base = preg_quote($CFG->wwwroot,"/");
// Link to the list of resources.
$search="/(".$base."\/mod\/resource\/index.php\?id\=)([0-9]+)/";
$content= preg_replace($search, '$@RESOURCEINDEX*$2@$', $content);
// Link to resource view by moduleid.
$search = "/(".$base."\/mod\/resource\/view.php\?id\=)([0-9]+)/";
// Link to resource view by recordid
$search2 = "/(".$base."\/mod\/resource\/view.php\?r\=)([0-9]+)/";
// Check whether there are contents in the resource old table.
if (static::$resourceoldexists === null) {
static::$resourceoldexists = $DB->record_exists('resource_old', array());
}
// If there are links to items in the resource_old table, rewrite them to be links to the correct URL
// for their new module.
if (static::$resourceoldexists) {
// Match all of the resources.
$result = preg_match_all($search, $content, $matches, PREG_PATTERN_ORDER);
// Course module ID resource links.
if ($result) {
list($insql, $params) = $DB->get_in_or_equal($matches[2]);
$oldrecs = $DB->get_records_select('resource_old', "cmid $insql", $params, '', 'cmid, newmodule');
for ($i = 0; $i < count($matches[0]); $i++) {
$cmid = $matches[2][$i];
if (isset($oldrecs[$cmid])) {
// Resource_old item, rewrite it
$replace = '$@' . strtoupper($oldrecs[$cmid]->newmodule) . 'VIEWBYID*' . $cmid . '@$';
} else {
// Not in the resource old table, don't rewrite
$replace = '$@RESOURCEVIEWBYID*'.$cmid.'@$';
}
$content = str_replace($matches[0][$i], $replace, $content);
}
}
$matches = null;
$result = preg_match_all($search2, $content, $matches, PREG_PATTERN_ORDER);
// No resource links.
if (!$result) {
return $content;
}
// Resource ID links.
list($insql, $params) = $DB->get_in_or_equal($matches[2]);
$oldrecs = $DB->get_records_select('resource_old', "oldid $insql", $params, '', 'oldid, cmid, newmodule');
for ($i = 0; $i < count($matches[0]); $i++) {
$recordid = $matches[2][$i];
if (isset($oldrecs[$recordid])) {
// Resource_old item, rewrite it
$replace = '$@' . strtoupper($oldrecs[$recordid]->newmodule) . 'VIEWBYID*' . $oldrecs[$recordid]->cmid . '@$';
$content = str_replace($matches[0][$i], $replace, $content);
}
}
} else {
$content = preg_replace($search, '$@RESOURCEVIEWBYID*$2@$', $content);
}
return $content;
}
}
@@ -0,0 +1,60 @@
<?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/>.
/**
* Define all the backup steps that will be used by the backup_resource_activity_task
*
* @package mod_resource
* @copyright 2010 onwards Eloy Lafuente (stronk7) {@link http://stronk7.com}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die;
/**
* Define the complete resource structure for backup, with file and id annotations
*/
class backup_resource_activity_structure_step extends backup_activity_structure_step {
protected function define_structure() {
// To know if we are including userinfo
$userinfo = $this->get_setting_value('userinfo');
// Define each element separated
$resource = new backup_nested_element('resource', array('id'), array(
'name', 'intro', 'introformat', 'tobemigrated',
'legacyfiles', 'legacyfileslast', 'display',
'displayoptions', 'filterfiles', 'revision', 'timemodified'));
// Build the tree
// (love this)
// Define sources
$resource->set_source_table('resource', array('id' => backup::VAR_ACTIVITYID));
// Define id annotations
// (none)
// Define file annotations
$resource->annotate_files('mod_resource', 'intro', null); // This file areas haven't itemid
$resource->annotate_files('mod_resource', 'content', null); // This file areas haven't itemid
// Return the root element (resource), wrapped into standard activity structure
return $this->prepare_activity_structure($resource);
}
}
@@ -0,0 +1,109 @@
<?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/>.
/**
* @package mod_resource
* @subpackage backup-moodle2
* @copyright 2010 onwards Eloy Lafuente (stronk7) {@link http://stronk7.com}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
require_once($CFG->dirroot . '/mod/resource/backup/moodle2/restore_resource_stepslib.php'); // Because it exists (must)
/**
* resource restore task that provides all the settings and steps to perform one
* complete restore of the activity
*/
class restore_resource_activity_task extends restore_activity_task {
/**
* Define (add) particular settings this activity can have
*/
protected function define_my_settings() {
// No particular settings for this activity
}
/**
* Define (add) particular steps this activity can have
*/
protected function define_my_steps() {
// Choice only has one structure step
$this->add_step(new restore_resource_activity_structure_step('resource_structure', 'resource.xml'));
}
/**
* Define the contents in the activity that must be
* processed by the link decoder
*/
public static function define_decode_contents() {
$contents = array();
$contents[] = new restore_decode_content('resource', array('intro'), 'resource');
return $contents;
}
/**
* Define the decoding rules for links belonging
* to the activity to be executed by the link decoder
*/
public static function define_decode_rules() {
$rules = array();
$rules[] = new restore_decode_rule('RESOURCEVIEWBYID', '/mod/resource/view.php?id=$1', 'course_module');
$rules[] = new restore_decode_rule('RESOURCEINDEX', '/mod/resource/index.php?id=$1', 'course');
return $rules;
}
/**
* Define the restore log rules that will be applied
* by the {@link restore_logs_processor} when restoring
* resource logs. It must return one array
* of {@link restore_log_rule} objects
*/
public static function define_restore_log_rules() {
$rules = array();
$rules[] = new restore_log_rule('resource', 'add', 'view.php?id={course_module}', '{resource}');
$rules[] = new restore_log_rule('resource', 'update', 'view.php?id={course_module}', '{resource}');
$rules[] = new restore_log_rule('resource', 'view', 'view.php?id={course_module}', '{resource}');
return $rules;
}
/**
* Define the restore log rules that will be applied
* by the {@link restore_logs_processor} when restoring
* course logs. It must return one array
* of {@link restore_log_rule} objects
*
* Note this rules are applied when restoring course logs
* by the restore final task, but are defined here at
* activity level. All them are rules not linked to any module instance (cmid = 0)
*/
public static function define_restore_log_rules_for_course() {
$rules = array();
$rules[] = new restore_log_rule('resource', 'view all', 'index.php?id={course}', null);
return $rules;
}
}
@@ -0,0 +1,64 @@
<?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/>.
/**
* @package mod_resource
* @subpackage backup-moodle2
* @copyright 2010 onwards Eloy Lafuente (stronk7) {@link http://stronk7.com}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
/**
* Define all the restore steps that will be used by the restore_resource_activity_task
*/
/**
* Structure step to restore one resource activity
*/
class restore_resource_activity_structure_step extends restore_activity_structure_step {
protected function define_structure() {
$paths = array();
$paths[] = new restore_path_element('resource', '/activity/resource');
// Return the paths wrapped into standard activity structure
return $this->prepare_activity_structure($paths);
}
protected function process_resource($data) {
global $DB;
$data = (object)$data;
$oldid = $data->id;
$data->course = $this->get_courseid();
// Any changes to the list of dates that needs to be rolled should be same during course restore and course reset.
// See MDL-9367.
// insert the resource record
$newitemid = $DB->insert_record('resource', $data);
// immediately after inserting "activity" record, call this
$this->apply_activity_instance($newitemid);
}
protected function after_execute() {
// Add choice related files, no need to match by itemname (just internally handled context)
$this->add_related_files('mod_resource', 'intro', null);
$this->add_related_files('mod_resource', 'content', null);
}
}
@@ -0,0 +1,46 @@
<?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/>.
/**
* Activity base class.
*
* @package mod_resource
* @copyright 2017 onwards Ankit Agarwal <ankit.agrr@gmail.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace mod_resource\analytics\indicator;
defined('MOODLE_INTERNAL') || die();
/**
* Activity base class.
*
* @package mod_resource
* @copyright 2017 onwards Ankit Agarwal <ankit.agrr@gmail.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
abstract class activity_base extends \core_analytics\local\indicator\community_of_inquiry_activity {
/**
* No need to fetch grades for resources.
*
* @param \core_analytics\course $course
* @return void
*/
public function fetch_student_grades(\core_analytics\course $course) {
}
}
@@ -0,0 +1,56 @@
<?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/>.
/**
* Cognitive depth indicator - resource.
*
* @package mod_resource
* @copyright 2017 David Monllao {@link http://www.davidmonllao.com}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace mod_resource\analytics\indicator;
defined('MOODLE_INTERNAL') || die();
/**
* Cognitive depth indicator - resource.
*
* @package mod_resource
* @copyright 2017 David Monllao {@link http://www.davidmonllao.com}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class cognitive_depth extends activity_base {
/**
* Returns the name.
*
* If there is a corresponding '_help' string this will be shown as well.
*
* @return \lang_string
*/
public static function get_name(): \lang_string {
return new \lang_string('indicator:cognitivedepth', 'mod_resource');
}
public function get_indicator_type() {
return self::INDICATOR_COGNITIVE;
}
public function get_cognitive_depth_level(\cm_info $cm) {
return self::COGNITIVE_LEVEL_1;
}
}
@@ -0,0 +1,56 @@
<?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/>.
/**
* Social breadth indicator - resource.
*
* @package mod_resource
* @copyright 2017 David Monllao {@link http://www.davidmonllao.com}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace mod_resource\analytics\indicator;
defined('MOODLE_INTERNAL') || die();
/**
* Social breadth indicator - resource.
*
* @package mod_resource
* @copyright 2017 David Monllao {@link http://www.davidmonllao.com}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class social_breadth extends activity_base {
/**
* Returns the name.
*
* If there is a corresponding '_help' string this will be shown as well.
*
* @return \lang_string
*/
public static function get_name(): \lang_string {
return new \lang_string('indicator:socialbreadth', 'mod_resource');
}
public function get_indicator_type() {
return self::INDICATOR_SOCIAL;
}
public function get_social_breadth_level(\cm_info $cm) {
return self::SOCIAL_LEVEL_1;
}
}
@@ -0,0 +1,92 @@
<?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/>.
declare(strict_types=1);
namespace mod_resource\completion;
use core_completion\activity_custom_completion;
/**
* Activity custom completion subclass for the resource.
*
* Class for defining mod_resource's custom completion rules and fetching the completion statuses
* of the custom completion rules for a given resource instance and a user.
*
* @package mod_resource
* @copyright 2021 Huong Nguyen <huongn@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class custom_completion extends activity_custom_completion {
/**
* Fetches the completion state for a given completion rule.
*
* @param string $rule The completion rule.
* @return int The completion state.
*/
public function get_state(string $rule): int {
return COMPLETION_UNKNOWN;
}
/**
* Fetch the list of custom completion rules that this module defines.
*
* @return array
*/
public static function get_defined_custom_rules(): array {
// This activity/resource do not have any custom rules.
return [];
}
/**
* Returns an associative array of the descriptions of custom completion rules.
*
* @return array
*/
public function get_custom_rule_descriptions(): array {
// This activity/resource do not have any custom rule descriptions.
return [];
}
/**
* Show the manual completion or not regardless of the course's showcompletionconditions setting.
*
* @return bool
*/
public function manual_completion_always_shown(): bool {
$display = $this->cm->customdata['display'] ?? null;
$displaytypes = [
RESOURCELIB_DISPLAY_NEW,
RESOURCELIB_DISPLAY_OPEN,
RESOURCELIB_DISPLAY_DOWNLOAD,
RESOURCELIB_DISPLAY_POPUP
];
return in_array($display, $displaytypes);
}
/**
* Returns an array of all completion rules, in the order they should be displayed to users.
*
* @return array
*/
public function get_sort_order(): array {
// This module only supports manual completion.
return [];
}
}
+61
View File
@@ -0,0 +1,61 @@
<?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/>.
/**
* Content export definition.
*
* @package mod_resource
* @copyright 2020 Simey Lameze <simey@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace mod_resource\content;
use core\content\export\exportable_items\exportable_filearea;
use core\content\export\exporters\abstract_mod_exporter;
/**
* A class which assists a component to export content.
*
* @copyright 2020 Simey Lameze <simey@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class exporter extends abstract_mod_exporter {
/**
* Get the exportable items for mod_resource.
*
* @param bool $includeuserdata Whether to include user data, in addition to shared content.
* @return \core\content\export\exportable_item[]
*/
public function get_exportables(bool $includeuserdata = false): array {
$contentitems = [];
$contentitems[] = new exportable_filearea(
$this->get_context(),
$this->get_component(),
get_string('resourcecontent', 'mod_resource'),
// The files held in mod_resource are stored in the 'content' filearea, under itemid 0.
'content',
0,
// The itemid is used in the URL when accessing.
0
);
return $contentitems;
}
}
@@ -0,0 +1,39 @@
<?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/>.
/**
* The mod_resource instance list viewed event.
*
* @package mod_resource
* @copyright 2014 Rajesh Taneja <rajesh@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace mod_resource\event;
defined('MOODLE_INTERNAL') || die();
/**
* The mod_resource instance list viewed event class.
*
* @package mod_resource
* @since Moodle 2.7
* @copyright 2014 Rajesh Taneja <rajesh@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class course_module_instance_list_viewed extends \core\event\course_module_instance_list_viewed {
// No need for any code here as everything is handled by the parent class.
}
@@ -0,0 +1,53 @@
<?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/>.
/**
* The mod_resource course module viewed event.
*
* @package mod_resource
* @copyright 2014 Rajesh Taneja <rajesh@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace mod_resource\event;
defined('MOODLE_INTERNAL') || die();
/**
* The mod_resource course module viewed event class.
*
* @package mod_resource
* @since Moodle 2.7
* @copyright 2014 Rajesh Taneja <rajesh@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class course_module_viewed extends \core\event\course_module_viewed {
/**
* Init method.
*
* @return void
*/
protected function init() {
$this->data['objecttable'] = 'resource';
$this->data['crud'] = 'r';
$this->data['edulevel'] = self::LEVEL_PARTICIPATING;
}
public static function get_objectid_mapping() {
return array('db' => 'resource', 'restore' => 'resource');
}
}
+197
View File
@@ -0,0 +1,197 @@
<?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/>.
use core_course\external\helper_for_get_mods_by_courses;
use core_external\external_api;
use core_external\external_files;
use core_external\external_function_parameters;
use core_external\external_multiple_structure;
use core_external\external_single_structure;
use core_external\external_value;
use core_external\external_warnings;
use core_external\util;
/**
* Resource external functions
*
* @package mod_resource
* @category external
* @copyright 2015 Juan Leyva <juan@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @since Moodle 3.0
*/
class mod_resource_external extends external_api {
/**
* Returns description of method parameters
*
* @return external_function_parameters
* @since Moodle 3.0
*/
public static function view_resource_parameters() {
return new external_function_parameters(
array(
'resourceid' => new external_value(PARAM_INT, 'resource instance id')
)
);
}
/**
* Simulate the resource/view.php web interface page: trigger events, completion, etc...
*
* @param int $resourceid the resource instance id
* @return array of warnings and status result
* @since Moodle 3.0
* @throws moodle_exception
*/
public static function view_resource($resourceid) {
global $DB, $CFG;
require_once($CFG->dirroot . "/mod/resource/lib.php");
$params = self::validate_parameters(self::view_resource_parameters(),
array(
'resourceid' => $resourceid
));
$warnings = array();
// Request and permission validation.
$resource = $DB->get_record('resource', array('id' => $params['resourceid']), '*', MUST_EXIST);
list($course, $cm) = get_course_and_cm_from_instance($resource, 'resource');
$context = context_module::instance($cm->id);
self::validate_context($context);
require_capability('mod/resource:view', $context);
// Call the resource/lib API.
resource_view($resource, $course, $cm, $context);
$result = array();
$result['status'] = true;
$result['warnings'] = $warnings;
return $result;
}
/**
* Returns description of method result value
*
* @return \core_external\external_description
* @since Moodle 3.0
*/
public static function view_resource_returns() {
return new external_single_structure(
array(
'status' => new external_value(PARAM_BOOL, 'status: true if success'),
'warnings' => new external_warnings()
)
);
}
/**
* Describes the parameters for get_resources_by_courses.
*
* @return external_function_parameters
* @since Moodle 3.3
*/
public static function get_resources_by_courses_parameters() {
return new external_function_parameters (
array(
'courseids' => new external_multiple_structure(
new external_value(PARAM_INT, 'Course id'), 'Array of course ids', VALUE_DEFAULT, array()
),
)
);
}
/**
* Returns a list of files in a provided list of courses.
* If no list is provided all files that the user can view will be returned.
*
* @param array $courseids course ids
* @return array of warnings and files
* @since Moodle 3.3
*/
public static function get_resources_by_courses($courseids = array()) {
$warnings = array();
$returnedresources = array();
$params = array(
'courseids' => $courseids,
);
$params = self::validate_parameters(self::get_resources_by_courses_parameters(), $params);
$mycourses = array();
if (empty($params['courseids'])) {
$mycourses = enrol_get_my_courses();
$params['courseids'] = array_keys($mycourses);
}
// Ensure there are courseids to loop through.
if (!empty($params['courseids'])) {
list($courses, $warnings) = util::validate_courses($params['courseids'], $mycourses);
// Get the resources in this course, this function checks users visibility permissions.
// We can avoid then additional validate_context calls.
$resources = get_all_instances_in_courses("resource", $courses);
foreach ($resources as $resource) {
$context = context_module::instance($resource->coursemodule);
helper_for_get_mods_by_courses::format_name_and_intro($resource, 'mod_resource');
$resource->contentfiles = util::get_area_files($context->id, 'mod_resource', 'content');
$returnedresources[] = $resource;
}
}
$result = array(
'resources' => $returnedresources,
'warnings' => $warnings
);
return $result;
}
/**
* Describes the get_resources_by_courses return value.
*
* @return external_single_structure
* @since Moodle 3.3
*/
public static function get_resources_by_courses_returns() {
return new external_single_structure(
array(
'resources' => new external_multiple_structure(
new external_single_structure(array_merge(
helper_for_get_mods_by_courses::standard_coursemodule_elements_returns(),
[
'contentfiles' => new external_files('Files in the content'),
'tobemigrated' => new external_value(PARAM_INT, 'Whether this resource was migrated'),
'legacyfiles' => new external_value(PARAM_INT, 'Legacy files flag'),
'legacyfileslast' => new external_value(PARAM_INT, 'Legacy files last control flag'),
'display' => new external_value(PARAM_INT, 'How to display the resource'),
'displayoptions' => new external_value(PARAM_RAW, 'Display options (width, height)'),
'filterfiles' => new external_value(PARAM_INT, 'If filters should be applied to the resource content'),
'revision' => new external_value(PARAM_INT, 'Incremented when after each file changes, to avoid cache'),
'timemodified' => new external_value(PARAM_INT, 'Last time the resource was modified'),
]
))
),
'warnings' => new external_warnings(),
)
);
}
}
@@ -0,0 +1,38 @@
<?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/>.
namespace mod_resource\output\courseformat;
/**
* Activity badge resource class, used for displaying the file type.
*
* @package mod_resource
* @copyright 2023 Sara Arjona <sara@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class activitybadge extends \core_courseformat\output\activitybadge {
/**
* This method will be called before exporting the template.
*/
protected function update_content(): void {
$customdata = $this->cminfo->customdata;
if (is_array($customdata) && isset($customdata['displayoptions'])) {
$options = (object) ['displayoptions' => $customdata['displayoptions']];
$this->content = resource_get_optional_filetype($options, $this->cminfo);
}
}
}
+44
View File
@@ -0,0 +1,44 @@
<?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/>.
/**
* Privacy Subsystem implementation for mod_resource.
*
* @package mod_resource
* @copyright 2018 Zig Tan <zig@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace mod_resource\privacy;
defined('MOODLE_INTERNAL') || die();
/**
* The mod_resource module does not store any data.
*
* @copyright 2018 Zig Tan <zig@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class provider implements \core_privacy\local\metadata\null_provider {
/**
* Get the language string identifier with the component's language
* file to explain why this plugin stores no data.
*
* @return string
*/
public static function get_reason(): string {
return 'privacy:metadata';
}
}
+58
View File
@@ -0,0 +1,58 @@
<?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/>.
/**
* Search area for mod_resource activities.
*
* @package mod_resource
* @copyright 2015 David Monllao {@link http://www.davidmonllao.com}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace mod_resource\search;
defined('MOODLE_INTERNAL') || die();
/**
* Search area for mod_resource activities.
*
* @package mod_resource
* @copyright 2015 David Monllao {@link http://www.davidmonllao.com}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class activity extends \core_search\base_activity {
/**
* Returns true if this area uses file indexing.
*
* @return bool
*/
public function uses_file_indexing() {
return true;
}
/**
* Return the context info required to index files for
* this search area.
*
* @return array
*/
public function get_search_fileareas() {
$fileareas = array('intro', 'content'); // Fileareas.
return $fileareas;
}
}
+60
View File
@@ -0,0 +1,60 @@
<?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/>.
/**
* Resource module capability definition
*
* @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;
$capabilities = array(
'mod/resource:view' => array(
'captype' => 'read',
'contextlevel' => CONTEXT_MODULE,
'archetypes' => array(
'guest' => CAP_ALLOW,
'user' => CAP_ALLOW,
)
),
'mod/resource:addinstance' => array(
'riskbitmask' => RISK_XSS,
'captype' => 'write',
'contextlevel' => CONTEXT_COURSE,
'archetypes' => array(
'editingteacher' => CAP_ALLOW,
'manager' => CAP_ALLOW
),
'clonepermissionsfrom' => 'moodle/course:manageactivities'
),
/* TODO: review public portfolio API first!
'mod/resource:portfolioexport' => array(
'captype' => 'read',
'contextlevel' => CONTEXT_MODULE,
'archetypes' => array(
'teacher' => CAP_ALLOW,
'editingteacher' => CAP_ALLOW,
)
),
*/
);
+58
View File
@@ -0,0 +1,58 @@
<?xml version="1.0" encoding="UTF-8" ?>
<XMLDB PATH="mod/resource/db" VERSION="20120122" COMMENT="XMLDB file for Resource module"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="../../../lib/xmldb/xmldb.xsd"
>
<TABLES>
<TABLE NAME="resource" COMMENT="Each record is one resource and its config data">
<FIELDS>
<FIELD NAME="id" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="true"/>
<FIELD NAME="course" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/>
<FIELD NAME="name" TYPE="char" LENGTH="255" NOTNULL="true" SEQUENCE="false"/>
<FIELD NAME="intro" TYPE="text" NOTNULL="false" SEQUENCE="false"/>
<FIELD NAME="introformat" TYPE="int" LENGTH="4" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/>
<FIELD NAME="tobemigrated" TYPE="int" LENGTH="4" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/>
<FIELD NAME="legacyfiles" TYPE="int" LENGTH="4" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/>
<FIELD NAME="legacyfileslast" TYPE="int" LENGTH="10" NOTNULL="false" SEQUENCE="false"/>
<FIELD NAME="display" TYPE="int" LENGTH="4" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/>
<FIELD NAME="displayoptions" TYPE="text" NOTNULL="false" SEQUENCE="false"/>
<FIELD NAME="filterfiles" TYPE="int" LENGTH="4" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/>
<FIELD NAME="revision" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false" COMMENT="incremented when after each file changes, solves browser caching issues"/>
<FIELD NAME="timemodified" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/>
</FIELDS>
<KEYS>
<KEY NAME="primary" TYPE="primary" FIELDS="id"/>
</KEYS>
<INDEXES>
<INDEX NAME="course" UNIQUE="false" FIELDS="course"/>
</INDEXES>
</TABLE>
<TABLE NAME="resource_old" COMMENT="backup of all old resource instances from 1.9">
<FIELDS>
<FIELD NAME="id" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="true"/>
<FIELD NAME="course" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/>
<FIELD NAME="name" TYPE="char" LENGTH="255" NOTNULL="true" SEQUENCE="false"/>
<FIELD NAME="type" TYPE="char" LENGTH="30" NOTNULL="true" SEQUENCE="false"/>
<FIELD NAME="reference" TYPE="char" LENGTH="255" NOTNULL="true" SEQUENCE="false"/>
<FIELD NAME="intro" TYPE="text" NOTNULL="false" SEQUENCE="false"/>
<FIELD NAME="introformat" TYPE="int" LENGTH="4" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/>
<FIELD NAME="alltext" TYPE="text" NOTNULL="true" SEQUENCE="false"/>
<FIELD NAME="popup" TYPE="text" NOTNULL="true" SEQUENCE="false"/>
<FIELD NAME="options" TYPE="char" LENGTH="255" NOTNULL="true" SEQUENCE="false"/>
<FIELD NAME="timemodified" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/>
<FIELD NAME="oldid" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="false"/>
<FIELD NAME="cmid" TYPE="int" LENGTH="10" NOTNULL="false" SEQUENCE="false"/>
<FIELD NAME="newmodule" TYPE="char" LENGTH="50" NOTNULL="false" SEQUENCE="false"/>
<FIELD NAME="newid" TYPE="int" LENGTH="10" NOTNULL="false" SEQUENCE="false"/>
<FIELD NAME="migrated" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/>
</FIELDS>
<KEYS>
<KEY NAME="primary" TYPE="primary" FIELDS="id"/>
</KEYS>
<INDEXES>
<INDEX NAME="oldid" UNIQUE="true" FIELDS="oldid"/>
<INDEX NAME="cmid" UNIQUE="false" FIELDS="cmid"/>
</INDEXES>
</TABLE>
</TABLES>
</XMLDB>
+34
View File
@@ -0,0 +1,34 @@
<?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/>.
/**
* Definition of log events
*
* @package mod_resource
* @category log
* @copyright 2010 Petr Skoda (http://skodak.org)
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
$logs = array(
array('module'=>'resource', 'action'=>'view', 'mtable'=>'resource', 'field'=>'name'),
array('module'=>'resource', 'action'=>'view all', 'mtable'=>'resource', 'field'=>'name'),
array('module'=>'resource', 'action'=>'update', 'mtable'=>'resource', 'field'=>'name'),
array('module'=>'resource', 'action'=>'add', 'mtable'=>'resource', 'field'=>'name'),
);
+48
View File
@@ -0,0 +1,48 @@
<?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/>.
/**
* Resource external functions and service definitions.
*
* @package mod_resource
* @category external
* @copyright 2015 Juan Leyva <juan@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @since Moodle 3.0
*/
defined('MOODLE_INTERNAL') || die;
$functions = array(
'mod_resource_view_resource' => array(
'classname' => 'mod_resource_external',
'methodname' => 'view_resource',
'description' => 'Simulate the view.php web interface resource: trigger events, completion, etc...',
'type' => 'write',
'capabilities' => 'mod/resource:view',
'services' => array(MOODLE_OFFICIAL_MOBILE_SERVICE)
),
'mod_resource_get_resources_by_courses' => array(
'classname' => 'mod_resource_external',
'methodname' => 'get_resources_by_courses',
'description' => 'Returns a list of files in a provided list of courses, if no list is provided all files that
the user can view will be returned.',
'type' => 'read',
'capabilities' => 'mod/resource:view',
'services' => array(MOODLE_OFFICIAL_MOBILE_SERVICE),
),
);
+59
View File
@@ -0,0 +1,59 @@
<?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/>.
/**
* Resource module upgrade code
*
* This file keeps track of upgrades to
* the resource module
*
* Sometimes, changes between versions involve
* alterations to database structures and other
* major things that may break installations.
*
* The upgrade function in this file will attempt
* to perform all the necessary actions to upgrade
* your older installation to the current version.
*
* If there's something it cannot do itself, it
* will tell you what you need to do.
*
* The commands in here will all be database-neutral,
* using the methods of database_manager class
*
* Please do not forget to use upgrade_set_timeout()
* before any action that may take longer time to finish.
*
* @package mod_resource
* @copyright 2009 Petr Skoda {@link http://skodak.org}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
function xmldb_resource_upgrade($oldversion) {
// Automatically generated Moodle v4.1.0 release upgrade line.
// Put any upgrade step following this.
// Automatically generated Moodle v4.2.0 release upgrade line.
// Put any upgrade step following this.
// Automatically generated Moodle v4.3.0 release upgrade line.
// Put any upgrade step following this.
// Automatically generated Moodle v4.4.0 release upgrade line.
// Put any upgrade step following this.
return true;
}
+59
View File
@@ -0,0 +1,59 @@
<?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/>.
/**
* List of deprecated mod_resource functions.
*
* @package mod_resource
* @copyright 2021 Peter D
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
/**
* Print resource heading.
*
* @deprecated since Moodle 4.0
* @param object $resource
* @param object $cm
* @param object $course
* @param bool $notused This variable is no longer used
* @return void
*/
function resource_print_heading($resource, $cm, $course, $notused = false) {
global $OUTPUT;
debugging('resource_print_heading is deprecated. Handled by activity_header now.', DEBUG_DEVELOPER);
echo $OUTPUT->heading(format_string($resource->name), 2);
}
/**
* Print resource introduction.
*
* @deprecated since Moodle 4.0
* @param object $resource
* @param object $cm
* @param object $course
* @param bool $ignoresettings print even if not specified in modedit
* @return void
*/
function resource_print_intro($resource, $cm, $course, $ignoresettings=false) {
global $OUTPUT;
debugging('resource_print_intro is deprecated. Handled by activity_header now.', DEBUG_DEVELOPER);
if ($intro = resource_get_intro($resource, $cm, $ignoresettings)) {
echo $OUTPUT->box_start('mod_introbox', 'resourceintro');
echo $intro;
echo $OUTPUT->box_end();
}
}
+111
View File
@@ -0,0 +1,111 @@
<?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/>.
/**
* List of all resources in course
*
* @package mod_resource
* @copyright 1999 onwards Martin Dougiamas (http://dougiamas.com)
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
require('../../config.php');
$id = required_param('id', PARAM_INT); // course id
$course = $DB->get_record('course', array('id'=>$id), '*', MUST_EXIST);
require_course_login($course, true);
$PAGE->set_pagelayout('incourse');
$params = array(
'context' => context_course::instance($course->id)
);
$event = \mod_resource\event\course_module_instance_list_viewed::create($params);
$event->add_record_snapshot('course', $course);
$event->trigger();
$strresource = get_string('modulename', 'resource');
$strresources = get_string('modulenameplural', 'resource');
$strsectionname = get_string('sectionname', 'format_'.$course->format);
$strname = get_string('name');
$strintro = get_string('moduleintro');
$strlastmodified = get_string('lastmodified');
$PAGE->set_url('/mod/resource/index.php', array('id' => $course->id));
$PAGE->set_title($course->shortname.': '.$strresources);
$PAGE->set_heading($course->fullname);
$PAGE->navbar->add($strresources);
echo $OUTPUT->header();
if (!$PAGE->has_secondary_navigation()) {
echo $OUTPUT->heading($strresources);
}
if (!$resources = get_all_instances_in_course('resource', $course)) {
notice(get_string('thereareno', 'moodle', $strresources), "$CFG->wwwroot/course/view.php?id=$course->id");
exit;
}
$usesections = course_format_uses_sections($course->format);
$table = new html_table();
$table->attributes['class'] = 'generaltable mod_index';
if ($usesections) {
$table->head = array ($strsectionname, $strname, $strintro);
$table->align = array ('center', 'left', 'left');
} else {
$table->head = array ($strlastmodified, $strname, $strintro);
$table->align = array ('left', 'left', 'left');
}
$modinfo = get_fast_modinfo($course);
$currentsection = '';
foreach ($resources as $resource) {
$cm = $modinfo->cms[$resource->coursemodule];
if ($usesections) {
$printsection = '';
if ($resource->section !== $currentsection) {
if ($resource->section) {
$printsection = get_section_name($course, $resource->section);
}
if ($currentsection !== '') {
$table->data[] = 'hr';
}
$currentsection = $resource->section;
}
} else {
$printsection = '<span class="smallinfo">'.userdate($resource->timemodified)."</span>";
}
$extra = empty($cm->extra) ? '' : $cm->extra;
$icon = '';
if (!empty($cm->icon)) {
// each resource file has an icon in 2.0
$icon = $OUTPUT->pix_icon($cm->icon, get_string('modulename', $cm->modname));
}
$class = $resource->visible ? '' : 'class="dimmed"'; // hidden modules are dimmed
$table->data[] = array (
$printsection,
"<a $class $extra href=\"view.php?id=$cm->id\">".$icon.format_string($resource->name)."</a>",
format_module_intro('resource', $resource, $cm->id));
}
echo html_writer::table($table);
echo $OUTPUT->footer();
+130
View File
@@ -0,0 +1,130 @@
<?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/>.
/**
* Strings for component 'resource', language 'en', branch 'MOODLE_20_STABLE'
*
* @package mod_resource
* @copyright 1999 onwards Martin Dougiamas {@link http://moodle.com}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
$string['clicktodownload'] = 'Click {$a} link to download the file.';
$string['clicktoopen2'] = 'Click {$a} link to view the file.';
$string['configdisplayoptions'] = 'Select all options that should be available, existing settings are not modified. Hold CTRL key to select multiple fields.';
$string['configframesize'] = 'When a web page or an uploaded file is displayed within a frame, this value is the height (in pixels) of the top frame (which contains the navigation).';
$string['configparametersettings'] = 'This sets the default value for the Parameter settings pane in the form when adding some new resources. After the first time, this becomes an individual user preference.';
$string['configpopup'] = 'When adding a new resource which is able to be shown in a popup window, should this option be enabled by default?';
$string['configpopupdirectories'] = 'Should popup windows show directory links by default?';
$string['configpopupheight'] = 'What height should be the default height for new popup windows?';
$string['configpopuplocation'] = 'Should popup windows show the location bar by default?';
$string['configpopupmenubar'] = 'Should popup windows show the menu bar by default?';
$string['configpopupresizable'] = 'Should popup windows be resizable by default?';
$string['configpopupscrollbars'] = 'Should popup windows be scrollable by default?';
$string['configpopupstatus'] = 'Should popup windows show the status bar by default?';
$string['configpopuptoolbar'] = 'Should popup windows show the tool bar by default?';
$string['configpopupwidth'] = 'What width should be the default width for new popup windows?';
$string['contentheader'] = 'Content';
$string['displayoptions'] = 'Available display options';
$string['displayselect'] = 'Display';
$string['displayselect_help'] = 'This setting, together with the file type and whether the browser allows embedding, determines how the file is displayed. Options may include:
* Automatic - The best display option for the file type is selected automatically
* Embed - The file is displayed within the page below the navigation bar together with the file description and any blocks
* Force download - The user is prompted to download the file
* Open - Only the file is displayed in the browser window
* In pop-up - The file is displayed in a new browser window without menus or an address bar
* In frame - The file is displayed within a frame below the navigation bar and file description
* New window - The file is displayed in a new browser window with menus and an address bar';
$string['displayselect_link'] = 'mod/file/mod';
$string['displayselectexplain'] = 'Choose display type, unfortunately not all types are suitable for all files.';
$string['dnduploadresource'] = 'Create file resource';
$string['encryptedcode'] = 'Encrypted code';
$string['filenotfound'] = 'File not found, sorry.';
$string['filterfiles'] = 'Use filters on file content';
$string['filterfilesexplain'] = 'Select type of file content filtering, please note this may cause problems for some Flash and Java applets. Please make sure that all text files are in UTF-8 encoding.';
$string['filtername'] = 'Resource names auto-linking';
$string['forcedownload'] = 'Force download';
$string['framesize'] = 'Frame height';
$string['indicator:cognitivedepth'] = 'File cognitive';
$string['indicator:cognitivedepth_help'] = 'This indicator is based on the cognitive depth reached by the student in a File resource.';
$string['indicator:cognitivedepthdef'] = 'File cognitive';
$string['indicator:cognitivedepthdef_help'] = 'The participant has reached this percentage of the cognitive engagement offered by the File resources during this analysis interval (Levels = No view, View)';
$string['indicator:cognitivedepthdef_link'] = 'Learning_analytics_indicators#Cognitive_depth';
$string['indicator:socialbreadth'] = 'File social';
$string['indicator:socialbreadth_help'] = 'This indicator is based on the social breadth reached by the student in a File resource.';
$string['indicator:socialbreadthdef'] = 'File social';
$string['indicator:socialbreadthdef_help'] = 'The participant has reached this percentage of the social engagement offered by the File resources during this analysis interval (Levels = No participation, Participant alone)';
$string['indicator:socialbreadthdef_link'] = 'Learning_analytics_indicators#Social_breadth';
$string['legacyfiles'] = 'Migration of old course file';
$string['legacyfilesactive'] = 'Active';
$string['legacyfilesdone'] = 'Finished';
$string['modifieddate'] = 'Modified {$a}';
$string['modulename'] = 'File';
$string['modulename_help'] = 'The file module enables a teacher to provide a file as a course resource. Where possible, the file will be displayed within the course interface; otherwise students will be prompted to download it. The file may include supporting files, for example an HTML page may have embedded images.
Note that students need to have the appropriate software on their computers in order to open the file.
A file may be used
* To share presentations given in class
* To include a mini website as a course resource
* To provide draft files of software programs so students can edit and submit them for assessment';
$string['modulename_link'] = 'mod/resource/view';
$string['modulenameplural'] = 'Files';
$string['notmigrated'] = 'This legacy resource type ({$a}) was not yet migrated, sorry.';
$string['optionsheader'] = 'Display options';
$string['page-mod-resource-x'] = 'Any file module page';
$string['pluginadministration'] = 'File module administration';
$string['pluginname'] = 'File';
$string['popupheight'] = 'Pop-up height (in pixels)';
$string['popupheightexplain'] = 'Specifies default height of popup windows.';
$string['popupresource'] = 'This resource should appear in a popup window.';
$string['popupresourcelink'] = 'If it didn\'t, click here: {$a}';
$string['popupwidth'] = 'Pop-up width (in pixels)';
$string['popupwidthexplain'] = 'Specifies default width of popup windows.';
$string['printintro'] = 'Display resource description';
$string['printintroexplain'] = 'Display resource description below content? Some display types may not display description even if enabled.';
$string['privacy:metadata'] = 'The File resource plugin does not store any personal data.';
$string['resource:addinstance'] = 'Add a new resource';
$string['resourcecontent'] = 'Files and subfolders';
$string['resourcedetails_sizetype'] = '{$a->size} · {$a->type}';
$string['resourcedetails_sizedate'] = '{$a->size} · {$a->date}';
$string['resourcedetails_typedate'] = '{$a->type} · {$a->date}';
$string['resourcedetails_sizetypedate'] = '{$a->size} · {$a->type} · {$a->date}';
$string['resource:exportresource'] = 'Export resource';
$string['resource:view'] = 'View resource';
$string['search:activity'] = 'File';
$string['selectmainfile'] = 'Please select the main file by clicking the icon next to file name.';
$string['showdate'] = 'Show upload/modified date';
$string['showdate_desc'] = 'Display upload/modified date on course page?';
$string['showdate_help'] = 'Displays the upload/modified date beside links to the file.
If there are multiple files in this resource, the start file upload/modified date is displayed.';
$string['showsize'] = 'Show size';
$string['showsize_help'] = 'Displays the file size, such as \'3.1 MB\', beside links to the file.
If there are multiple files in this resource, the total size of all files is displayed.';
$string['showsize_desc'] = 'Display file size on course page?';
$string['showtype'] = 'Show type';
$string['showtype_desc'] = 'Display file type (e.g. \'Word document\') on course page?';
$string['showtype_help'] = 'Displays the type of the file, such as \'Word document\', beside links to the file.
If there are multiple files in this resource, the start file type is displayed.
If the file type is not known to the system, it will not display.';
$string['uploadeddate'] = 'Uploaded {$a}';
+614
View File
@@ -0,0 +1,614 @@
<?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/>.
/**
* @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;
/**
* List of features supported in Resource module
* @param string $feature FEATURE_xx constant for requested feature
* @return mixed True if module supports feature, false if not, null if doesn't know or string for the module purpose.
*/
function resource_supports($feature) {
switch($feature) {
case FEATURE_MOD_ARCHETYPE: return MOD_ARCHETYPE_RESOURCE;
case FEATURE_GROUPS: return false;
case FEATURE_GROUPINGS: return false;
case FEATURE_MOD_INTRO: return true;
case FEATURE_COMPLETION_TRACKS_VIEWS: return true;
case FEATURE_GRADE_HAS_GRADE: return false;
case FEATURE_GRADE_OUTCOMES: return false;
case FEATURE_BACKUP_MOODLE2: return true;
case FEATURE_SHOW_DESCRIPTION: return true;
case FEATURE_MOD_PURPOSE: return MOD_PURPOSE_CONTENT;
default: return null;
}
}
/**
* This function is used by the reset_course_userdata function in moodlelib.
* @param $data the data submitted from the reset course.
* @return array status array
*/
function resource_reset_userdata($data) {
// Any changes to the list of dates that needs to be rolled should be same during course restore and course reset.
// See MDL-9367.
return array();
}
/**
* List the actions that correspond to a view of this module.
* This is used by the participation report.
*
* Note: This is not used by new logging system. Event with
* crud = 'r' and edulevel = LEVEL_PARTICIPATING will
* be considered as view action.
*
* @return array
*/
function resource_get_view_actions() {
return array('view','view all');
}
/**
* List the actions that correspond to a post of this module.
* This is used by the participation report.
*
* Note: This is not used by new logging system. Event with
* crud = ('c' || 'u' || 'd') and edulevel = LEVEL_PARTICIPATING
* will be considered as post action.
*
* @return array
*/
function resource_get_post_actions() {
return array('update', 'add');
}
/**
* Add resource instance.
* @param object $data
* @param object $mform
* @return int new resource instance id
*/
function resource_add_instance($data, $mform) {
global $CFG, $DB;
require_once("$CFG->libdir/resourcelib.php");
require_once("$CFG->dirroot/mod/resource/locallib.php");
$cmid = $data->coursemodule;
$data->timemodified = time();
resource_set_display_options($data);
$data->id = $DB->insert_record('resource', $data);
// we need to use context now, so we need to make sure all needed info is already in db
$DB->set_field('course_modules', 'instance', $data->id, array('id'=>$cmid));
resource_set_mainfile($data);
$completiontimeexpected = !empty($data->completionexpected) ? $data->completionexpected : null;
\core_completion\api::update_completion_date_event($cmid, 'resource', $data->id, $completiontimeexpected);
return $data->id;
}
/**
* Update resource instance.
* @param object $data
* @param object $mform
* @return bool true
*/
function resource_update_instance($data, $mform) {
global $CFG, $DB;
require_once("$CFG->libdir/resourcelib.php");
$data->timemodified = time();
$data->id = $data->instance;
$data->revision++;
resource_set_display_options($data);
$DB->update_record('resource', $data);
resource_set_mainfile($data);
$completiontimeexpected = !empty($data->completionexpected) ? $data->completionexpected : null;
\core_completion\api::update_completion_date_event($data->coursemodule, 'resource', $data->id, $completiontimeexpected);
return true;
}
/**
* Updates display options based on form input.
*
* Shared code used by resource_add_instance and resource_update_instance.
*
* @param object $data Data object
*/
function resource_set_display_options($data) {
$displayoptions = array();
if ($data->display == RESOURCELIB_DISPLAY_POPUP) {
$displayoptions['popupwidth'] = $data->popupwidth;
$displayoptions['popupheight'] = $data->popupheight;
}
if (in_array($data->display, array(RESOURCELIB_DISPLAY_AUTO, RESOURCELIB_DISPLAY_EMBED, RESOURCELIB_DISPLAY_FRAME))) {
$displayoptions['printintro'] = (int)!empty($data->printintro);
}
if (!empty($data->showsize)) {
$displayoptions['showsize'] = 1;
}
if (!empty($data->showtype)) {
$displayoptions['showtype'] = 1;
}
if (!empty($data->showdate)) {
$displayoptions['showdate'] = 1;
}
$data->displayoptions = serialize($displayoptions);
}
/**
* Delete resource instance.
* @param int $id
* @return bool true
*/
function resource_delete_instance($id) {
global $DB;
if (!$resource = $DB->get_record('resource', array('id'=>$id))) {
return false;
}
$cm = get_coursemodule_from_instance('resource', $id);
\core_completion\api::update_completion_date_event($cm->id, 'resource', $id, null);
// note: all context files are deleted automatically
$DB->delete_records('resource', array('id'=>$resource->id));
return true;
}
/**
* Given a course_module object, this function returns any
* "extra" information that may be needed when printing
* this activity in a course listing.
*
* See {@link course_modinfo::get_array_of_activities()}
*
* @param stdClass $coursemodule
* @return cached_cm_info info
*/
function resource_get_coursemodule_info($coursemodule) {
global $CFG, $DB;
require_once("$CFG->libdir/filelib.php");
require_once("$CFG->dirroot/mod/resource/locallib.php");
require_once($CFG->libdir.'/completionlib.php');
$context = context_module::instance($coursemodule->id);
if (!$resource = $DB->get_record('resource', array('id'=>$coursemodule->instance),
'id, name, display, displayoptions, tobemigrated, revision, intro, introformat')) {
return NULL;
}
$info = new cached_cm_info();
$info->name = $resource->name;
if ($coursemodule->showdescription) {
// Convert intro to html. Do not filter cached version, filters run at display time.
$info->content = format_module_intro('resource', $resource, $coursemodule->id, false);
}
if ($resource->tobemigrated) {
return $info;
}
// See if there is at least one file.
$fs = get_file_storage();
$files = $fs->get_area_files($context->id, 'mod_resource', 'content', 0, 'sortorder DESC, id ASC', false, 0, 0, 1);
if (count($files) >= 1) {
$mainfile = reset($files);
$resource->mainfile = $mainfile->get_filename();
$info->icon = file_file_icon($mainfile);
$info->customdata['filtericon'] = true;
}
$display = resource_get_final_display_type($resource);
if ($display == RESOURCELIB_DISPLAY_POPUP) {
$fullurl = "$CFG->wwwroot/mod/resource/view.php?id=$coursemodule->id&amp;redirect=1";
$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";
$info->onclick = "window.open('$fullurl', '', '$wh'); return false;";
} else if ($display == RESOURCELIB_DISPLAY_NEW) {
$fullurl = "$CFG->wwwroot/mod/resource/view.php?id=$coursemodule->id&amp;redirect=1";
$info->onclick = "window.open('$fullurl'); return false;";
}
// If any optional extra details are turned on, store in custom data,
// add some file details as well to be used later by resource_get_optional_details() without retriving.
// Do not store filedetails if this is a reference - they will still need to be retrieved every time.
if (($filedetails = resource_get_file_details($resource, $coursemodule)) && empty($filedetails['isref'])) {
$displayoptions = (array) unserialize_array($resource->displayoptions);
$displayoptions['filedetails'] = $filedetails;
$info->customdata['displayoptions'] = serialize($displayoptions);
} else {
$info->customdata['displayoptions'] = $resource->displayoptions;
}
$info->customdata['display'] = $display;
return $info;
}
/**
* Called when viewing course page. Shows extra details after the link if
* enabled.
*
* @param cm_info $cm Course module information
*/
function resource_cm_info_view(cm_info $cm) {
global $CFG;
require_once($CFG->dirroot . '/mod/resource/locallib.php');
$customdata = $cm->customdata;
if (is_array($customdata) && isset($customdata['displayoptions'])) {
$resource = (object) ['displayoptions' => $customdata['displayoptions']];
$details = resource_get_optional_details($resource, $cm, false);
if ($details) {
$cm->set_after_link(' ' . html_writer::tag('span', $details, ['class' => 'resourcelinkdetails']));
}
}
}
/**
* Lists all browsable file areas
*
* @package mod_resource
* @category files
* @param stdClass $course course object
* @param stdClass $cm course module object
* @param stdClass $context context object
* @return array
*/
function resource_get_file_areas($course, $cm, $context) {
$areas = array();
$areas['content'] = get_string('resourcecontent', 'resource');
return $areas;
}
/**
* File browsing support for resource module content area.
*
* @package mod_resource
* @category files
* @param file_browser $browser file browser instance
* @param stdClass $areas file areas
* @param stdClass $course course object
* @param stdClass $cm course module object
* @param stdClass $context context object
* @param string $filearea file area
* @param int $itemid item ID
* @param string $filepath file path
* @param string $filename file name
* @return file_info instance or null if not found
*/
function resource_get_file_info($browser, $areas, $course, $cm, $context, $filearea, $itemid, $filepath, $filename) {
global $CFG;
if (!has_capability('moodle/course:managefiles', $context)) {
// students can not peak here!
return null;
}
$fs = get_file_storage();
if ($filearea === 'content') {
$filepath = is_null($filepath) ? '/' : $filepath;
$filename = is_null($filename) ? '.' : $filename;
$urlbase = $CFG->wwwroot.'/pluginfile.php';
if (!$storedfile = $fs->get_file($context->id, 'mod_resource', 'content', 0, $filepath, $filename)) {
if ($filepath === '/' and $filename === '.') {
$storedfile = new virtual_root_file($context->id, 'mod_resource', 'content', 0);
} else {
// not found
return null;
}
}
require_once("$CFG->dirroot/mod/resource/locallib.php");
return new resource_content_file_info($browser, $context, $storedfile, $urlbase, $areas[$filearea], true, true, true, false);
}
// note: resource_intro handled in file_browser automatically
return null;
}
/**
* Serves the resource files.
*
* @package mod_resource
* @category files
* @param stdClass $course course object
* @param stdClass $cm course module object
* @param stdClass $context context object
* @param string $filearea file area
* @param array $args extra arguments
* @param bool $forcedownload whether or not force download
* @param array $options additional options affecting the file serving
* @return bool false if file not found, does not return if found - just send the file
*/
function resource_pluginfile($course, $cm, $context, $filearea, $args, $forcedownload, array $options=array()) {
global $CFG, $DB;
require_once("$CFG->libdir/resourcelib.php");
if ($context->contextlevel != CONTEXT_MODULE) {
return false;
}
require_course_login($course, true, $cm);
if (!has_capability('mod/resource:view', $context)) {
return false;
}
if ($filearea !== 'content') {
// intro is handled automatically in pluginfile.php
return false;
}
array_shift($args); // ignore revision - designed to prevent caching problems only
$fs = get_file_storage();
$relativepath = implode('/', $args);
$fullpath = rtrim("/$context->id/mod_resource/$filearea/0/$relativepath", '/');
do {
if (!$file = $fs->get_file_by_hash(sha1($fullpath))) {
if ($fs->get_file_by_hash(sha1("$fullpath/."))) {
if ($file = $fs->get_file_by_hash(sha1("$fullpath/index.htm"))) {
break;
}
if ($file = $fs->get_file_by_hash(sha1("$fullpath/index.html"))) {
break;
}
if ($file = $fs->get_file_by_hash(sha1("$fullpath/Default.htm"))) {
break;
}
}
$resource = $DB->get_record('resource', array('id'=>$cm->instance), 'id, legacyfiles', MUST_EXIST);
if ($resource->legacyfiles != RESOURCELIB_LEGACYFILES_ACTIVE) {
return false;
}
if (!$file = resourcelib_try_file_migration('/'.$relativepath, $cm->id, $cm->course, 'mod_resource', 'content', 0)) {
return false;
}
// file migrate - update flag
$resource->legacyfileslast = time();
$DB->update_record('resource', $resource);
}
} while (false);
// should we apply filters?
$mimetype = $file->get_mimetype();
if ($mimetype === 'text/html' or $mimetype === 'text/plain' or $mimetype === 'application/xhtml+xml') {
$filter = $DB->get_field('resource', 'filterfiles', array('id'=>$cm->instance));
$CFG->embeddedsoforcelinktarget = true;
} else {
$filter = 0;
}
// finally send the file
send_stored_file($file, null, $filter, $forcedownload, $options);
}
/**
* Return a list of page types
* @param string $pagetype current page type
* @param stdClass $parentcontext Block's parent context
* @param stdClass $currentcontext Current context of block
*/
function resource_page_type_list($pagetype, $parentcontext, $currentcontext) {
$module_pagetype = array('mod-resource-*'=>get_string('page-mod-resource-x', 'resource'));
return $module_pagetype;
}
/**
* Export file resource contents
*
* @return array of file content
*/
function resource_export_contents($cm, $baseurl) {
global $CFG, $DB;
$contents = array();
$context = context_module::instance($cm->id);
$resource = $DB->get_record('resource', array('id'=>$cm->instance), '*', MUST_EXIST);
$fs = get_file_storage();
$files = $fs->get_area_files($context->id, 'mod_resource', 'content', 0, 'sortorder DESC, id ASC', false);
foreach ($files as $fileinfo) {
$file = array();
$file['type'] = 'file';
$file['filename'] = $fileinfo->get_filename();
$file['filepath'] = $fileinfo->get_filepath();
$file['filesize'] = $fileinfo->get_filesize();
$file['fileurl'] = file_encode_url("$CFG->wwwroot/" . $baseurl, '/'.$context->id.'/mod_resource/content/'.$resource->revision.$fileinfo->get_filepath().$fileinfo->get_filename(), true);
$file['timecreated'] = $fileinfo->get_timecreated();
$file['timemodified'] = $fileinfo->get_timemodified();
$file['sortorder'] = $fileinfo->get_sortorder();
$file['userid'] = $fileinfo->get_userid();
$file['author'] = $fileinfo->get_author();
$file['license'] = $fileinfo->get_license();
$file['mimetype'] = $fileinfo->get_mimetype();
$file['isexternalfile'] = $fileinfo->is_external_file();
if ($file['isexternalfile']) {
$file['repositorytype'] = $fileinfo->get_repository_type();
}
$contents[] = $file;
}
return $contents;
}
/**
* Register the ability to handle drag and drop file uploads
* @return array containing details of the files / types the mod can handle
*/
function resource_dndupload_register() {
return array('files' => array(
array('extension' => '*', 'message' => get_string('dnduploadresource', 'mod_resource'))
));
}
/**
* Handle a file that has been uploaded
* @param object $uploadinfo details of the file / content that has been uploaded
* @return int instance id of the newly created mod
*/
function resource_dndupload_handle($uploadinfo) {
// Gather the required info.
$data = new stdClass();
$data->course = $uploadinfo->course->id;
$data->name = $uploadinfo->displayname;
$data->intro = '';
$data->introformat = FORMAT_HTML;
$data->coursemodule = $uploadinfo->coursemodule;
$data->files = $uploadinfo->draftitemid;
// Set the display options to the site defaults.
$config = get_config('resource');
$data->display = $config->display;
$data->popupheight = $config->popupheight;
$data->popupwidth = $config->popupwidth;
$data->printintro = $config->printintro;
$data->showsize = (isset($config->showsize)) ? $config->showsize : 0;
$data->showtype = (isset($config->showtype)) ? $config->showtype : 0;
$data->showdate = (isset($config->showdate)) ? $config->showdate : 0;
$data->filterfiles = $config->filterfiles;
return resource_add_instance($data, null);
}
/**
* Mark the activity completed (if required) and trigger the course_module_viewed event.
*
* @param stdClass $resource resource object
* @param stdClass $course course object
* @param stdClass $cm course module object
* @param stdClass $context context object
* @since Moodle 3.0
*/
function resource_view($resource, $course, $cm, $context) {
// Trigger course_module_viewed event.
$params = array(
'context' => $context,
'objectid' => $resource->id
);
$event = \mod_resource\event\course_module_viewed::create($params);
$event->add_record_snapshot('course_modules', $cm);
$event->add_record_snapshot('course', $course);
$event->add_record_snapshot('resource', $resource);
$event->trigger();
// Completion.
$completion = new completion_info($course);
$completion->set_module_viewed($cm);
}
/**
* Check if the module has any update that affects the current user since a given time.
*
* @param cm_info $cm course module data
* @param int $from the time to check updates from
* @param array $filter if we need to check only specific updates
* @return stdClass an object with the different type of areas indicating if they were updated or not
* @since Moodle 3.2
*/
function resource_check_updates_since(cm_info $cm, $from, $filter = array()) {
$updates = course_check_module_updates_since($cm, $from, array('content'), $filter);
return $updates;
}
/**
* This function receives a calendar event and returns the action associated with it, or null if there is none.
*
* This is used by block_myoverview in order to display the event appropriately. If null is returned then the event
* is not displayed on the block.
*
* @param calendar_event $event
* @param \core_calendar\action_factory $factory
* @return \core_calendar\local\event\entities\action_interface|null
*/
function mod_resource_core_calendar_provide_event_action(calendar_event $event,
\core_calendar\action_factory $factory, $userid = 0) {
global $USER;
if (empty($userid)) {
$userid = $USER->id;
}
$cm = get_fast_modinfo($event->courseid, $userid)->instances['resource'][$event->instance];
$completion = new \completion_info($cm->get_course());
$completiondata = $completion->get_data($cm, false, $userid);
if ($completiondata->completionstate != COMPLETION_INCOMPLETE) {
return null;
}
return $factory->create_instance(
get_string('view'),
new \moodle_url('/mod/resource/view.php', ['id' => $cm->id]),
1,
true
);
}
/**
* Given an array with a file path, it returns the itemid and the filepath for the defined filearea.
*
* @param string $filearea The filearea.
* @param array $args The path (the part after the filearea and before the filename).
* @return array The itemid and the filepath inside the $args path, for the defined filearea.
*/
function mod_resource_get_path_from_pluginfile(string $filearea, array $args): array {
// Resource never has an itemid (the number represents the revision but it's not stored in database).
array_shift($args);
// Get the filepath.
if (empty($args)) {
$filepath = '/';
} else {
$filepath = '/' . implode('/', $args) . '/';
}
return [
'itemid' => 0,
'filepath' => $filepath,
];
}
+557
View File
@@ -0,0 +1,557 @@
<?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&amp;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) {
$resourceintro = !empty($options['printintro']) && !html_is_blank($resource->intro);
if ($resourceintro) {
$content .= format_module_intro('resource', $resource, $cm->id);
}
if ($extraintro) {
$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);
}
}
+231
View File
@@ -0,0 +1,231 @@
<?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/>.
/**
* Resource configuration form
*
* @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->dirroot.'/course/moodleform_mod.php');
require_once($CFG->dirroot.'/mod/resource/locallib.php');
require_once($CFG->libdir.'/filelib.php');
class mod_resource_mod_form extends moodleform_mod {
function definition() {
global $CFG, $DB;
$mform =& $this->_form;
$config = get_config('resource');
if ($this->current->instance and $this->current->tobemigrated) {
// resource not migrated yet
$resource_old = $DB->get_record('resource_old', array('oldid'=>$this->current->instance));
$mform->addElement('static', 'warning', '', get_string('notmigrated', 'resource', $resource_old->type));
$mform->addElement('cancel');
$this->standard_hidden_coursemodule_elements();
return;
}
//-------------------------------------------------------
$mform->addElement('header', 'general', get_string('general', 'form'));
$mform->addElement('text', 'name', get_string('name'), array('size'=>'48'));
if (!empty($CFG->formatstringstriptags)) {
$mform->setType('name', PARAM_TEXT);
} else {
$mform->setType('name', PARAM_CLEANHTML);
}
$mform->addRule('name', null, 'required', null, 'client');
$mform->addRule('name', get_string('maximumchars', '', 255), 'maxlength', 255, 'client');
$this->standard_intro_elements();
$element = $mform->getElement('introeditor');
$attributes = $element->getAttributes();
$attributes['rows'] = 5;
$element->setAttributes($attributes);
$filemanager_options = array();
$filemanager_options['accepted_types'] = '*';
$filemanager_options['maxbytes'] = 0;
$filemanager_options['maxfiles'] = -1;
$filemanager_options['mainfile'] = true;
$mform->addElement('filemanager', 'files', get_string('selectfiles'), null, $filemanager_options);
// add legacy files flag only if used
if (isset($this->current->legacyfiles) and $this->current->legacyfiles != RESOURCELIB_LEGACYFILES_NO) {
$options = array(RESOURCELIB_LEGACYFILES_DONE => get_string('legacyfilesdone', 'resource'),
RESOURCELIB_LEGACYFILES_ACTIVE => get_string('legacyfilesactive', 'resource'));
$mform->addElement('select', 'legacyfiles', get_string('legacyfiles', 'resource'), $options);
}
//-------------------------------------------------------
$mform->addElement('header', 'optionssection', get_string('appearance'));
if ($this->current->instance) {
$options = resourcelib_get_displayoptions(explode(',', $config->displayoptions), $this->current->display);
} else {
$options = resourcelib_get_displayoptions(explode(',', $config->displayoptions));
}
if (count($options) == 1) {
$mform->addElement('hidden', 'display');
$mform->setType('display', PARAM_INT);
reset($options);
$mform->setDefault('display', key($options));
} else {
$mform->addElement('select', 'display', get_string('displayselect', 'resource'), $options);
$mform->setDefault('display', $config->display);
$mform->addHelpButton('display', 'displayselect', 'resource');
}
$mform->addElement('checkbox', 'showsize', get_string('showsize', 'resource'));
$mform->setDefault('showsize', $config->showsize);
$mform->addHelpButton('showsize', 'showsize', 'resource');
$mform->addElement('checkbox', 'showtype', get_string('showtype', 'resource'));
$mform->setDefault('showtype', $config->showtype);
$mform->addHelpButton('showtype', 'showtype', 'resource');
$mform->addElement('checkbox', 'showdate', get_string('showdate', 'resource'));
$mform->setDefault('showdate', $config->showdate);
$mform->addHelpButton('showdate', 'showdate', 'resource');
if (array_key_exists(RESOURCELIB_DISPLAY_POPUP, $options)) {
$mform->addElement('text', 'popupwidth', get_string('popupwidth', 'resource'), array('size'=>3));
if (count($options) > 1) {
$mform->hideIf('popupwidth', 'display', 'noteq', RESOURCELIB_DISPLAY_POPUP);
}
$mform->setType('popupwidth', PARAM_INT);
$mform->setDefault('popupwidth', $config->popupwidth);
$mform->setAdvanced('popupwidth', true);
$mform->addElement('text', 'popupheight', get_string('popupheight', 'resource'), array('size'=>3));
if (count($options) > 1) {
$mform->hideIf('popupheight', 'display', 'noteq', RESOURCELIB_DISPLAY_POPUP);
}
$mform->setType('popupheight', PARAM_INT);
$mform->setDefault('popupheight', $config->popupheight);
$mform->setAdvanced('popupheight', true);
}
if (array_key_exists(RESOURCELIB_DISPLAY_AUTO, $options) or
array_key_exists(RESOURCELIB_DISPLAY_EMBED, $options) or
array_key_exists(RESOURCELIB_DISPLAY_FRAME, $options)) {
$mform->addElement('checkbox', 'printintro', get_string('printintro', 'resource'));
$mform->hideIf('printintro', 'display', 'eq', RESOURCELIB_DISPLAY_POPUP);
$mform->hideIf('printintro', 'display', 'eq', RESOURCELIB_DISPLAY_DOWNLOAD);
$mform->hideIf('printintro', 'display', 'eq', RESOURCELIB_DISPLAY_OPEN);
$mform->hideIf('printintro', 'display', 'eq', RESOURCELIB_DISPLAY_NEW);
$mform->setDefault('printintro', $config->printintro);
}
$options = array('0' => get_string('none'), '1' => get_string('allfiles'), '2' => get_string('htmlfilesonly'));
$mform->addElement('select', 'filterfiles', get_string('filterfiles', 'resource'), $options);
$mform->setDefault('filterfiles', $config->filterfiles);
$mform->setAdvanced('filterfiles', true);
//-------------------------------------------------------
$this->standard_coursemodule_elements();
//-------------------------------------------------------
$this->add_action_buttons();
//-------------------------------------------------------
$mform->addElement('hidden', 'revision');
$mform->setType('revision', PARAM_INT);
$mform->setDefault('revision', 1);
}
function data_preprocessing(&$default_values) {
if ($this->current->instance and !$this->current->tobemigrated) {
$draftitemid = file_get_submitted_draft_itemid('files');
file_prepare_draft_area($draftitemid, $this->context->id, 'mod_resource', 'content', 0, array('subdirs'=>true));
$default_values['files'] = $draftitemid;
}
if (!empty($default_values['displayoptions'])) {
$displayoptions = (array) unserialize_array($default_values['displayoptions']);
if (isset($displayoptions['printintro'])) {
$default_values['printintro'] = $displayoptions['printintro'];
}
if (!empty($displayoptions['popupwidth'])) {
$default_values['popupwidth'] = $displayoptions['popupwidth'];
}
if (!empty($displayoptions['popupheight'])) {
$default_values['popupheight'] = $displayoptions['popupheight'];
}
if (!empty($displayoptions['showsize'])) {
$default_values['showsize'] = $displayoptions['showsize'];
} else {
// Must set explicitly to 0 here otherwise it will use system
// default which may be 1.
$default_values['showsize'] = 0;
}
if (!empty($displayoptions['showtype'])) {
$default_values['showtype'] = $displayoptions['showtype'];
} else {
$default_values['showtype'] = 0;
}
if (!empty($displayoptions['showdate'])) {
$default_values['showdate'] = $displayoptions['showdate'];
} else {
$default_values['showdate'] = 0;
}
}
}
function definition_after_data() {
if ($this->current->instance and $this->current->tobemigrated) {
// resource not migrated yet
return;
}
parent::definition_after_data();
}
function validation($data, $files) {
global $USER;
$errors = parent::validation($data, $files);
$usercontext = context_user::instance($USER->id);
$fs = get_file_storage();
if (!$files = $fs->get_area_files($usercontext->id, 'user', 'draft', $data['files'], 'sortorder, id', false)) {
$errors['files'] = get_string('required');
return $errors;
}
if (count($files) == 1) {
// no need to select main file if only one picked
return $errors;
} else if(count($files) > 1) {
$mainfile = false;
foreach($files as $file) {
if ($file->get_sortorder() == 1) {
$mainfile = true;
break;
}
}
// set a default main file
if (!$mainfile) {
$file = reset($files);
file_set_sortorder($file->get_contextid(), $file->get_component(), $file->get_filearea(), $file->get_itemid(),
$file->get_filepath(), $file->get_filename(), 1);
}
}
return $errors;
}
}
+3
View File
@@ -0,0 +1,3 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="xMinYMid meet">
<path fill-rule="evenodd" clip-rule="evenodd" d="M13.2426 3.90637H7.8501C7.02167 3.90637 6.3501 4.57794 6.3501 5.40637V18.4109C6.3501 19.2393 7.02167 19.9109 7.8501 19.9109H16.856C17.6844 19.9109 18.356 19.2393 18.356 18.4109V8.88903V8.42232C18.356 8.14618 18.1321 7.92232 17.856 7.92232H15.8465C15.0181 7.92232 14.3465 7.25075 14.3465 6.42232V4.40637C14.3465 4.13122 14.1242 3.90797 13.8495 3.90638C13.8485 3.90637 13.8475 3.90637 13.8465 3.90637L13.2486 3.90641C13.2466 3.90641 13.2446 3.9064 13.2426 3.90637ZM15.3465 4.58847V6.42232C15.3465 6.69847 15.5704 6.92232 15.8465 6.92232H17.668L15.3465 4.58847ZM19.356 8.42232V8.88903V18.4109C19.356 19.7916 18.2367 20.9109 16.856 20.9109H7.8501C6.46939 20.9109 5.3501 19.7916 5.3501 18.4109V5.40637C5.3501 4.02566 6.46939 2.90637 7.8501 2.90637H13.8465C13.8482 2.90637 13.8499 2.90637 13.8516 2.90638L14.0443 2.90637C14.7096 2.90634 15.3476 3.17156 15.8168 3.64331L18.6284 6.46987C19.0944 6.93833 19.356 7.5722 19.356 8.23294V8.42232ZM12.8535 10.9194C12.8535 10.6433 12.6297 10.4194 12.3535 10.4194C12.0774 10.4194 11.8535 10.6433 11.8535 10.9194V12.9157L9.85683 12.9184C9.58068 12.9187 9.35712 13.1429 9.35749 13.419C9.35785 13.6952 9.582 13.9187 9.85815 13.9184L11.8535 13.9157V15.9108C11.8535 16.1869 12.0774 16.4108 12.3535 16.4108C12.6297 16.4108 12.8535 16.1869 12.8535 15.9108V13.9144L14.8495 13.9118C15.1256 13.9114 15.3492 13.6873 15.3488 13.4111C15.3484 13.135 15.1243 12.9114 14.8481 12.9118L12.8535 12.9144V10.9194Z" fill="#212529"/>
</svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

+29
View File
@@ -0,0 +1,29 @@
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/>.
copyright 2009 Petr Skoda (http://skodak.org)
license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
Resource module
=============
Resource module one of the successors to original 'file' type plugin of Resource module.
TODO:
* reimplement portfolio support (MDL-20079)
* new backup/restore and old restore migration (MDL-20081)
* reimplement resource name filter as part of more general activitynames filter (MDL-20083)
+74
View File
@@ -0,0 +1,74 @@
<?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/>.
/**
* Resource module admin settings and defaults
*
* @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;
if ($ADMIN->fulltree) {
require_once("$CFG->libdir/resourcelib.php");
$displayoptions = resourcelib_get_displayoptions(array(RESOURCELIB_DISPLAY_AUTO,
RESOURCELIB_DISPLAY_EMBED,
RESOURCELIB_DISPLAY_FRAME,
RESOURCELIB_DISPLAY_DOWNLOAD,
RESOURCELIB_DISPLAY_OPEN,
RESOURCELIB_DISPLAY_NEW,
RESOURCELIB_DISPLAY_POPUP,
));
$defaultdisplayoptions = array(RESOURCELIB_DISPLAY_AUTO,
RESOURCELIB_DISPLAY_EMBED,
RESOURCELIB_DISPLAY_DOWNLOAD,
RESOURCELIB_DISPLAY_OPEN,
RESOURCELIB_DISPLAY_POPUP,
);
//--- general settings -----------------------------------------------------------------------------------
$settings->add(new admin_setting_configtext('resource/framesize',
get_string('framesize', 'resource'), get_string('configframesize', 'resource'), 130, PARAM_INT));
$settings->add(new admin_setting_configmultiselect('resource/displayoptions',
get_string('displayoptions', 'resource'), get_string('configdisplayoptions', 'resource'),
$defaultdisplayoptions, $displayoptions));
//--- modedit defaults -----------------------------------------------------------------------------------
$settings->add(new admin_setting_heading('resourcemodeditdefaults', get_string('modeditdefaults', 'admin'), get_string('condifmodeditdefaults', 'admin')));
$settings->add(new admin_setting_configcheckbox('resource/printintro',
get_string('printintro', 'resource'), get_string('printintroexplain', 'resource'), 1));
$settings->add(new admin_setting_configselect('resource/display',
get_string('displayselect', 'resource'), get_string('displayselectexplain', 'resource'), RESOURCELIB_DISPLAY_AUTO,
$displayoptions));
$settings->add(new admin_setting_configcheckbox('resource/showsize',
get_string('showsize', 'resource'), get_string('showsize_desc', 'resource'), 0));
$settings->add(new admin_setting_configcheckbox('resource/showtype',
get_string('showtype', 'resource'), get_string('showtype_desc', 'resource'), 1));
$settings->add(new admin_setting_configcheckbox('resource/showdate',
get_string('showdate', 'resource'), get_string('showdate_desc', 'resource'), 0));
$settings->add(new admin_setting_configtext('resource/popupwidth',
get_string('popupwidth', 'resource'), get_string('popupwidthexplain', 'resource'), 620, PARAM_INT, 7));
$settings->add(new admin_setting_configtext('resource/popupheight',
get_string('popupheight', 'resource'), get_string('popupheightexplain', 'resource'), 450, PARAM_INT, 7));
$options = array('0' => get_string('none'), '1' => get_string('allfiles'), '2' => get_string('htmlfilesonly'));
$settings->add(new admin_setting_configselect('resource/filterfiles',
get_string('filterfiles', 'resource'), get_string('filterfilesexplain', 'resource'), 0, $options));
}
+13
View File
@@ -0,0 +1,13 @@
.path-mod-resource .resourcecontent {
text-align: center;
}
.path-mod-resource .resourcedetails {
font-size: 0.8em;
color: #555;
}
.resourcelinkdetails {
font-size: 0.8em;
color: #555;
}
@@ -0,0 +1,45 @@
<?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/>.
namespace mod_resource\backup;
defined('MOODLE_INTERNAL') || die();
global $CFG;
require_once($CFG->libdir . "/phpunit/classes/restore_date_testcase.php");
/**
* Restore date tests.
*
* @package mod_resource
* @copyright 2017 onwards Ankit Agarwal <ankit.agrr@gmail.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class restore_date_test extends \restore_date_testcase {
public function test_restore_dates(): void {
global $DB;
$time = 10000;
list($course, $resource) = $this->create_course_and_module('resource');
// Do backup and restore.
$newcourseid = $this->backup_and_restore($course);
$newresource = $DB->get_record('resource', ['course' => $newcourseid]);
$this->assertFieldsNotRolledForward($resource, $newresource, ['timemodified']);
}
}
@@ -0,0 +1,90 @@
@mod @mod_resource
Feature: Teacher can specify different display options for the resource
In order to provide more information about a file
As a teacher
I need to be able to show size, type and modified date
Background:
Given the following "users" exist:
| username | firstname | lastname | email |
| student1 | Student | 1 | student1@example.com |
| teacher1 | Teacher | 1 | teacher1@example.com |
And the following "courses" exist:
| fullname | shortname | category |
| Course 1 | C1 | 0 |
And the following "course enrolments" exist:
| user | course | role |
| teacher1 | C1 | editingteacher |
| student1 | C1 | student |
And the following "activities" exist:
| activity | course | name | intro | defaultfilename | uploaded |
| resource | C1 | Myfile | My cool file | mod/resource/tests/fixtures/samplefile.txt | 1 |
And I log in as "teacher1"
And I am on "Course 1" course homepage with editing mode on
Scenario: Specifying no additional display options for a file resource
When I am on the "Myfile" "resource activity editing" page
And I set the following fields to these values:
| Show upload/modified date | 0 |
| showsize | 0 |
| showtype | 0 |
And I press "Save and display"
Then ".resourcedetails" "css_element" should not exist
And I am on "Course 1" course homepage
And ".activity.resource .resourcelinkdetails" "css_element" should not exist
Scenario Outline: Specifying different display options for a file resource
When I am on the "Myfile" "resource activity editing" page
And I set the following fields to these values:
| display | 5 |
| Show size | <showsize> |
| Show type | <showtype> |
| Show upload/modified date | <showdate> |
And I press "Save and display"
Then I <seesize> see "6 bytes" in the ".resourcedetails" "css_element"
And I <seetype> see "TXT" in the ".resourcedetails" "css_element"
And I <seedate> see "Uploaded" in the ".resourcedetails" "css_element"
And I am on "Course 1" course homepage
And I <seesize> see "6 bytes" in the ".activity.resource .resourcelinkdetails" "css_element"
And I <seetype> see "TXT" in the ".activity.resource .activitybadge" "css_element"
And I <seedate> see "Uploaded" in the ".activity.resource .resourcelinkdetails" "css_element"
Examples:
| showsize | showtype | showdate | seesize | seetype | seedate |
| 1 | 0 | 0 | should | should not | should not |
| 0 | 0 | 1 | should not | should not | should |
| 1 | 1 | 0 | should | should | should not |
| 1 | 0 | 1 | should | should not | should |
| 0 | 1 | 1 | should not | should | should |
| 1 | 1 | 1 | should | should | should |
Scenario Outline: Specify different display options for an embedded file resource
When I am on the "Myfile" "resource activity editing" page
And I set the following fields to these values:
| display | Embed |
| Show type | <showtype> |
| Display resource description | <showdesc> |
And I press "Save and display"
Then I <seetype> see "TXT" in the "region-main" "region"
And I <seedesc> see "My cool file" in the "region-main" "region"
Examples:
| showtype | showdesc | seetype | seedesc |
| 1 | 0 | should | should not |
| 1 | 1 | should | should |
| 0 | 1 | should not | should |
| 0 | 0 | should not | should not |
Scenario: Specifying only show type for a file resource
When I am on the "Myfile" "resource activity editing" page
And I set the following fields to these values:
| display | 5 |
| Show size | 0 |
| Show type | 1 |
| Show upload/modified date | 0 |
And I press "Save and display"
Then I should see "TXT" in the ".resourcedetails" "css_element"
Then I should not see "6 bytes" in the ".resourcedetails" "css_element"
And I should see "TXT" in the ".resourcedetails" "css_element"
And I should not see "Uploaded" in the ".resourcedetails" "css_element"
And I am on "Course 1" course homepage
And I should see "TXT" in the ".activity.resource .activitybadge" "css_element"
And ".activity.resource .resourcelinkdetails" "css_element" should not exist
@@ -0,0 +1,89 @@
@mod @mod_resource @core_completion @_file_upload
Feature: View activity completion information for file resources
In order to have visibility of file resource completion requirements
As a student
I need to be able to view my file resource completion progress
Background:
Given the following "users" exist:
| username | firstname | lastname | email |
| student1 | Vinnie | Student1 | student1@example.com |
| teacher1 | Darrell | Teacher1 | teacher1@example.com |
And the following "courses" exist:
| fullname | shortname | category | enablecompletion |
| Course 1 | C1 | 0 | 1 |
And the following "course enrolments" exist:
| user | course | role |
| student1 | C1 | student |
| teacher1 | C1 | editingteacher |
And the following config values are set as admin:
| displayoptions | 0,1,2,3,4,5,6 | resource |
@javascript
Scenario Outline: The manual completion button will be shown on the course page for Open, In pop-up, New window and Force download display mode if Show activity completion conditions is set to No
Given the following "activities" exist:
| activity | course | name | display | showsize | showtype | showdate | completion | defaultfilename | popupwidth | popupheight | uploaded |
| resource | C1 | Myfile | <display> | 0 | 0 | 0 | 1 | mod/resource/tests/fixtures/samplefile.txt | 620 | 450 | 1 |
And I am on the "Course 1" course page logged in as teacher1
# Teacher view.
And "Myfile" should have the "Mark as done" completion condition
# Student view.
When I am on the "Course 1" course page logged in as student1
Then the manual completion button for "Myfile" should exist
And the manual completion button of "Myfile" is displayed as "Mark as done"
And I toggle the manual completion state of "Myfile"
And the manual completion button of "Myfile" is displayed as "Done"
Examples:
| display |
| 5 |
| 6 |
| 4 |
| 3 |
@javascript
Scenario: The manual completion button will be shown on the activity page and course page if Show activity completion conditions is set to Yes
Given the following "activities" exist:
| activity | course | name | display | defaultfilename | uploaded |
| resource | C1 | Myfile | 1 | mod/resource/tests/fixtures/samplefile.txt | 1 |
And I am on the "Course 1" "course editing" page logged in as "teacher1"
And I expand all fieldsets
And I set the field "Show activity completion conditions" to "Yes"
And I press "Save and display"
And I am on the "Myfile" "resource activity editing" page
And I set the following fields to these values:
| Students must manually mark the activity as done | 1 |
And I click on "Save and return to course" "button"
# Teacher view.
And "Myfile" should have the "Mark as done" completion condition
And I am on the "Myfile" "resource activity" page
And the manual completion button for "Myfile" should exist
And the manual completion button for "Myfile" should be disabled
# Student view.
When I am on the "Course 1" course page logged in as student1
Then the manual completion button for "Myfile" should exist
And I am on the "Myfile" "resource activity" page
And the manual completion button of "Myfile" is displayed as "Mark as done"
And I toggle the manual completion state of "Myfile"
And the manual completion button of "Myfile" is displayed as "Done"
@javascript
Scenario: View automatic completion items
Given the following "activities" exist:
| activity | course | name | display | defaultfilename | uploaded |
| resource | C1 | Myfile | 1 | mod/resource/tests/fixtures/samplefile.txt | 1 |
And I am on the "Course 1" "course editing" page logged in as "teacher1"
And I expand all fieldsets
And I set the field "Show activity completion conditions" to "Yes"
And I press "Save and display"
And I am on the "Myfile" "resource activity editing" page
And I set the following fields to these values:
| Add requirements | 1 |
| View the activity | 1 |
And I press "Save and display"
# Teacher view.
And I am on the "Myfile" "resource activity" page
And "Myfile" should have the "View" completion condition
# Student view.
When I am on the "Myfile" "resource activity" page logged in as student1
Then the "View" completion condition of "Myfile" is displayed as "done"
+101
View File
@@ -0,0 +1,101 @@
<?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/>.
/**
* Events test.
*
* @package mod_resource
* @copyright 2014 Rajesh Taneja <rajesh@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace mod_resource\event;
/**
* Resource events test cases.
*
* @package mod_resource
* @copyright 2014 Rajesh Taneja <rajesh@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class events_test extends \advanced_testcase {
/**
* Setup is called before calling test case.
*/
public function setUp(): void {
$this->resetAfterTest();
// Must be a non-guest user to create resources.
$this->setAdminUser();
}
/**
* Test course_module_instance_list_viewed event.
*/
public function test_course_module_instance_list_viewed(): void {
// There is no proper API to call to trigger this event, so what we are
// doing here is simply making sure that the events returns the right information.
$course = $this->getDataGenerator()->create_course();
$params = array(
'context' => \context_course::instance($course->id)
);
$event = \mod_resource\event\course_module_instance_list_viewed::create($params);
// Triggering and capturing the event.
$sink = $this->redirectEvents();
$event->trigger();
$events = $sink->get_events();
$this->assertCount(1, $events);
$event = reset($events);
// Checking that the event contains the expected values.
$this->assertInstanceOf('\mod_resource\event\course_module_instance_list_viewed', $event);
$this->assertEquals(\context_course::instance($course->id), $event->get_context());
$this->assertEventContextNotUsed($event);
}
/**
* Test course_module_viewed event.
*/
public function test_course_module_viewed(): void {
// There is no proper API to call to trigger this event, so what we are
// doing here is simply making sure that the events returns the right information.
$course = $this->getDataGenerator()->create_course();
$resource = $this->getDataGenerator()->create_module('resource', array('course' => $course->id));
$params = array(
'context' => \context_module::instance($resource->cmid),
'objectid' => $resource->id
);
$event = \mod_resource\event\course_module_viewed::create($params);
// Triggering and capturing the event.
$sink = $this->redirectEvents();
$event->trigger();
$events = $sink->get_events();
$this->assertCount(1, $events);
$event = reset($events);
// Checking that the event contains the expected values.
$this->assertInstanceOf('\mod_resource\event\course_module_viewed', $event);
$this->assertEquals(\context_module::instance($resource->cmid), $event->get_context());
$this->assertEquals($resource->id, $event->objectid);
$this->assertEventContextNotUsed($event);
}
}
+254
View File
@@ -0,0 +1,254 @@
<?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/>.
namespace mod_resource;
use core_external\external_api;
use externallib_advanced_testcase;
use mod_resource_external;
defined('MOODLE_INTERNAL') || die();
global $CFG;
require_once($CFG->dirroot . '/webservice/tests/helpers.php');
/**
* External mod_resource functions unit tests
*
* @package mod_resource
* @category external
* @copyright 2015 Juan Leyva <juan@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @since Moodle 3.0
*/
class externallib_test extends externallib_advanced_testcase {
/**
* Test view_resource
*/
public function test_view_resource(): void {
global $DB;
$this->resetAfterTest(true);
$this->setAdminUser();
// Setup test data.
$course = $this->getDataGenerator()->create_course();
$resource = $this->getDataGenerator()->create_module('resource', array('course' => $course->id));
$context = \context_module::instance($resource->cmid);
$cm = get_coursemodule_from_instance('resource', $resource->id);
// Test invalid instance id.
try {
mod_resource_external::view_resource(0);
$this->fail('Exception expected due to invalid mod_resource instance id.');
} catch (\moodle_exception $e) {
$this->assertEquals('invalidrecord', $e->errorcode);
}
// Test not-enrolled user.
$user = self::getDataGenerator()->create_user();
$this->setUser($user);
try {
mod_resource_external::view_resource($resource->id);
$this->fail('Exception expected due to not enrolled user.');
} catch (\moodle_exception $e) {
$this->assertEquals('requireloginerror', $e->errorcode);
}
// Test user with full capabilities.
$studentrole = $DB->get_record('role', array('shortname' => 'student'));
$this->getDataGenerator()->enrol_user($user->id, $course->id, $studentrole->id);
// Trigger and capture the event.
$sink = $this->redirectEvents();
$result = mod_resource_external::view_resource($resource->id);
$result = external_api::clean_returnvalue(mod_resource_external::view_resource_returns(), $result);
$events = $sink->get_events();
$this->assertCount(1, $events);
$event = array_shift($events);
// Checking that the event contains the expected values.
$this->assertInstanceOf('\mod_resource\event\course_module_viewed', $event);
$this->assertEquals($context, $event->get_context());
$moodleurl = new \moodle_url('/mod/resource/view.php', array('id' => $cm->id));
$this->assertEquals($moodleurl, $event->get_url());
$this->assertEventContextNotUsed($event);
$this->assertNotEmpty($event->get_name());
// Test user with no capabilities.
// We need a explicit prohibit since this capability is only defined in authenticated user and guest roles.
assign_capability('mod/resource:view', CAP_PROHIBIT, $studentrole->id, $context->id);
// Empty all the caches that may be affected by this change.
accesslib_clear_all_caches_for_unit_testing();
\course_modinfo::clear_instance_cache();
try {
mod_resource_external::view_resource($resource->id);
$this->fail('Exception expected due to missing capability.');
} catch (\moodle_exception $e) {
$this->assertEquals('requireloginerror', $e->errorcode);
}
}
/**
* Test test_mod_resource_get_resources_by_courses
*/
public function test_mod_resource_get_resources_by_courses(): void {
global $DB;
$this->resetAfterTest(true);
$course1 = self::getDataGenerator()->create_course();
$course2 = self::getDataGenerator()->create_course();
$student = self::getDataGenerator()->create_user();
$studentrole = $DB->get_record('role', array('shortname' => 'student'));
$this->getDataGenerator()->enrol_user($student->id, $course1->id, $studentrole->id);
self::setUser($student);
// First resource.
$record = new \stdClass();
$record->course = $course1->id;
$resource1 = self::getDataGenerator()->create_module('resource', $record);
// Second resource.
$record = new \stdClass();
$record->course = $course2->id;
$resource2 = self::getDataGenerator()->create_module('resource', $record);
// Execute real Moodle enrolment as we'll call unenrol() method on the instance later.
$enrol = enrol_get_plugin('manual');
$enrolinstances = enrol_get_instances($course2->id, true);
foreach ($enrolinstances as $courseenrolinstance) {
if ($courseenrolinstance->enrol == "manual") {
$instance2 = $courseenrolinstance;
break;
}
}
$enrol->enrol_user($instance2, $student->id, $studentrole->id);
$returndescription = mod_resource_external::get_resources_by_courses_returns();
// Create what we expect to be returned when querying the two courses.
$expectedfields = array('id', 'coursemodule', 'course', 'name', 'intro', 'introformat', 'introfiles', 'lang',
'contentfiles', 'tobemigrated', 'legacyfiles', 'legacyfileslast', 'display', 'displayoptions',
'filterfiles', 'revision', 'timemodified', 'section', 'visible', 'groupmode', 'groupingid');
// Add expected coursemodule and data.
$resource1->coursemodule = $resource1->cmid;
$resource1->introformat = 1;
$resource1->contentformat = 1;
$resource1->section = 0;
$resource1->visible = true;
$resource1->groupmode = 0;
$resource1->groupingid = 0;
$resource1->introfiles = [];
$resource1->contentfiles = [];
$resource1->lang = '';
$resource2->coursemodule = $resource2->cmid;
$resource2->introformat = 1;
$resource2->contentformat = 1;
$resource2->section = 0;
$resource2->visible = true;
$resource2->groupmode = 0;
$resource2->groupingid = 0;
$resource2->introfiles = [];
$resource2->contentfiles = [];
$resource2->lang = '';
foreach ($expectedfields as $field) {
$expected1[$field] = $resource1->{$field};
$expected2[$field] = $resource2->{$field};
}
$expectedresources = array($expected2, $expected1);
// Call the external function passing course ids.
$result = mod_resource_external::get_resources_by_courses(array($course2->id, $course1->id));
$result = external_api::clean_returnvalue($returndescription, $result);
// Remove the contentfiles (to be checked bellow).
$result['resources'][0]['contentfiles'] = [];
$result['resources'][1]['contentfiles'] = [];
// Now, check that we retrieve the same data we created.
$this->assertEquals($expectedresources, $result['resources']);
$this->assertCount(0, $result['warnings']);
// Call the external function without passing course id.
$result = mod_resource_external::get_resources_by_courses();
$result = external_api::clean_returnvalue($returndescription, $result);
// Remove the contentfiles (to be checked bellow).
$result['resources'][0]['contentfiles'] = [];
$result['resources'][1]['contentfiles'] = [];
// Check that without course ids we still get the correct data.
$this->assertEquals($expectedresources, $result['resources']);
$this->assertCount(0, $result['warnings']);
// Add a file to the intro.
$fileintroname = "fileintro.txt";
$filerecordinline = array(
'contextid' => \context_module::instance($resource2->cmid)->id,
'component' => 'mod_resource',
'filearea' => 'intro',
'itemid' => 0,
'filepath' => '/',
'filename' => $fileintroname,
);
$fs = get_file_storage();
$timepost = time();
$fs->create_file_from_string($filerecordinline, 'image contents (not really)');
$result = mod_resource_external::get_resources_by_courses(array($course2->id, $course1->id));
$result = external_api::clean_returnvalue($returndescription, $result);
// Check that we receive correctly the files.
$this->assertCount(1, $result['resources'][0]['introfiles']);
$this->assertEquals($fileintroname, $result['resources'][0]['introfiles'][0]['filename']);
$this->assertCount(1, $result['resources'][0]['contentfiles']);
$this->assertCount(1, $result['resources'][1]['contentfiles']);
// Test autogenerated resource.
$this->assertEquals('resource2.txt', $result['resources'][0]['contentfiles'][0]['filename']);
$this->assertEquals('resource1.txt', $result['resources'][1]['contentfiles'][0]['filename']);
// Unenrol user from second course.
$enrol->unenrol_user($instance2, $student->id);
array_shift($expectedresources);
// Call the external function without passing course id.
$result = mod_resource_external::get_resources_by_courses();
$result = external_api::clean_returnvalue($returndescription, $result);
// Remove the contentfiles (to be checked bellow).
$result['resources'][0]['contentfiles'] = [];
$this->assertEquals($expectedresources, $result['resources']);
// Call for the second course we unenrolled the user from, expected warning.
$result = mod_resource_external::get_resources_by_courses(array($course2->id));
$this->assertCount(1, $result['warnings']);
$this->assertEquals('1', $result['warnings'][0]['warningcode']);
$this->assertEquals($course2->id, $result['warnings'][0]['itemid']);
}
}
+1
View File
@@ -0,0 +1 @@
Hello!
+112
View File
@@ -0,0 +1,112 @@
<?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/>.
/**
* Data generator.
*
* @package mod_resource
* @copyright 2013 The Open University
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
/**
* Resource module data generator class.
*
* @package mod_resource
* @copyright 2013 The Open University
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class mod_resource_generator extends testing_module_generator {
/**
* Creates new resource module instance. By default it contains a short
* text file.
*
* @param array|stdClass $record data for module being generated. Requires 'course' key
* (an id or the full object). Also can have any fields from add module form, and a
* 'defaultfilename' to set the name of the file created if no draft ID is supplied.
* @param null|array $options general options for course module. Since 2.6 it is
* possible to omit this argument by merging options into $record
* @return stdClass record from module-defined table with additional field
* cmid (corresponding id in course_modules table)
*/
public function create_instance($record = null, array $options = null) {
global $CFG, $USER;
require_once($CFG->dirroot . '/lib/resourcelib.php');
// Ensure the record can be modified without affecting calling code.
$record = (object)(array)$record;
// Fill in optional values if not specified.
if (!isset($record->display)) {
$record->display = RESOURCELIB_DISPLAY_AUTO;
}
if (!isset($record->printintro)) {
$record->printintro = 0;
}
if (!isset($record->showsize)) {
$record->showsize = 0;
}
if (!isset($record->showtype)) {
$record->showtype = 0;
}
if (!isset($record->uploaded)) {
$record->uploaded = 0;
}
// The 'files' value corresponds to the draft file area ID. If not
// specified, create a default file.
if (!isset($record->files)) {
if (empty($USER->username) || $USER->username === 'guest') {
throw new coding_exception('resource generator requires a current user');
}
$usercontext = context_user::instance($USER->id);
$filename = $record->defaultfilename ?? 'resource' . ($this->instancecount + 1) . '.txt';
// Pick a random context id for specified user.
$record->files = file_get_unused_draft_itemid();
// Add actual file there.
$filerecord = ['component' => 'user', 'filearea' => 'draft',
'contextid' => $usercontext->id, 'itemid' => $record->files,
'filename' => basename($filename), 'filepath' => '/'];
$fs = get_file_storage();
if ($record->uploaded == 1) {
// For uploading a file, it's required to specify a file, how not!
if (!isset($record->defaultfilename)) {
throw new coding_exception(
'The $record->defaultfilename option is required in order to upload a file');
}
// We require the full file path to exist when uploading a real file (fixture or whatever).
$fullfilepath = $CFG->dirroot . '/' . $record->defaultfilename;
if (!is_readable($fullfilepath)) {
throw new coding_exception(
'The $record->defaultfilename option must point to an existing file within dirroot');
}
// Create file using pathname (defaultfilename) set.
$fs->create_file_from_pathname($filerecord, $fullfilepath);
} else {
// If defaultfilename is not set, create file from string "resource 1.txt".
$fs->create_file_from_string($filerecord, 'Test resource ' . $filename . ' file');
}
}
// Do work to actually add the instance.
return parent::create_instance($record, $options);
}
}
+123
View File
@@ -0,0 +1,123 @@
<?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/>.
namespace mod_resource;
/**
* PHPUnit data generator testcase.
*
* @package mod_resource
* @category phpunit
* @covers \mod_resource_generator
* @copyright 2013 The Open University
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class generator_test extends \advanced_testcase {
public function test_generator(): void {
global $DB, $SITE;
$this->resetAfterTest(true);
// Must be a non-guest user to create resources.
$this->setAdminUser();
// There are 0 resources initially.
$this->assertEquals(0, $DB->count_records('resource'));
// Create the generator object and do standard checks.
$generator = $this->getDataGenerator()->get_plugin_generator('mod_resource');
$this->assertInstanceOf('mod_resource_generator', $generator);
$this->assertEquals('resource', $generator->get_modulename());
// Create three instances in the site course.
$generator->create_instance(array('course' => $SITE->id));
$generator->create_instance(array('course' => $SITE->id));
$resource = $generator->create_instance(array('course' => $SITE->id));
$this->assertEquals(3, $DB->count_records('resource'));
// Check the course-module is correct.
$cm = get_coursemodule_from_instance('resource', $resource->id);
$this->assertEquals($resource->id, $cm->instance);
$this->assertEquals('resource', $cm->modname);
$this->assertEquals($SITE->id, $cm->course);
// Check the context is correct.
$context = \context_module::instance($cm->id);
$this->assertEquals($resource->cmid, $context->instanceid);
// Check that generated resource module contains a file.
$fs = get_file_storage();
$files = $fs->get_area_files($context->id, 'mod_resource', 'content', false, '', false);
$file = array_values($files)[0];
$this->assertCount(1, $files);
$this->assertEquals('resource3.txt', $file->get_filename());
$this->assertEquals('Test resource resource3.txt file', $file->get_content());
// Create a new resource specifying the file name.
$resource = $generator->create_instance(['course' => $SITE->id, 'defaultfilename' => 'myfile.pdf']);
// Check that generated resource module contains a file with the specified name.
$cm = get_coursemodule_from_instance('resource', $resource->id);
$context = \context_module::instance($cm->id);
$files = $fs->get_area_files($context->id, 'mod_resource', 'content', false, '', false);
$file = array_values($files)[0];
$this->assertCount(1, $files);
$this->assertEquals('myfile.pdf', $file->get_filename());
$this->assertEquals('Test resource myfile.pdf file', $file->get_content());
// Create a new resource uploading a file.
$resource = $generator->create_instance([
'course' => $SITE->id,
'uploaded' => true,
'defaultfilename' => 'mod/resource/tests/fixtures/samplefile.txt',
]);
// Check that generated resource module contains the uploaded samplefile.txt.
$cm = get_coursemodule_from_instance('resource', $resource->id);
$context = \context_module::instance($cm->id);
$files = $fs->get_area_files($context->id, 'mod_resource', 'content', false, '', false);
$file = array_values($files)[0];
$this->assertCount(1, $files);
$this->assertEquals('samplefile.txt', $file->get_filename());
$this->assertEquals('Hello!', $file->get_content());
// Try to generate a resource with uploaded file without specifying the file.
try {
$resource = $generator->create_instance([
'course' => $SITE->id,
'uploaded' => true,
]);
$this->assertTrue(false, 'coding_exception expected, defaultfilename is required');
} catch (\Exception $e) {
$this->assertInstanceOf(\coding_exception::class, $e);
$this->assertStringContainsString('defaultfilename option is required', $e->getMessage());
}
// Try to generate a resource with uploaded file pointing to non-existing file.
try {
$resource = $generator->create_instance([
'course' => $SITE->id,
'uploaded' => true,
'defaultfilename' => 'mod/resource/tests/fixtures/doesnotexist.txt',
]);
$this->assertTrue(false, 'coding_exception expected, defaultfilename must point to an existing file');
} catch (\Exception $e) {
$this->assertInstanceOf(\coding_exception::class, $e);
$this->assertStringContainsString('defaultfilename option must point to an existing file', $e->getMessage());
}
}
}
+285
View File
@@ -0,0 +1,285 @@
<?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/>.
/**
* Unit tests for mod_resource lib
*
* @package mod_resource
* @category external
* @copyright 2015 Juan Leyva <juan@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @since Moodle 3.0
*/
namespace mod_resource;
defined('MOODLE_INTERNAL') || die();
/**
* Unit tests for mod_resource lib
*
* @package mod_resource
* @category external
* @copyright 2015 Juan Leyva <juan@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @since Moodle 3.0
*/
class lib_test extends \advanced_testcase {
/**
* Prepares things before this test case is initialised
* @return void
*/
public static function setUpBeforeClass(): void {
global $CFG;
require_once($CFG->dirroot . '/mod/resource/lib.php');
}
/**
* Test resource_view
* @return void
*/
public function test_resource_view(): void {
global $CFG;
$CFG->enablecompletion = 1;
$this->resetAfterTest();
$this->setAdminUser();
// Setup test data.
$course = $this->getDataGenerator()->create_course(array('enablecompletion' => 1));
$resource = $this->getDataGenerator()->create_module('resource', array('course' => $course->id),
array('completion' => 2, 'completionview' => 1));
$context = \context_module::instance($resource->cmid);
$cm = get_coursemodule_from_instance('resource', $resource->id);
// Trigger and capture the event.
$sink = $this->redirectEvents();
resource_view($resource, $course, $cm, $context);
$events = $sink->get_events();
// 2 additional events thanks to completion.
$this->assertCount(3, $events);
$event = array_shift($events);
// Checking that the event contains the expected values.
$this->assertInstanceOf('\mod_resource\event\course_module_viewed', $event);
$this->assertEquals($context, $event->get_context());
$moodleurl = new \moodle_url('/mod/resource/view.php', array('id' => $cm->id));
$this->assertEquals($moodleurl, $event->get_url());
$this->assertEventContextNotUsed($event);
$this->assertNotEmpty($event->get_name());
// Check completion status.
$completion = new \completion_info($course);
$completiondata = $completion->get_data($cm);
$this->assertEquals(1, $completiondata->completionstate);
}
/**
* Tests the resource_get_coursemodule_info function.
*
* Note: This currently doesn't test every aspect of the function, mainly focusing on the icon.
*/
public function test_get_coursemodule_info(): void {
global $DB, $USER;
$this->resetAfterTest();
$this->setAdminUser();
// Create course.
$generator = $this->getDataGenerator();
$course = $generator->create_course();
// Create a resource with no files.
$draftid = file_get_unused_draft_itemid();
$resource1 = $generator->create_module('resource', array('course' => $course->id,
'name' => 'R1', 'files' => $draftid));
// Create a resource with one file.
$draftid = file_get_unused_draft_itemid();
$contextid = \context_user::instance($USER->id)->id;
$filerecord = array('component' => 'user', 'filearea' => 'draft', 'contextid' => $contextid,
'itemid' => $draftid, 'filename' => 'r2.txt', 'filepath' => '/');
$fs = get_file_storage();
$fs->create_file_from_string($filerecord, 'Test');
$resource2 = $generator->create_module('resource', array('course' => $course->id,
'name' => 'R2', 'files' => $draftid));
// Create a resource with two files.
$draftid = file_get_unused_draft_itemid();
$filerecord = array('component' => 'user', 'filearea' => 'draft', 'contextid' => $contextid,
'itemid' => $draftid, 'filename' => 'r3.txt', 'filepath' => '/', 'sortorder' => 1);
$fs->create_file_from_string($filerecord, 'Test');
$filerecord['filename'] = 'r3.doc';
$filerecord['sortorder'] = 2;
$fs->create_file_from_string($filerecord, 'Test');
$resource3 = $generator->create_module('resource', array('course' => $course->id,
'name' => 'R3', 'files' => $draftid));
// Try get_coursemodule_info for first one.
$info = resource_get_coursemodule_info(
$DB->get_record('course_modules', array('id' => $resource1->cmid)));
// The name should be set. There is no overridden icon.
$this->assertEquals('R1', $info->name);
$this->assertEmpty($info->icon);
// For second one, there should be an overridden icon.
$info = resource_get_coursemodule_info(
$DB->get_record('course_modules', array('id' => $resource2->cmid)));
$this->assertEquals('R2', $info->name);
$this->assertEquals('f/text', $info->icon);
// For third one, it should use the highest sortorder icon.
$info = resource_get_coursemodule_info(
$DB->get_record('course_modules', array('id' => $resource3->cmid)));
$this->assertEquals('R3', $info->name);
$this->assertEquals('f/document', $info->icon);
}
public function test_resource_core_calendar_provide_event_action(): void {
$this->resetAfterTest();
$this->setAdminUser();
// Create the activity.
$course = $this->getDataGenerator()->create_course();
$resource = $this->getDataGenerator()->create_module('resource', array('course' => $course->id));
// Create a calendar event.
$event = $this->create_action_event($course->id, $resource->id,
\core_completion\api::COMPLETION_EVENT_TYPE_DATE_COMPLETION_EXPECTED);
// Create an action factory.
$factory = new \core_calendar\action_factory();
// Decorate action event.
$actionevent = mod_resource_core_calendar_provide_event_action($event, $factory);
// Confirm the event was decorated.
$this->assertInstanceOf('\core_calendar\local\event\value_objects\action', $actionevent);
$this->assertEquals(get_string('view'), $actionevent->get_name());
$this->assertInstanceOf('moodle_url', $actionevent->get_url());
$this->assertEquals(1, $actionevent->get_item_count());
$this->assertTrue($actionevent->is_actionable());
}
public function test_resource_core_calendar_provide_event_action_already_completed(): void {
global $CFG;
$this->resetAfterTest();
$this->setAdminUser();
$CFG->enablecompletion = 1;
// Create the activity.
$course = $this->getDataGenerator()->create_course(array('enablecompletion' => 1));
$resource = $this->getDataGenerator()->create_module('resource', array('course' => $course->id),
array('completion' => 2, 'completionview' => 1, 'completionexpected' => time() + DAYSECS));
// Get some additional data.
$cm = get_coursemodule_from_instance('resource', $resource->id);
// Create a calendar event.
$event = $this->create_action_event($course->id, $resource->id,
\core_completion\api::COMPLETION_EVENT_TYPE_DATE_COMPLETION_EXPECTED);
// Mark the activity as completed.
$completion = new \completion_info($course);
$completion->set_module_viewed($cm);
// Create an action factory.
$factory = new \core_calendar\action_factory();
// Decorate action event.
$actionevent = mod_resource_core_calendar_provide_event_action($event, $factory);
// Ensure result was null.
$this->assertNull($actionevent);
}
/**
* Test mod_resource_core_calendar_provide_event_action with user override
*/
public function test_resource_core_calendar_provide_event_action_user_override(): void {
global $CFG, $USER;
$this->resetAfterTest();
$this->setAdminUser();
$user = $this->getDataGenerator()->create_user();
$CFG->enablecompletion = 1;
// Create the activity.
$course = $this->getDataGenerator()->create_course(array('enablecompletion' => 1));
$resource = $this->getDataGenerator()->create_module('resource', array('course' => $course->id),
array('completion' => 2, 'completionview' => 1, 'completionexpected' => time() + DAYSECS));
// Get some additional data.
$cm = get_coursemodule_from_instance('resource', $resource->id);
// Create a calendar event.
$event = $this->create_action_event($course->id, $resource->id,
\core_completion\api::COMPLETION_EVENT_TYPE_DATE_COMPLETION_EXPECTED);
// Mark the activity as completed.
$completion = new \completion_info($course);
$completion->set_module_viewed($cm);
// Create an action factory.
$factory = new \core_calendar\action_factory();
// Decorate action event.
$actionevent = mod_resource_core_calendar_provide_event_action($event, $factory, $USER->id);
// Decorate action with a userid override.
$actionevent2 = mod_resource_core_calendar_provide_event_action($event, $factory, $user->id);
// Ensure result was null because it has been marked as completed for the associated user.
// Logic was brought across from the "_already_completed" function.
$this->assertNull($actionevent);
// Confirm the event was decorated.
$this->assertNotNull($actionevent2);
$this->assertInstanceOf('\core_calendar\local\event\value_objects\action', $actionevent2);
$this->assertEquals(get_string('view'), $actionevent2->get_name());
$this->assertInstanceOf('moodle_url', $actionevent2->get_url());
$this->assertEquals(1, $actionevent2->get_item_count());
$this->assertTrue($actionevent2->is_actionable());
}
/**
* Creates an action event.
*
* @param int $courseid The course id.
* @param int $instanceid The instance id.
* @param string $eventtype The event type.
* @return bool|calendar_event
*/
private function create_action_event($courseid, $instanceid, $eventtype) {
$event = new \stdClass();
$event->name = 'Calendar event';
$event->modulename = 'resource';
$event->courseid = $courseid;
$event->instance = $instanceid;
$event->type = CALENDAR_EVENT_TYPE_ACTION;
$event->eventtype = $eventtype;
$event->timestart = time();
return \calendar_event::create($event);
}
}
+123
View File
@@ -0,0 +1,123 @@
<?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/>.
/**
* Resource search unit tests.
*
* @package mod_resource
* @category test
* @copyright 2016 Eric Merrill {@link http://www.merrilldigital.com}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace mod_resource\search;
defined('MOODLE_INTERNAL') || die();
global $CFG;
require_once($CFG->dirroot . '/search/tests/fixtures/testable_core_search.php');
/**
* Provides the unit tests for forum search.
*
* @package mod_resource
* @category test
* @copyright 2016 Eric Merrill {@link http://www.merrilldigital.com}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class search_test extends \advanced_testcase {
/**
* @var string Area id
*/
protected $resourceareaid = null;
public function setUp(): void {
$this->resetAfterTest(true);
set_config('enableglobalsearch', true);
$this->resourceareaid = \core_search\manager::generate_areaid('mod_resource', 'activity');
// Set \core_search::instance to the mock_search_engine as we don't require the search engine to be working to test this.
$search = \testable_core_search::instance();
}
/**
* Test for resource file attachments.
*
* @return void
*/
public function test_attach_files(): void {
global $USER;
$this->setAdminUser();
// Setup test data.
$course = $this->getDataGenerator()->create_course();
$fs = get_file_storage();
$usercontext = \context_user::instance($USER->id);
$record = new \stdClass();
$record->course = $course->id;
$record->files = file_get_unused_draft_itemid();
// Attach the main file. We put them in the draft area, create_module will move them.
$filerecord = array(
'contextid' => $usercontext->id,
'component' => 'user',
'filearea' => 'draft',
'itemid' => $record->files,
'filepath' => '/',
'filename' => 'mainfile',
'sortorder' => 1
);
$fs->create_file_from_string($filerecord, 'Test resource file');
// Attach a second file.
$filerecord['filename'] = 'extrafile';
$filerecord['sortorder'] = 0;
$fs->create_file_from_string($filerecord, 'Test resource file 2');
$resource = $this->getDataGenerator()->create_module('resource', $record);
$searcharea = \core_search\manager::get_search_area($this->resourceareaid);
$this->assertInstanceOf('\mod_resource\search\activity', $searcharea);
$recordset = $searcharea->get_recordset_by_timestamp(0);
$nrecords = 0;
foreach ($recordset as $record) {
$doc = $searcharea->get_document($record);
$searcharea->attach_files($doc);
$files = $doc->get_files();
// Resources should return all added files.
$this->assertCount(2, $files);
$filenames = array();
foreach ($files as $file) {
$filenames[] = $file->get_filename();
}
$this->assertContains('mainfile', $filenames);
$this->assertContains('extrafile', $filenames);
$nrecords++;
}
$recordset->close();
$this->assertEquals(1, $nrecords);
}
}
+10
View File
@@ -0,0 +1,10 @@
This file describes API changes in the resource code.
=== 4.3 ===
* Function resource_get_optional_details() has now one new parameter, $showtype, to decide whether the file type should be
displayed or not (regardless the display option is enabled).
=== 4.0 ===
* Functions resource_print_heading and resource_print_intro have been deprecated in favour for the activity header.
+30
View File
@@ -0,0 +1,30 @@
<?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/>.
/**
* Resource module version information
*
* @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();
$plugin->version = 2024042200; // The current module version (Date: YYYYMMDDXX).
$plugin->requires = 2024041600; // Requires this Moodle version.
$plugin->component = 'mod_resource'; // Full name of the plugin (used for diagnostics)
$plugin->cron = 0;
+108
View File
@@ -0,0 +1,108 @@
<?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/>.
/**
* Resource module version information
*
* @package mod_resource
* @copyright 2009 Petr Skoda {@link http://skodak.org}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
require('../../config.php');
require_once($CFG->dirroot.'/mod/resource/lib.php');
require_once($CFG->dirroot.'/mod/resource/locallib.php');
require_once($CFG->libdir.'/completionlib.php');
$id = optional_param('id', 0, PARAM_INT); // Course Module ID
$r = optional_param('r', 0, PARAM_INT); // Resource instance ID
$redirect = optional_param('redirect', 0, PARAM_BOOL);
$forceview = optional_param('forceview', 0, PARAM_BOOL);
if ($r) {
if (!$resource = $DB->get_record('resource', array('id'=>$r))) {
resource_redirect_if_migrated($r, 0);
throw new \moodle_exception('invalidaccessparameter');
}
$cm = get_coursemodule_from_instance('resource', $resource->id, $resource->course, false, MUST_EXIST);
} else {
if (!$cm = get_coursemodule_from_id('resource', $id)) {
resource_redirect_if_migrated(0, $id);
throw new \moodle_exception('invalidcoursemodule');
}
$resource = $DB->get_record('resource', array('id'=>$cm->instance), '*', MUST_EXIST);
}
$course = $DB->get_record('course', array('id'=>$cm->course), '*', MUST_EXIST);
require_course_login($course, true, $cm);
$context = context_module::instance($cm->id);
require_capability('mod/resource:view', $context);
// Completion and trigger events.
resource_view($resource, $course, $cm, $context);
$PAGE->set_url('/mod/resource/view.php', array('id' => $cm->id));
if ($resource->tobemigrated) {
resource_print_tobemigrated($resource, $cm, $course);
die;
}
$fs = get_file_storage();
$files = $fs->get_area_files($context->id, 'mod_resource', 'content', 0, 'sortorder DESC, id ASC', false); // TODO: this is not very efficient!!
if (count($files) < 1) {
resource_print_filenotfound($resource, $cm, $course);
die;
} else {
$file = reset($files);
unset($files);
}
$resource->mainfile = $file->get_filename();
$displaytype = resource_get_final_display_type($resource);
if ($displaytype == RESOURCELIB_DISPLAY_OPEN || $displaytype == RESOURCELIB_DISPLAY_DOWNLOAD) {
$redirect = true;
}
// Don't redirect teachers, otherwise they can not access course or module settings.
if ($redirect && !course_get_format($course)->has_view_page() &&
(has_capability('moodle/course:manageactivities', $context) ||
has_capability('moodle/course:update', context_course::instance($course->id)))) {
$redirect = false;
}
if ($redirect && !$forceview) {
// coming from course page or url index page
// this redirect trick solves caching problems when tracking views ;-)
$path = '/'.$context->id.'/mod_resource/content/'.$resource->revision.$file->get_filepath().$file->get_filename();
$fullurl = moodle_url::make_file_url('/pluginfile.php', $path, $displaytype == RESOURCELIB_DISPLAY_DOWNLOAD);
redirect($fullurl);
}
switch ($displaytype) {
case RESOURCELIB_DISPLAY_EMBED:
resource_display_embed($resource, $cm, $course, $file);
break;
case RESOURCELIB_DISPLAY_FRAME:
resource_display_frame($resource, $cm, $course, $file);
break;
default:
resource_print_workaround($resource, $cm, $course, $file);
break;
}