. /** * Upgrade steps for mod_meetletacbmarketplace. * * @package mod_meetletacbmarketplace * @copyright 2026 MeetLet * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ defined('MOODLE_INTERNAL') || die(); /** * xmldb upgrade. * * @param int $oldversion * @return bool */ function xmldb_meetletacbmarketplace_upgrade($oldversion) { global $DB; $dbman = $DB->get_manager(); // Plugin table is 10 chars; never alter core {modules}/{event} (CHAR(20) is enough). xmldb_meetletacbmarketplace_rename_legacy_main_table($dbman); if ($oldversion < 2026080906) { foreach (['meetlet_meetings', 'meetlet_recordings'] as $tname) { if (!$dbman->table_exists($tname)) { continue; } $table = new xmldb_table($tname); $key = new xmldb_key('fk_instance', XMLDB_KEY_FOREIGN, ['instanceid'], 'meetlet', ['id']); if ($dbman->find_key_name($table, $key)) { $dbman->drop_key($table, $key); } } $map = [ 'meetlet' => 'meetletacbmarketplace', 'meetlet_meetings' => 'meetlet_marketplace_meetings', 'meetlet_recordings' => 'meetlet_marketplace_recordings', ]; foreach ($map as $from => $to) { $table = new xmldb_table($from); if ($dbman->table_exists($from) && !$dbman->table_exists($to)) { $dbman->rename_table($table, $to); } } foreach (['meetlet_marketplace_meetings', 'meetlet_marketplace_recordings'] as $tname) { if ($dbman->table_exists($tname) && $dbman->table_exists('meetletacbmarketplace')) { $table = new xmldb_table($tname); $key = new xmldb_key('fk_instance', XMLDB_KEY_FOREIGN, ['instanceid'], 'meetletacbmarketplace', ['id']); if (!$dbman->find_key_name($table, $key)) { $dbman->add_key($table, $key); } } } foreach (['meetlet', 'meetletacbmarketplace'] as $oldmodname) { if ($mod = $DB->get_record('modules', ['name' => $oldmodname])) { $mod->name = 'meetletacbmarketplace'; $DB->update_record('modules', $mod); } $DB->set_field('event', 'modulename', 'meetletacbmarketplace', ['modulename' => $oldmodname]); if ($dbman->table_exists('grade_items')) { $DB->set_field('grade_items', 'itemmodule', 'meetletacbmarketplace', ['itemmodule' => $oldmodname]); } } upgrade_mod_savepoint(true, 2026080906, 'meetletacbmarketplace'); } if ($oldversion < 2026080908) { $table = new xmldb_table('meetletacbmarketplace'); $fields = [ new xmldb_field('showzip', XMLDB_TYPE_INTEGER, '1', null, XMLDB_NOTNULL, null, '1', 'autooffline'), new xmldb_field('showofflineplayer', XMLDB_TYPE_INTEGER, '1', null, XMLDB_NOTNULL, null, '1', 'showzip'), new xmldb_field('showrecordingstab', XMLDB_TYPE_INTEGER, '1', null, XMLDB_NOTNULL, null, '1', 'showofflineplayer'), new xmldb_field('showcontenttab', XMLDB_TYPE_INTEGER, '1', null, XMLDB_NOTNULL, null, '1', 'showrecordingstab'), ]; foreach ($fields as $field) { if ($dbman->table_exists($table) && !$dbman->field_exists($table, $field)) { $dbman->add_field($table, $field); } } upgrade_mod_savepoint(true, 2026080908, 'meetletacbmarketplace'); } if ($oldversion < 2026080909) { $table = new xmldb_table('meetlet_adobe_connect_bridge'); if ($dbman->table_exists('meetlet_adobe_connect_bridge') && !$dbman->table_exists('meetletacbmarketplace')) { $dbman->rename_table($table, 'meetletacbmarketplace'); } // Re-point FKs on related tables if needed - drop old FK and add new foreach (['meetlet_marketplace_meetings', 'meetlet_marketplace_recordings'] as $tname) { if ($dbman->table_exists($tname) && $dbman->table_exists('meetletacbmarketplace')) { $t = new xmldb_table($tname); $oldkey = new xmldb_key('fk_instance', XMLDB_KEY_FOREIGN, ['instanceid'], 'meetlet_adobe_connect_bridge', ['id']); if ($dbman->find_key_name($t, $oldkey)) { $dbman->drop_key($t, $oldkey); } $newkey = new xmldb_key('fk_instance', XMLDB_KEY_FOREIGN, ['instanceid'], 'meetletacbmarketplace', ['id']); if (!$dbman->find_key_name($t, $newkey)) { $dbman->add_key($t, $newkey); } } } upgrade_mod_savepoint(true, 2026080909, 'meetletacbmarketplace'); } if ($oldversion < 2026080910) { $table = new xmldb_table('meetletacbmarketplace'); $field = new xmldb_field('showmp4', XMLDB_TYPE_INTEGER, '1', null, XMLDB_NOTNULL, null, '1', 'showcontenttab'); if ($dbman->table_exists($table) && !$dbman->field_exists($table, $field)) { $dbman->add_field($table, $field); } // Migrate legacy allow_manual_offline into enable_mp4 when unset. $enablemp4 = get_config('meetletacbmarketplace', 'enable_mp4'); if ($enablemp4 === false) { $legacy = get_config('meetletacbmarketplace', 'allow_manual_offline'); set_config('enable_mp4', ($legacy === false || (bool)$legacy) ? 1 : 0, 'meetletacbmarketplace'); } if (get_config('meetletacbmarketplace', 'allow_override_mp4') === false) { set_config('allow_override_mp4', 1, 'meetletacbmarketplace'); } upgrade_mod_savepoint(true, 2026080910, 'meetletacbmarketplace'); } if ($oldversion < 2026080911) { // ZIP download is opt-in from this release. set_config('enable_zip', 0, 'meetletacbmarketplace'); upgrade_mod_savepoint(true, 2026080911, 'meetletacbmarketplace'); } if ($oldversion < 2026080912) { // Remove Adobe offline player (pbMode) from product settings. set_config('enable_offlineplayer', 0, 'meetletacbmarketplace'); set_config('allow_override_offlineplayer', 0, 'meetletacbmarketplace'); upgrade_mod_savepoint(true, 2026080912, 'meetletacbmarketplace'); } if ($oldversion < 2026080913) { $table = new xmldb_table('meetletacbmarketplace'); $fields = [ new xmldb_field('linkmode', XMLDB_TYPE_INTEGER, '1', null, XMLDB_NOTNULL, null, '0', 'showmp4'), new xmldb_field('existingscoid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0', 'linkmode'), new xmldb_field('meetinglang', XMLDB_TYPE_CHAR, '20', null, null, null, null, 'existingscoid'), new xmldb_field('waitforhost', XMLDB_TYPE_INTEGER, '1', null, XMLDB_NOTNULL, null, '0', 'meetinglang'), ]; foreach ($fields as $field) { if ($dbman->table_exists($table) && !$dbman->field_exists($table, $field)) { $dbman->add_field($table, $field); } } upgrade_mod_savepoint(true, 2026080913, 'meetletacbmarketplace'); } if ($oldversion < 2026080914) { $table = new xmldb_table('meetletacbmarketplace'); $field = new xmldb_field('featureaccess', XMLDB_TYPE_TEXT, null, null, null, null, null, 'waitforhost'); if ($dbman->table_exists($table) && !$dbman->field_exists($table, $field)) { $dbman->add_field($table, $field); } if (get_config('meetletacbmarketplace', 'featureaccess') === false) { set_config( 'featureaccess', json_encode(\mod_meetletacbmarketplace\local\featureaccess::builtin_defaults(), JSON_UNESCAPED_UNICODE), 'meetletacbmarketplace' ); } upgrade_mod_savepoint(true, 2026080914, 'meetletacbmarketplace'); } if ($oldversion < 2026080915) { if (get_config('meetletacbmarketplace', 'activity_featureaccess') === false) { set_config('activity_featureaccess', 1, 'meetletacbmarketplace'); } // Ensure adobeeditor key exists in stored site matrix. $raw = get_config('meetletacbmarketplace', 'featureaccess'); if ($raw !== false && $raw !== '') { $decoded = json_decode($raw, true); if (is_array($decoded)) { $normalized = \mod_meetletacbmarketplace\local\featureaccess::normalize($decoded); set_config( 'featureaccess', json_encode($normalized, JSON_UNESCAPED_UNICODE), 'meetletacbmarketplace' ); } } upgrade_mod_savepoint(true, 2026080915, 'meetletacbmarketplace'); } if ($oldversion < 2026080916) { $raw = get_config('meetletacbmarketplace', 'featureaccess'); if ($raw !== false && $raw !== '') { $decoded = json_decode($raw, true); if (is_array($decoded)) { set_config( 'featureaccess', json_encode( \mod_meetletacbmarketplace\local\featureaccess::normalize($decoded), JSON_UNESCAPED_UNICODE ), 'meetletacbmarketplace' ); } } upgrade_mod_savepoint(true, 2026080916, 'meetletacbmarketplace'); } if ($oldversion < 2026080917) { upgrade_mod_savepoint(true, 2026080917, 'meetletacbmarketplace'); } if ($oldversion < 2026080918) { upgrade_mod_savepoint(true, 2026080918, 'meetletacbmarketplace'); } if ($oldversion < 2026080919) { upgrade_mod_savepoint(true, 2026080919, 'meetletacbmarketplace'); } if ($oldversion < 2026080920) { upgrade_mod_savepoint(true, 2026080920, 'meetletacbmarketplace'); } if ($oldversion < 2026080921) { // Expand stored matrix to include every Moodle role. $raw = get_config('meetletacbmarketplace', 'featureaccess'); if ($raw !== false && $raw !== null && $raw !== '') { $decoded = json_decode((string)$raw, true); if (is_array($decoded)) { set_config( 'featureaccess', json_encode( \mod_meetletacbmarketplace\local\featureaccess::normalize($decoded), JSON_UNESCAPED_UNICODE ), 'meetletacbmarketplace' ); } } else { set_config( 'featureaccess', json_encode( \mod_meetletacbmarketplace\local\featureaccess::builtin_defaults(), JSON_UNESCAPED_UNICODE ), 'meetletacbmarketplace' ); } upgrade_mod_savepoint(true, 2026080921, 'meetletacbmarketplace'); } if ($oldversion < 2026080922) { // Apply sensible defaults to blank role rows (e.g. newly listed custom roles). $raw = get_config('meetletacbmarketplace', 'featureaccess'); $decoded = []; if ($raw !== false && $raw !== null && $raw !== '') { $tmp = json_decode((string)$raw, true); if (is_array($tmp)) { $decoded = $tmp; } } set_config( 'featureaccess', json_encode( \mod_meetletacbmarketplace\local\featureaccess::normalize_fill_blank_roles($decoded), JSON_UNESCAPED_UNICODE ), 'meetletacbmarketplace' ); upgrade_mod_savepoint(true, 2026080922, 'meetletacbmarketplace'); } if ($oldversion < 2026080923) { upgrade_mod_savepoint(true, 2026080923, 'meetletacbmarketplace'); } if ($oldversion < 2026080924) { upgrade_mod_savepoint(true, 2026080924, 'meetletacbmarketplace'); } if ($oldversion < 2026080925) { // Site ZIP was enabled while activities kept showzip=0 (form default), which hid links. if ((bool)get_config('meetletacbmarketplace', 'enable_zip')) { $DB->set_field('meetletacbmarketplace', 'showzip', 1); } upgrade_mod_savepoint(true, 2026080925, 'meetletacbmarketplace'); } if ($oldversion < 2026080926) { upgrade_mod_savepoint(true, 2026080926, 'meetletacbmarketplace'); } if ($oldversion < 2026081110) { $table = new xmldb_table('meetlet_marketplace_license'); if (!$dbman->table_exists($table)) { $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE); $table->add_field('installation_id', XMLDB_TYPE_CHAR, '128', null, XMLDB_NOTNULL); $table->add_field('private_key_pem', XMLDB_TYPE_TEXT, null, null, XMLDB_NOTNULL); $table->add_field('public_key_pem', XMLDB_TYPE_TEXT, null, null, XMLDB_NOTNULL); $table->add_field('auth_json', XMLDB_TYPE_TEXT, null, null, null); $table->add_field('license_uuid', XMLDB_TYPE_CHAR, '64', null, null); $table->add_field('status', XMLDB_TYPE_CHAR, '32', null, XMLDB_NOTNULL, null, 'inactive'); $table->add_field('last_error', XMLDB_TYPE_TEXT, null, null, null); $table->add_field('last_validated', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0'); $table->add_field('timecreated', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0'); $table->add_field('timemodified', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0'); $table->add_key('primary', XMLDB_KEY_PRIMARY, ['id']); $table->add_index('installation_uniq', XMLDB_INDEX_UNIQUE, ['installation_id']); $dbman->create_table($table); } upgrade_mod_savepoint(true, 2026081110, 'meetletacbmarketplace'); } if ($oldversion < 2026081120) { $table = new xmldb_table('meetlet_marketplace_recordings'); $field = new xmldb_field('agentjobid', XMLDB_TYPE_CHAR, '64', null, null, null, null, 'jobstatus'); if (!$dbman->field_exists($table, $field)) { $dbman->add_field($table, $field); } upgrade_mod_savepoint(true, 2026081120, 'meetletacbmarketplace'); } if ($oldversion < 2026081305) { // Offline MP4 / Render Agent is opt-in. Preserve existing agent_url sites. $enabled = get_config('meetletacbmarketplace', 'offline_render_enabled'); if ($enabled === false) { $agenturl = trim((string)get_config('meetletacbmarketplace', 'agent_url')); set_config( 'offline_render_enabled', $agenturl !== '' ? 1 : 0, 'meetletacbmarketplace' ); } upgrade_mod_savepoint(true, 2026081305, 'meetletacbmarketplace'); } if ($oldversion < 2026081401) { unset_config('offline_render_enabled', 'meetletacbmarketplace'); upgrade_mod_savepoint(true, 2026081401, 'meetletacbmarketplace'); } if ($oldversion < 2026081402) { upgrade_mod_savepoint(true, 2026081402, 'meetletacbmarketplace'); } if ($oldversion < 2026081410) { $table = new xmldb_table('meetletacbmarketplace'); $field = new xmldb_field('showmakeoffline', XMLDB_TYPE_INTEGER, '1', null, XMLDB_NOTNULL, null, '1', 'showmp4'); if ($dbman->table_exists($table) && !$dbman->field_exists($table, $field)) { $dbman->add_field($table, $field); } if (get_config('meetletacbmarketplace', 'enable_makeoffline') === false) { set_config('enable_makeoffline', 1, 'meetletacbmarketplace'); } if (get_config('meetletacbmarketplace', 'allow_override_makeoffline') === false) { set_config('allow_override_makeoffline', 1, 'meetletacbmarketplace'); } $raw = get_config('meetletacbmarketplace', 'featureaccess'); $decoded = []; if ($raw !== false && $raw !== null && $raw !== '') { $tmp = json_decode((string)$raw, true); if (is_array($tmp)) { $decoded = $tmp; } } set_config( 'featureaccess', json_encode( \mod_meetletacbmarketplace\local\featureaccess::copy_missing_feature_from( $decoded, 'mp4', 'makeoffline' ), JSON_UNESCAPED_UNICODE ), 'meetletacbmarketplace' ); $activities = $dbman->table_exists('meetletacbmarketplace') ? $DB->get_records_select('meetletacbmarketplace', 'featureaccess IS NOT NULL AND featureaccess <> \'\'') : []; foreach ($activities as $activity) { $matrix = json_decode((string)$activity->featureaccess, true); if (!is_array($matrix)) { continue; } $updated = \mod_meetletacbmarketplace\local\featureaccess::copy_missing_feature_from( $matrix, 'mp4', 'makeoffline' ); $DB->set_field( 'meetletacbmarketplace', 'featureaccess', json_encode($updated, JSON_UNESCAPED_UNICODE), ['id' => $activity->id] ); } upgrade_mod_savepoint(true, 2026081410, 'meetletacbmarketplace'); } if ($oldversion < 2026081411) { xmldb_meetletacbmarketplace_rename_legacy_main_table($dbman); foreach (['meetletadobeconnectbridge', 'meetlet_adobe_connect_bridge', 'meetlet'] as $oldmodname) { if ($mod = $DB->get_record('modules', ['name' => $oldmodname])) { $mod->name = 'meetletacbmarketplace'; $DB->update_record('modules', $mod); } if ($dbman->table_exists('event')) { $DB->set_field('event', 'modulename', 'meetletacbmarketplace', ['modulename' => $oldmodname]); } if ($dbman->table_exists('grade_items')) { $DB->set_field('grade_items', 'itemmodule', 'meetletacbmarketplace', ['itemmodule' => $oldmodname]); } } upgrade_mod_savepoint(true, 2026081411, 'meetletacbmarketplace'); } if ($oldversion < 2026081702) { upgrade_mod_savepoint(true, 2026081702, 'meetletacbmarketplace'); } if ($oldversion < 2026081703) { upgrade_mod_savepoint(true, 2026081703, 'meetletacbmarketplace'); } if ($oldversion < 2026081704) { upgrade_mod_savepoint(true, 2026081704, 'meetletacbmarketplace'); } if ($oldversion < 2026081800) { $table = new xmldb_table('meetlet_marketplace_meetings'); $fields = [ new xmldb_field('islive', XMLDB_TYPE_INTEGER, '1', null, XMLDB_NOTNULL, null, '0', 'urlpath'), new xmldb_field('liveat', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0', 'islive'), new xmldb_field('closedat', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0', 'liveat'), new xmldb_field('sweepuntil', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0', 'closedat'), new xmldb_field('sweptat', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0', 'sweepuntil'), ]; foreach ($fields as $field) { if ($dbman->table_exists($table) && !$dbman->field_exists($table, $field)) { $dbman->add_field($table, $field); } } if (get_config('meetletacbmarketplace', 'cron_interval') === false) { set_config('cron_interval', 5, 'meetletacbmarketplace'); } \mod_meetletacbmarketplace\local\config::apply_cron_interval(); upgrade_mod_savepoint(true, 2026081800, 'meetletacbmarketplace'); } if ($oldversion < 2026081901) { $table = new xmldb_table('meetlet_marketplace_recordings'); $field = new xmldb_field('jobmessage', XMLDB_TYPE_CHAR, '255', null, null, null, null, 'jobstatus'); if ($dbman->table_exists($table) && !$dbman->field_exists($table, $field)) { $dbman->add_field($table, $field); } upgrade_mod_savepoint(true, 2026081901, 'meetletacbmarketplace'); } if ($oldversion < 2026081902) { upgrade_mod_savepoint(true, 2026081902, 'meetletacbmarketplace'); } if ($oldversion < 2026081903) { $table = new xmldb_table('meetlet_marketplace_jobqueue'); if (!$dbman->table_exists($table)) { $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE); $table->add_field('instanceid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0'); $table->add_field('recordingscoid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0'); $table->add_field('groupid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0'); $table->add_field('status', XMLDB_TYPE_CHAR, '20', null, XMLDB_NOTNULL, null, 'pending'); $table->add_field('attempts', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0'); $table->add_field('lasterror', XMLDB_TYPE_CHAR, '255', null, null, null, null); $table->add_field('timesent', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0'); $table->add_field('timecreated', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0'); $table->add_field('timemodified', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0'); $table->add_key('primary', XMLDB_KEY_PRIMARY, ['id']); $table->add_index('instance_sco', XMLDB_INDEX_UNIQUE, ['instanceid', 'recordingscoid']); $table->add_index('status_idx', XMLDB_INDEX_NOTUNIQUE, ['status']); $dbman->create_table($table); } if (get_config('meetletacbmarketplace', 'agent_dispatch') === false) { set_config('agent_dispatch', 'immediate', 'meetletacbmarketplace'); } if (get_config('meetletacbmarketplace', 'agent_dispatch_hours') === false) { set_config('agent_dispatch_hours', '22,23,0,1,2,3,4,5', 'meetletacbmarketplace'); } upgrade_mod_savepoint(true, 2026081903, 'meetletacbmarketplace'); } if ($oldversion < 2026081904) { upgrade_mod_savepoint(true, 2026081904, 'meetletacbmarketplace'); } if ($oldversion < 2026081905) { upgrade_mod_savepoint(true, 2026081905, 'meetletacbmarketplace'); } if ($oldversion < 2026081906) { upgrade_mod_savepoint(true, 2026081906, 'meetletacbmarketplace'); } if ($oldversion < 2026081912) { $table = new xmldb_table('meetletacbmarketplace'); $fields = [ new xmldb_field('settingoverrides', XMLDB_TYPE_TEXT, null, null, null, null, null, 'featureaccess'), new xmldb_field('participantsmode', XMLDB_TYPE_INTEGER, '1', null, XMLDB_NOTNULL, null, '0', 'settingoverrides'), ]; foreach ($fields as $field) { if ($dbman->table_exists($table) && !$dbman->field_exists($table, $field)) { $dbman->add_field($table, $field); } } if ($dbman->table_exists($table)) { $activities = $DB->get_records('meetletacbmarketplace'); foreach ($activities as $activity) { $overrides = []; foreach ([ 'waitforhost', 'autooffline', 'showzip', 'showrecordingstab', 'showcontenttab', 'showmp4', 'showmakeoffline', ] as $field) { $overrides[$field] = !empty($activity->{$field}) ? \mod_meetletacbmarketplace\local\config::OVERRIDE_ON : \mod_meetletacbmarketplace\local\config::OVERRIDE_OFF; } $update = (object)[ 'id' => $activity->id, 'settingoverrides' => \mod_meetletacbmarketplace\local\config::setting_overrides_json($overrides), 'participantsmode' => 1, ]; $DB->update_record('meetletacbmarketplace', $update); } } upgrade_mod_savepoint(true, 2026081912, 'meetletacbmarketplace'); } // 1.5.45 — MP4 import download_one fix + agent-gone reconciliation (no schema). if ($oldversion < 2026082127) { upgrade_mod_savepoint(true, 2026082127, 'meetletacbmarketplace'); } // 1.5.50 — Agent download without forced Import + Delete from Moodle (no schema). if ($oldversion < 2026082132) { upgrade_mod_savepoint(true, 2026082132, 'meetletacbmarketplace'); } // 1.5.51 — Dual Moodle/Agent MP4 download buttons + source tooltips (no schema). if ($oldversion < 2026082133) { upgrade_mod_savepoint(true, 2026082133, 'meetletacbmarketplace'); } // 1.5.54 — Agent MP4 proxy: send_temp_file path fix + stored ftyp validation (no schema). if ($oldversion < 2026082236) { upgrade_mod_savepoint(true, 2026082236, 'meetletacbmarketplace'); } // 1.5.63 — Content download via Moodle SSO proxy + content view launch URL (no schema). if ($oldversion < 2026082245) { upgrade_mod_savepoint(true, 2026082245, 'meetletacbmarketplace'); } // 1.5.66 — Content download button loading state (no schema). if ($oldversion < 2026082248) { upgrade_mod_savepoint(true, 2026082248, 'meetletacbmarketplace'); } // 1.5.68 — Free license: recordings view/edit; MP4 Premium-only (no schema). if ($oldversion < 2026082250) { upgrade_mod_savepoint(true, 2026082250, 'meetletacbmarketplace'); } // 1.0.1-marketplace — rename component from mod_meetletacbmdlrules. if ($oldversion < 2026090122) { xmldb_meetletacbmarketplace_migrate_from_mdlrules($dbman); upgrade_mod_savepoint(true, 2026090122, 'meetletacbmarketplace'); } // 1.0.1-marketplace — UI cleanup, role defaults, lang prune. if ($oldversion < 2026090123) { upgrade_mod_savepoint(true, 2026090123, 'meetletacbmarketplace'); } // 1.0.1-marketplace — plugin display titles (fa/en). if ($oldversion < 2026090124) { upgrade_mod_savepoint(true, 2026090124, 'meetletacbmarketplace'); } // 1.0.1-marketplace — dedupe modules row after component rename. if ($oldversion < 2026090125) { $marketmods = $DB->get_records('modules', ['name' => 'meetletacbmarketplace'], 'id ASC'); if (count($marketmods) > 1) { array_shift($marketmods); foreach ($marketmods as $dup) { $DB->delete_records('modules', ['id' => $dup->id]); } } upgrade_mod_savepoint(true, 2026090125, 'meetletacbmarketplace'); } // 1.0.1-marketplace — MeetLet logo + visit website button on About tab (no schema). if ($oldversion < 2026090127) { upgrade_mod_savepoint(true, 2026090127, 'meetletacbmarketplace'); } // 1.0.2-marketplace — optional transparent site registration tab + daily heartbeat. if ($oldversion < 2026090128) { $table = new xmldb_table('meetlet_marketplace_license'); if (!$dbman->table_exists($table)) { $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE); $table->add_field('installation_id', XMLDB_TYPE_CHAR, '128', null, XMLDB_NOTNULL); $table->add_field('private_key_pem', XMLDB_TYPE_TEXT, null, null, XMLDB_NOTNULL); $table->add_field('public_key_pem', XMLDB_TYPE_TEXT, null, null, XMLDB_NOTNULL); $table->add_field('auth_json', XMLDB_TYPE_TEXT, null, null, null); $table->add_field('license_uuid', XMLDB_TYPE_CHAR, '64', null, null); $table->add_field('status', XMLDB_TYPE_CHAR, '32', null, XMLDB_NOTNULL, null, 'inactive'); $table->add_field('last_error', XMLDB_TYPE_TEXT, null, null, null); $table->add_field('last_validated', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0'); $table->add_field('timecreated', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0'); $table->add_field('timemodified', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0'); $table->add_key('primary', XMLDB_KEY_PRIMARY, ['id']); $table->add_index('installation_uniq', XMLDB_INDEX_UNIQUE, ['installation_id']); $dbman->create_table($table); } upgrade_mod_savepoint(true, 2026090128, 'meetletacbmarketplace'); } if ($oldversion < 2026090129) { upgrade_mod_savepoint(true, 2026090129, 'meetletacbmarketplace'); } if ($oldversion < 2026090130) { upgrade_mod_savepoint(true, 2026090130, 'meetletacbmarketplace'); } if ($oldversion < 2026090131) { upgrade_mod_savepoint(true, 2026090131, 'meetletacbmarketplace'); } // 1.0.3-marketplace — optional registration: remove feature gating (no schema). if ($oldversion < 2026090132) { upgrade_mod_savepoint(true, 2026090132, 'meetletacbmarketplace'); } // 1.0.3-marketplace — hide locked settings tabs until online activation (no schema). if ($oldversion < 2026090134) { upgrade_mod_savepoint(true, 2026090134, 'meetletacbmarketplace'); } // 1.0.4-marketplace — activity icon badge to distinguish from commercial meetletacb (no schema). if ($oldversion < 2026090135) { upgrade_mod_savepoint(true, 2026090135, 'meetletacbmarketplace'); } // 1.0.4-marketplace — in-plugin Privacy admin tab; remove external policy link (no schema). if ($oldversion < 2026090136) { upgrade_mod_savepoint(true, 2026090136, 'meetletacbmarketplace'); } // 1.0.4-marketplace — Privacy tab visible before online activation (no schema). if ($oldversion < 2026090137) { upgrade_mod_savepoint(true, 2026090137, 'meetletacbmarketplace'); } // 1.0.4-marketplace — fix privacy tab deep-link; enlarge activity icon M badge (no schema). if ($oldversion < 2026090138) { upgrade_mod_savepoint(true, 2026090138, 'meetletacbmarketplace'); } // 1.0.4-marketplace — privacy tab copy fixes (no schema). if ($oldversion < 2026090139) { upgrade_mod_savepoint(true, 2026090139, 'meetletacbmarketplace'); } // 1.0.4-marketplace — remove vague local-data privacy paragraph (no schema). if ($oldversion < 2026090140) { upgrade_mod_savepoint(true, 2026090140, 'meetletacbmarketplace'); } // 1.0.4-marketplace — privacy tab deep-link uses hash anchor (no schema). if ($oldversion < 2026090141) { upgrade_mod_savepoint(true, 2026090141, 'meetletacbmarketplace'); } // 1.0.5-marketplace — hide activity chooser until online registration (no schema). if ($oldversion < 2026090143) { upgrade_mod_savepoint(true, 2026090143, 'meetletacbmarketplace'); } // 1.0.6-marketplace — registration confirm modal UI (no schema). if ($oldversion < 2026090145) { upgrade_mod_savepoint(true, 2026090145, 'meetletacbmarketplace'); } // 1.0.6-marketplace — plugin activation terminology (no schema). if ($oldversion < 2026090146) { upgrade_mod_savepoint(true, 2026090146, 'meetletacbmarketplace'); } // 1.0.6-marketplace — server guide: no live credentials in admin UI (no schema). if ($oldversion < 2026090147) { upgrade_mod_savepoint(true, 2026090147, 'meetletacbmarketplace'); } if ($oldversion < 2026090148) { upgrade_mod_savepoint(true, 2026090148, 'meetletacbmarketplace'); } return true; } /** * Migrate legacy meetletacbmdlrules / meetlet_mdlrules_* tables and config. * * @param \database_manager $dbman * @return void */ function xmldb_meetletacbmarketplace_migrate_from_mdlrules($dbman): void { global $DB; $legacymain = new xmldb_table('meetletacbmdlrules'); $newmain = new xmldb_table('meetletacbmarketplace'); if ($dbman->table_exists($legacymain)) { if ($dbman->table_exists($newmain)) { $dbman->drop_table($newmain); } $dbman->rename_table($legacymain, 'meetletacbmarketplace'); } $tablemap = [ 'meetlet_mdlrules_meetings' => 'meetlet_marketplace_meetings', 'meetlet_mdlrules_recordings' => 'meetlet_marketplace_recordings', ]; foreach ($tablemap as $from => $to) { $fromtable = new xmldb_table($from); $totable = new xmldb_table($to); if ($dbman->table_exists($fromtable)) { if ($dbman->table_exists($totable)) { $dbman->drop_table($totable); } $dbman->rename_table($fromtable, $to); } } if ($dbman->table_exists('meetletacbmarketplace')) { foreach (['meetlet_marketplace_meetings', 'meetlet_marketplace_recordings'] as $tname) { if (!$dbman->table_exists($tname)) { continue; } $t = new xmldb_table($tname); $oldkeys = [ new xmldb_key('fk_instance', XMLDB_KEY_FOREIGN, ['instanceid'], 'meetletacbmdlrules', ['id']), new xmldb_key('fk_instance', XMLDB_KEY_FOREIGN, ['instanceid'], 'meetletadobeconnectbridge', ['id']), ]; foreach ($oldkeys as $oldkey) { if ($dbman->find_key_name($t, $oldkey)) { $dbman->drop_key($t, $oldkey); } } $newkey = new xmldb_key('fk_instance', XMLDB_KEY_FOREIGN, ['instanceid'], 'meetletacbmarketplace', ['id']); if (!$dbman->find_key_name($t, $newkey)) { $dbman->add_key($t, $newkey); } } } if ($mod = $DB->get_record('modules', ['name' => 'meetletacbmdlrules'])) { $mod->name = 'meetletacbmarketplace'; $DB->update_record('modules', $mod); } $marketmods = $DB->get_records('modules', ['name' => 'meetletacbmarketplace'], 'id ASC'); if (count($marketmods) > 1) { $keep = array_shift($marketmods); foreach ($marketmods as $dup) { $DB->delete_records('modules', ['id' => $dup->id]); } } else if (empty($marketmods) && !$DB->record_exists('modules', ['name' => 'meetletacbmarketplace'])) { $mod = (object)['name' => 'meetletacbmarketplace', 'cron' => 0, 'visible' => 1]; $DB->insert_record('modules', $mod); } foreach (['meetletacbmdlrules', 'meetletadobeconnectbridge', 'meetlet'] as $oldmodname) { if ($dbman->table_exists('event')) { $DB->set_field('event', 'modulename', 'meetletacbmarketplace', ['modulename' => $oldmodname]); } if ($dbman->table_exists('grade_items')) { $DB->set_field('grade_items', 'itemmodule', 'meetletacbmarketplace', ['itemmodule' => $oldmodname]); } if ($dbman->table_exists('course_modules')) { $DB->execute( "UPDATE {course_modules} SET module = ( SELECT id FROM {modules} WHERE name = 'meetletacbmarketplace' ) WHERE module = ( SELECT id FROM {modules} WHERE name = ? )", [$oldmodname] ); } } $configs = $DB->get_records('config_plugins', ['plugin' => 'meetletacbmdlrules']); foreach ($configs as $cfg) { if ($DB->record_exists('config_plugins', ['plugin' => 'meetletacbmarketplace', 'name' => $cfg->name])) { continue; } $cfg->plugin = 'meetletacbmarketplace'; $DB->insert_record('config_plugins', $cfg); } $DB->delete_records('config_plugins', ['plugin' => 'meetletacbmdlrules']); } /** * Rename pre-Marketplace main table via XMLDB (MySQL and PostgreSQL). * * @param \database_manager $dbman * @return void */ function xmldb_meetletacbmarketplace_rename_legacy_main_table($dbman): void { foreach (['meetlet_marketplace_meetings', 'meetlet_marketplace_recordings'] as $tname) { if (!$dbman->table_exists($tname)) { continue; } $t = new xmldb_table($tname); $oldkey = new xmldb_key('fk_instance', XMLDB_KEY_FOREIGN, ['instanceid'], 'meetletadobeconnectbridge', ['id']); if ($dbman->find_key_name($t, $oldkey)) { $dbman->drop_key($t, $oldkey); } } $oldtable = new xmldb_table('meetletadobeconnectbridge'); if ($dbman->table_exists('meetletadobeconnectbridge') && !$dbman->table_exists('meetletacbmarketplace')) { $dbman->rename_table($oldtable, 'meetletacbmarketplace'); } foreach (['meetlet_marketplace_meetings', 'meetlet_marketplace_recordings'] as $tname) { if (!$dbman->table_exists($tname) || !$dbman->table_exists('meetletacbmarketplace')) { continue; } $t = new xmldb_table($tname); $newkey = new xmldb_key('fk_instance', XMLDB_KEY_FOREIGN, ['instanceid'], 'meetletacbmarketplace', ['id']); if (!$dbman->find_key_name($t, $newkey)) { $dbman->add_key($t, $newkey); } } }