diff --git a/backup/moodle2/backup_edflex_activity_task.class.php b/backup/moodle2/backup_edflex_activity_task.class.php new file mode 100644 index 0000000..d725560 --- /dev/null +++ b/backup/moodle2/backup_edflex_activity_task.class.php @@ -0,0 +1,74 @@ +. + +/** + * Backup task for mod_edflex. + * + * @package mod_edflex + * @copyright 2025 Edflex + * @license https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die(); + +require_once($CFG->dirroot . '/mod/edflex/backup/moodle2/backup_edflex_stepslib.php'); + +/** + * Provides the steps to perform one complete backup of the edflex instance. + * + * @package mod_edflex + * @copyright 2025 Edflex + * @license https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class backup_edflex_activity_task extends backup_activity_task { + /** + * Defines particular settings for this activity task. None required. + * + * @return void + */ + protected function define_my_settings() { + } + + /** + * Defines particular steps for this activity backup. + * + * @return void + */ + protected function define_my_steps() { + $this->add_step(new backup_edflex_activity_structure_step('edflex_structure', 'edflex.xml')); + } + + /** + * Encodes URLs to the view and index scripts so they can be decoded on restore. + * + * @param string $content The content to encode. + * + * @return string The content with encoded links. + */ + public static function encode_content_links($content) { + global $CFG; + + $base = preg_quote($CFG->wwwroot, '/'); + + $search = '/(' . $base . '\/mod\/edflex\/view\.php\?id\=)([0-9]+)/'; + $content = preg_replace($search, '$@EDFLEXVIEWBYID*$2@$', $content); + + $search = '/(' . $base . '\/mod\/edflex\/index\.php\?id\=)([0-9]+)/'; + $content = preg_replace($search, '$@EDFLEXINDEX*$2@$', $content); + + return $content; + } +} diff --git a/backup/moodle2/backup_edflex_stepslib.php b/backup/moodle2/backup_edflex_stepslib.php new file mode 100644 index 0000000..283c57c --- /dev/null +++ b/backup/moodle2/backup_edflex_stepslib.php @@ -0,0 +1,49 @@ +. + +/** + * Backup steps for mod_edflex. + * + * @package mod_edflex + * @copyright 2025 Edflex + * @license https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +/** + * Defines the complete edflex structure for backup, with file annotations. + * + * @package mod_edflex + * @copyright 2025 Edflex + * @license https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class backup_edflex_activity_structure_step extends backup_activity_structure_step { + /** + * Defines the backup structure of the edflex activity. + * + * @return backup_nested_element The prepared activity structure to back up. + */ + protected function define_structure() { + $edflex = new backup_nested_element('edflex', ['id'], [ + 'name', 'intro', 'introformat', 'timemodified', + ]); + + $edflex->set_source_table('edflex', ['id' => backup::VAR_ACTIVITYID]); + + $edflex->annotate_files('mod_edflex', 'intro', null); + + return $this->prepare_activity_structure($edflex); + } +} diff --git a/backup/moodle2/restore_edflex_activity_task.class.php b/backup/moodle2/restore_edflex_activity_task.class.php new file mode 100644 index 0000000..87a07f9 --- /dev/null +++ b/backup/moodle2/restore_edflex_activity_task.class.php @@ -0,0 +1,90 @@ +. + +/** + * Restore task for mod_edflex. + * + * @package mod_edflex + * @copyright 2025 Edflex + * @license https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die(); + +require_once($CFG->dirroot . '/mod/edflex/backup/moodle2/restore_edflex_stepslib.php'); + +/** + * Restore task for the edflex activity module. + * + * @package mod_edflex + * @copyright 2025 Edflex + * @license https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class restore_edflex_activity_task extends restore_activity_task { + /** + * Defines particular settings for this activity task. None required. + * + * @return void + */ + protected function define_my_settings() { + } + + /** + * Defines particular steps for this activity restore. + * + * @return void + */ + protected function define_my_steps() { + $this->add_step(new restore_edflex_activity_structure_step('edflex_structure', 'edflex.xml')); + } + + /** + * Defines the contents in the activity that must be processed by the link decoder. + * + * @return array The decode contents. + */ + public static function define_decode_contents() { + $contents = []; + $contents[] = new restore_decode_content('edflex', ['intro'], 'edflex'); + + return $contents; + } + + /** + * Defines the decoding rules for links belonging to the activity to be executed by the link decoder. + * + * @return array The decode rules. + */ + public static function define_decode_rules() { + $rules = []; + $rules[] = new restore_decode_rule('EDFLEXVIEWBYID', '/mod/edflex/view.php?id=$1', 'course_module'); + $rules[] = new restore_decode_rule('EDFLEXINDEX', '/mod/edflex/index.php?id=$1', 'course'); + + return $rules; + } + + /** + * Defines the restore log rules that will be applied for the activity logs. + * + * @return array The restore log rules. + */ + public static function define_restore_log_rules() { + $rules = []; + $rules[] = new restore_log_rule('edflex', 'view', 'view.php?id={course_module}', '{edflex}'); + + return $rules; + } +} diff --git a/backup/moodle2/restore_edflex_stepslib.php b/backup/moodle2/restore_edflex_stepslib.php new file mode 100644 index 0000000..64be4e0 --- /dev/null +++ b/backup/moodle2/restore_edflex_stepslib.php @@ -0,0 +1,71 @@ +. + +/** + * Restore steps for mod_edflex. + * + * @package mod_edflex + * @copyright 2025 Edflex + * @license https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +/** + * Defines the structure step to restore one edflex activity. + * + * @package mod_edflex + * @copyright 2025 Edflex + * @license https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class restore_edflex_activity_structure_step extends restore_activity_structure_step { + /** + * Defines the structure to be restored for the edflex activity. + * + * @return mixed The prepared activity structure. + */ + protected function define_structure() { + $paths = []; + $paths[] = new restore_path_element('edflex', '/activity/edflex'); + + return $this->prepare_activity_structure($paths); + } + + /** + * Restores one edflex instance from the backup data. + * + * @param array $data The edflex record to restore. + * + * @return void + */ + protected function process_edflex($data) { + global $DB; + + $data = (object) $data; + $data->course = $this->get_courseid(); + $data->timemodified = $this->apply_date_offset($data->timemodified); + + $newitemid = $DB->insert_record('edflex', $data); + $this->apply_activity_instance($newitemid); + } + + /** + * Re-adds the files belonging to the restored instance once execution completes. + * + * @return void + */ + protected function after_execute() { + $this->add_related_files('mod_edflex', 'intro', null); + } +} diff --git a/classes/event/course_module_viewed.php b/classes/event/course_module_viewed.php new file mode 100644 index 0000000..5db228d --- /dev/null +++ b/classes/event/course_module_viewed.php @@ -0,0 +1,54 @@ +. + +/** + * The mod_edflex course module viewed event. + * + * @package mod_edflex + * @copyright 2025 Edflex + * @license https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +namespace mod_edflex\event; + +/** + * The mod_edflex course module viewed event class. + * + * @package mod_edflex + * @copyright 2025 Edflex + * @license https://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['crud'] = 'r'; + $this->data['edulevel'] = self::LEVEL_PARTICIPATING; + $this->data['objecttable'] = 'edflex'; + } + + /** + * Returns the mapping used by restore to remap the objectid. + * + * @return array The objectid mapping. + */ + public static function get_objectid_mapping() { + return ['db' => 'edflex', 'restore' => 'edflex']; + } +} diff --git a/db/access.php b/db/access.php index d4d67f3..d8f32eb 100755 --- a/db/access.php +++ b/db/access.php @@ -31,4 +31,15 @@ 'contextlevel' => CONTEXT_COURSE, 'archetypes' => ['editingteacher' => CAP_ALLOW, 'manager' => CAP_ALLOW], ], + 'mod/edflex:view' => [ + 'captype' => 'read', + 'contextlevel' => CONTEXT_MODULE, + 'archetypes' => [ + 'guest' => CAP_ALLOW, + 'student' => CAP_ALLOW, + 'teacher' => CAP_ALLOW, + 'editingteacher' => CAP_ALLOW, + 'manager' => CAP_ALLOW, + ], + ], ]; diff --git a/lang/en/edflex.php b/lang/en/edflex.php index c360c68..95723ff 100755 --- a/lang/en/edflex.php +++ b/lang/en/edflex.php @@ -60,6 +60,7 @@ $string['downloadscormzipmissing'] = 'Scorm download URL is missing'; $string['duration'] = 'Duration'; $string['edflex:addinstance'] = 'Add a new Edflex activity'; +$string['edflex:view'] = 'View Edflex activity'; $string['edflexbrowserloading'] = 'Loading...'; $string['edflexbrowsertitle'] = 'Browse Edflex Contents'; $string['edflexcontentidinvalid'] = 'Edflex content ID invalid'; diff --git a/lib.php b/lib.php index e75e225..cc3191a 100755 --- a/lib.php +++ b/lib.php @@ -36,7 +36,14 @@ * @return mixed True if module supports feature, null if doesn't know */ function edflex_supports($feature) { - return null; + switch ($feature) { + case FEATURE_MOD_INTRO: + case FEATURE_SHOW_DESCRIPTION: + case FEATURE_BACKUP_MOODLE2: + return true; + default: + return null; + } } /** @@ -48,6 +55,8 @@ function edflex_supports($feature) { * @return bool */ function edflex_add_instance($moduleinstance, $mform = null) { + // The mod_edflex form is a launcher: it spawns SCORM modules via the + // Edflex browser, so no standalone edflex instance is ever persisted. return false; } diff --git a/version.php b/version.php index a646671..61ef6f7 100755 --- a/version.php +++ b/version.php @@ -25,8 +25,8 @@ defined('MOODLE_INTERNAL') || die(); $plugin->component = 'mod_edflex'; -$plugin->release = 'v1.0.1'; -$plugin->version = 2026062400; +$plugin->release = 'v1.0.2'; +$plugin->version = 2026062900; $plugin->requires = 2022041900; $plugin->maturity = MATURITY_STABLE; $plugin->dependencies = [ diff --git a/view.php b/view.php index 96c0b07..067b397 100755 --- a/view.php +++ b/view.php @@ -26,9 +26,27 @@ $id = required_param('id', PARAM_INT); $cm = get_coursemodule_from_id('edflex', $id, 0, false, MUST_EXIST); $course = $DB->get_record('course', ['id' => $cm->course], '*', MUST_EXIST); +$moduleinstance = $DB->get_record('edflex', ['id' => $cm->instance], '*', MUST_EXIST); require_login($course, true, $cm); +$context = context_module::instance($cm->id); +require_capability('mod/edflex:view', $context); + +$PAGE->set_url('/mod/edflex/view.php', ['id' => $cm->id]); +$PAGE->set_title(format_string($moduleinstance->name)); +$PAGE->set_heading(format_string($course->fullname)); +$PAGE->set_context($context); + +$event = \mod_edflex\event\course_module_viewed::create([ + 'objectid' => $moduleinstance->id, + 'context' => $context, +]); +$event->add_record_snapshot('course', $course); +$event->add_record_snapshot('course_modules', $cm); +$event->add_record_snapshot('edflex', $moduleinstance); +$event->trigger(); + echo $OUTPUT->header(); echo $OUTPUT->heading(get_string('outputheading', 'mod_edflex')); echo $OUTPUT->footer();