+ Before starting the migration, you can download a CSV which will list all courses which contain items that will be affected by the migration.
+ This CSV can be used for review, and no system modifications will occur.
+
+
+
+
+ This migration will enable existing openEQUELLA links to be opened using LTI 1.3 technology. openEQUELLA items shown in courses may display slightly differently
+ (e.g. use different thumbnails) after the migration. Please ensure that you have backed up your Moodle data before proceeding.
+
- Before starting the migration, you can download a CSV which will list all courses which contain items that will be affected by the migration.
- This CSV can be used for review, and no system modifications will occur.
-
-
-
-
- This migration will enable existing openEQUELLA links to be opened using LTI 1.3 technology. openEQUELLA items shown in courses may display slightly differently
- (e.g. use different thumbnails) after the migration. Please ensure that you have backed up your Moodle data before proceeding.
-
-
-
-";
+echo "
+
Update oEQ resource links to use LTI 1.3
+
+
+ Before starting the migration, you can download a CSV which will list all courses which contain items that will be
+ affected by the migration. This CSV can be used for review, and no system modifications will occur.
+
+
+
+
+ This migration will enable existing openEQUELLA links to be opened using LTI 1.3 technology. openEQUELLA items shown
+ in courses may display slightly differently (e.g. use different thumbnails) after the migration. Please ensure that
+ you have backed up your Moodle data before proceeding.
+
+ "
+?>
+
+
From e69df06e86e1ba4c2db95d8e9af6ebcbffacf603 Mon Sep 17 00:00:00 2001
From: Penghai
Date: Wed, 31 May 2023 10:55:38 +1000
Subject: [PATCH 5/9] refactor: create a new directory for LTI 1.3 migration
---
lti13migration.php => lti13migration/main.php | 3 +--
settings.php | 2 +-
2 files changed, 2 insertions(+), 3 deletions(-)
rename lti13migration.php => lti13migration/main.php (95%)
diff --git a/lti13migration.php b/lti13migration/main.php
similarity index 95%
rename from lti13migration.php
rename to lti13migration/main.php
index 79e66d7..19eceb3 100644
--- a/lti13migration.php
+++ b/lti13migration/main.php
@@ -29,8 +29,7 @@
Before starting the migration, you can download a CSV which will list all courses which contain items that will be
affected by the migration. This CSV can be used for review, and no system modifications will occur.
-
diff --git a/settings.php b/settings.php
index 7ce9c88..946fe66 100644
--- a/settings.php
+++ b/settings.php
@@ -111,6 +111,6 @@ function ecs($configoption, $params = null) {
// LTI 1.3 migration
//
$settings->add(new admin_setting_heading('equella_lti_migration', ecs('lti13.migration.title'), ''));
- $lti13MigrationUrl = new moodle_url('/mod/equella/lti13migration.php');
+ $lti13MigrationUrl = new moodle_url('/mod/equella/lti13migration/main.php');
$settings->add(new admin_setting_openlink('lti13migration', ecs('lti13.migration.title'), ecs('lti13.migration.description'), $lti13MigrationUrl->out()));
}
From 65dfad5cb113a810447d674da83ba9b8e019aec9 Mon Sep 17 00:00:00 2001
From: Penghai
Date: Wed, 31 May 2023 10:56:24 +1000
Subject: [PATCH 6/9] feat: add the support for downloading a CSV of courses
affected by the migration
---
lti13migration/downloadcsv.php | 61 ++++++++++++++++++++++++++++++++++
1 file changed, 61 insertions(+)
create mode 100644 lti13migration/downloadcsv.php
diff --git a/lti13migration/downloadcsv.php b/lti13migration/downloadcsv.php
new file mode 100644
index 0000000..184051b
--- /dev/null
+++ b/lti13migration/downloadcsv.php
@@ -0,0 +1,61 @@
+.
+
+require_once('../../../config.php');
+require_once($CFG->dirroot . '/mod/lti/classes/external.php');
+require_once($CFG->dirroot . '/lib/datalib.php');
+require_once($CFG->dirroot . '/mod/equella/lib.php');
+
+global $DB;
+
+header('Content-Type: text/csv; charset=utf-8');
+header('Content-Disposition: attachment; filename=courses.csv');
+
+// Cannot use `$DB0->get_field` due to issue .
+$oeqMoodleModuleID = $DB->get_field_sql("SELECT id FROM {modules} WHERE name = 'equella'");
+
+// Moodle does not provide a function that can return a list of courses that contain certain specified modules.
+// One would have to get a full list of courses and then filter the list by checking whether each course has
+// the specified modules.
+// So using the below SQL should be better.
+$courseSql = "SELECT c.id, c.fullname FROM {course} c, {course_modules} cm" .
+ " WHERE cm.module = " . $oeqMoodleModuleID .
+ " AND c.id = cm.course" .
+ " GROUP BY c.id, c.fullname HAVING count(*) > 0";
+$courses = $DB->get_records_sql($courseSql);
+
+$csvHeaders = array('Course ID', 'Course name', 'Course URL');
+$csvContent = array_map(function ($course) {
+ $courseId = $course->id;
+ $courseUrl = new moodle_url('/course/view.php', array('id' => $courseId));
+ return array($courseId, $course->fullname, $courseUrl->out(false));
+}, $courses);
+
+ob_start();
+
+$outputBuffer = fopen('php://output', 'w');
+fputcsv($outputBuffer, $csvHeaders);
+
+foreach ($csvContent as $i => $row) {
+ fputcsv($outputBuffer, $row);
+ if ($i % 100 == 0) {
+ ob_flush();
+ flush();
+ }
+}
+
+fclose($outputBuffer);
+exit;
From 9796e67ffdd91654e5e5b0ec3e41ccc9ac76922f Mon Sep 17 00:00:00 2001
From: Penghai
Date: Tue, 6 Jun 2023 14:09:42 +1000
Subject: [PATCH 7/9] feat: display a drop-down to let users select which LTI
platform to be used in the migration
---
lti13migration/main.php | 12 ++++++++++--
1 file changed, 10 insertions(+), 2 deletions(-)
diff --git a/lti13migration/main.php b/lti13migration/main.php
index 19eceb3..5b29a16 100644
--- a/lti13migration/main.php
+++ b/lti13migration/main.php
@@ -22,6 +22,12 @@
get_fieldset_sql("SELECT name FROM {lti_types} WHERE ltiversion='1.3.0'");
+$options = implode(array_map(function ($name) { return ""; }, $ltiToolNames));
+
echo "
Update oEQ resource links to use LTI 1.3
@@ -38,8 +44,10 @@
in courses may display slightly differently (e.g. use different thumbnails) after the migration. Please ensure that
you have backed up your Moodle data before proceeding.
- "
?>
From 45b046aea25e358e1600dbe74478eb65c2269c29 Mon Sep 17 00:00:00 2001
From: Penghai
Date: Tue, 6 Jun 2023 14:25:49 +1000
Subject: [PATCH 8/9] feat: create a new page to submit the migration task
---
lti13migration/migrate.php | 47 ++++++++++++++++++++++++++++++++++++++
1 file changed, 47 insertions(+)
create mode 100644 lti13migration/migrate.php
diff --git a/lti13migration/migrate.php b/lti13migration/migrate.php
new file mode 100644
index 0000000..3801c16
--- /dev/null
+++ b/lti13migration/migrate.php
@@ -0,0 +1,47 @@
+ out(false);
+}
+
+$runningTasksPage = buildUrl('/admin/tool/task/runningtasks.php');
+$taskLogsPage = buildUrl('/admin/tasklogs.php');
+$purgeCachePage = buildUrl('/admin/purgecaches.php');
+
+$task = new \mod_equella\task\lti13_migration_task();
+$task -> set_custom_data($_GET['ltiTypeName']);
+\core\task\manager::queue_adhoc_task($task);
+?>
+
+
+
+LTI 1.3 Migration
+
+
+
Update oEQ resource links to use LTI 1.3
+
+
+ A Moodle adhoc task has been submitted to do the migration.
+
+
+ However, when the task will start depends on how often the Moodle cron script is executed.
+
+
+ Running tasks page,
+ and you can find out the task result in the Task logs page.";
+ ?>
+
+
+ Purge caches page.";
+ ?>
+
+
+
+
From 34da075c66487eea14069c13c2f8cc0bc6c65dbd Mon Sep 17 00:00:00 2001
From: Penghai
Date: Tue, 6 Jun 2023 15:29:49 +1000
Subject: [PATCH 9/9] feat: create a new adhoc task to do the LTI 1.3 migration
---
classes/task/lti13_migration_task.php | 132 ++++++++++++++++++++++++++
1 file changed, 132 insertions(+)
create mode 100644 classes/task/lti13_migration_task.php
diff --git a/classes/task/lti13_migration_task.php b/classes/task/lti13_migration_task.php
new file mode 100644
index 0000000..0ab7d45
--- /dev/null
+++ b/classes/task/lti13_migration_task.php
@@ -0,0 +1,132 @@
+.
+
+namespace mod_equella\task;
+
+use core\task\adhoc_task;
+use dml_exception;
+use stdClass;
+
+global $CFG;
+require_once($CFG->dirroot . '/mod/lti/lib.php');
+require_once($CFG->dirroot . '/mod/lti/locallib.php');
+
+class lti13_migration_task extends adhoc_task
+{
+ /**
+ * Create a new LTI external tool instance based on the provided course module info, details of the OEQ instance used in this
+ * course module and the configurations of an LTI external tool.
+ *
+ * @param $courseModule stdClass An instance of CourseModule to be updated to use LTI 1.3 as its module.
+ * @param $ltiToolDetails stdClass Details of the LTI external tool to be used to generate a new LTI instance.
+ *
+ * @throws dml_exception
+ */
+ private function createLtiInstance($courseModule, $ltiToolDetails): int
+ {
+ global $DB;
+
+ $oeqInstance = $DB->get_record('equella', array('id' => $courseModule->instance));
+ $ltiConfigurations = $ltiToolDetails->configurations;
+ $ltiToolID = $ltiToolDetails->id;
+
+ $lti = new stdClass();
+
+ $lti->typeid = $ltiToolID;
+
+ $lti->course = $courseModule->course;
+ $lti->showdescriptionlaunch = $courseModule->showdescription;
+ $lti->coursemodule = $courseModule->id;
+
+ $lti->icon = unserialize($oeqInstance->metadata)['thumbnail'];
+ $lti->intro = $oeqInstance->intro;
+ $lti->introformat = $oeqInstance->introformat;
+ $lti->name = $oeqInstance->name;
+ $lti->timecreated = $oeqInstance->timecreated;
+ $lti->timemodified = $oeqInstance->timemodified;
+ $lti->toolurl = $oeqInstance->url;
+
+ $lti->instructorchoicesendname = $ltiConfigurations['sendname'] ?? 1;
+ $lti->instructorchoicesendmailaddr = $ltiConfigurations['sendemailaddr'] ?? 1;
+ $lti->instructorchoiceacceptgrades = $ltiConfigurations['acceptgrades'] == LTI_SETTING_ALWAYS ? $ltiConfigurations['acceptgrades'] : 0;
+ $lti->instructorchoiceallowsetting = $ltiConfigurations['ltiservice_toolsettings'] ?? null;
+ $lti->instructorchoiceallowroster = $ltiConfigurations['allowroster ltiservice_memberships'] ?? null;
+ $lti->instructorcustomparameters = $ltiConfigurations['customparameters'] ?? "";
+ $lti->launchcontainer = $ltiConfigurations['launchcontainer'];
+
+ return lti_add_instance($lti, null); // The second parameter is not used at all in this function.;
+ }
+
+ /**
+ * Update an existing course module to use a new LTI instance. To achieve this, the value of `module` needs to be
+ * updated to the ID of LTI module, and the value of instance needs to be updated to the ID of a new LTI instance.
+ *
+ * @param $courseModule stdClass An instance of CourseModule to be updated to use LTI 1.3 as its module.
+ * @param $ltiToolDetails stdClass Details of the LTI external tool to be used to generate a new LTI instance.
+ * @param $ltiModuleID int ID of the LTI module.
+ *
+ * @throws dml_exception
+ */
+ private function updateCourseModule($courseModule, $ltiToolDetails, $ltiModuleID): void
+ {
+ global $DB;
+
+ $courseModule->module = $ltiModuleID;
+ $courseModule->instance = $this->createLtiInstance($courseModule, $ltiToolDetails);
+ $DB->update_record("course_modules", $courseModule);
+ }
+
+ /**
+ * Return the ID of Moodle module for the provided module name.
+ *
+ * @param $moduleName string Name of a Moodle module.
+ *
+ * @throws dml_exception
+ */
+ private function getModuleId($moduleName) {
+ global $DB;
+ return $DB->get_field_sql("SELECT id FROM {modules} WHERE name = '$moduleName'");
+ }
+
+ public function execute()
+ {
+ global $DB;
+
+ try {
+ $oeqMoodleModuleID = $this->getModuleId('equella');
+ $ltiModuleID = $this->getModuleId('lti');
+
+ $ltiTool = new stdClass();
+ $ltiTypeName = $this->get_custom_data();
+ $ltiTypeID = $DB->get_field_sql("SELECT id FROM {lti_types} WHERE name = '" . $ltiTypeName . "'");
+ $ltiTool->id = $ltiTypeID;
+ $ltiTool->configurations = lti_get_type_config($ltiTypeID);
+
+ $courseModuleList = $DB->get_records_sql("SELECT * FROM {course_modules} cm WHERE cm.module = " . $oeqMoodleModuleID);
+
+ foreach ($courseModuleList as $cm) {
+ echo "Processing course ID: " . $cm->course . " openEQUELLA resource ID: " . $cm->instance . "\n";
+ $this->updateCourseModule($cm, $ltiTool, $ltiModuleID);
+ }
+
+ echo "LTI 1.3 migration has been successfully completed!";
+ } catch (dml_exception $e) {
+ echo "LTI 1.3 migration failed: $e";
+ }
+ }
+
+
+}
\ No newline at end of file