diff --git a/classes/task/update_customfield_context.php b/classes/task/update_customfield_context.php new file mode 100644 index 0000000..cf0bac8 --- /dev/null +++ b/classes/task/update_customfield_context.php @@ -0,0 +1,58 @@ +. + +namespace mod_cms\task; + +use core\task\adhoc_task; + +/** + * Runs customfield context update. + * + * @package mod_cms + * @author Tomo Tsuyuki + * @copyright 2023 Catalyst IT + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class update_customfield_context extends adhoc_task { + + /** + * Run the task. + * + * @return void + */ + public function execute() { + global $DB; + + // Record {customfield_data}.instanceid is from {cms}.id. + // Record {customfield_data}.contextid is from contextid of {course_modules}, which is linked to {cms}. + + // Collect records which have wrong contextid in the customfield data. + $sql = "SELECT mcd.id mcdid, mcd.contextid mcdcontextid, mc.id mcid + FROM {customfield_data} mcd + JOIN {customfield_field} mcf ON mcf.id = mcd.fieldid + JOIN {customfield_category} mcc ON mcc.id = mcf.categoryid + JOIN {course_modules} mcm ON mcm.instance = mcd.instanceid AND mcm.module = ( + SELECT id FROM {modules} WHERE name = 'cms' + ) + JOIN {context} mc ON mc.instanceid = mcm.id AND contextlevel = " . CONTEXT_MODULE . " + WHERE mcc.component = 'mod_cms' AND mcc.area = 'cmsfield' AND mcd.contextid != mc.id"; + $records = $DB->get_records_sql($sql); + // Update records with correct contextid. + foreach ($records as $record) { + $DB->set_field('customfield_data', 'contextid', $record->mcid, ['id' => $record->mcdid]); + } + } +} diff --git a/db/upgrade.php b/db/upgrade.php index a584342..af44f7b 100644 --- a/db/upgrade.php +++ b/db/upgrade.php @@ -23,11 +23,13 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ +use core\task\manager; use mod_cms\local\lib; use mod_cms\local\model\cms_types; use mod_cms\local\model\cms; use mod_cms\local\datasource\fields; use mod_cms\local\datasource\userlist; +use mod_cms\task\update_customfield_context; /** * Function to upgrade mod_cms database @@ -341,5 +343,75 @@ function xmldb_cms_upgrade($oldversion) { upgrade_mod_savepoint(true, 2023112100, 'cms'); } + if ($oldversion < 2023120101) { + // Add adhoc task to update contextid in customfield records for 'cmsfield' type. + manager::queue_adhoc_task(new update_customfield_context()); + upgrade_mod_savepoint(true, 2023120101, 'cms'); + } + + if ($oldversion < 2023120102) { + $dbman = $DB->get_manager(); + // Update valuetrust if exists for mod_cms (both 'cmsfield' and 'cmsuserlist'). + if ($dbman->field_exists('customfield_data', 'valuetrust')) { + $sql = "SELECT mcd.id mcdid + FROM {customfield_data} mcd + JOIN {customfield_field} mcf ON mcf.id = mcd.fieldid + JOIN {customfield_category} mcc ON mcc.id = mcf.categoryid + WHERE mcc.component = 'mod_cms' AND mcd.valuetrust = 0"; + $records = $DB->get_records_sql($sql); + $mcdids = array_keys($records); + foreach (array_chunk($mcdids, 1000) as $ids) { + [$sql, $params] = $DB->get_in_or_equal($ids); + $sql = 'UPDATE {customfield_data} SET valuetrust = 1 WHERE id ' . $sql; + $DB->execute($sql, $params); + } + } + upgrade_mod_savepoint(true, 2023120102, 'cms'); + } + + if ($oldversion < 2023120103) { + // Update contextid in customfield records for 'cmsuserlist' type. + // {customfield_data}.instanceid" is from one of id from userlistinstanceids which is JSON encoded in {cms}.customdata. + // "userlistinstanceids" is a unique id for the customfield_data. + // New ID is from userlistmaxinstanceid which is JSON encoded in the {cms_types}.customdata" and add 1 to use. + $sql = "SELECT mc.id, mc.customdata, mcx.id contextid + FROM {cms} mc + JOIN {course_modules} mcm ON mc.id = mcm.instance AND mcm.module = ( + SELECT id FROM {modules} WHERE name = 'cms' + ) + JOIN {context} mcx ON mcx.instanceid = mcm.id AND mcx.contextlevel = " . CONTEXT_MODULE . " + WHERE mc.customdata LIKE '%userlistinstanceids%'"; + $cmsrecords = $DB->get_records_sql($sql); + + // Load userlist from customfield_data and set to array. + $userlist = []; + foreach ($cmsrecords as $cmsrecord) { + $customdata = json_decode($cmsrecord->customdata); + foreach ($customdata->userlistinstanceids as $instanceid) { + $userlist[$instanceid] = [ + 'id' => $cmsrecord->id, + 'contextid' => $cmsrecord->contextid, + ]; + } + } + + // Check cmsuserlist records and set correct contextid if it's different one. + $sql = "SELECT mcd.id, mcd.instanceid, mcd.contextid + FROM {customfield_data} mcd + JOIN {customfield_field} mcf ON mcf.id = mcd.fieldid + JOIN {customfield_category} mcc ON mcc.id = mcf.categoryid + WHERE mcc.component = 'mod_cms' AND mcc.area = 'cmsuserlist'"; + $cmsuserlistdata = $DB->get_records_sql($sql); + foreach ($cmsuserlistdata as $cmsuserlist) { + if (!empty($userlist[$cmsuserlist->instanceid])) { + if ($userlist[$cmsuserlist->instanceid]['contextid'] != $cmsuserlist->contextid) { + $DB->set_field('customfield_data', 'contextid', $userlist[$cmsuserlist->instanceid]['contextid'], + ['id' => $cmsuserlist->id]); + } + } + } + upgrade_mod_savepoint(true, 2023120103, 'cms'); + } + return true; } diff --git a/version.php b/version.php index 17c6f1b..74c78a9 100644 --- a/version.php +++ b/version.php @@ -25,7 +25,7 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2023120100; +$plugin->version = 2023120103; $plugin->requires = 2020061500; // Moodle 3.9.0 and above. $plugin->supported = [39, 401]; // Moodle 3.9 to 4.1 inclusive. $plugin->component = 'mod_cms';