diff --git a/backup/moodle2/restore_stepslib.php b/backup/moodle2/restore_stepslib.php index 7e9e3252751d4..2b28e74a2b97f 100644 --- a/backup/moodle2/restore_stepslib.php +++ b/backup/moodle2/restore_stepslib.php @@ -1881,6 +1881,11 @@ public function process_course($data) { $data->idnumber = ''; } + // If we restore a course from this site, let's capture the original course id. + if ($isnewcourse && $this->get_task()->is_samesite()) { + $data->originalcourseid = $this->get_task()->get_old_courseid(); + } + // Any empty value for course->hiddensections will lead to 0 (default, show collapsed). // It has been reported that some old 1.9 courses may have it null leading to DB error. MDL-31532 if (empty($data->hiddensections)) { diff --git a/lib/db/install.xml b/lib/db/install.xml index 43e82bc17e191..0643897ce64e9 100644 --- a/lib/db/install.xml +++ b/lib/db/install.xml @@ -1,5 +1,5 @@ - @@ -101,6 +101,7 @@ + diff --git a/lib/db/upgrade.php b/lib/db/upgrade.php index e9df47aa262d5..41b2f5c596728 100644 --- a/lib/db/upgrade.php +++ b/lib/db/upgrade.php @@ -2694,5 +2694,19 @@ function xmldb_main_upgrade($oldversion) { upgrade_main_savepoint(true, 2021052500.13); } + if ($oldversion < 2021052500.15) { + // Copy From id captures the id of the source course when a new course originates from a restore + // of another course on the same site. + $table = new xmldb_table('course'); + $field = new xmldb_field('originalcourseid', XMLDB_TYPE_INTEGER, '10', null, null, null, null); + + if (!$dbman->field_exists($table, $field)) { + $dbman->add_field($table, $field); + } + + // Main savepoint reached. + upgrade_main_savepoint(true, 2021052500.15); + } + return true; } diff --git a/lib/upgrade.txt b/lib/upgrade.txt index 5e5c3d1a612c3..6b84c747c5084 100644 --- a/lib/upgrade.txt +++ b/lib/upgrade.txt @@ -2,6 +2,7 @@ This files describes API changes in core libraries and APIs, information provided here is intended especially for developers. === 3.10 === +* Retains the source course id when a course is copied from another course on the same site. * Added function setScrollable in core/modal. This function can be used to set the modal's body to be scrollable or not when the modal's height exceeds the browser's height. This is also supported in core/modal_factory through the 'scrollable' config parameter which can be set to either true or false. If not explicitly defined, the default value diff --git a/mod/lti/locallib.php b/mod/lti/locallib.php index a5db3ec0585a7..1e548d5e64c40 100644 --- a/mod/lti/locallib.php +++ b/mod/lti/locallib.php @@ -2008,10 +2008,30 @@ function lti_calculate_custom_parameter($value) { switch ($value) { case 'Moodle.Person.userGroupIds': return implode(",", groups_get_user_groups($COURSE->id, $USER->id)[0]); + case 'Context.id.history': + return implode(",", get_course_history($COURSE)); } return null; } +/** + * Build the history chain for this course using the course originalcourseid. + * + * @param object $course course for which the history is returned. + * + * @return array ids of the source course in ancestry order, immediate parent 1st. + */ +function get_course_history($course) { + global $DB; + $history = []; + $parentid = $course->originalcourseid; + while (!empty($parentid) && !in_array($parentid, $history)) { + $history[] = $parentid; + $parentid = $DB->get_field('course', 'originalcourseid', array('id' => $parentid)); + } + return $history; +} + /** * Used for building the names of the different custom parameters * @@ -3641,6 +3661,7 @@ function lti_get_capabilities() { 'Context.id' => 'context_id', 'Context.title' => 'context_title', 'Context.label' => 'context_label', + 'Context.id.history' => null, 'Context.sourcedId' => 'lis_course_section_sourcedid', 'Context.longDescription' => '$COURSE->summary', 'Context.timeFrame.begin' => '$COURSE->startdate', diff --git a/mod/lti/tests/locallib_test.php b/mod/lti/tests/locallib_test.php index 1a9800ae80319..680da402dfccb 100644 --- a/mod/lti/tests/locallib_test.php +++ b/mod/lti/tests/locallib_test.php @@ -1528,6 +1528,25 @@ public function test_lti_get_launch_data_default_organizationid_orgid_override() $this->assertEquals($launchdata[1]['tool_consumer_instance_guid'], 'overridden!'); } + public function test_get_course_history() { + global $DB; + $this->resetAfterTest(); + $this->setAdminUser(); + $parentparentcourse = $this->getDataGenerator()->create_course(); + $parentcourse = $this->getDataGenerator()->create_course(); + $parentcourse->originalcourseid = $parentparentcourse->id; + $DB->update_record('course', $parentcourse); + $course = $this->getDataGenerator()->create_course(); + $course->originalcourseid = $parentcourse->id; + $DB->update_record('course', $course); + $this->assertEquals(get_course_history($parentparentcourse), []); + $this->assertEquals(get_course_history($parentcourse), [$parentparentcourse->id]); + $this->assertEquals(get_course_history($course), [$parentcourse->id, $parentparentcourse->id]); + $course->originalcourseid = 38903; + $DB->update_record('course', $course); + $this->assertEquals(get_course_history($course), [38903]); + } + /** * Create an LTI Tool. * diff --git a/version.php b/version.php index 883efbb464de2..99b3f82eb261b 100644 --- a/version.php +++ b/version.php @@ -29,7 +29,7 @@ defined('MOODLE_INTERNAL') || die(); -$version = 2021052500.14; // YYYYMMDD = weekly release date of this DEV branch. +$version = 2021052500.15; // YYYYMMDD = weekly release date of this DEV branch. // RR = release increments - 00 in DEV branches. // .XX = incremental changes. $release = '4.0dev (Build: 20200918)'; // Human-friendly version name