function xmldb_block_taskchain_navigation_upgrade($oldversion = 0) { global $CFG, $DB; $result = true; $newversion = 2014051601; if ($oldversion < $newversion) { update_capabilities('block/taskchain_navigation'); upgrade_block_savepoint($result, "{$newversion}", 'taskchain_navigation'); } return $result; }
/** * ELIS(TM): Enterprise Learning Intelligence Suite * Copyright (C) 2008-2013 Remote-Learner.net Inc (http://www.remote-learner.net) * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. * * @package local_elisprogram * @author Remote-Learner.net Inc * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later * @copyright (C) 2008-2013 Remote Learner.net Inc http://www.remote-learner.net * */ function xmldb_local_elisprogram_install() { global $CFG, $DB; $elisadminblockinstalled = file_exists($CFG->dirroot . '/local/elisprogram/lib/setup.php') && $DB->record_exists('block', array('name' => 'elisadmin')); if ($elisadminblockinstalled) { require_once $CFG->dirroot . '/blocks/elisadmin/lib.php'; } require_once $CFG->dirroot . '/local/elisprogram/lib/lib.php'; // Install custom context levels. \local_eliscore\context\helper::set_custom_levels(\local_elisprogram\context\contextinfo::get_contextinfo()); \local_eliscore\context\helper::install_custom_levels(); // Initialize custom context levels. context_helper::reset_levels(); \local_eliscore\context\helper::reset_levels(); \local_eliscore\context\helper::init_levels(); // Migrate component. $migrator = new \local_elisprogram\install\migration\elis26(); if ($migrator->old_component_installed() === true) { $migrator->migrate(); } //make sure the site has exactly one curr admin block instance //that is viewable everywhere if ($elisadminblockinstalled) { block_elisadmin_create_instance(); } // make sure that the manager role can be assigned to all PM context levels update_capabilities('local_elisprogram'); // load context levels pm_ensure_role_assignable('manager'); pm_ensure_role_assignable('curriculumadmin'); // Migrate dataroot files pm_migrate_certificate_files(); // These notifications are default-on. pm_set_config('notify_addedtowaitlist_user', 1); pm_set_config('notify_enroledfromwaitlist_user', 1); pm_set_config('notify_incompletecourse_user', 1); // Ensure ELIS scheduled tasks is initialized. require_once $CFG->dirroot . '/local/eliscore/lib/tasklib.php'; elis_tasks_update_definition('local_elisprogram'); // Remove some lingering subplugins that were renamed unset_all_config_for_plugin('usersetenrol_manual'); unset_all_config_for_plugin('usersetenrol_moodle_profile'); }
function xmldb_enrol_category_install() { global $CFG, $DB; if (!$DB->record_exists_select('role_assignments', "contextid IN (SELECT id FROM {context} WHERE contextlevel = ?)", array(CONTEXT_COURSECAT))) { // fresh install or nobody used category enrol return; } // existing sites need a way to keep category role enrols, but we do not want to encourage that on new sites // extremely ugly hack, the sync depends on the capabilities so we unfortunately force update of caps here // note: this is not officially supported and should not be copied elsewhere! :-( update_capabilities('enrol_category'); $syscontext = get_context_instance(CONTEXT_SYSTEM); $archetypes = array('student', 'teacher', 'editingteacher'); $enableplugin = false; foreach ($archetypes as $archetype) { $roles = get_archetype_roles($archetype); foreach ($roles as $role) { if (!$DB->record_exists_select('role_assignments', "roleid = ? AND contextid IN (SELECT id FROM {context} WHERE contextlevel = ?)", array($role->id, CONTEXT_COURSECAT))) { continue; } assign_capability('enrol/category:synchronised', CAP_ALLOW, $role->id, $syscontext->id, true); $levels = get_role_contextlevels($role->id); $levels[] = CONTEXT_COURSECAT; set_role_contextlevels($role->id, $levels); $enableplugin = true; } } if (!$enableplugin) { return; } // enable this plugin $enabledplugins = explode(',', $CFG->enrol_plugins_enabled); $enabledplugins[] = 'category'; $enabledplugins = array_unique($enabledplugins); set_config('enrol_plugins_enabled', implode(',', $enabledplugins)); // brute force course resync, this may take a while require_once "{$CFG->dirroot}/enrol/category/locallib.php"; enrol_category_sync_full(); }
$status = main_upgrade($CFG->version); } /// If succesful and exists launch the new main upgrade (XMLDB), called xmldb_main_upgrade if ($status && function_exists('xmldb_main_upgrade')) { $status = xmldb_main_upgrade($CFG->version); } $db->debug = false; /// If successful, continue upgrading roles and setting everything properly if ($status) { if (empty($CFG->rolesactive)) { /// Groups upgrade is now in core above. // Upgrade to the roles system. moodle_install_roles(); set_config('rolesactive', 1); } else { if (!update_capabilities()) { error('Had trouble upgrading the core capabilities for the Roles System'); } } // update core events events_update_definition(); require_once $CFG->libdir . '/statslib.php'; if (!stats_upgrade_for_roles_wrapper()) { notify('Couldn\'t upgrade the stats tables to use the new roles system'); } if (set_config("version", $version)) { remove_dir($CFG->dataroot . '/cache', true); // flush cache notify($strdatabasesuccess, "green"); print_continue("upgradesettings.php"); print_footer('none');
/** * Upgrade moodle core * @param float $version target version * @param bool $verbose * @return void, may throw exception */ function upgrade_core($version, $verbose) { global $CFG; raise_memory_limit(MEMORY_EXTRA); require_once($CFG->libdir.'/db/upgrade.php'); // Defines upgrades try { // Reset caches before any output purge_all_caches(); // Upgrade current language pack if we can upgrade_language_pack(); print_upgrade_part_start('moodle', false, $verbose); // one time special local migration pre 2.0 upgrade script if ($CFG->version < 2007101600) { $pre20upgradefile = "$CFG->dirroot/local/upgrade_pre20.php"; if (file_exists($pre20upgradefile)) { set_time_limit(0); require($pre20upgradefile); // reset upgrade timeout to default upgrade_set_timeout(); } } $result = xmldb_main_upgrade($CFG->version); if ($version > $CFG->version) { // store version if not already there upgrade_main_savepoint($result, $version, false); } // perform all other component upgrade routines update_capabilities('moodle'); log_update_descriptions('moodle'); external_update_descriptions('moodle'); events_update_definition('moodle'); message_update_providers('moodle'); // Reset caches again, just to be sure purge_all_caches(); // Clean up contexts - more and more stuff depends on existence of paths and contexts context_helper::cleanup_instances(); context_helper::create_instances(null, false); context_helper::build_all_paths(false); $syscontext = context_system::instance(); $syscontext->mark_dirty(); print_upgrade_part_end('moodle', false, $verbose); } catch (Exception $ex) { upgrade_handle_exception($ex); } }
/** * This function checks to see whether local database customisations are up-to-date * by comparing $CFG->local_version to the variable $local_version defined in * local/version.php. If not, it looks for a function called 'xmldb_local_upgrade' * in a file called 'local/db/upgrade.php', and if it's there calls it with the * appropiate $oldversion parameter. Then it updates $CFG->local_version. * On success it prints a continue link. On failure it prints an error. * * @uses $CFG * @uses $db to do something really evil with the debug setting that should probably be eliminated. TODO! * @param string $continueto a URL passed to print_continue() if the local upgrades succeed. */ function upgrade_local_dbs($continueto) { global $CFG, $db; $path = '/local'; $pat = 'local'; $status = true; $changed = false; $firstloop = true; while (is_dir($CFG->dirroot . $path)) { // if we don't have code version or a db upgrade file, check lower if (!file_exists($CFG->dirroot . "{$path}/version.php") || !file_exists($CFG->dirroot . "{$path}/db/upgrade.php")) { $path .= '/local'; $pat .= 'local'; continue; } require_once $CFG->dirroot . "{$path}/version.php"; // Get code versions $cfgvarname = "{$pat}_version"; if (empty($CFG->{$cfgvarname})) { // normally we'd install, but just replay all the upgrades. $CFG->{$cfgvarname} = 0; } $localversionvar = "{$pat}_version"; // echo "($localversionvar) ".$$localversionvar." > ($cfgvarname) ".$CFG->{$cfgvarname}."<br/>"; if (${$localversionvar} > $CFG->{$cfgvarname}) { // something upgrades! upgrade_log_start(); /// Capabilities /// do this first *instead of* last , so that the installer has the chance to locally assign caps if (!update_capabilities($pat)) { error('Could not set up the capabilities for ' . $pat . '!'); } if ($firstloop) { $strdatabaseupgrades = get_string('databaseupgrades'); print_header($strdatabaseupgrades, $strdatabaseupgrades, build_navigation(array(array('name' => $strdatabaseupgrades, 'link' => null, 'type' => 'misc'))), '', upgrade_get_javascript()); $firstloop = false; } $changed = true; require_once $CFG->dirroot . "{$path}/db/upgrade.php"; $db->debug = true; $upgradefunc = "xmldb_{$pat}_upgrade"; if ($upgradefunc($CFG->{$cfgvarname})) { $db->debug = false; if (set_config($localversionvar, ${$localversionvar})) { notify(get_string('databasesuccess'), 'notifysuccess'); notify(get_string('databaseupgradelocal', '', $path . ' >> ' . ${$localversionvar}), 'notifysuccess'); } else { $status = false; error('Upgrade of local database customisations failed in $path! (Could not update version in config table)'); } } else { $db->debug = false; error("Upgrade failed! See {$path}/version.php"); } if (!events_update_definition($pat)) { error('Could not set up the events definitions for ' . $pat . '!'); } upgrade_log_finish(); } else { if (${$localversionvar} < $CFG->{$cfgvarname}) { notify("WARNING!!! The local version you are using in {$path} is OLDER than the version that made these databases!"); } } $path .= '/local'; $pat .= 'local'; } if ($changed) { print_continue($continueto); print_footer('none'); exit; } }
function upgrade_blocks_plugins($continueto) { global $CFG, $db; $blocktitles = array(); $invalidblocks = array(); $validblocks = array(); $notices = array(); //Count the number of blocks in db $blockcount = count_records('block'); //If there isn't records. This is the first install, so I remember it if ($blockcount == 0) { $first_install = true; } else { $first_install = false; } $site = get_site(); if (!($blocks = get_list_of_plugins('blocks', 'db'))) { error('No blocks installed!'); } include_once $CFG->dirroot . '/blocks/moodleblock.class.php'; if (!class_exists('block_base')) { error('Class block_base is not defined or file not found for /blocks/moodleblock.class.php'); } foreach ($blocks as $blockname) { if ($blockname == 'NEWBLOCK') { // Someone has unzipped the template, ignore it continue; } if (!block_is_compatible($blockname)) { // This is an old-style block //$notices[] = 'Block '. $blockname .' is not compatible with the current version of Mooodle and needs to be updated by a programmer.'; $invalidblocks[] = $blockname; continue; } $fullblock = $CFG->dirroot . '/blocks/' . $blockname; if (is_readable($fullblock . '/block_' . $blockname . '.php')) { include_once $fullblock . '/block_' . $blockname . '.php'; } else { $notices[] = 'Block ' . $blockname . ': ' . $fullblock . '/block_' . $blockname . '.php was not readable'; continue; } $oldupgrade = false; $newupgrade = false; if (@is_dir($fullblock . '/db/')) { if (@is_readable($fullblock . '/db/' . $CFG->dbtype . '.php')) { include_once $fullblock . '/db/' . $CFG->dbtype . '.php'; // defines old upgrading function $oldupgrade = true; } if (@is_readable($fullblock . '/db/upgrade.php')) { include_once $fullblock . '/db/upgrade.php'; // defines new upgrading function $newupgrade = true; } } $classname = 'block_' . $blockname; if (!class_exists($classname)) { $notices[] = 'Block ' . $blockname . ': ' . $classname . ' not implemented'; continue; } // Here is the place to see if the block implements a constructor (old style), // an init() function (new style) or nothing at all (error time). $constructor = get_class_constructor($classname); if (empty($constructor)) { // No constructor $notices[] = 'Block ' . $blockname . ': class does not have a constructor'; $invalidblocks[] = $blockname; continue; } $block = new stdClass(); // This may be used to update the db below $blockobj = new $classname(); // This is what we 'll be testing // Inherits from block_base? if (!is_subclass_of($blockobj, 'block_base')) { $notices[] = 'Block ' . $blockname . ': class does not inherit from block_base'; continue; } // OK, it's as we all hoped. For further tests, the object will do them itself. if (!$blockobj->_self_test()) { $notices[] = 'Block ' . $blockname . ': self test failed'; continue; } $block->version = $blockobj->get_version(); if (!isset($block->version)) { $notices[] = 'Block ' . $blockname . ': has no version support. It must be updated by a programmer.'; continue; } $block->name = $blockname; // The name MUST match the directory $blocktitle = $blockobj->get_title(); if ($currblock = get_record('block', 'name', $block->name)) { if ($currblock->version == $block->version) { // do nothing } else { if ($currblock->version < $block->version) { if (empty($updated_blocks)) { $strblocksetup = get_string('blocksetup'); print_header($strblocksetup, $strblocksetup, build_navigation(array(array('name' => $strblocksetup, 'link' => null, 'type' => 'misc'))), '', upgrade_get_javascript(), false, ' ', ' '); } $updated_blocks = true; upgrade_log_start(); print_heading('New version of ' . $blocktitle . ' (' . $block->name . ') exists'); @set_time_limit(0); // To allow slow databases to complete the long SQL /// Run de old and new upgrade functions for the module $oldupgrade_function = $block->name . '_upgrade'; $newupgrade_function = 'xmldb_block_' . $block->name . '_upgrade'; /// First, the old function if exists $oldupgrade_status = true; if ($oldupgrade && function_exists($oldupgrade_function)) { $db->debug = true; $oldupgrade_status = $oldupgrade_function($currblock->version, $block); } else { if ($oldupgrade) { notify('Upgrade function ' . $oldupgrade_function . ' was not available in ' . $fullblock . '/db/' . $CFG->dbtype . '.php'); } } /// Then, the new function if exists and the old one was ok $newupgrade_status = true; if ($newupgrade && function_exists($newupgrade_function) && $oldupgrade_status) { $db->debug = true; $newupgrade_status = $newupgrade_function($currblock->version, $block); } else { if ($newupgrade) { notify('Upgrade function ' . $newupgrade_function . ' was not available in ' . $fullblock . '/db/upgrade.php'); } } $db->debug = false; /// Now analyze upgrade results if ($oldupgrade_status && $newupgrade_status) { // No upgrading failed // Set the block cron on upgrade $block->cron = !empty($blockobj->cron) ? $blockobj->cron : 0; // OK so far, now update the block record $block->id = $currblock->id; if (!update_record('block', $block)) { error('Could not update block ' . $block->name . ' record in block table!'); } $component = 'block/' . $block->name; if (!update_capabilities($component)) { error('Could not update ' . $block->name . ' capabilities!'); } events_update_definition($component); notify(get_string('blocksuccess', '', $blocktitle), 'notifysuccess'); } else { notify('Upgrading block ' . $block->name . ' from ' . $currblock->version . ' to ' . $block->version . ' FAILED!'); } echo '<hr />'; } else { upgrade_log_start(); error('Version mismatch: block ' . $block->name . ' can\'t downgrade ' . $currblock->version . ' -> ' . $block->version . '!'); } } } else { // block not installed yet, so install it // If it allows multiples, start with it enabled if ($blockobj->instance_allow_multiple()) { $block->multiple = 1; } // Set the block cron on install $block->cron = !empty($blockobj->cron) ? $blockobj->cron : 0; // [pj] Normally this would be inline in the if, but we need to // check for NULL (necessary for 4.0.5 <= PHP < 4.2.0) $conflictblock = array_search($blocktitle, $blocktitles); if ($conflictblock !== false && $conflictblock !== NULL) { // Duplicate block titles are not allowed, they confuse people // AND PHP's associative arrays ;) error('<strong>Naming conflict</strong>: block <strong>' . $block->name . '</strong> has the same title with an existing block, <strong>' . $conflictblock . '</strong>!'); } if (empty($updated_blocks)) { $strblocksetup = get_string('blocksetup'); print_header($strblocksetup, $strblocksetup, build_navigation(array(array('name' => $strblocksetup, 'link' => null, 'type' => 'misc'))), '', upgrade_get_javascript(), false, ' ', ' '); } $updated_blocks = true; upgrade_log_start(); print_heading($block->name); $db->debug = true; @set_time_limit(0); // To allow slow databases to complete the long SQL /// Both old .sql files and new install.xml are supported /// but we priorize install.xml (XMLDB) if present $status = false; if (file_exists($fullblock . '/db/install.xml')) { $status = install_from_xmldb_file($fullblock . '/db/install.xml'); //New method } else { if (file_exists($fullblock . '/db/' . $CFG->dbtype . '.sql')) { $status = modify_database($fullblock . '/db/' . $CFG->dbtype . '.sql'); //Old method } else { $status = true; } } $db->debug = false; if ($status) { if ($block->id = insert_record('block', $block)) { $blockobj->after_install(); $component = 'block/' . $block->name; if (!update_capabilities($component)) { notify('Could not set up ' . $block->name . ' capabilities!'); } events_update_definition($component); notify(get_string('blocksuccess', '', $blocktitle), 'notifysuccess'); echo '<hr />'; } else { error($block->name . ' block could not be added to the block list!'); } } else { error('Block ' . $block->name . ' tables could NOT be set up successfully!'); } } $blocktitles[$block->name] = $blocktitle; } if (!empty($notices)) { upgrade_log_start(); foreach ($notices as $notice) { notify($notice); } } // Finally, if we are in the first_install of BLOCKS (this means that we are // upgrading from Moodle < 1.3), put blocks in all existing courses. if ($first_install) { upgrade_log_start(); //Iterate over each course if ($courses = get_records('course')) { foreach ($courses as $course) { $page = page_create_object(PAGE_COURSE_VIEW, $course->id); blocks_repopulate_page($page); } } } if (!empty($CFG->siteblocksadded)) { /// This is a once-off hack to make a proper upgrade upgrade_log_start(); $page = page_create_object(PAGE_COURSE_VIEW, SITEID); blocks_repopulate_page($page); delete_records('config', 'name', 'siteblocksadded'); } upgrade_log_finish(); if (!empty($updated_blocks)) { print_continue($continueto); print_footer('none'); die; } }
function test_get_users_by_capability() { global $CFG; $tablenames = array('capabilities', 'context', 'role', 'role_capabilities', 'role_allow_assign', 'role_allow_override', 'role_assignments', 'role_context_levels', 'user', 'groups_members', 'cache_flags', 'events_handlers', 'user_lastaccess', 'course'); $this->create_test_tables($tablenames, 'lib'); accesslib_clear_all_caches_for_unit_testing(); $this->switch_to_test_db(); $this->switch_to_test_cfg(); $course = new stdClass(); $course->category = 0; $this->testdb->insert_record('course', $course); $syscontext = get_system_context(false); /// Install the roles system. $coursecreatorrole = create_role(get_string('coursecreators'), 'coursecreator', get_string('coursecreatorsdescription'), 'coursecreator'); $editteacherrole = create_role(get_string('defaultcourseteacher'), 'editingteacher', get_string('defaultcourseteacherdescription'), 'editingteacher'); $noneditteacherrole = create_role(get_string('noneditingteacher'), 'teacher', get_string('noneditingteacherdescription'), 'teacher'); $studentrole = create_role(get_string('defaultcoursestudent'), 'student', get_string('defaultcoursestudentdescription'), 'student'); $guestrole = create_role(get_string('guest'), 'guest', get_string('guestdescription'), 'guest'); $userrole = create_role(get_string('authenticateduser'), 'user', get_string('authenticateduserdescription'), 'user'); /// Now is the correct moment to install capabilities - after creation of legacy roles, but before assigning of roles update_capabilities('moodle'); update_capabilities('mod_forum'); update_capabilities('mod_quiz'); // Create some nested contexts. instanceid does not matter for this. Just // ensure we don't violate any unique keys by using an unlikely number. // We will fix paths in a second. $contexts = $this->load_test_data('context', array('contextlevel', 'instanceid', 'path', 'depth'), array(1 => array(40, 666, '', 2), 2 => array(50, 666, '', 3), 3 => array(70, 666, '', 4))); $contexts[0] = $syscontext; $contexts[1]->path = $contexts[0]->path . '/' . $contexts[1]->id; $this->testdb->set_field('context', 'path', $contexts[1]->path, array('id' => $contexts[1]->id)); $contexts[2]->path = $contexts[1]->path . '/' . $contexts[2]->id; $this->testdb->set_field('context', 'path', $contexts[2]->path, array('id' => $contexts[2]->id)); $contexts[3]->path = $contexts[2]->path . '/' . $contexts[3]->id; $this->testdb->set_field('context', 'path', $contexts[3]->path, array('id' => $contexts[3]->id)); // Now make some test users. $users = $this->load_test_data('user', array('username', 'confirmed', 'deleted'), array('a' => array('a', 1, 0), 'cc' => array('cc', 1, 0), 't1' => array('t1', 1, 0), 's1' => array('s1', 1, 0), 's2' => array('s2', 1, 0), 'del' => array('del', 1, 1), 'unc' => array('unc', 0, 0))); // Get some of the standard roles. $creator = $this->testdb->get_record('role', array('shortname' => 'coursecreator')); $teacher = $this->testdb->get_record('role', array('shortname' => 'editingteacher')); $student = $this->testdb->get_record('role', array('shortname' => 'student')); $authuser = $this->testdb->get_record('role', array('shortname' => 'user')); // And some role assignments. $ras = $this->load_test_data('role_assignments', array('userid', 'roleid', 'contextid'), array('cc' => array($users['cc']->id, $creator->id, $contexts[1]->id), 't1' => array($users['t1']->id, $teacher->id, $contexts[2]->id), 's1' => array($users['s1']->id, $student->id, $contexts[2]->id), 's2' => array($users['s2']->id, $student->id, $contexts[2]->id))); // And make user a into admin $CFG->siteadmins = $users['a']->id; $CFG->defaultuserroleid = $userrole; // And some group memebership. $gms = $this->load_test_data('groups_members', array('userid', 'groupid'), array(array($users['t1']->id, 666), array($users['s1']->id, 666), array($users['s2']->id, 667))); // Test some simple cases - check that looking in coruse and module contextlevel gives the same answer. foreach (array(2, 3) as $conindex) { $results = get_users_by_capability($contexts[$conindex], 'mod/forum:replypost'); // note: admin accounts are never returned, so no admin return here $this->assert(new ArraysHaveSameValuesExpectation(array($users['t1']->id, $users['s1']->id, $users['s2']->id)), array_map(create_function('$o', 'return $o->id;'), $results)); // Paging. $firstuser = reset($results); $this->assertEqual(array($firstuser->id => $firstuser), get_users_by_capability($contexts[$conindex], 'mod/forum:replypost', '', '', 0, 1)); $seconduser = next($results); $this->assertEqual(array($seconduser->id => $seconduser), get_users_by_capability($contexts[$conindex], 'mod/forum:replypost', '', '', 1, 1)); // $doanything = false (ignored now) $this->assert(new ArraysHaveSameValuesExpectation(array($users['t1']->id, $users['s1']->id, $users['s2']->id)), array_map(create_function('$o', 'return $o->id;'), get_users_by_capability($contexts[$conindex], 'mod/forum:replypost', '', '', '', '', '', '', false))); // group $this->assert(new ArraysHaveSameValuesExpectation(array($users['t1']->id, $users['s1']->id)), array_map(create_function('$o', 'return $o->id;'), get_users_by_capability($contexts[$conindex], 'mod/forum:replypost', '', '', '', '', 666))); // exceptions $this->assert(new ArraysHaveSameValuesExpectation(array($users['s1']->id, $users['s2']->id)), array_map(create_function('$o', 'return $o->id;'), get_users_by_capability($contexts[$conindex], 'mod/forum:replypost', '', '', '', '', '', array($users['t1']->id)))); $this->assert(new ArraysHaveSameValuesExpectation(array($users['s1']->id)), array_map(create_function('$o', 'return $o->id;'), get_users_by_capability($contexts[$conindex], 'mod/forum:replypost', '', '', '', '', 666, array($users['t1']->id)))); // $useviewallgroups $this->assert(new ArraysHaveSameValuesExpectation(array($users['t1']->id, $users['s2']->id)), array_map(create_function('$o', 'return $o->id;'), get_users_by_capability($contexts[$conindex], 'mod/forum:replypost', '', '', '', '', 667, '', false, false, true))); // More than one capability. $this->assert(new ArraysHaveSameValuesExpectation(array($users['s1']->id, $users['s2']->id)), array_map(create_function('$o', 'return $o->id;'), get_users_by_capability($contexts[$conindex], array('mod/quiz:attempt', 'mod/quiz:reviewmyattempts')))); } // For reference: get_users_by_capability argument order: // $context, $capability, $fields='', $sort='', $limitfrom='', $limitnum='', // $groups='', $exceptions='', $doanything=true, $view=false, $useviewallgroups=false // Now add some role overrides. $rcs = $this->load_test_data('role_capabilities', array('capability', 'roleid', 'contextid', 'permission'), array(array('mod/forum:replypost', $student->id, $contexts[1]->id, CAP_PREVENT), array('mod/forum:replypost', $student->id, $contexts[3]->id, CAP_ALLOW), array('mod/quiz:attempt', $student->id, $contexts[2]->id, CAP_PREVENT), array('mod/forum:startdiscussion', $student->id, $contexts[1]->id, CAP_PROHIBIT), array('mod/forum:startdiscussion', $student->id, $contexts[3]->id, CAP_ALLOW), array('mod/forum:viewrating', $authuser->id, $contexts[1]->id, CAP_PROHIBIT), array('mod/forum:createattachment', $authuser->id, $contexts[3]->id, CAP_PREVENT))); // Now test the overridden cases. // Students prevented at category level, with and without doanything. $this->assert(new ArraysHaveSameValuesExpectation(array($users['t1']->id)), array_map(create_function('$o', 'return $o->id;'), get_users_by_capability($contexts[2], 'mod/forum:replypost'))); $this->assert(new ArraysHaveSameValuesExpectation(array($users['t1']->id)), array_map(create_function('$o', 'return $o->id;'), get_users_by_capability($contexts[2], 'mod/forum:replypost', '', '', '', '', '', '', false))); // Students prevented at category level, but re-allowed at module level, with and without doanything. $this->assert(new ArraysHaveSameValuesExpectation(array($users['t1']->id, $users['s1']->id, $users['s2']->id)), array_map(create_function('$o', 'return $o->id;'), get_users_by_capability($contexts[3], 'mod/forum:replypost', '', '', '', '', '', '', false))); $this->assert(new ArraysHaveSameValuesExpectation(array($users['t1']->id, $users['s1']->id, $users['s2']->id)), array_map(create_function('$o', 'return $o->id;'), get_users_by_capability($contexts[3], 'mod/forum:replypost'))); // Students prohibited at category level, re-allowed at module level should have no effect. $this->assert(new ArraysHaveSameValuesExpectation(array($users['t1']->id)), array_map(create_function('$o', 'return $o->id;'), get_users_by_capability($contexts[2], 'mod/forum:startdiscussion'))); $this->assert(new ArraysHaveSameValuesExpectation(array($users['t1']->id)), array_map(create_function('$o', 'return $o->id;'), get_users_by_capability($contexts[3], 'mod/forum:startdiscussion'))); // Prevent on logged-in user should be overridden by student allow. $this->assert(new ArraysHaveSameValuesExpectation(array($users['t1']->id, $users['s1']->id, $users['s2']->id)), array_map(create_function('$o', 'return $o->id;'), get_users_by_capability($contexts[3], 'mod/forum:createattachment'))); // Prohibit on logged-in user should trump student/teacher allow. $this->assert(new ArraysHaveSameValuesExpectation(array()), array_map(create_function('$o', 'return $o->id;'), get_users_by_capability($contexts[3], 'mod/forum:viewrating'))); // More than one capability, where students have one, but not the other. $this->assert(new ArraysHaveSameValuesExpectation(array($users['s1']->id, $users['s2']->id)), array_map(create_function('$o', 'return $o->id;'), get_users_by_capability($contexts[3], array('mod/quiz:attempt', 'mod/quiz:reviewmyattempts'), '', '', '', '', '', '', false))); }
function xmldb_main_install() { global $CFG, $DB, $SITE, $OUTPUT; /// make sure system context exists $syscontext = get_system_context(false); if ($syscontext->id != 1) { throw new moodle_exception('generalexceptionmessage', 'error', '', 'Unexpected new system context id!'); } /// create site course $newsite = new stdClass(); $newsite->fullname = ''; $newsite->shortname = ''; $newsite->summary = NULL; $newsite->newsitems = 3; $newsite->numsections = 0; $newsite->category = 0; $newsite->format = 'site'; // Only for this course $newsite->timecreated = time(); $newsite->timemodified = $newsite->timecreated; $newsite->id = $DB->insert_record('course', $newsite); $SITE = get_site(); if ($newsite->id != 1 or $SITE->id != 1) { throw new moodle_exception('generalexceptionmessage', 'error', '', 'Unexpected new site course id!'); } /// make sure site course context exists get_context_instance(CONTEXT_COURSE, $SITE->id); /// create default course category $cat = get_course_category(); $defaults = array('rolesactive' => '0', 'auth' => 'email', 'auth_pop3mailbox' => 'INBOX', 'enrol_plugins_enabled' => 'manual,guest,self,cohort', 'theme' => theme_config::DEFAULT_THEME, 'filter_multilang_converted' => 1, 'siteidentifier' => random_string(32) . get_host_from_url($CFG->wwwroot), 'backup_version' => 2008111700, 'backup_release' => '2.0 dev', 'mnet_dispatcher_mode' => 'off', 'sessiontimeout' => 7200, 'stringfilters' => '', 'filterall' => 0, 'texteditors' => 'tinymce,textarea'); foreach ($defaults as $key => $value) { set_config($key, $value); } /// bootstrap mnet $mnethost = new stdClass(); $mnethost->wwwroot = $CFG->wwwroot; $mnethost->name = ''; $mnethost->name = ''; $mnethost->public_key = ''; if (empty($_SERVER['SERVER_ADDR'])) { // SERVER_ADDR is only returned by Apache-like webservers preg_match("@^(?:http[s]?://)?([A-Z0-9\\-\\.]+).*@i", $CFG->wwwroot, $matches); $my_hostname = $matches[1]; $my_ip = gethostbyname($my_hostname); // Returns unmodified hostname on failure. DOH! if ($my_ip == $my_hostname) { $mnethost->ip_address = 'UNKNOWN'; } else { $mnethost->ip_address = $my_ip; } } else { $mnethost->ip_address = $_SERVER['SERVER_ADDR']; } $mnetid = $DB->insert_record('mnet_host', $mnethost); set_config('mnet_localhost_id', $mnetid); // Initial insert of mnet applications info $mnet_app = new stdClass(); $mnet_app->name = 'moodle'; $mnet_app->display_name = 'Moodle'; $mnet_app->xmlrpc_server_url = '/mnet/xmlrpc/server.php'; $mnet_app->sso_land_url = '/auth/mnet/land.php'; $mnet_app->sso_jump_url = '/auth/mnet/jump.php'; $moodleapplicationid = $DB->insert_record('mnet_application', $mnet_app); $mnet_app = new stdClass(); $mnet_app->name = 'mahara'; $mnet_app->display_name = 'Mahara'; $mnet_app->xmlrpc_server_url = '/api/xmlrpc/server.php'; $mnet_app->sso_land_url = '/auth/xmlrpc/land.php'; $mnet_app->sso_jump_url = '/auth/xmlrpc/jump.php'; $DB->insert_record('mnet_application', $mnet_app); // Set up the probably-to-be-removed-soon 'All hosts' record $mnetallhosts = new stdClass(); $mnetallhosts->wwwroot = ''; $mnetallhosts->ip_address = ''; $mnetallhosts->public_key = ''; $mnetallhosts->public_key_expires = 0; $mnetallhosts->last_connect_time = 0; $mnetallhosts->last_log_id = 0; $mnetallhosts->deleted = 0; $mnetallhosts->name = 'All Hosts'; $mnetallhosts->applicationid = $moodleapplicationid; $mnetallhosts->id = $DB->insert_record('mnet_host', $mnetallhosts, true); set_config('mnet_all_hosts_id', $mnetallhosts->id); /// Create guest record - do not assign any role, guest user get's the default guest role automatically on the fly $guest = new stdClass(); $guest->auth = 'manual'; $guest->username = '******'; $guest->password = hash_internal_user_password('guest'); $guest->firstname = get_string('guestuser'); $guest->lastname = ' '; $guest->email = 'root@localhost'; $guest->description = get_string('guestuserinfo'); $guest->mnethostid = $CFG->mnet_localhost_id; $guest->confirmed = 1; $guest->lang = $CFG->lang; $guest->timemodified = time(); $guest->id = $DB->insert_record('user', $guest); if ($guest->id != 1) { echo $OUTPUT->notification('Unexpected id generated for the Guest account. Your database configuration or clustering setup may not be fully supported', 'notifyproblem'); } // Store guest id set_config('siteguest', $guest->id); /// Now create admin user $admin = new stdClass(); $admin->auth = 'manual'; $admin->firstname = get_string('admin'); $admin->lastname = get_string('user'); $admin->username = '******'; $admin->password = '******'; $admin->email = ''; $admin->confirmed = 1; $admin->mnethostid = $CFG->mnet_localhost_id; $admin->lang = $CFG->lang; $admin->maildisplay = 1; $admin->timemodified = time(); $admin->lastip = CLI_SCRIPT ? '0.0.0.0' : getremoteaddr(); // installation hijacking prevention $admin->id = $DB->insert_record('user', $admin); if ($admin->id != 2) { echo $OUTPUT->notification('Unexpected id generated for the Admin account. Your database configuration or clustering setup may not be fully supported', 'notifyproblem'); } if ($admin->id != $guest->id + 1) { echo $OUTPUT->notification('Nonconsecutive id generated for the Admin account. Your database configuration or clustering setup may not be fully supported.', 'notifyproblem'); } /// Store list of admins set_config('siteadmins', $admin->id); /// Install the roles system. $managerrole = create_role(get_string('manager', 'role'), 'manager', get_string('managerdescription', 'role'), 'manager'); $coursecreatorrole = create_role(get_string('coursecreators'), 'coursecreator', get_string('coursecreatorsdescription'), 'coursecreator'); $editteacherrole = create_role(get_string('defaultcourseteacher'), 'editingteacher', get_string('defaultcourseteacherdescription'), 'editingteacher'); $noneditteacherrole = create_role(get_string('noneditingteacher'), 'teacher', get_string('noneditingteacherdescription'), 'teacher'); $studentrole = create_role(get_string('defaultcoursestudent'), 'student', get_string('defaultcoursestudentdescription'), 'student'); $guestrole = create_role(get_string('guest'), 'guest', get_string('guestdescription'), 'guest'); $userrole = create_role(get_string('authenticateduser'), 'user', get_string('authenticateduserdescription'), 'user'); $frontpagerole = create_role(get_string('frontpageuser', 'role'), 'frontpage', get_string('frontpageuserdescription', 'role'), 'frontpage'); /// Now is the correct moment to install capabilities - after creation of legacy roles, but before assigning of roles update_capabilities('moodle'); /// Default allow assign $defaultallowassigns = array(array($managerrole, $managerrole), array($managerrole, $coursecreatorrole), array($managerrole, $editteacherrole), array($managerrole, $noneditteacherrole), array($managerrole, $studentrole), array($editteacherrole, $noneditteacherrole), array($editteacherrole, $studentrole)); foreach ($defaultallowassigns as $allow) { list($fromroleid, $toroleid) = $allow; allow_assign($fromroleid, $toroleid); } /// Default allow override $defaultallowoverrides = array(array($managerrole, $managerrole), array($managerrole, $coursecreatorrole), array($managerrole, $editteacherrole), array($managerrole, $noneditteacherrole), array($managerrole, $studentrole), array($managerrole, $guestrole), array($managerrole, $userrole), array($managerrole, $frontpagerole), array($editteacherrole, $noneditteacherrole), array($editteacherrole, $studentrole), array($editteacherrole, $guestrole)); foreach ($defaultallowoverrides as $allow) { list($fromroleid, $toroleid) = $allow; allow_override($fromroleid, $toroleid); // There is a rant about this in MDL-15841. } /// Default allow switch. $defaultallowswitch = array(array($managerrole, $editteacherrole), array($managerrole, $noneditteacherrole), array($managerrole, $studentrole), array($managerrole, $guestrole), array($editteacherrole, $noneditteacherrole), array($editteacherrole, $studentrole), array($editteacherrole, $guestrole), array($noneditteacherrole, $studentrole), array($noneditteacherrole, $guestrole)); foreach ($defaultallowswitch as $allow) { list($fromroleid, $toroleid) = $allow; allow_switch($fromroleid, $toroleid); } /// Set up the context levels where you can assign each role. set_role_contextlevels($managerrole, get_default_contextlevels('manager')); set_role_contextlevels($coursecreatorrole, get_default_contextlevels('coursecreator')); set_role_contextlevels($editteacherrole, get_default_contextlevels('editingteacher')); set_role_contextlevels($noneditteacherrole, get_default_contextlevels('teacher')); set_role_contextlevels($studentrole, get_default_contextlevels('student')); set_role_contextlevels($guestrole, get_default_contextlevels('guest')); set_role_contextlevels($userrole, get_default_contextlevels('user')); // Init themes set_config('themerev', 1); // Install licenses require_once $CFG->libdir . '/licenselib.php'; license_manager::install_licenses(); /// Add two lines of data into this new table $mypage = new stdClass(); $mypage->userid = NULL; $mypage->name = '__default'; $mypage->private = 0; $mypage->sortorder = 0; if (!$DB->record_exists('my_pages', array('userid' => NULL, 'private' => 0))) { $DB->insert_record('my_pages', $mypage); } $mypage->private = 1; if (!$DB->record_exists('my_pages', array('userid' => NULL, 'private' => 1))) { $DB->insert_record('my_pages', $mypage); } }
/** * A small functional test of accesslib functions and classes. */ public function test_everything_in_accesslib() { global $USER, $SITE, $CFG, $DB, $ACCESSLIB_PRIVATE; // First of all finalize the session, we must not carry over any of this mess to the next page via SESSION!!! session_get_instance()->write_close(); // hack - this is going to take very long time set_time_limit(3600); // Get rid of current user that would not work anyway, // do NOT even think about using $this->switch_global_user_id()! if (!isset($this->accesslibprevuser)) { $this->accesslibprevuser = clone $USER; $USER = new stdClass(); $USER->id = 0; } // Backup $SITE global if (!isset($this->accesslibprevsite)) { $this->accesslibprevsite = $SITE; } // Switch DB, if it somehow fails or you specified wrong unittest prefix it will nuke real data, you have been warned! $this->switch_to_test_db(); // Let's switch the CFG $prevcfg = clone $CFG; $this->switch_to_test_cfg(); $CFG->config_php_settings = $prevcfg->config_php_settings; $CFG->noemailever = true; $CFG->admin = $prevcfg->admin; $CFG->lang = 'en'; $CFG->tempdir = $prevcfg->tempdir; $CFG->cachedir = $prevcfg->cachedir; $CFG->directorypermissions = $prevcfg->directorypermissions; $CFG->filepermissions = $prevcfg->filepermissions; // Reset all caches accesslib_clear_all_caches_for_unit_testing(); // Add some core tables - this is known to break constantly because we keep adding dependencies... $tablenames = array('config', 'config_plugins', 'modules', 'course', 'course_modules', 'course_sections', 'course_categories', 'mnet_host', 'mnet_application', 'capabilities', 'context', 'context_temp', 'role', 'role_capabilities', 'role_allow_switch', 'license', 'my_pages', 'block', 'block_instances', 'block_positions', 'role_allow_assign', 'role_allow_override', 'role_assignments', 'role_context_levels', 'enrol', 'user_enrolments', 'filter_active', 'filter_config', 'comments', 'user', 'groups_members', 'cache_flags', 'events_handlers', 'user_lastaccess', 'rating', 'files', 'role_names', 'user_preferences'); $this->create_test_tables($tablenames, 'lib'); // Create all core default records and default settings require_once "{$CFG->libdir}/db/install.php"; xmldb_main_install(); // installs the capabilities too // Fake mod_page install $tablenames = array('page'); $this->create_test_tables($tablenames, 'mod/page'); $module = new stdClass(); require $CFG->dirroot . '/mod/page/version.php'; $module->name = 'page'; $pagemoduleid = $DB->insert_record('modules', $module); update_capabilities('mod_page'); // Fake block_online_users install $plugin = new stdClass(); $plugin->version = NULL; $plugin->cron = 0; include $CFG->dirroot . '/blocks/online_users/version.php'; $plugin->name = 'online_users'; $onlineusersblockid = $DB->insert_record('block', $plugin); update_capabilities('block_online_users'); // Finish roles setup set_config('defaultfrontpageroleid', $DB->get_field('role', 'id', array('archetype' => 'frontpage'))); set_config('defaultuserroleid', $DB->get_field('role', 'id', array('archetype' => 'user'))); set_config('notloggedinroleid', $DB->get_field('role', 'id', array('archetype' => 'guest'))); set_config('rolesactive', 1); // Init manual enrol set_config('status', ENROL_INSTANCE_ENABLED, 'enrol_manual'); set_config('defaultperiod', 0, 'enrol_manual'); $manualenrol = enrol_get_plugin('manual'); // Fill the site with some real data $testcategories = array(); $testcourses = array(); $testpages = array(); $testblocks = array(); $allroles = $DB->get_records_menu('role', array(), 'id', 'archetype, id'); $systemcontext = context_system::instance(); $frontpagecontext = context_course::instance(SITEID); // Add block to system context $bi = new stdClass(); $bi->blockname = 'online_users'; $bi->parentcontextid = $systemcontext->id; $bi->showinsubcontexts = 1; $bi->pagetypepattern = ''; $bi->subpagepattern = ''; $bi->defaultregion = ''; $bi->defaultweight = 0; $bi->configdata = ''; $biid = $DB->insert_record('block_instances', $bi); context_block::instance($biid); $testblocks[] = $biid; // Some users $testusers = array(); for ($i = 0; $i < 20; $i++) { $user = new stdClass(); $user->auth = 'manual'; $user->firstname = 'user' . $i; $user->lastname = 'user' . $i; $user->username = '******' . $i; $user->password = '******'; $user->email = "user{$i}@example.com"; $user->confirmed = 1; $user->mnethostid = $CFG->mnet_localhost_id; $user->lang = $CFG->lang; $user->maildisplay = 1; $user->timemodified = time(); $user->deleted = 0; $user->lastip = '0.0.0.0'; $userid = $DB->insert_record('user', $user); $testusers[$i] = $userid; $usercontext = context_user::instance($userid); // Add block to user profile $bi->parentcontextid = $usercontext->id; $biid = $DB->insert_record('block_instances', $bi); context_block::instance($biid); $testblocks[] = $biid; } // Deleted user - should be ignored everywhere, can not have context $user = new stdClass(); $user->auth = 'manual'; $user->firstname = ''; $user->lastname = ''; $user->username = '******'; $user->password = ''; $user->email = ''; $user->confirmed = 1; $user->mnethostid = $CFG->mnet_localhost_id; $user->lang = $CFG->lang; $user->maildisplay = 1; $user->timemodified = time(); $user->deleted = 1; $user->lastip = '0.0.0.0'; $DB->insert_record('user', $user); unset($user); // Add block to frontpage $bi->parentcontextid = $frontpagecontext->id; $biid = $DB->insert_record('block_instances', $bi); $frontpageblockcontext = context_block::instance($biid); $testblocks[] = $biid; // Add a resource to frontpage $page = new stdClass(); $page->course = $SITE->id; $page->intro = '...'; $page->introformat = FORMAT_HTML; $page->content = '...'; $page->contentformat = FORMAT_HTML; $pageid = $DB->insert_record('page', $page); $testpages[] = $pageid; $cm = new stdClass(); $cm->course = $SITE->id; $cm->module = $pagemoduleid; $cm->section = 1; $cm->instance = $pageid; $cmid = $DB->insert_record('course_modules', $cm); $frontpagepagecontext = context_module::instance($cmid); // Add block to frontpage resource $bi->parentcontextid = $frontpagepagecontext->id; $biid = $DB->insert_record('block_instances', $bi); $frontpagepageblockcontext = context_block::instance($biid); $testblocks[] = $biid; // Some nested course categories with courses require_once "{$CFG->dirroot}/course/lib.php"; $path = ''; $parentcat = 0; for ($i = 0; $i < 5; $i++) { $cat = new stdClass(); $cat->name = 'category' . $i; $cat->parent = $parentcat; $cat->depth = $i + 1; $cat->sortorder = MAX_COURSES_IN_CATEGORY * ($i + 2); $cat->timemodified = time(); $catid = $DB->insert_record('course_categories', $cat); $path = $path . '/' . $catid; $DB->set_field('course_categories', 'path', $path, array('id' => $catid)); $parentcat = $catid; $testcategories[] = $catid; $catcontext = context_coursecat::instance($catid); if ($i >= 4) { continue; } // Add resource to each category $bi->parentcontextid = $catcontext->id; $biid = $DB->insert_record('block_instances', $bi); context_block::instance($biid); // Add a few courses to each category for ($j = 0; $j < 6; $j++) { $course = new stdClass(); $course->fullname = 'course' . $j; $course->shortname = 'c' . $j; $course->summary = 'bah bah bah'; $course->newsitems = 0; $course->numsections = 1; $course->category = $catid; $course->format = 'topics'; $course->timecreated = time(); $course->visible = 1; $course->timemodified = $course->timecreated; $courseid = $DB->insert_record('course', $course); $section = new stdClass(); $section->course = $courseid; $section->section = 0; $section->summaryformat = FORMAT_HTML; $DB->insert_record('course_sections', $section); $section->section = 1; $DB->insert_record('course_sections', $section); $testcourses[] = $courseid; $coursecontext = context_course::instance($courseid); if ($j >= 5) { continue; } // Add manual enrol instance $manualenrol->add_default_instance($DB->get_record('course', array('id' => $courseid))); // Add block to each course $bi->parentcontextid = $coursecontext->id; $biid = $DB->insert_record('block_instances', $bi); context_block::instance($biid); $testblocks[] = $biid; // Add a resource to each course $page->course = $courseid; $pageid = $DB->insert_record('page', $page); $testpages[] = $pageid; $cm->course = $courseid; $cm->instance = $pageid; $cm->id = $DB->insert_record('course_modules', $cm); $modcontext = context_module::instance($cm->id); // Add block to each module $bi->parentcontextid = $modcontext->id; $biid = $DB->insert_record('block_instances', $bi); context_block::instance($biid); $testblocks[] = $biid; } } // Make sure all contexts were created properly $count = 1; //system $count += $DB->count_records('user', array('deleted' => 0)); $count += $DB->count_records('course_categories'); $count += $DB->count_records('course'); $count += $DB->count_records('course_modules'); $count += $DB->count_records('block_instances'); $this->assertEqual($DB->count_records('context'), $count); $this->assertEqual($DB->count_records('context', array('depth' => 0)), 0); $this->assertEqual($DB->count_records('context', array('path' => NULL)), 0); // ====== context_helper::get_level_name() ================================ $levels = context_helper::get_all_levels(); foreach ($levels as $level => $classname) { $name = context_helper::get_level_name($level); $this->assertFalse(empty($name)); } // ======= context::instance_by_id(), context_xxx::instance(); $context = context::instance_by_id($frontpagecontext->id); $this->assertidentical($context->contextlevel, CONTEXT_COURSE); $this->assertFalse(context::instance_by_id(-1, IGNORE_MISSING)); try { context::instance_by_id(-1); $this->fail('exception expected'); } catch (Exception $e) { $this->assertTrue(true); } $this->assertTrue(context_system::instance() instanceof context_system); $this->assertTrue(context_coursecat::instance($testcategories[0]) instanceof context_coursecat); $this->assertTrue(context_course::instance($testcourses[0]) instanceof context_course); $this->assertTrue(context_module::instance($testpages[0]) instanceof context_module); $this->assertTrue(context_block::instance($testblocks[0]) instanceof context_block); $this->assertFalse(context_coursecat::instance(-1, IGNORE_MISSING)); $this->assertFalse(context_course::instance(-1, IGNORE_MISSING)); $this->assertFalse(context_module::instance(-1, IGNORE_MISSING)); $this->assertFalse(context_block::instance(-1, IGNORE_MISSING)); try { context_coursecat::instance(-1); $this->fail('exception expected'); } catch (Exception $e) { $this->assertTrue(true); } try { context_course::instance(-1); $this->fail('exception expected'); } catch (Exception $e) { $this->assertTrue(true); } try { context_module::instance(-1); $this->fail('exception expected'); } catch (Exception $e) { $this->assertTrue(true); } try { context_block::instance(-1); $this->fail('exception expected'); } catch (Exception $e) { $this->assertTrue(true); } // ======= $context->get_url(), $context->get_context_name(), $context->get_capabilities() ========= $testcontexts = array(); $testcontexts[CONTEXT_SYSTEM] = context_system::instance(); $testcontexts[CONTEXT_COURSECAT] = context_coursecat::instance($testcategories[0]); $testcontexts[CONTEXT_COURSE] = context_course::instance($testcourses[0]); $testcontexts[CONTEXT_MODULE] = context_module::instance($testpages[0]); $testcontexts[CONTEXT_BLOCK] = context_block::instance($testblocks[0]); foreach ($testcontexts as $context) { $name = $context->get_context_name(true, true); $this->assertFalse(empty($name)); $this->assertTrue($context->get_url() instanceof moodle_url); $caps = $context->get_capabilities(); $this->assertTrue(is_array($caps)); foreach ($caps as $cap) { $cap = (array) $cap; $this->assertIdentical(array_keys($cap), array('id', 'name', 'captype', 'contextlevel', 'component', 'riskbitmask')); } } unset($testcontexts); // ===== $context->get_course_context() ========================================= $this->assertFalse($systemcontext->get_course_context(false)); try { $systemcontext->get_course_context(); $this->fail('exception expected'); } catch (Exception $e) { $this->assertTrue(true); } $context = context_coursecat::instance($testcategories[0]); $this->assertFalse($context->get_course_context(false)); try { $context->get_course_context(); $this->fail('exception expected'); } catch (Exception $e) { $this->assertTrue(true); } $this->assertIdentical($frontpagecontext->get_course_context(true), $frontpagecontext); $this->assertIdentical($frontpagepagecontext->get_course_context(true), $frontpagecontext); $this->assertIdentical($frontpagepageblockcontext->get_course_context(true), $frontpagecontext); // ======= $context->get_parent_context(), $context->get_parent_contexts(), $context->get_parent_context_ids() ======= $userid = reset($testusers); $usercontext = context_user::instance($userid); $this->assertIdentical($usercontext->get_parent_context(), $systemcontext); $this->assertIdentical($usercontext->get_parent_contexts(), array($systemcontext->id => $systemcontext)); $this->assertIdentical($usercontext->get_parent_contexts(true), array($usercontext->id => $usercontext, $systemcontext->id => $systemcontext)); $this->assertIdentical($systemcontext->get_parent_contexts(), array()); $this->assertIdentical($systemcontext->get_parent_contexts(true), array($systemcontext->id => $systemcontext)); $this->assertIdentical($systemcontext->get_parent_context_ids(), array()); $this->assertIdentical($systemcontext->get_parent_context_ids(true), array($systemcontext->id)); $this->assertIdentical($frontpagecontext->get_parent_context(), $systemcontext); $this->assertIdentical($frontpagecontext->get_parent_contexts(), array($systemcontext->id => $systemcontext)); $this->assertIdentical($frontpagecontext->get_parent_contexts(true), array($frontpagecontext->id => $frontpagecontext, $systemcontext->id => $systemcontext)); $this->assertIdentical($frontpagecontext->get_parent_context_ids(), array($systemcontext->id)); $this->assertEqual($frontpagecontext->get_parent_context_ids(true), array($frontpagecontext->id, $systemcontext->id)); $this->assertIdentical($systemcontext->get_parent_context(), false); $frontpagecontext = context_course::instance($SITE->id); $parent = $systemcontext; foreach ($testcategories as $catid) { $catcontext = context_coursecat::instance($catid); $this->assertIdentical($catcontext->get_parent_context(), $parent); $parent = $catcontext; } $this->assertIdentical($frontpagepagecontext->get_parent_context(), $frontpagecontext); $this->assertIdentical($frontpageblockcontext->get_parent_context(), $frontpagecontext); $this->assertIdentical($frontpagepageblockcontext->get_parent_context(), $frontpagepagecontext); // ====== $context->get_child_contexts() ================================ $children = $systemcontext->get_child_contexts(); $this->assertEqual(count($children) + 1, $DB->count_records('context')); $context = context_coursecat::instance($testcategories[3]); $children = $context->get_child_contexts(); $countcats = 0; $countcourses = 0; $countblocks = 0; foreach ($children as $child) { if ($child->contextlevel == CONTEXT_COURSECAT) { $countcats++; } if ($child->contextlevel == CONTEXT_COURSE) { $countcourses++; } if ($child->contextlevel == CONTEXT_BLOCK) { $countblocks++; } } $this->assertEqual(count($children), 8); $this->assertEqual($countcats, 1); $this->assertEqual($countcourses, 6); $this->assertEqual($countblocks, 1); $context = context_course::instance($testcourses[2]); $children = $context->get_child_contexts(); $this->assertEqual(count($children), 3); $context = context_module::instance($testpages[3]); $children = $context->get_child_contexts(); $this->assertEqual(count($children), 1); $context = context_block::instance($testblocks[1]); $children = $context->get_child_contexts(); $this->assertEqual(count($children), 0); unset($children); unset($countcats); unset($countcourses); unset($countblocks); // ======= context_helper::reset_caches() ============================ context_helper::reset_caches(); $this->assertEqual(context_inspection::test_context_cache_size(), 0); context_course::instance($SITE->id); $this->assertEqual(context_inspection::test_context_cache_size(), 1); // ======= context preloading ======================================== context_helper::reset_caches(); $sql = "SELECT " . context_helper::get_preload_record_columns_sql('c') . "\n FROM {context} c\n WHERE c.contextlevel <> " . CONTEXT_SYSTEM; $records = $DB->get_records_sql($sql); $firstrecord = reset($records); $columns = context_helper::get_preload_record_columns('c'); $firstrecord = (array) $firstrecord; $this->assertIdentical(array_keys($firstrecord), array_values($columns)); context_helper::reset_caches(); foreach ($records as $record) { context_helper::preload_from_record($record); $this->assertIdentical($record, new stdClass()); } $this->assertEqual(context_inspection::test_context_cache_size(), count($records)); unset($records); unset($columns); context_helper::reset_caches(); context_helper::preload_course($SITE->id); $this->assertEqual(context_inspection::test_context_cache_size(), 4); // ====== assign_capability(), unassign_capability() ==================== $rc = $DB->get_record('role_capabilities', array('contextid' => $frontpagecontext->id, 'roleid' => $allroles['teacher'], 'capability' => 'moodle/site:accessallgroups')); $this->assertFalse($rc); assign_capability('moodle/site:accessallgroups', CAP_ALLOW, $allroles['teacher'], $frontpagecontext->id); $rc = $DB->get_record('role_capabilities', array('contextid' => $frontpagecontext->id, 'roleid' => $allroles['teacher'], 'capability' => 'moodle/site:accessallgroups')); $this->assertEqual($rc->permission, CAP_ALLOW); assign_capability('moodle/site:accessallgroups', CAP_PREVENT, $allroles['teacher'], $frontpagecontext->id); $rc = $DB->get_record('role_capabilities', array('contextid' => $frontpagecontext->id, 'roleid' => $allroles['teacher'], 'capability' => 'moodle/site:accessallgroups')); $this->assertEqual($rc->permission, CAP_ALLOW); assign_capability('moodle/site:accessallgroups', CAP_PREVENT, $allroles['teacher'], $frontpagecontext, true); $rc = $DB->get_record('role_capabilities', array('contextid' => $frontpagecontext->id, 'roleid' => $allroles['teacher'], 'capability' => 'moodle/site:accessallgroups')); $this->assertEqual($rc->permission, CAP_PREVENT); assign_capability('moodle/site:accessallgroups', CAP_INHERIT, $allroles['teacher'], $frontpagecontext); $rc = $DB->get_record('role_capabilities', array('contextid' => $frontpagecontext->id, 'roleid' => $allroles['teacher'], 'capability' => 'moodle/site:accessallgroups')); $this->assertFalse($rc); assign_capability('moodle/site:accessallgroups', CAP_ALLOW, $allroles['teacher'], $frontpagecontext); unassign_capability('moodle/site:accessallgroups', $allroles['teacher'], $frontpagecontext, true); $rc = $DB->get_record('role_capabilities', array('contextid' => $frontpagecontext->id, 'roleid' => $allroles['teacher'], 'capability' => 'moodle/site:accessallgroups')); $this->assertFalse($rc); unassign_capability('moodle/site:accessallgroups', $allroles['teacher'], $frontpagecontext->id, true); unset($rc); accesslib_clear_all_caches(false); // must be done after assign_capability() // ======= role_assign(), role_unassign(), role_unassign_all() ============== $context = context_course::instance($testcourses[1]); $this->assertEqual($DB->count_records('role_assignments', array('contextid' => $context->id)), 0); role_assign($allroles['teacher'], $testusers[1], $context->id); role_assign($allroles['teacher'], $testusers[2], $context->id); role_assign($allroles['manager'], $testusers[1], $context->id); $this->assertEqual($DB->count_records('role_assignments', array('contextid' => $context->id)), 3); role_unassign($allroles['teacher'], $testusers[1], $context->id); $this->assertEqual($DB->count_records('role_assignments', array('contextid' => $context->id)), 2); role_unassign_all(array('contextid' => $context->id)); $this->assertEqual($DB->count_records('role_assignments', array('contextid' => $context->id)), 0); unset($context); accesslib_clear_all_caches(false); // just in case // ====== has_capability(), get_users_by_capability(), role_switch(), reload_all_capabilities() and friends ======================== $adminid = get_admin()->id; $guestid = $CFG->siteguest; // Enrol some users into some courses $course1 = $DB->get_record('course', array('id' => $testcourses[22]), '*', MUST_EXIST); $course2 = $DB->get_record('course', array('id' => $testcourses[7]), '*', MUST_EXIST); $cms = $DB->get_records('course_modules', array('course' => $course1->id), 'id'); $cm1 = reset($cms); $blocks = $DB->get_records('block_instances', array('parentcontextid' => context_module::instance($cm1->id)->id), 'id'); $block1 = reset($blocks); $instance1 = $DB->get_record('enrol', array('enrol' => 'manual', 'courseid' => $course1->id)); $instance2 = $DB->get_record('enrol', array('enrol' => 'manual', 'courseid' => $course2->id)); for ($i = 0; $i < 9; $i++) { $manualenrol->enrol_user($instance1, $testusers[$i], $allroles['student']); } $manualenrol->enrol_user($instance1, $testusers[8], $allroles['teacher']); $manualenrol->enrol_user($instance1, $testusers[9], $allroles['editingteacher']); for ($i = 10; $i < 15; $i++) { $manualenrol->enrol_user($instance2, $testusers[$i], $allroles['student']); } $manualenrol->enrol_user($instance2, $testusers[15], $allroles['editingteacher']); // Add tons of role assignments - the more the better role_assign($allroles['coursecreator'], $testusers[11], context_coursecat::instance($testcategories[2])); role_assign($allroles['manager'], $testusers[12], context_coursecat::instance($testcategories[1])); role_assign($allroles['student'], $testusers[9], context_module::instance($cm1->id)); role_assign($allroles['teacher'], $testusers[8], context_module::instance($cm1->id)); role_assign($allroles['guest'], $testusers[13], context_course::instance($course1->id)); role_assign($allroles['teacher'], $testusers[7], context_block::instance($block1->id)); role_assign($allroles['manager'], $testusers[9], context_block::instance($block1->id)); role_assign($allroles['editingteacher'], $testusers[9], context_course::instance($course1->id)); role_assign($allroles['teacher'], $adminid, context_course::instance($course1->id)); role_assign($allroles['editingteacher'], $adminid, context_block::instance($block1->id)); // Add tons of overrides - the more the better assign_capability('moodle/site:accessallgroups', CAP_ALLOW, $CFG->defaultuserroleid, $frontpageblockcontext, true); assign_capability('moodle/site:accessallgroups', CAP_ALLOW, $CFG->defaultfrontpageroleid, $frontpageblockcontext, true); assign_capability('moodle/block:view', CAP_PROHIBIT, $allroles['guest'], $frontpageblockcontext, true); assign_capability('block/online_users:viewlist', CAP_PREVENT, $allroles['user'], $frontpageblockcontext, true); assign_capability('block/online_users:viewlist', CAP_PREVENT, $allroles['student'], $frontpageblockcontext, true); assign_capability('moodle/site:accessallgroups', CAP_PREVENT, $CFG->defaultuserroleid, $frontpagepagecontext, true); assign_capability('moodle/site:accessallgroups', CAP_ALLOW, $CFG->defaultfrontpageroleid, $frontpagepagecontext, true); assign_capability('mod/page:view', CAP_PREVENT, $allroles['guest'], $frontpagepagecontext, true); assign_capability('mod/page:view', CAP_ALLOW, $allroles['user'], $frontpagepagecontext, true); assign_capability('moodle/page:view', CAP_ALLOW, $allroles['student'], $frontpagepagecontext, true); assign_capability('moodle/site:accessallgroups', CAP_ALLOW, $CFG->defaultuserroleid, $frontpagecontext, true); assign_capability('moodle/site:accessallgroups', CAP_ALLOW, $CFG->defaultfrontpageroleid, $frontpagecontext, true); assign_capability('mod/page:view', CAP_ALLOW, $allroles['guest'], $frontpagecontext, true); assign_capability('mod/page:view', CAP_PROHIBIT, $allroles['user'], $frontpagecontext, true); assign_capability('mod/page:view', CAP_PREVENT, $allroles['guest'], $systemcontext, true); accesslib_clear_all_caches(false); // must be done after assign_capability() // Extra tests for guests and not-logged-in users because they can not be verified by cross checking // with get_users_by_capability() where they are ignored $this->assertFalse(has_capability('moodle/block:view', $frontpageblockcontext, $guestid)); $this->assertFalse(has_capability('mod/page:view', $frontpagepagecontext, $guestid)); $this->assertTrue(has_capability('mod/page:view', $frontpagecontext, $guestid)); $this->assertFalse(has_capability('mod/page:view', $systemcontext, $guestid)); $this->assertFalse(has_capability('moodle/block:view', $frontpageblockcontext, 0)); $this->assertFalse(has_capability('mod/page:view', $frontpagepagecontext, 0)); $this->assertTrue(has_capability('mod/page:view', $frontpagecontext, 0)); $this->assertFalse(has_capability('mod/page:view', $systemcontext, 0)); $this->assertFalse(has_capability('moodle/course:create', $systemcontext, $testusers[11])); $this->assertTrue(has_capability('moodle/course:create', context_coursecat::instance($testcategories[2]), $testusers[11])); $this->assertFalse(has_capability('moodle/course:create', context_course::instance($testcourses[1]), $testusers[11])); $this->assertTrue(has_capability('moodle/course:create', context_course::instance($testcourses[19]), $testusers[11])); $this->assertFalse(has_capability('moodle/course:update', context_course::instance($testcourses[1]), $testusers[9])); $this->assertFalse(has_capability('moodle/course:update', context_course::instance($testcourses[19]), $testusers[9])); $this->assertFalse(has_capability('moodle/course:update', $systemcontext, $testusers[9])); // Test the list of enrolled users $coursecontext = context_course::instance($course1->id); $enrolled = get_enrolled_users($coursecontext); $this->assertEqual(count($enrolled), 10); for ($i = 0; $i < 10; $i++) { $this->assertTrue(isset($enrolled[$testusers[$i]])); } $enrolled = get_enrolled_users($coursecontext, 'moodle/course:update'); $this->assertEqual(count($enrolled), 1); $this->assertTrue(isset($enrolled[$testusers[9]])); unset($enrolled); // role switching $userid = $testusers[9]; $USER = $DB->get_record('user', array('id' => $userid)); load_all_capabilities(); $coursecontext = context_course::instance($course1->id); $this->assertTrue(has_capability('moodle/course:update', $coursecontext)); $this->assertFalse(is_role_switched($course1->id)); role_switch($allroles['student'], $coursecontext); $this->assertTrue(is_role_switched($course1->id)); $this->assertEqual($USER->access['rsw'][$coursecontext->path], $allroles['student']); $this->assertFalse(has_capability('moodle/course:update', $coursecontext)); reload_all_capabilities(); $this->assertFalse(has_capability('moodle/course:update', $coursecontext)); role_switch(0, $coursecontext); $this->assertTrue(has_capability('moodle/course:update', $coursecontext)); $userid = $adminid; $USER = $DB->get_record('user', array('id' => $userid)); load_all_capabilities(); $coursecontext = context_course::instance($course1->id); $blockcontext = context_block::instance($block1->id); $this->assertTrue(has_capability('moodle/course:update', $blockcontext)); role_switch($allroles['student'], $coursecontext); $this->assertEqual($USER->access['rsw'][$coursecontext->path], $allroles['student']); $this->assertFalse(has_capability('moodle/course:update', $blockcontext)); reload_all_capabilities(); $this->assertFalse(has_capability('moodle/course:update', $blockcontext)); load_all_capabilities(); $this->assertTrue(has_capability('moodle/course:update', $blockcontext)); // temp course role for enrol $DB->delete_records('cache_flags', array()); // this prevents problem with dirty contexts immediately resetting the temp role - this is a known problem... $userid = $testusers[5]; $roleid = $allroles['editingteacher']; $USER = $DB->get_record('user', array('id' => $userid)); load_all_capabilities(); $coursecontext = context_course::instance($course1->id); $this->assertFalse(has_capability('moodle/course:update', $coursecontext)); $this->assertFalse(isset($USER->access['ra'][$coursecontext->path][$roleid])); load_temp_course_role($coursecontext, $roleid); $this->assertEqual($USER->access['ra'][$coursecontext->path][$roleid], $roleid); $this->assertTrue(has_capability('moodle/course:update', $coursecontext)); remove_temp_course_roles($coursecontext); $this->assertFalse(has_capability('moodle/course:update', $coursecontext, $userid)); load_temp_course_role($coursecontext, $roleid); reload_all_capabilities(); $this->assertFalse(has_capability('moodle/course:update', $coursecontext, $userid)); $USER = new stdClass(); $USER->id = 0; // Now cross check has_capability() with get_users_by_capability(), each using different code paths, // they have to be kept in sync, usually only one of them breaks, so we know when something is wrong, // at the same time validate extra restrictions (guest read only no risks, admin exception, non existent and deleted users) $contexts = $DB->get_records('context', array(), 'id'); $contexts = array_values($contexts); $capabilities = $DB->get_records('capabilities', array(), 'id'); $capabilities = array_values($capabilities); $roles = array($allroles['guest'], $allroles['user'], $allroles['teacher'], $allroles['editingteacher'], $allroles['coursecreator'], $allroles['manager']); // Random time! srand(666); foreach ($testusers as $userid) { // no guest or deleted // each user gets 0-20 random roles $rcount = rand(0, 10); for ($j = 0; $j < $rcount; $j++) { $roleid = $roles[rand(0, count($roles) - 1)]; $contextid = $contexts[rand(0, count($contexts) - 1)]->id; role_assign($roleid, $userid, $contextid); } } $permissions = array(CAP_ALLOW, CAP_PREVENT, CAP_INHERIT, CAP_PREVENT); for ($j = 0; $j < 10000; $j++) { $roleid = $roles[rand(0, count($roles) - 1)]; $contextid = $contexts[rand(0, count($contexts) - 1)]->id; $permission = $permissions[rand(0, count($permissions) - 1)]; $capname = $capabilities[rand(0, count($capabilities) - 1)]->name; assign_capability($capname, $permission, $roleid, $contextid, true); } unset($permissions); unset($roles); unset($contexts); unset($users); unset($capabilities); accesslib_clear_all_caches(false); // must be done after assign_capability() // Test time - let's set up some real user, just in case the logic for USER affects the others... $USER = $DB->get_record('user', array('id' => $testusers[3])); load_all_capabilities(); $contexts = $DB->get_records('context', array(), 'id'); $users = $DB->get_records('user', array(), 'id', 'id'); $capabilities = $DB->get_records('capabilities', array(), 'id'); $users[0] = null; // not-logged-in user $users[-1] = null; // non-existent user foreach ($contexts as $crecord) { $context = context::instance_by_id($crecord->id); if ($coursecontext = $context->get_course_context(false)) { $enrolled = get_enrolled_users($context); } else { $enrolled = array(); } foreach ($capabilities as $cap) { $allowed = get_users_by_capability($context, $cap->name, 'u.id, u.username'); if ($enrolled) { $enrolledwithcap = get_enrolled_users($context, $cap->name); } else { $enrolledwithcap = array(); } foreach ($users as $userid => $unused) { if ($userid == 0 or isguestuser($userid)) { if ($userid == 0) { $CFG->forcelogin = true; $this->assertFalse(has_capability($cap->name, $context, $userid)); unset($CFG->forcelogin); } if ($cap->captype === 'write' or $cap->riskbitmask & (RISK_XSS | RISK_CONFIG | RISK_DATALOSS)) { $this->assertFalse(has_capability($cap->name, $context, $userid)); } $this->assertFalse(isset($allowed[$userid])); } else { if (is_siteadmin($userid)) { $this->assertTrue(has_capability($cap->name, $context, $userid, true)); } $hascap = has_capability($cap->name, $context, $userid, false); $this->assertIdentical($hascap, isset($allowed[$userid]), "Capability result mismatch user:{$userid}, context:{$context->id}, {$cap->name}, hascap: " . (int) $hascap . " "); if (isset($enrolled[$userid])) { $this->assertIdentical(isset($allowed[$userid]), isset($enrolledwithcap[$userid]), "Enrolment with capability result mismatch user:{$userid}, context:{$context->id}, {$cap->name}, hascap: " . (int) $hascap . " "); } } } } } // Back to nobody $USER = new stdClass(); $USER->id = 0; unset($contexts); unset($users); unset($capabilities); // Now let's do all the remaining tests that break our carefully prepared fake site // ======= $context->mark_dirty() ======================================= $DB->delete_records('cache_flags', array()); accesslib_clear_all_caches(false); $systemcontext->mark_dirty(); $dirty = get_cache_flags('accesslib/dirtycontexts', time() - 2); $this->assertTrue(isset($dirty[$systemcontext->path])); $this->assertTrue(isset($ACCESSLIB_PRIVATE->dirtycontexts[$systemcontext->path])); // ======= $context->reload_if_dirty(); ================================= $DB->delete_records('cache_flags', array()); accesslib_clear_all_caches(false); load_all_capabilities(); $context = context_course::instance($testcourses[2]); $page = $DB->get_record('page', array('course' => $testcourses[2])); $pagecontext = context_module::instance($page->id); $context->mark_dirty(); $this->assertTrue(isset($ACCESSLIB_PRIVATE->dirtycontexts[$context->path])); $USER->access['test'] = true; $context->reload_if_dirty(); $this->assertFalse(isset($USER->access['test'])); $context->mark_dirty(); $this->assertTrue(isset($ACCESSLIB_PRIVATE->dirtycontexts[$context->path])); $USER->access['test'] = true; $pagecontext->reload_if_dirty(); $this->assertFalse(isset($USER->access['test'])); // ======= context_helper::build_all_paths() ============================ $oldcontexts = $DB->get_records('context', array(), 'id'); $DB->set_field_select('context', 'path', NULL, "contextlevel <> " . CONTEXT_SYSTEM); $DB->set_field_select('context', 'depth', 0, "contextlevel <> " . CONTEXT_SYSTEM); context_helper::build_all_paths(); $newcontexts = $DB->get_records('context', array(), 'id'); $this->assertIdentical($oldcontexts, $newcontexts); unset($oldcontexts); unset($newcontexts); // ======= $context->reset_paths() ====================================== $context = context_course::instance($testcourses[2]); $children = $context->get_child_contexts(); $context->reset_paths(false); $this->assertIdentical($DB->get_field('context', 'path', array('id' => $context->id)), NULL); $this->assertEqual($DB->get_field('context', 'depth', array('id' => $context->id)), 0); foreach ($children as $child) { $this->assertIdentical($DB->get_field('context', 'path', array('id' => $child->id)), NULL); $this->assertEqual($DB->get_field('context', 'depth', array('id' => $child->id)), 0); } $this->assertEqual(count($children) + 1, $DB->count_records('context', array('depth' => 0))); $this->assertEqual(count($children) + 1, $DB->count_records('context', array('path' => NULL))); $context = context_course::instance($testcourses[2]); $context->reset_paths(true); $context = context_course::instance($testcourses[2]); $this->assertEqual($DB->get_field('context', 'path', array('id' => $context->id)), $context->path); $this->assertEqual($DB->get_field('context', 'depth', array('id' => $context->id)), $context->depth); $this->assertEqual(0, $DB->count_records('context', array('depth' => 0))); $this->assertEqual(0, $DB->count_records('context', array('path' => NULL))); // ====== $context->update_moved(); ====================================== accesslib_clear_all_caches(false); $DB->delete_records('cache_flags', array()); $course = $DB->get_record('course', array('id' => $testcourses[0])); $context = context_course::instance($course->id); $oldpath = $context->path; $miscid = $DB->get_field_sql("SELECT MIN(id) FROM {course_categories}"); $categorycontext = context_coursecat::instance($miscid); $course->category = $miscid; $DB->update_record('course', $course); $context->update_moved($categorycontext); $context = context_course::instance($course->id); $this->assertIdentical($context->get_parent_context(), $categorycontext); $dirty = get_cache_flags('accesslib/dirtycontexts', time() - 2); $this->assertTrue(isset($dirty[$oldpath])); $this->assertTrue(isset($dirty[$context->path])); // ====== $context->delete_content() ===================================== context_helper::reset_caches(); $context = context_module::instance($testpages[3]); $this->assertTrue($DB->record_exists('context', array('id' => $context->id))); $this->assertEqual(1, $DB->count_records('block_instances', array('parentcontextid' => $context->id))); $context->delete_content(); $this->assertTrue($DB->record_exists('context', array('id' => $context->id))); $this->assertEqual(0, $DB->count_records('block_instances', array('parentcontextid' => $context->id))); // ====== $context->delete() ============================= context_helper::reset_caches(); $context = context_module::instance($testpages[4]); $this->assertTrue($DB->record_exists('context', array('id' => $context->id))); $this->assertEqual(1, $DB->count_records('block_instances', array('parentcontextid' => $context->id))); $bi = $DB->get_record('block_instances', array('parentcontextid' => $context->id)); $bicontext = context_block::instance($bi->id); $DB->delete_records('cache_flags', array()); $context->delete(); // should delete also linked blocks $dirty = get_cache_flags('accesslib/dirtycontexts', time() - 2); $this->assertTrue(isset($dirty[$context->path])); $this->assertFalse($DB->record_exists('context', array('id' => $context->id))); $this->assertFalse($DB->record_exists('context', array('id' => $bicontext->id))); $this->assertFalse($DB->record_exists('context', array('contextlevel' => CONTEXT_MODULE, 'instanceid' => $testpages[4]))); $this->assertFalse($DB->record_exists('context', array('contextlevel' => CONTEXT_BLOCK, 'instanceid' => $bi->id))); $this->assertEqual(0, $DB->count_records('block_instances', array('parentcontextid' => $context->id))); context_module::instance($testpages[4]); // ====== context_helper::delete_instance() ============================= context_helper::reset_caches(); $lastcourse = array_pop($testcourses); $this->assertTrue($DB->record_exists('context', array('contextlevel' => CONTEXT_COURSE, 'instanceid' => $lastcourse))); $coursecontext = context_course::instance($lastcourse); $this->assertEqual(context_inspection::test_context_cache_size(), 1); $this->assertFalse($coursecontext->instanceid == CONTEXT_COURSE); $DB->delete_records('cache_flags', array()); context_helper::delete_instance(CONTEXT_COURSE, $lastcourse); $dirty = get_cache_flags('accesslib/dirtycontexts', time() - 2); $this->assertTrue(isset($dirty[$coursecontext->path])); $this->assertEqual(context_inspection::test_context_cache_size(), 0); $this->assertFalse($DB->record_exists('context', array('contextlevel' => CONTEXT_COURSE, 'instanceid' => $lastcourse))); context_course::instance($lastcourse); // ======= context_helper::create_instances() ========================== $prevcount = $DB->count_records('context'); $DB->delete_records('context', array('contextlevel' => CONTEXT_BLOCK)); context_helper::create_instances(null, true); $this->assertIdentical($DB->count_records('context'), $prevcount); $this->assertEqual($DB->count_records('context', array('depth' => 0)), 0); $this->assertEqual($DB->count_records('context', array('path' => NULL)), 0); $DB->delete_records('context', array('contextlevel' => CONTEXT_BLOCK)); $DB->delete_records('block_instances', array()); $prevcount = $DB->count_records('context'); $DB->delete_records_select('context', 'contextlevel <> ' . CONTEXT_SYSTEM); context_helper::create_instances(null, true); $this->assertIdentical($DB->count_records('context'), $prevcount); $this->assertEqual($DB->count_records('context', array('depth' => 0)), 0); $this->assertEqual($DB->count_records('context', array('path' => NULL)), 0); // ======= context_helper::cleanup_instances() ========================== $lastcourse = $DB->get_field_sql("SELECT MAX(id) FROM {course}"); $DB->delete_records('course', array('id' => $lastcourse)); $lastcategory = $DB->get_field_sql("SELECT MAX(id) FROM {course_categories}"); $DB->delete_records('course_categories', array('id' => $lastcategory)); $lastuser = $DB->get_field_sql("SELECT MAX(id) FROM {user} WHERE deleted=0"); $DB->delete_records('user', array('id' => $lastuser)); $DB->delete_records('block_instances', array('parentcontextid' => $frontpagepagecontext->id)); $DB->delete_records('course_modules', array('id' => $frontpagepagecontext->instanceid)); context_helper::cleanup_instances(); $count = 1; //system $count += $DB->count_records('user', array('deleted' => 0)); $count += $DB->count_records('course_categories'); $count += $DB->count_records('course'); $count += $DB->count_records('course_modules'); $count += $DB->count_records('block_instances'); $this->assertEqual($DB->count_records('context'), $count); // ======= context cache size restrictions ============================== $testusers = array(); for ($i = 0; $i < CONTEXT_CACHE_MAX_SIZE + 100; $i++) { $user = new stdClass(); $user->auth = 'manual'; $user->firstname = 'xuser' . $i; $user->lastname = 'xuser' . $i; $user->username = '******' . $i; $user->password = '******'; $user->email = "xuser{$i}@example.com"; $user->confirmed = 1; $user->mnethostid = $CFG->mnet_localhost_id; $user->lang = $CFG->lang; $user->maildisplay = 1; $user->timemodified = time(); $user->lastip = '0.0.0.0'; $userid = $DB->insert_record('user', $user); $testusers[$i] = $userid; } context_helper::create_instances(null, true); context_helper::reset_caches(); for ($i = 0; $i < CONTEXT_CACHE_MAX_SIZE + 100; $i++) { context_user::instance($testusers[$i]); if ($i == CONTEXT_CACHE_MAX_SIZE - 1) { $this->assertEqual(context_inspection::test_context_cache_size(), CONTEXT_CACHE_MAX_SIZE); } else { if ($i == CONTEXT_CACHE_MAX_SIZE) { // once the limit is reached roughly 1/3 of records should be removed from cache $this->assertEqual(context_inspection::test_context_cache_size(), (int) (CONTEXT_CACHE_MAX_SIZE * (2 / 3) + 102)); } } } // We keep the first 100 cached $prevsize = context_inspection::test_context_cache_size(); for ($i = 0; $i < 100; $i++) { context_user::instance($testusers[$i]); $this->assertEqual(context_inspection::test_context_cache_size(), $prevsize); } context_user::instance($testusers[102]); $this->assertEqual(context_inspection::test_context_cache_size(), $prevsize + 1); unset($testusers); // ================================================================= // ======= basic test of legacy functions ========================== // ================================================================= // note: watch out, the fake site might be pretty borked already $this->assertIdentical(get_system_context(), context_system::instance()); foreach ($DB->get_records('context') as $contextid => $record) { $context = context::instance_by_id($contextid); $this->assertIdentical(get_context_instance_by_id($contextid), $context); $this->assertIdentical(get_context_instance($record->contextlevel, $record->instanceid), $context); $this->assertIdentical(get_parent_contexts($context), $context->get_parent_context_ids()); if ($context->id == SYSCONTEXTID) { $this->assertIdentical(get_parent_contextid($context), false); } else { $this->assertIdentical(get_parent_contextid($context), $context->get_parent_context()->id); } } $children = get_child_contexts($systemcontext); $this->assertEqual(count($children), $DB->count_records('context') - 1); unset($children); $DB->delete_records('context', array('contextlevel' => CONTEXT_BLOCK)); create_contexts(); $this->assertFalse($DB->record_exists('context', array('contextlevel' => CONTEXT_BLOCK))); $DB->set_field('context', 'depth', 0, array('contextlevel' => CONTEXT_BLOCK)); build_context_path(); $this->assertFalse($DB->record_exists('context', array('depth' => 0))); $lastcourse = $DB->get_field_sql("SELECT MAX(id) FROM {course}"); $DB->delete_records('course', array('id' => $lastcourse)); $lastcategory = $DB->get_field_sql("SELECT MAX(id) FROM {course_categories}"); $DB->delete_records('course_categories', array('id' => $lastcategory)); $lastuser = $DB->get_field_sql("SELECT MAX(id) FROM {user} WHERE deleted=0"); $DB->delete_records('user', array('id' => $lastuser)); $DB->delete_records('block_instances', array('parentcontextid' => $frontpagepagecontext->id)); $DB->delete_records('course_modules', array('id' => $frontpagepagecontext->instanceid)); cleanup_contexts(); $count = 1; //system $count += $DB->count_records('user', array('deleted' => 0)); $count += $DB->count_records('course_categories'); $count += $DB->count_records('course'); $count += $DB->count_records('course_modules'); $count += $DB->count_records('block_instances'); $this->assertEqual($DB->count_records('context'), $count); context_helper::reset_caches(); preload_course_contexts($SITE->id); $this->assertEqual(context_inspection::test_context_cache_size(), 1); context_helper::reset_caches(); list($select, $join) = context_instance_preload_sql('c.id', CONTEXT_COURSECAT, 'ctx'); $sql = "SELECT c.id {$select} FROM {course_categories} c {$join}"; $records = $DB->get_records_sql($sql); foreach ($records as $record) { context_instance_preload($record); $record = (array) $record; $this->assertEqual(1, count($record)); // only id left } $this->assertEqual(count($records), context_inspection::test_context_cache_size()); accesslib_clear_all_caches(true); $DB->delete_records('cache_flags', array()); mark_context_dirty($systemcontext->path); $dirty = get_cache_flags('accesslib/dirtycontexts', time() - 2); $this->assertTrue(isset($dirty[$systemcontext->path])); accesslib_clear_all_caches(false); $DB->delete_records('cache_flags', array()); $course = $DB->get_record('course', array('id' => $testcourses[2])); $context = get_context_instance(CONTEXT_COURSE, $course->id); $oldpath = $context->path; $miscid = $DB->get_field_sql("SELECT MIN(id) FROM {course_categories}"); $categorycontext = context_coursecat::instance($miscid); $course->category = $miscid; $DB->update_record('course', $course); context_moved($context, $categorycontext); $context = get_context_instance(CONTEXT_COURSE, $course->id); $this->assertIdentical($context->get_parent_context(), $categorycontext); $this->assertTrue($DB->record_exists('context', array('contextlevel' => CONTEXT_COURSE, 'instanceid' => $testcourses[2]))); delete_context(CONTEXT_COURSE, $testcourses[2]); $this->assertFalse($DB->record_exists('context', array('contextlevel' => CONTEXT_COURSE, 'instanceid' => $testcourses[2]))); $name = get_contextlevel_name(CONTEXT_COURSE); $this->assertFalse(empty($name)); $context = get_context_instance(CONTEXT_COURSE, $testcourses[2]); $name = print_context_name($context); $this->assertFalse(empty($name)); $url = get_context_url($coursecontext); $this->assertFalse($url instanceof modole_url); $page = $DB->get_record('page', array('id' => $testpages[7])); $context = get_context_instance(CONTEXT_MODULE, $page->id); $coursecontext = get_course_context($context); $this->assertEqual($coursecontext->contextlevel, CONTEXT_COURSE); $this->assertEqual(get_courseid_from_context($context), $page->course); $caps = fetch_context_capabilities($systemcontext); $this->assertTrue(is_array($caps)); unset($caps); }
/** * This function checks to see whether local database customisations are up-to-date * by comparing $CFG->local_version to the variable $local_version defined in * local/version.php. If not, it looks for a function called 'xmldb_local_upgrade' * in a file called 'local/db/upgrade.php', and if it's there calls it with the * appropiate $oldversion parameter. Then it updates $CFG->local_version. * * @uses $CFG */ function upgrade_local_db($startcallback, $endcallback) { global $CFG, $DB; // if we don't have code version, just return false if (!file_exists($CFG->dirroot . '/local/version.php')) { return; } $local_version = null; require $CFG->dirroot . '/local/version.php'; // Get code versions if (empty($CFG->local_version)) { // install $startcallback('local', true); if (file_exists($CFG->dirroot . '/local/db/install.php')) { require_once $CFG->dirroot . '/local/db/install.php'; xmldb_local_install(); } set_config('local_version', $local_version); /// Install various components events_update_definition('local'); update_capabilities('local'); message_update_providers('local'); $endcallback('local', true); } else { if ($local_version > $CFG->local_version) { // upgrade! $startcallback('local', false); if (file_exists($CFG->dirroot . '/local/db/upgrade.php')) { require_once $CFG->dirroot . '/local/db/upgrade.php'; xmldb_local_upgrade($CFG->local_version); } set_config('local_version', $local_version); /// Upgrade various components events_update_definition('local'); update_capabilities('local'); message_update_providers('local'); $endcallback('local', false); } else { if ($local_version < $CFG->local_version) { throw new downgrade_exception('local', $CFG->local_version, $local_version); } } } }
function xmldb_main_install() { global $CFG, $DB, $SITE; /// make sure system context exists $syscontext = get_system_context(false); if ($syscontext->id != 1) { throw new moodle_exception('generalexceptionmessage', 'error', '', 'Unexpected system context id created!'); } // create site course $newsite = new object(); $newsite->fullname = ""; $newsite->shortname = ""; $newsite->summary = NULL; $newsite->newsitems = 3; $newsite->numsections = 0; $newsite->category = 0; $newsite->format = 'site'; // Only for this course $newsite->teacher = get_string("defaultcourseteacher"); $newsite->teachers = get_string("defaultcourseteachers"); $newsite->student = get_string("defaultcoursestudent"); $newsite->students = get_string("defaultcoursestudents"); $newsite->timemodified = time(); $DB->insert_record('course', $newsite); $SITE = get_site(); if ($SITE->id != 1) { throw new moodle_exception('generalexceptionmessage', 'error', '', 'Unexpected site course id created!'); } /// make sure site course context exists get_context_instance(CONTEXT_COURSE, $SITE->id); /// create default course category $cat = get_course_category(); $defaults = array('rolesactive' => '0', 'auth' => 'email', 'auth_pop3mailbox' => 'INBOX', 'enrol' => 'manual', 'enrol_plugins_enabled' => 'manual', 'style' => 'default', 'template' => 'default', 'theme' => 'standardwhite', 'filter_multilang_converted' => 1, 'siteidentifier' => random_string(32) . get_host_from_url($CFG->wwwroot), 'backup_version' => 2008111700, 'backup_release' => '2.0 dev', 'blocks_version' => 2007081300, 'mnet_dispatcher_mode' => 'off', 'sessiontimeout' => 7200, 'stringfilters' => '', 'filterall' => 0, 'texteditors' => 'tinymce,textarea'); foreach ($defaults as $key => $value) { set_config($key, $value); } /// bootstrap mnet $mnethost = new object(); $mnethost->wwwroot = $CFG->wwwroot; $mnethost->name = ''; $mnethost->name = ''; $mnethost->public_key = ''; if (empty($_SERVER['SERVER_ADDR'])) { // SERVER_ADDR is only returned by Apache-like webservers preg_match("@^(?:http[s]?://)?([A-Z0-9\\-\\.]+).*@i", $CFG->wwwroot, $matches); $my_hostname = $matches[1]; $my_ip = gethostbyname($my_hostname); // Returns unmodified hostname on failure. DOH! if ($my_ip == $my_hostname) { $mnethost->ip_address = 'UNKNOWN'; } else { $mnethost->ip_address = $my_ip; } } else { $mnethost->ip_address = $_SERVER['SERVER_ADDR']; } $mnetid = $DB->insert_record('mnet_host', $mnethost); set_config('mnet_localhost_id', $mnetid); // Initial insert of mnet applications info $mnet_app = new object(); $mnet_app->name = 'moodle'; $mnet_app->display_name = 'Moodle'; $mnet_app->xmlrpc_server_url = '/mnet/xmlrpc/server.php'; $mnet_app->sso_land_url = '/auth/mnet/land.php'; $mnet_app->sso_jump_url = '/auth/mnet/land.php'; $DB->insert_record('mnet_application', $mnet_app); $mnet_app = new object(); $mnet_app->name = 'mahara'; $mnet_app->display_name = 'Mahara'; $mnet_app->xmlrpc_server_url = '/api/xmlrpc/server.php'; $mnet_app->sso_land_url = '/auth/xmlrpc/land.php'; $mnet_app->sso_jump_url = '/auth/xmlrpc/jump.php'; $DB->insert_record('mnet_application', $mnet_app); /// insert log entries - replaces statements section in install.xml update_log_display_entry('user', 'view', 'user', 'CONCAT(firstname,\' \',lastname)'); update_log_display_entry('course', 'user report', 'user', 'CONCAT(firstname,\' \',lastname)'); update_log_display_entry('course', 'view', 'course', 'fullname'); update_log_display_entry('course', 'update', 'course', 'fullname'); update_log_display_entry('course', 'enrol', 'course', 'fullname'); update_log_display_entry('course', 'unenrol', 'course', 'fullname'); update_log_display_entry('course', 'report log', 'course', 'fullname'); update_log_display_entry('course', 'report live', 'course', 'fullname'); update_log_display_entry('course', 'report outline', 'course', 'fullname'); update_log_display_entry('course', 'report participation', 'course', 'fullname'); update_log_display_entry('course', 'report stats', 'course', 'fullname'); update_log_display_entry('message', 'write', 'user', 'CONCAT(firstname,\' \',lastname)'); update_log_display_entry('message', 'read', 'user', 'CONCAT(firstname,\' \',lastname)'); update_log_display_entry('message', 'add contact', 'user', 'CONCAT(firstname,\' \',lastname)'); update_log_display_entry('message', 'remove contact', 'user', 'CONCAT(firstname,\' \',lastname)'); update_log_display_entry('message', 'block contact', 'user', 'CONCAT(firstname,\' \',lastname)'); update_log_display_entry('message', 'unblock contact', 'user', 'CONCAT(firstname,\' \',lastname)'); update_log_display_entry('group', 'view', 'groups', 'name'); /// Create guest record $guest = new object(); $guest->auth = 'manual'; $guest->username = '******'; $guest->password = hash_internal_user_password('guest'); $guest->firstname = get_string('guestuser'); $guest->lastname = ' '; $guest->email = 'root@localhost'; $guest->description = get_string('guestuserinfo'); $guest->mnethostid = $CFG->mnet_localhost_id; $guest->confirmed = 1; $guest->lang = $CFG->lang; $guest->timemodified = time(); $guest->id = $DB->insert_record('user', $guest); /// Now create admin user $admin = new object(); $admin->auth = 'manual'; $admin->firstname = get_string('admin'); $admin->lastname = get_string('user'); $admin->username = '******'; $admin->password = '******'; $admin->email = ''; $admin->confirmed = 1; $admin->mnethostid = $CFG->mnet_localhost_id; $admin->lang = $CFG->lang; $admin->maildisplay = 1; $admin->timemodified = time(); $admin->lastip = CLI_SCRIPT ? '0.0.0.0' : getremoteaddr(); // installation hijacking prevention $admin->id = $DB->insert_record('user', $admin); /// Install the roles system. $adminrole = create_role(get_string('administrator'), 'admin', get_string('administratordescription'), 'moodle/legacy:admin'); $coursecreatorrole = create_role(get_string('coursecreators'), 'coursecreator', get_string('coursecreatorsdescription'), 'moodle/legacy:coursecreator'); $editteacherrole = create_role(get_string('defaultcourseteacher'), 'editingteacher', get_string('defaultcourseteacherdescription'), 'moodle/legacy:editingteacher'); $noneditteacherrole = create_role(get_string('noneditingteacher'), 'teacher', get_string('noneditingteacherdescription'), 'moodle/legacy:teacher'); $studentrole = create_role(get_string('defaultcoursestudent'), 'student', get_string('defaultcoursestudentdescription'), 'moodle/legacy:student'); $guestrole = create_role(get_string('guest'), 'guest', get_string('guestdescription'), 'moodle/legacy:guest'); $userrole = create_role(get_string('authenticateduser'), 'user', get_string('authenticateduserdescription'), 'moodle/legacy:user'); /// Now is the correct moment to install capabilities - after creation of legacy roles, but before assigning of roles assign_capability('moodle/site:doanything', CAP_ALLOW, $adminrole, $syscontext->id); update_capabilities('moodle'); /// assign default roles role_assign($guestrole, $guest->id, 0, $syscontext->id); role_assign($adminrole, $admin->id, 0, $syscontext->id); /// Default allow assign/override/switch. $defaultallows = array($coursecreatorrole => $noneditteacherrole, $coursecreatorrole => $editteacherrole, $coursecreatorrole => $studentrole, $coursecreatorrole => $guestrole, $editteacherrole => $noneditteacherrole, $editteacherrole => $studentrole, $editteacherrole => $guestrole); foreach ($defaultallows as $fromroleid => $toroleid) { allow_assign($fromroleid, $toroleid); allow_override($fromroleid, $toroleid); // There is a rant about this in MDL-15841. allow_switch($fromroleid, $toroleid); } allow_switch($noneditteacherrole, $studentrole); /// Set up the context levels where you can assign each role. set_role_contextlevels($adminrole, get_default_contextlevels('admin')); set_role_contextlevels($coursecreatorrole, get_default_contextlevels('coursecreator')); set_role_contextlevels($editteacherrole, get_default_contextlevels('editingteacher')); set_role_contextlevels($noneditteacherrole, get_default_contextlevels('teacher')); set_role_contextlevels($studentrole, get_default_contextlevels('student')); set_role_contextlevels($guestrole, get_default_contextlevels('guest')); set_role_contextlevels($userrole, get_default_contextlevels('user')); }
/** * Upgrade moodle core * @param float $version target version * @param bool $verbose * @return void, may throw exception */ function upgrade_core($version, $verbose) { global $CFG; raise_memory_limit(MEMORY_EXTRA); require_once $CFG->libdir . '/db/upgrade.php'; // Defines upgrades try { // Reset caches before any output. cache_helper::purge_all(true); purge_all_caches(); // Upgrade current language pack if we can upgrade_language_pack(); print_upgrade_part_start('moodle', false, $verbose); // Pre-upgrade scripts for local hack workarounds. $preupgradefile = "{$CFG->dirroot}/local/preupgrade.php"; if (file_exists($preupgradefile)) { core_php_time_limit::raise(); require $preupgradefile; // Reset upgrade timeout to default. upgrade_set_timeout(); } $result = xmldb_main_upgrade($CFG->version); if ($version > $CFG->version) { // store version if not already there upgrade_main_savepoint($result, $version, false); } // perform all other component upgrade routines update_capabilities('moodle'); log_update_descriptions('moodle'); external_update_descriptions('moodle'); events_update_definition('moodle'); message_update_providers('moodle'); // Update core definitions. cache_helper::update_definitions(true); // Purge caches again, just to be sure we arn't holding onto old stuff now. cache_helper::purge_all(true); purge_all_caches(); // Clean up contexts - more and more stuff depends on existence of paths and contexts context_helper::cleanup_instances(); context_helper::create_instances(null, false); context_helper::build_all_paths(false); $syscontext = context_system::instance(); $syscontext->mark_dirty(); print_upgrade_part_end('moodle', false, $verbose); } catch (Exception $ex) { upgrade_handle_exception($ex); } }
/** * Upgrade moodle core * @param float $version target version * @param bool $verbose * @return void, may throw exception */ function upgrade_core($version, $verbose) { global $CFG; raise_memory_limit(MEMORY_EXTRA); require_once $CFG->libdir . '/db/upgrade.php'; // Defines upgrades try { // Reset caches before any output purge_all_caches(); // Disable the use of cache stores here. We will reset the factory after we've performed the installation. // This ensures that we don't permanently cache anything during installation. cache_factory::disable_stores(); // Upgrade current language pack if we can upgrade_language_pack(); print_upgrade_part_start('moodle', false, $verbose); // one time special local migration pre 2.0 upgrade script if ($CFG->version < 2007101600) { $pre20upgradefile = "{$CFG->dirroot}/local/upgrade_pre20.php"; if (file_exists($pre20upgradefile)) { set_time_limit(0); require $pre20upgradefile; // reset upgrade timeout to default upgrade_set_timeout(); } } $result = xmldb_main_upgrade($CFG->version); if ($version > $CFG->version) { // store version if not already there upgrade_main_savepoint($result, $version, false); } // perform all other component upgrade routines update_capabilities('moodle'); log_update_descriptions('moodle'); external_update_descriptions('moodle'); events_update_definition('moodle'); message_update_providers('moodle'); // Update core definitions. cache_helper::update_definitions(true); // Reset the cache, this returns it to a normal operation state. cache_factory::reset(); // Purge caches again, just to be sure we arn't holding onto old stuff now. purge_all_caches(); // Clean up contexts - more and more stuff depends on existence of paths and contexts context_helper::cleanup_instances(); context_helper::create_instances(null, false); context_helper::build_all_paths(false); $syscontext = context_system::instance(); $syscontext->mark_dirty(); print_upgrade_part_end('moodle', false, $verbose); } catch (Exception $ex) { upgrade_handle_exception($ex); } }
/** * Find and check all modules and load them up or upgrade them if necessary * * @uses $db * @uses $CFG * @param string $return The url to prompt the user to continue to * @todo Finish documenting this function */ function upgrade_activity_modules($return) { global $CFG, $db; if (!($mods = get_list_of_plugins('mod'))) { error('No modules installed!'); } $updated_modules = false; $strmodulesetup = get_string('modulesetup'); foreach ($mods as $mod) { if ($mod == 'NEWMODULE') { // Someone has unzipped the template, ignore it continue; } $fullmod = $CFG->dirroot . '/mod/' . $mod; unset($module); if (is_readable($fullmod . '/version.php')) { include_once $fullmod . '/version.php'; // defines $module with version etc } else { notify('Module ' . $mod . ': ' . $fullmod . '/version.php was not readable'); continue; } $oldupgrade = false; $newupgrade = false; if (is_readable($fullmod . '/db/' . $CFG->dbtype . '.php')) { include_once $fullmod . '/db/' . $CFG->dbtype . '.php'; // defines old upgrading function $oldupgrade = true; } if (is_readable($fullmod . '/db/upgrade.php')) { include_once $fullmod . '/db/upgrade.php'; // defines new upgrading function $newupgrade = true; } if (!isset($module)) { continue; } if (!empty($module->requires)) { if ($module->requires > $CFG->version) { $info = new object(); $info->modulename = $mod; $info->moduleversion = $module->version; $info->currentmoodle = $CFG->version; $info->requiremoodle = $module->requires; if (!$updated_modules) { print_header($strmodulesetup, $strmodulesetup, build_navigation(array(array('name' => $strmodulesetup, 'link' => null, 'type' => 'misc'))), '', upgrade_get_javascript(), false, ' ', ' '); } upgrade_log_start(); notify(get_string('modulerequirementsnotmet', 'error', $info)); $updated_modules = true; continue; } } $module->name = $mod; // The name MUST match the directory include_once $fullmod . '/lib.php'; // defines upgrading and/or installing functions if ($currmodule = get_record('modules', 'name', $module->name)) { if ($currmodule->version == $module->version) { // do nothing } else { if ($currmodule->version < $module->version) { /// If versions say that we need to upgrade but no upgrade files are available, notify and continue if (!$oldupgrade && !$newupgrade) { notify('Upgrade files ' . $mod . ': ' . $fullmod . '/db/' . $CFG->dbtype . '.php or ' . $fullmod . '/db/upgrade.php were not readable'); continue; } if (!$updated_modules) { print_header($strmodulesetup, $strmodulesetup, build_navigation(array(array('name' => $strmodulesetup, 'link' => null, 'type' => 'misc'))), '', upgrade_get_javascript(), false, ' ', ' '); } upgrade_log_start(); print_heading($module->name . ' module needs upgrading'); /// Run de old and new upgrade functions for the module $oldupgrade_function = $module->name . '_upgrade'; $newupgrade_function = 'xmldb_' . $module->name . '_upgrade'; /// First, the old function if exists $oldupgrade_status = true; if ($oldupgrade && function_exists($oldupgrade_function)) { $db->debug = true; $oldupgrade_status = $oldupgrade_function($currmodule->version, $module); if (!$oldupgrade_status) { notify('Upgrade function ' . $oldupgrade_function . ' did not complete successfully.'); } } else { if ($oldupgrade) { notify('Upgrade function ' . $oldupgrade_function . ' was not available in ' . $mod . ': ' . $fullmod . '/db/' . $CFG->dbtype . '.php'); } } /// Then, the new function if exists and the old one was ok $newupgrade_status = true; if ($newupgrade && function_exists($newupgrade_function) && $oldupgrade_status) { $db->debug = true; $newupgrade_status = $newupgrade_function($currmodule->version, $module); } else { if ($newupgrade && $oldupgrade_status) { notify('Upgrade function ' . $newupgrade_function . ' was not available in ' . $mod . ': ' . $fullmod . '/db/upgrade.php'); } } $db->debug = false; /// Now analyze upgrade results if ($oldupgrade_status && $newupgrade_status) { // No upgrading failed // OK so far, now update the modules record $module->id = $currmodule->id; if (!update_record('modules', $module)) { error('Could not update ' . $module->name . ' record in modules table!'); } remove_dir($CFG->dataroot . '/cache', true); // flush cache notify(get_string('modulesuccess', '', $module->name), 'notifysuccess'); echo '<hr />'; } else { notify('Upgrading ' . $module->name . ' from ' . $currmodule->version . ' to ' . $module->version . ' FAILED!'); } /// Update the capabilities table? if (!update_capabilities('mod/' . $module->name)) { error('Could not update ' . $module->name . ' capabilities!'); } events_update_definition('mod/' . $module->name); $updated_modules = true; } else { upgrade_log_start(); error('Version mismatch: ' . $module->name . ' can\'t downgrade ' . $currmodule->version . ' -> ' . $module->version . ' !'); } } } else { // module not installed yet, so install it if (!$updated_modules) { print_header($strmodulesetup, $strmodulesetup, build_navigation(array(array('name' => $strmodulesetup, 'link' => null, 'type' => 'misc'))), '', upgrade_get_javascript(), false, ' ', ' '); } upgrade_log_start(); print_heading($module->name); $updated_modules = true; $db->debug = true; @set_time_limit(0); // To allow slow databases to complete the long SQL /// Both old .sql files and new install.xml are supported /// but we priorize install.xml (XMLDB) if present if (file_exists($fullmod . '/db/install.xml')) { $status = install_from_xmldb_file($fullmod . '/db/install.xml'); //New method } else { $status = modify_database($fullmod . '/db/' . $CFG->dbtype . '.sql'); //Old method } $db->debug = false; /// Continue with the installation, roles and other stuff if ($status) { if ($module->id = insert_record('modules', $module)) { /// Capabilities if (!update_capabilities('mod/' . $module->name)) { error('Could not set up the capabilities for ' . $module->name . '!'); } /// Events events_update_definition('mod/' . $module->name); /// Run local install function if there is one $installfunction = $module->name . '_install'; if (function_exists($installfunction)) { if (!$installfunction()) { notify('Encountered a problem running install function for ' . $module->name . '!'); } } notify(get_string('modulesuccess', '', $module->name), 'notifysuccess'); echo '<hr />'; } else { error($module->name . ' module could not be added to the module list!'); } } else { error($module->name . ' tables could NOT be set up successfully!'); } } /// Check submodules of this module if necessary $submoduleupgrade = $module->name . '_upgrade_submodules'; if (function_exists($submoduleupgrade)) { $submoduleupgrade(); } /// Run any defaults or final code that is necessary for this module if (is_readable($fullmod . '/defaults.php')) { // Insert default values for any important configuration variables unset($defaults); include $fullmod . '/defaults.php'; // include here means execute, not library include if (!empty($defaults)) { foreach ($defaults as $name => $value) { if (!isset($CFG->{$name})) { set_config($name, $value); } } } } } upgrade_log_finish(); // finish logging if started if ($updated_modules) { print_continue($return); print_footer('none'); die; } }
/** * Find and check all submodules and load them up or upgrade them if necessary * * @global object * @global object */ function vmoodle_upgrade_subplugins_modules($startcallback, $endcallback, $verbose = true) { global $CFG, $DB; include $CFG->dirroot . '/local/vmoodle/db/subplugins.php'; foreach ($subplugins as $type => $subpluginpath) { $plugindirs = glob($CFG->dirroot . '/' . $subpluginpath . '/*'); foreach ($plugindirs as $dir) { $plug = basename($dir); $fullplug = $dir; if ($plug === 'CVS') { // Someone has unzipped the template, ignore it. continue; } if ($plug === 'NEWMODULE') { // Someone has unzipped the template, ignore it. continue; } // Reset time so that it works when installing a large number of plugins. set_time_limit(600); $component = clean_param($type . '_' . $plug, PARAM_COMPONENT); // standardised plugin name // Check plugin dir is valid name. if (empty($component)) { throw new plugin_defective_exception($type . '_' . $plug, 'Invalid plugin directory name.'); } if (!is_readable($fullplug . '/version.php')) { continue; } $plugin = new stdClass(); require $fullplug . '/version.php'; // Defines $plugin with version etc. // If plugin tells us it's full name we may check the location. if (isset($plugin->component)) { if ($plugin->component !== $component) { throw new plugin_defective_exception($component, 'Plugin installed in wrong folder.'); } } if (empty($plugin->version)) { throw new plugin_defective_exception($component, 'Missing version value in version.php'); } $plugin->name = $plug; $plugin->fullname = $component; if (!empty($plugin->requires)) { if ($plugin->requires > $CFG->version) { throw new upgrade_requires_exception($component, $plugin->version, $CFG->version, $plugin->requires); } else { if ($plugin->requires < 2010000000) { throw new plugin_defective_exception($component, 'Plugin is not compatible with Moodle 2.x or later.'); } } } // Try to recover from interrupted install.php if needed. if (file_exists($fullplug . '/db/install.php')) { if (get_config($plugin->fullname, 'installrunning')) { require_once $fullplug . '/db/install.php'; $recover_install_function = 'xmldb_' . $plugin->fullname . '_install_recovery'; if (function_exists($recover_install_function)) { $startcallback($component, true, $verbose); $recover_install_function(); unset_config('installrunning', $plugin->fullname); update_capabilities($component); log_update_descriptions($component); external_update_descriptions($component); events_update_definition($component); message_update_providers($component); if ($type === 'message') { message_update_processors($plug); } vmoodle_upgrade_plugin_mnet_functions($component, $fullplug); // Fix wrongly twicked paths. if ($rpc_shifted_defines = $DB->get_records_select('mnet_rpc', " xmlrpcpath LIKE 'vmoodleadminset' ", array())) { foreach ($rpc_shifted_defines as $rpc) { $rpc->xmlrpcpath = str_replace('vmoocleadminset', 'local/vmoodle/plugins'); $DB->update_record('mnet_rpc', $rpc); } } $endcallback($component, true, $verbose); } } } $installedversion = get_config($plugin->fullname, 'version'); if (empty($installedversion)) { // New installation. $startcallback($component, true, $verbose); // Install tables if defined. if (file_exists($fullplug . '/db/install.xml')) { $DB->get_manager()->install_from_xmldb_file($fullplug . '/db/install.xml'); } // Store version. upgrade_plugin_savepoint(true, $plugin->version, $type, $plug, false); // Execute post install file. if (file_exists($fullplug . '/db/install.php')) { require_once $fullplug . '/db/install.php'; set_config('installrunning', 1, $plugin->fullname); $post_install_function = 'xmldb_' . $plugin->fullname . '_install'; $post_install_function(); unset_config('installrunning', $plugin->fullname); } // Install various components. update_capabilities($component); log_update_descriptions($component); external_update_descriptions($component); events_update_definition($component); message_update_providers($component); if ($type === 'message') { message_update_processors($plug); } vmoodle_upgrade_plugin_mnet_functions($component, $fullplug); // Fix wrongly twicked paths. if ($rpc_shifted_defines = $DB->get_records_select('mnet_rpc', " xmlrpcpath LIKE 'vmoodleadminset' ", array())) { foreach ($rpc_shifted_defines as $rpc) { $rpc->xmlrpcpath = str_replace('vmoocleadminset', 'local/vmoodle/plugins'); $DB->update_record('mnet_rpc', $rpc); } } purge_all_caches(); $endcallback($component, true, $verbose); } else { if ($installedversion < $plugin->version) { // Upgrade // Run the upgrade function for the plugin. $startcallback($component, false, $verbose); if (is_readable($fullplug . '/db/upgrade.php')) { require_once $fullplug . '/db/upgrade.php'; // Defines upgrading function $newupgrade_function = 'xmldb_' . $plugin->fullname . '_upgrade'; $result = $newupgrade_function($installedversion); } else { $result = true; } $installedversion = get_config($plugin->fullname, 'version'); if ($installedversion < $plugin->version) { // store version if not already there. upgrade_plugin_savepoint($result, $plugin->version, $type, $plug, false); } // Upgrade various components. update_capabilities($component); log_update_descriptions($component); external_update_descriptions($component); events_update_definition($component); message_update_providers($component); if ($type === 'message') { message_update_processors($plug); } vmoodle_upgrade_plugin_mnet_functions($component, $fullplug); purge_all_caches(); $endcallback($component, false, $verbose); } else { if ($installedversion > $plugin->version) { throw new downgrade_exception($component, $installedversion, $plugin->version); } } } } } }
/** * This function checks to see whether local database customisations are up-to-date * by comparing $CFG->local_version to the variable $local_version defined in * local/version.php. If not, it looks for a function called 'xmldb_local_upgrade' * in a file called 'local/db/upgrade.php', and if it's there calls it with the * appropiate $oldversion parameter. Then it updates $CFG->local_version. * On success it prints a continue link. On failure it prints an error. * * @uses $CFG * @uses $db to do something really evil with the debug setting that should probably be eliminated. TODO! * @param string $continueto a URL passed to print_continue() if the local upgrades succeed. */ function upgrade_local_db($continueto) { global $CFG, $db; // if we don't have code version or a db upgrade file, just return true, we're unneeded if (!file_exists($CFG->dirroot . '/local/version.php') || !file_exists($CFG->dirroot . '/local/db/upgrade.php')) { return true; } require_once $CFG->dirroot . '/local/version.php'; // Get code versions if (empty($CFG->local_version)) { // normally we'd install, but just replay all the upgrades. $CFG->local_version = 0; } if ($local_version > $CFG->local_version) { // upgrade! $strdatabaseupgrades = get_string('databaseupgrades'); print_header($strdatabaseupgrades, $strdatabaseupgrades, build_navigation(array(array('name' => $strdatabaseupgrades, 'link' => null, 'type' => 'misc'))), '', upgrade_get_javascript()); upgrade_log_start(); require_once $CFG->dirroot . '/local/db/upgrade.php'; $db->debug = true; if (xmldb_local_upgrade($CFG->local_version)) { $db->debug = false; if (set_config('local_version', $local_version)) { notify(get_string('databasesuccess'), 'notifysuccess'); notify(get_string('databaseupgradelocal', '', $local_version), 'notifysuccess'); print_continue($continueto); print_footer('none'); exit; } else { error('Upgrade of local database customisations failed! (Could not update version in config table)'); } } else { $db->debug = false; error('Upgrade failed! See local/version.php'); } } else { if ($local_version < $CFG->local_version) { upgrade_log_start(); notify('WARNING!!! The local version you are using is OLDER than the version that made these databases!'); } } /// Capabilities if (!update_capabilities('local')) { error('Could not set up the capabilities for local!'); } if (!events_update_definition('local')) { error('Could not set up the events definitions for local!'); } upgrade_log_finish(); }
die; } else { /// Launch main upgrade try { // Upgrade current language pack if we can if (empty($CFG->skiplangupgrade)) { upgrade_language_pack(false); } print_upgrade_part_start('moodle', false); $result = xmldb_main_upgrade($CFG->version); if ($version > $CFG->version) { // store version if not already there upgrade_main_savepoint($result, $version, false); } // perform all other component upgrade routines update_capabilities('moodle'); events_update_definition('moodle'); message_update_providers('moodle'); message_update_providers('message'); remove_dir($CFG->dataroot . '/cache', true); // flush cache print_upgrade_part_end('moodle', false); } catch (Exception $ex) { upgrade_handle_exception($ex); } } } } else { if ($version < $CFG->version) { notify("WARNING!!! The code you are using is OLDER than the version that made these databases!"); }
public function test_update_capabilities() { global $DB, $SITE; $this->resetAfterTest(true); $froncontext = context_course::instance($SITE->id); $student = $DB->get_record('role', array('archetype'=>'student')); $teacher = $DB->get_record('role', array('archetype'=>'teacher')); $existingcaps = $DB->get_records('capabilities', array(), 'id', 'name, captype, contextlevel, component, riskbitmask'); $this->assertFalse(isset($existingcaps['moodle/site:restore'])); // moved to new 'moodle/restore:restorecourse' $this->assertTrue(isset($existingcaps['moodle/restore:restorecourse'])); // new cap from 'moodle/site:restore' $this->assertTrue(isset($existingcaps['moodle/site:sendmessage'])); // new capability $this->assertTrue(isset($existingcaps['moodle/backup:backupcourse'])); $this->assertTrue(isset($existingcaps['moodle/backup:backupsection'])); // cloned from 'moodle/backup:backupcourse' $this->assertTrue(isset($existingcaps['moodle/site:approvecourse'])); // updated bitmask $this->assertTrue(isset($existingcaps['moodle/course:manageactivities'])); $this->assertTrue(isset($existingcaps['mod/page:addinstance'])); // cloned from core 'moodle/course:manageactivities' // fake state before upgrade $DB->set_field('capabilities', 'name', 'moodle/site:restore', array('name'=>'moodle/restore:restorecourse')); $DB->set_field('role_capabilities', 'capability', 'moodle/site:restore', array('capability'=>'moodle/restore:restorecourse')); assign_capability('moodle/site:restore', CAP_PROHIBIT, $teacher->id, $froncontext->id, true); $perms1 = array_values($DB->get_records('role_capabilities', array('capability'=>'moodle/site:restore', 'roleid'=>$teacher->id), 'contextid, permission', 'contextid, permission')); $DB->delete_records('role_capabilities', array('capability'=>'moodle/site:sendmessage')); $DB->delete_records('capabilities', array('name'=>'moodle/site:sendmessage')); $DB->delete_records('role_capabilities', array('capability'=>'moodle/backup:backupsection')); $DB->delete_records('capabilities', array('name'=>'moodle/backup:backupsection')); assign_capability('moodle/backup:backupcourse', CAP_PROHIBIT, $student->id, $froncontext->id, true); assign_capability('moodle/backup:backupcourse', CAP_ALLOW, $teacher->id, $froncontext->id, true); $DB->set_field('capabilities', 'riskbitmask', 0, array('name'=>'moodle/site:approvecourse')); $DB->delete_records('role_capabilities', array('capability'=>'mod/page:addinstance')); $DB->delete_records('capabilities', array('name'=>'mod/page:addinstance')); assign_capability('moodle/course:manageactivities', CAP_PROHIBIT, $student->id, $froncontext->id, true); assign_capability('moodle/course:manageactivities', CAP_ALLOW, $teacher->id, $froncontext->id, true); // execute core update_capabilities('moodle'); // only core should be upgraded $caps = $DB->get_records('capabilities', array(), 'id', 'name, captype, contextlevel, component, riskbitmask'); $this->assertFalse(isset($existingcaps['moodle/site:restore'])); $this->assertTrue(isset($caps['moodle/restore:restorecourse'])); $this->assertEquals($existingcaps['moodle/restore:restorecourse'], $caps['moodle/restore:restorecourse']); $perms2 = array_values($DB->get_records('role_capabilities', array('capability'=>'moodle/restore:restorecourse', 'roleid'=>$teacher->id), 'contextid, permission', 'contextid, permission')); $this->assertEquals($perms1, $perms2); $this->assertTrue(isset($caps['moodle/site:sendmessage'])); $this->assertEquals($existingcaps['moodle/site:sendmessage'], $caps['moodle/site:sendmessage']); $this->assertTrue(isset($caps['moodle/backup:backupsection'])); $this->assertEquals($existingcaps['moodle/backup:backupsection'], $caps['moodle/backup:backupsection']); $roles = $DB->get_records_sql('SELECT DISTINCT roleid AS id FROM {role_capabilities} WHERE capability=? OR capability=?', array('moodle/backup:backupcourse', 'moodle/backup:backupsection')); foreach ($roles as $role) { $perms1 = array_values($DB->get_records('role_capabilities', array('capability'=>'moodle/backup:backupcourse', 'roleid'=>$role->id), 'contextid, permission', 'contextid, permission')); $perms2 = array_values($DB->get_records('role_capabilities', array('capability'=>'moodle/backup:backupsection', 'roleid'=>$role->id), 'contextid, permission', 'contextid, permission')); $this->assertEquals($perms1, $perms2); } $this->assertTrue(isset($caps['moodle/site:approvecourse'])); $this->assertEquals($existingcaps['moodle/site:approvecourse'], $caps['moodle/site:approvecourse']); $this->assertFalse(isset($caps['mod/page:addinstance'])); // execute plugin update_capabilities('mod_page'); $caps = $DB->get_records('capabilities', array(), 'id', 'name, captype, contextlevel, component, riskbitmask'); $this->assertTrue(isset($caps['mod/page:addinstance'])); $roles = $DB->get_records_sql('SELECT DISTINCT roleid AS id FROM {role_capabilities} WHERE capability=? OR capability=?', array('moodle/course:manageactivities', 'mod/page:addinstance')); foreach ($roles as $role) { $perms1 = array_values($DB->get_records('role_capabilities', array('capability'=>'moodle/course:manageactivities', 'roleid'=>$role->id), 'contextid, permission', 'contextid, permission')); $perms2 = array_values($DB->get_records('role_capabilities', array('capability'=>'mod/page:addinstance', 'roleid'=>$role->id), 'contextid, permission', 'contextid, permission')); } $this->assertEquals($perms1, $perms2); }
/** * xmldb_hotpot_upgrade * * @param xxx $oldversion * @return xxx */ function xmldb_hotpot_upgrade($oldversion) { global $CFG, $DB; // this flag will be set to true if any upgrade needs to empty the HotPot cache $empty_cache = false; $dbman = $DB->get_manager(); //===== 1.9.0 upgrade line ======// // update hotpot grades from sites earlier than Moodle 1.9, 27th March 2008 $newversion = 2007101511; if ($oldversion < $newversion) { // ensure "hotpot_upgrade_grades" function is available require_once $CFG->dirroot . '/mod/hotpot/lib.php'; hotpot_upgrade_grades(); upgrade_mod_savepoint(true, "{$newversion}", 'hotpot'); } $newversion = 2008011200; if ($oldversion < $newversion) { // remove unused config setting unset_config('hotpot_initialdisable'); upgrade_mod_savepoint(true, "{$newversion}", 'hotpot'); } $newversion = 2010080301; if ($oldversion < $newversion) { // remove unused config settings unset_config('hotpot_showtimes'); unset_config('hotpot_excelencodings'); // modify table: hotpot $table = new xmldb_table('hotpot'); // expected structure of hotpot table when we start this upgrade: // (i.e. this is how things were at the end of Moodle 1.9) // id, course, name, summary, timeopen, timeclose, location, reference, // outputformat, navigation, studentfeedback, studentfeedbackurl, // forceplugins, shownextquiz, review, grade, grademethod, attempts, // password, subnet, clickreporting, timecreated, timemodified // convert, move and rename fields ($newname => $oldfield) $fields = array('outputformat' => new xmldb_field('outputformat', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL), 'timeopen' => new xmldb_field('timeopen', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0', 'studentfeedbackurl'), 'timeclose' => new xmldb_field('timeclose', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0', 'timeopen'), 'grademethod' => new xmldb_field('grademethod', XMLDB_TYPE_INTEGER, '4', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0', 'grade'), 'sourcefile' => new xmldb_field('reference', XMLDB_TYPE_CHAR, '255', null, null, null, null, 'name'), 'sourcelocation' => new xmldb_field('location', XMLDB_TYPE_INTEGER, '4', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0', 'sourcefile'), 'entrytext' => new xmldb_field('summary', XMLDB_TYPE_TEXT, 'small', null, null, null, null, 'sourcelocation'), 'reviewoptions' => new xmldb_field('review', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0'), 'attemptlimit' => new xmldb_field('attempts', XMLDB_TYPE_INTEGER, '6', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0', 'reviewoptions'), 'gradeweighting' => new xmldb_field('grade', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0', 'attemptlimit')); foreach ($fields as $newname => $field) { if ($dbman->field_exists($table, $field)) { xmldb_hotpot_fix_previous_field($dbman, $table, $field); $dbman->change_field_type($table, $field); if ($field->getName() != $newname) { $dbman->rename_field($table, $field, $newname); } } } // add fields $fields = array(new xmldb_field('sourcefile', XMLDB_TYPE_CHAR, '255', null, null, null, null, 'name'), new xmldb_field('sourcetype', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null, 'sourcefile'), new xmldb_field('sourceitemid', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0', 'sourcetype'), new xmldb_field('sourcelocation', XMLDB_TYPE_INTEGER, '4', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0', 'sourceitemid'), new xmldb_field('configfile', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null, 'sourcelocation'), new xmldb_field('configitemid', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0', 'configfile'), new xmldb_field('configlocation', XMLDB_TYPE_INTEGER, '4', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0', 'configitemid'), new xmldb_field('entrycm', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0', 'configlocation'), new xmldb_field('entrygrade', XMLDB_TYPE_INTEGER, '6', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '100', 'entrycm'), new xmldb_field('entrypage', XMLDB_TYPE_INTEGER, '2', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0', 'entrygrade'), new xmldb_field('entrytext', XMLDB_TYPE_TEXT, 'small', null, null, null, null, 'entrypage'), new xmldb_field('entryformat', XMLDB_TYPE_INTEGER, '4', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0', 'entrytext'), new xmldb_field('entryoptions', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0', 'entryformat'), new xmldb_field('exitpage', XMLDB_TYPE_INTEGER, '2', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0', 'entryoptions'), new xmldb_field('exittext', XMLDB_TYPE_TEXT, 'small', null, null, null, null, 'exitpage'), new xmldb_field('exitformat', XMLDB_TYPE_INTEGER, '4', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0', 'exittext'), new xmldb_field('exitoptions', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0', 'exitformat'), new xmldb_field('exitcm', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0', 'exitoptions'), new xmldb_field('title', XMLDB_TYPE_INTEGER, '6', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '3', 'navigation'), new xmldb_field('stopbutton', XMLDB_TYPE_INTEGER, '2', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0', 'title'), new xmldb_field('stoptext', XMLDB_TYPE_CHAR, '255', null, null, null, null, 'stopbutton'), new xmldb_field('usefilters', XMLDB_TYPE_INTEGER, '2', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0', 'stoptext'), new xmldb_field('useglossary', XMLDB_TYPE_INTEGER, '2', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0', 'usefilters'), new xmldb_field('usemediafilter', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null, 'useglossary'), new xmldb_field('timelimit', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0', 'timeclose'), new xmldb_field('delay1', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0', 'timelimit'), new xmldb_field('delay2', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0', 'delay1'), new xmldb_field('delay3', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '2', 'delay2'), new xmldb_field('discarddetails', XMLDB_TYPE_INTEGER, '2', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0', 'clickreporting')); foreach ($fields as $field) { if (!$dbman->field_exists($table, $field)) { xmldb_hotpot_fix_previous_field($dbman, $table, $field); $dbman->add_field($table, $field); } } // remove field: forceplugins (replaced by "usemediafilter") $field = new xmldb_field('forceplugins', XMLDB_TYPE_INTEGER, '4', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0'); if ($dbman->field_exists($table, $field)) { $DB->execute('UPDATE {hotpot} SET ' . "usemediafilter='moodle'" . ' WHERE forceplugins=1'); $dbman->drop_field($table, $field); } // remove field: shownextquiz (replaced by "exitcm") $field = new xmldb_field('shownextquiz', XMLDB_TYPE_INTEGER, '4', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0'); if ($dbman->field_exists($table, $field)) { // set exitcm to show next HotPot: -4 = hotpot::ACTIVITY_SECTION_HOTPOT $DB->execute('UPDATE {hotpot} SET exitcm=-4 WHERE shownextquiz=1'); $dbman->drop_field($table, $field); } // append "id" to fields that are foreign keys in other hotpot tables $fields = array('hotpot_attempts' => array('hotpot'), 'hotpot_details' => array('attempt'), 'hotpot_questions' => array('hotpot'), 'hotpot_responses' => array('attempt', 'question')); foreach ($fields as $tablename => $fieldnames) { $table = new xmldb_table($tablename); foreach ($fieldnames as $fieldname) { $field = new xmldb_field($fieldname, XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0'); if ($dbman->field_exists($table, $field)) { // maybe we should remove all indexes and keys // using this $fieldname before we rename the field $dbman->rename_field($table, $field, $fieldname . 'id'); } } } // create new table: hotpot_cache $table = new xmldb_table('hotpot_cache'); if (!$dbman->table_exists($table)) { $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); $table->add_field('hotpotid', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0'); $table->add_field('slasharguments', XMLDB_TYPE_CHAR, '1', null, XMLDB_NOTNULL); $table->add_field('hotpot_enableobfuscate', XMLDB_TYPE_CHAR, '1', null, XMLDB_NOTNULL); $table->add_field('hotpot_enableswf', XMLDB_TYPE_CHAR, '1', null, XMLDB_NOTNULL); $table->add_field('name', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL); $table->add_field('sourcefile', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL); $table->add_field('sourcetype', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL); $table->add_field('sourcelocation', XMLDB_TYPE_INTEGER, '2', XMLDB_UNSIGNED, XMLDB_NOTNULL); $table->add_field('sourcelastmodified', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL); $table->add_field('sourceetag', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL); $table->add_field('configfile', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL); $table->add_field('configlocation', XMLDB_TYPE_INTEGER, '2', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0'); $table->add_field('configlastmodified', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL); $table->add_field('configetag', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL); $table->add_field('navigation', XMLDB_TYPE_INTEGER, '4', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0'); $table->add_field('title', XMLDB_TYPE_INTEGER, '6', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0'); $table->add_field('stopbutton', XMLDB_TYPE_INTEGER, '2', XMLDB_UNSIGNED, null, null, '0'); $table->add_field('stoptext', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL); $table->add_field('usefilters', XMLDB_TYPE_INTEGER, '4', XMLDB_UNSIGNED, null, null, '0'); $table->add_field('useglossary', XMLDB_TYPE_INTEGER, '4', XMLDB_UNSIGNED, null, null, '0'); $table->add_field('usemediafilter', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, '0'); $table->add_field('studentfeedback', XMLDB_TYPE_INTEGER, '4', null, XMLDB_NOTNULL, null, '0'); $table->add_field('studentfeedbackurl', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL); $table->add_field('timelimit', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0'); $table->add_field('delay3', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '-1'); $table->add_field('clickreporting', XMLDB_TYPE_INTEGER, '2', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0'); $table->add_field('content', XMLDB_TYPE_TEXT, 'medium', null, XMLDB_NOTNULL); $table->add_field('timemodified', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL); $table->add_field('md5key', XMLDB_TYPE_CHAR, '32', null, XMLDB_NOTNULL); // Add keys to table hotpot_cache $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); $table->add_key('hotpotid', XMLDB_KEY_FOREIGN, array('hotpotid'), 'hotpot', array('id')); // Add indexes to table hotpot_cache $table->add_index('hotpotid-md5key', XMLDB_INDEX_NOTUNIQUE, array('hotpotid', 'md5key')); $dbman->create_table($table); } // add new logging actions log_update_descriptions('mod/hotpot'); // hotpot savepoint reached upgrade_mod_savepoint(true, "{$newversion}", 'hotpot'); } $newversion = 2010080302; if ($oldversion < $newversion) { // navigation setting of "none" is now "0" (was "6") $DB->execute('UPDATE {hotpot} SET navigation=0 WHERE navigation=6'); // navigation's "give up" button, is replaced by the "stopbutton" field $DB->execute('UPDATE {hotpot} SET stopbutton=0 WHERE navigation=5'); $DB->execute('UPDATE {hotpot} SET navigation=0 WHERE navigation=5'); upgrade_mod_savepoint(true, "{$newversion}", 'hotpot'); } $newversion = 2010080303; if ($oldversion < $newversion) { // modify table: hotpot_attempts $table = new xmldb_table('hotpot_attempts'); // add field: timemodified $field = new xmldb_field('timemodified', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0'); if (!$dbman->field_exists($table, $field)) { $dbman->add_field($table, $field); $DB->execute('UPDATE {hotpot_attempts} SET timemodified = timefinish WHERE timemodified=0'); $DB->execute('UPDATE {hotpot_attempts} SET timemodified = timestart WHERE timemodified=0'); } upgrade_mod_savepoint(true, "{$newversion}", 'hotpot'); } $newversion = 2010080305; if ($oldversion < $newversion) { // modify table: hotpot $table = new xmldb_table('hotpot'); // change fields // - entrycm (-> signed) // - outputformat (-> varchar) // - timelimit (-> signed) // - delay3 (-> signed) // - attemptlimit (-> unsigned) // - gradeweighting (-> unsigned) // - grademethod (-> unsigned) $fields = array(new xmldb_field('entrycm', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0'), new xmldb_field('outputformat', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL), new xmldb_field('timelimit', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0'), new xmldb_field('delay3', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '2'), new xmldb_field('attemptlimit', XMLDB_TYPE_INTEGER, '6', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0'), new xmldb_field('gradeweighting', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0'), new xmldb_field('grademethod', XMLDB_TYPE_INTEGER, '4', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0')); foreach ($fields as $field) { if ($dbman->field_exists($table, $field)) { xmldb_hotpot_fix_previous_field($dbman, $table, $field); $dbman->change_field_type($table, $field); } } upgrade_mod_savepoint(true, "{$newversion}", 'hotpot'); } $newversion = 2010080306; if ($oldversion < $newversion) { // modify table: hotpot $table = new xmldb_table('hotpot'); // rename field: gradelimit -> gradeweighting $field = new xmldb_field('gradelimit', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0'); if ($dbman->field_exists($table, $field)) { $dbman->rename_field($table, $field, 'gradeweighting'); } upgrade_mod_savepoint(true, "{$newversion}", 'hotpot'); } $newversion = 2010080308; if ($oldversion < $newversion) { // add display fields to hotpot // (these fields were missing from access.xml so won't be on new sites) $tables = array('hotpot' => array(new xmldb_field('title', XMLDB_TYPE_INTEGER, '6', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '3', 'navigation'), new xmldb_field('stopbutton', XMLDB_TYPE_INTEGER, '2', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0', 'title'), new xmldb_field('stoptext', XMLDB_TYPE_CHAR, '255', null, null, null, null, 'stopbutton'), new xmldb_field('usefilters', XMLDB_TYPE_INTEGER, '2', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0', 'stoptext'), new xmldb_field('useglossary', XMLDB_TYPE_INTEGER, '2', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0', 'usefilters'), new xmldb_field('usemediafilter', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null, 'useglossary'))); foreach ($tables as $tablename => $fields) { $table = new xmldb_table($tablename); foreach ($fields as $field) { xmldb_hotpot_fix_previous_field($dbman, $table, $field); if ($dbman->field_exists($table, $field)) { $dbman->change_field_type($table, $field); } else { $dbman->add_field($table, $field); } } } $table = new xmldb_table('hotpot'); $field = new xmldb_field('forceplugins', XMLDB_TYPE_INTEGER, '4', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0'); if ($dbman->field_exists($table, $field)) { $DB->execute('UPDATE {hotpot} SET ' . "usemediafilter='moodle'" . ' WHERE forceplugins=1'); $dbman->drop_field($table, $field); } // force certain fields to be not null $tables = array('hotpot' => array(new xmldb_field('entrygrade', XMLDB_TYPE_INTEGER, '6', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '100')), 'hotpot_cache' => array(new xmldb_field('stopbutton', XMLDB_TYPE_INTEGER, '2', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0'), new xmldb_field('usefilters', XMLDB_TYPE_INTEGER, '2', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0'), new xmldb_field('useglossary', XMLDB_TYPE_INTEGER, '2', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0'), new xmldb_field('studentfeedback', XMLDB_TYPE_INTEGER, '4', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0'))); foreach ($tables as $tablename => $fields) { $table = new xmldb_table($tablename); foreach ($fields as $field) { if ($dbman->field_exists($table, $field)) { $dbman->change_field_type($table, $field); } } } upgrade_mod_savepoint(true, "{$newversion}", 'hotpot'); } $newversion = 2010080309; if ($oldversion < $newversion) { // force certain text fields to be not null $tables = array('hotpot' => array(new xmldb_field('sourcefile', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL), new xmldb_field('entrytext', XMLDB_TYPE_TEXT, 'small', null, XMLDB_NOTNULL), new xmldb_field('exittext', XMLDB_TYPE_TEXT, 'small', null, XMLDB_NOTNULL), new xmldb_field('stoptext', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL))); foreach ($tables as $tablename => $fields) { $table = new xmldb_table($tablename); foreach ($fields as $field) { if ($dbman->field_exists($table, $field)) { $fieldname = $field->getName(); $DB->set_field_select($tablename, $fieldname, '', "{$fieldname} IS NULL"); $dbman->change_field_type($table, $field); } } } upgrade_mod_savepoint(true, "{$newversion}", 'hotpot'); } $newversion = 2010080311; if ($oldversion < $newversion) { require_once $CFG->dirroot . '/mod/hotpot/locallib.php'; ///////////////////////////////////// /// new file storage migrate code /// ///////////////////////////////////// // set up sql strings to select HotPots with Moodle 1.x file paths (i.e. no leading slash) $strupdating = get_string('migratingfiles', 'hotpot'); $select = 'h.*, cm.id AS cmid'; $from = '{hotpot} h, {course_modules} cm, {modules} m'; $where = 'm.name=? AND m.id=cm.module AND cm.instance=h.id AND h.sourcefile<>?' . ' AND ' . $DB->sql_like('h.sourcefile', '?', false, false, true); // NOT LIKE $params = array('hotpot', '', '/%', 0); $orderby = 'h.course, h.id'; // get HotPot records that need to be updated if ($count = $DB->count_records_sql("SELECT COUNT('x') FROM {$from} WHERE {$where}", $params)) { $rs = $DB->get_recordset_sql("SELECT {$select} FROM {$from} WHERE {$where} ORDER BY {$orderby}", $params); } else { $rs = false; } if ($rs) { $i = 0; $bar = new progress_bar('hotpotmigratefiles', 500, true); // get file storage object $fs = get_file_storage(); if (class_exists('context_course')) { $sitecontext = context_course::instance(SITEID); } else { $sitecontext = get_context_instance(CONTEXT_COURSE, SITEID); } $coursecontext = null; $modulecontext = null; foreach ($rs as $hotpot) { // apply for more script execution time (3 mins) upgrade_set_timeout(); // get course context for this $hotpot if ($coursecontext === null || $coursecontext->instanceid != $hotpot->course) { if (class_exists('context_course')) { $coursecontext = context_course::instance($hotpot->course); } else { $coursecontext = get_context_instance(CONTEXT_COURSE, $hotpot->course); } } // get module context for this $hotpot/$task if ($modulecontext === null || $modulecontext->instanceid != $hotpot->cmid) { if (class_exists('context_module')) { $modulecontext = context_module::instance($hotpot->cmid); } else { $modulecontext = get_context_instance(CONTEXT_MODULE, $hotpot->cmid); } } // actually there shouldn't be any urls in HotPot activities, // but this code will also be used to convert QuizPort to TaskChain if (preg_match('/^https?:\\/\\//i', $hotpot->sourcefile)) { $url = $hotpot->sourcefile; $path = parse_url($url, PHP_URL_PATH); } else { $url = ''; $path = $hotpot->sourcefile; } $path = clean_param($path, PARAM_PATH); // this information should be enough to access the file // if it has been migrated into Moodle 2.0 file system $old_filename = basename($path); $old_filepath = dirname($path); if ($old_filepath == '.' || $old_filepath == '') { $old_filepath = '/'; } else { $old_filepath = '/' . ltrim($old_filepath, '/'); // require leading slash $old_filepath = rtrim($old_filepath, '/') . '/'; // require trailing slash } // update $hotpot->sourcefile, if necessary if ($hotpot->sourcefile != $old_filepath . $old_filename) { $hotpot->sourcefile = $old_filepath . $old_filename; $DB->set_field('hotpot', 'sourcefile', $hotpot->sourcefile, array('id' => $hotpot->id)); } // set $courseid and $contextid from $task->$location // of where we expect to find the $file // 0 : HOTPOT_LOCATION_COURSEFILES // 1 : HOTPOT_LOCATION_SITEFILES // 2 : HOTPOT_LOCATION_WWW (not used) if ($hotpot->sourcelocation) { $courseid = SITEID; $contextid = $sitecontext->id; } else { $courseid = $hotpot->course; $contextid = $coursecontext->id; } // we expect to need the $filehash to get a file that has been migrated $filehash = sha1('/' . $contextid . '/course/legacy/0' . $old_filepath . $old_filename); // we might also need the old file path, if the file has not been migrated $oldfilepath = $CFG->dataroot . '/' . $courseid . $old_filepath . $old_filename; // set parameters used to add file to filearea // (sortorder=1 siginifies the "mainfile" in this filearea) $file_record = array('contextid' => $modulecontext->id, 'component' => 'mod_hotpot', 'filearea' => 'sourcefile', 'sortorder' => 1, 'itemid' => 0, 'filepath' => $old_filepath, 'filename' => $old_filename); // initialize sourcefile settings $hotpot->sourcefile = $old_filepath . $old_filename; $hotpot->sourcetype = ''; $hotpot->sourceitemid = 0; if ($file = $fs->get_file($modulecontext->id, 'mod_hotpot', 'sourcefile', 0, $old_filepath, $old_filename)) { // file already exists for this context - shouldn't happen !! // maybe an earlier upgrade failed for some reason ? // anyway we must do this check, so that create_file_from_xxx() does not abort } else { if ($url) { // file is on an external url - unusual ?! $file = false; // $fs->create_file_from_url($file_record, $url); } else { if ($file = $fs->get_file_by_hash($filehash)) { // $file has already been migrated to Moodle's file system // this is the route we expect most people to come :-) $file = $fs->create_file_from_storedfile($file_record, $file); } else { if (file_exists($oldfilepath)) { // $file still exists on server's filesystem - unusual ?! $file = $fs->create_file_from_pathname($file_record, $oldfilepath); } else { // file was not migrated and is not on server's filesystem $file = false; } } } } // if source file did not exist, notify user of the problem if (empty($file)) { if ($url) { $msg = "course_modules.id={$hotpot->cmid}, url={$url}"; } else { $msg = "course_modules.id={$hotpot->cmid}, path={$path}"; } $params = array('update' => $hotpot->cmid, 'onclick' => 'this.target="_blank"'); $msg = html_writer::link(new moodle_url('/course/modedit.php', $params), $msg); $msg = get_string('sourcefilenotfound', 'hotpot', $msg); echo html_writer::tag('div', $msg, array('class' => 'notifyproblem')); } // set $hotpot->sourcetype if ($pos = strrpos($hotpot->sourcefile, '.')) { $filetype = substr($hotpot->sourcefile, $pos + 1); switch ($filetype) { case 'jcl': $hotpot->sourcetype = 'hp_6_jcloze_xml'; break; case 'jcw': $hotpot->sourcetype = 'hp_6_jcross_xml'; break; case 'jmt': $hotpot->sourcetype = 'hp_6_jmatch_xml'; break; case 'jmx': $hotpot->sourcetype = 'hp_6_jmix_xml'; break; case 'jqz': $hotpot->sourcetype = 'hp_6_jquiz_xml'; break; case 'rhb': $hotpot->sourcetype = 'hp_6_rhubarb_xml'; break; case 'sqt': $hotpot->sourcetype = 'hp_6_sequitur_xml'; break; case 'htm': case 'html': default: if ($file) { $pathnamehash = $fs->get_pathname_hash($modulecontext->id, 'mod_hotpot', 'sourcefile', 0, $old_filepath, $old_filename); if ($contenthash = $DB->get_field('files', 'contenthash', array('pathnamehash' => $pathnamehash))) { $l1 = $contenthash[0] . $contenthash[1]; $l2 = $contenthash[2] . $contenthash[3]; if (file_exists("{$CFG->dataroot}/filedir/{$l1}/{$l2}/{$contenthash}")) { $hotpot->sourcetype = hotpot::get_sourcetype($file); } else { $msg = html_writer::link(new moodle_url('/course/modedit.php', array('update' => $hotpot->cmid)), "course_modules.id={$hotpot->cmid}, path={$path}"); $msg .= html_writer::empty_tag('br'); $msg .= "filedir path={$l1}/{$l2}/{$contenthash}"; $msg = get_string('sourcefilenotfound', 'hotpot', $msg); echo html_writer::tag('div', $msg, array('class' => 'notifyproblem')); } } } } } // JMatch has 2 output formats // 14 : v6 : drop down menus : hp_6_jmatch_xml_v6 // 15 : v6+ : drag-and-drop : hp_6_jmatch_xml_v6_plus // JMix has 2 output formats // 14 : v6 : links : hp_6_jmix_xml_v6 // 15 : v6+ : drag-and-drop : hp_6_jmix_xml_v6_plus // since drag-and-drop is the "best" outputformat for both types of quiz, // we only need to worry about HotPots whose outputformat was 14 (="v6") // set $hotpot->outputformat if ($hotpot->outputformat == 14 && ($hotpot->sourcetype == 'hp_6_jmatch_xml' || $hotpot->sourcetype == 'hp_6_jmix_xml')) { $hotpot->outputformat = $hotpot->sourcetype . '_v6'; } else { $hotpot->outputformat = ''; // = "best" output format } $DB->update_record('hotpot', $hotpot); // update progress bar $i++; $bar->update($i, $count, $strupdating . ": ({$i}/{$count})"); } $rs->close(); } upgrade_mod_savepoint(true, "{$newversion}", 'hotpot'); } $newversion = 2010080316; if ($oldversion < $newversion) { // because the HotPot activities were probably hidden until now // we need to reset the course caches (using "course/lib.php") require_once $CFG->dirroot . '/course/lib.php'; $courseids = array(); if ($hotpots = $DB->get_records('hotpot', null, '', 'id,course')) { foreach ($hotpots as $hotpot) { $courseids[$hotpot->course] = true; } $courseids = array_keys($courseids); } unset($hotpots, $hotpot); foreach ($courseids as $courseid) { rebuild_course_cache($courseid, true); } unset($courseids, $courseid); // reset theme cache to force inclusion of new hotpot css theme_reset_all_caches(); upgrade_mod_savepoint(true, "{$newversion}", 'hotpot'); } $newversion = 2010080325; if ($oldversion < $newversion) { $table = new xmldb_table('hotpot'); $fieldnames = array('sourceitemid', 'configitemid'); foreach ($fieldnames as $fieldname) { $field = new xmldb_field($fieldname); if ($dbman->field_exists($table, $field)) { $dbman->drop_field($table, $field); } } upgrade_mod_savepoint(true, "{$newversion}", 'hotpot'); } $newversion = 2010080330; if ($oldversion < $newversion) { require_once $CFG->dirroot . '/mod/hotpot/lib.php'; hotpot_refresh_events(); } $newversion = 2010080333; if ($oldversion < $newversion) { update_capabilities('mod/hotpot'); upgrade_mod_savepoint(true, "{$newversion}", 'hotpot'); } $newversion = 2010080339; if ($oldversion < $newversion) { $table = new xmldb_table('hotpot'); $field = new xmldb_field('exitgrade', XMLDB_TYPE_INTEGER, '6', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0', 'exitcm'); xmldb_hotpot_fix_previous_field($dbman, $table, $field); if (!$dbman->field_exists($table, $field)) { $dbman->add_field($table, $field); } upgrade_mod_savepoint(true, "{$newversion}", 'hotpot'); } $newversion = 2010080340; if ($oldversion < $newversion) { // force all text fields to be long text, the default for Moodle 2.3 and later $tables = array('hotpot' => array(new xmldb_field('entrytext', XMLDB_TYPE_TEXT, 'long', null, XMLDB_NOTNULL), new xmldb_field('exittext', XMLDB_TYPE_TEXT, 'long', null, XMLDB_NOTNULL)), 'hotpot_cache' => array(new xmldb_field('content', XMLDB_TYPE_TEXT, 'long', null, XMLDB_NOTNULL)), 'hotpot_details' => array(new xmldb_field('details', XMLDB_TYPE_TEXT, 'long', null, XMLDB_NOTNULL)), 'hotpot_questions' => array(new xmldb_field('name', XMLDB_TYPE_TEXT, 'long', null, XMLDB_NOTNULL)), 'hotpot_strings' => array(new xmldb_field('string', XMLDB_TYPE_TEXT, 'long', null, XMLDB_NOTNULL))); foreach ($tables as $tablename => $fields) { $table = new xmldb_table($tablename); foreach ($fields as $field) { if ($dbman->field_exists($table, $field)) { $fieldname = $field->getName(); $DB->set_field_select($tablename, $fieldname, '', "{$fieldname} IS NULL"); $dbman->change_field_type($table, $field); } } } upgrade_mod_savepoint(true, "{$newversion}", 'hotpot'); } $newversion = 2010080342; if ($oldversion < $newversion) { // force all MySQL integer fields to be signed, the default for Moodle 2.3 and later if ($DB->get_dbfamily() == 'mysql') { $prefix = $DB->get_prefix(); $tables = $DB->get_tables(); foreach ($tables as $table) { if (substr($table, 0, 6) == 'hotpot') { $rs = $DB->get_recordset_sql("SHOW COLUMNS FROM {$CFG->prefix}{$table} WHERE type LIKE '%unsigned%'"); foreach ($rs as $column) { // copied from as "lib/db/upgradelib.php" $type = preg_replace('/\\s*unsigned/i', 'signed', $column->type); $notnull = $column->null === 'NO' ? 'NOT NULL' : 'NULL'; $default = is_null($column->default) || $column->default === '' ? '' : "DEFAULT '{$column->default}'"; $autoinc = stripos($column->extra, 'auto_increment') === false ? '' : 'AUTO_INCREMENT'; $sql = "ALTER TABLE `{$prefix}{$table}` MODIFY COLUMN `{$column->field}` {$type} {$notnull} {$default} {$autoinc}"; $DB->change_database_structure($sql); } } } } upgrade_mod_savepoint(true, "{$newversion}", 'hotpot'); } $newversion = 2010080353; if ($oldversion < $newversion) { // remove any unwanted "course_files" folders that may have been created // when restoring Moodle 1.9 HotPot activities to a Moodle 2.x site // select all HotPot activities which have a "course_files" folder // but whose "sourcefile" path does not require such a folder $select = 'f.*,' . 'h.id AS hotpotid,' . 'h.sourcefile AS sourcefile'; $from = '{hotpot} h,' . '{course_modules} cm,' . '{context} c,' . '{files} f'; $where = $DB->sql_like('h.sourcefile', '?', false, false, true) . ' AND h.id=cm.instance' . ' AND cm.id=c.instanceid' . ' AND c.id=f.contextid' . ' AND f.component=?' . ' AND f.filearea=?' . ' AND f.filepath=?' . ' AND f.filename=?'; $params = array('/course_files/%', 'mod_hotpot', 'sourcefile', '/course_files/', '.'); if ($filerecords = $DB->get_records_sql("SELECT {$select} FROM {$from} WHERE {$where}", $params)) { $fs = get_file_storage(); foreach ($filerecords as $filerecord) { $file = $fs->get_file_instance($filerecord); xmldb_hotpot_move_file($file, '/'); } } upgrade_mod_savepoint(true, "{$newversion}", 'hotpot'); } $newversion = 2010080366; if ($oldversion < $newversion) { if ($hotpots = $DB->get_records_select('hotpot', $DB->sql_like('sourcefile', '?'), array('%http://localhost/19/99/%'))) { foreach ($hotpots as $hotpot) { $sourcefile = str_replace('http://localhost/19/99/', '', $hotpot->sourcefile); $DB->set_field('hotpot', 'sourcefile', $sourcefile, array('id' => $hotpot->id)); } } upgrade_mod_savepoint(true, "{$newversion}", 'hotpot'); } $newversion = 2010080370; if ($oldversion < $newversion) { require_once $CFG->dirroot . '/mod/hotpot/locallib.php'; $reviewoptions = 0; list($times, $items) = hotpot::reviewoptions_times_items(); foreach ($times as $timename => $timevalue) { foreach ($items as $itemname => $itemvalue) { $reviewoptions += $timevalue & $itemvalue; } } // $reviewoptions should now be set to 62415 $DB->set_field('hotpot', 'reviewoptions', $reviewoptions); upgrade_mod_savepoint(true, "{$newversion}", 'hotpot'); } $newversion = 2013111685; if ($oldversion < $newversion) { $tables = array('hotpot' => array(new xmldb_field('allowpaste', XMLDB_TYPE_INTEGER, '2', null, XMLDB_NOTNULL, null, '0', 'stoptext')), 'hotpot_cache' => array(new xmldb_field('hotpot_bodystyles', XMLDB_TYPE_CHAR, '8', null, XMLDB_NOTNULL, null, null, 'slasharguments'), new xmldb_field('sourcerepositoryid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0', 'sourcelocation'), new xmldb_field('configrepositoryid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0', 'configlocation'), new xmldb_field('allowpaste', XMLDB_TYPE_INTEGER, '2', null, XMLDB_NOTNULL, null, '0', 'stoptext'))); foreach ($tables as $table => $fields) { $table = new xmldb_table($table); foreach ($fields as $field) { xmldb_hotpot_fix_previous_field($dbman, $table, $field); if ($dbman->field_exists($table, $field)) { $dbman->change_field_type($table, $field); } else { $dbman->add_field($table, $field); } } } upgrade_mod_savepoint(true, "{$newversion}", 'hotpot'); } $newversion = 2014011694; if ($oldversion < $newversion) { require_once $CFG->dirroot . '/mod/hotpot/lib.php'; hotpot_update_grades(); upgrade_mod_savepoint(true, "{$newversion}", 'hotpot'); } $newversion = 2014042111; if ($oldversion < $newversion) { $empty_cache = true; upgrade_mod_savepoint(true, "{$newversion}", 'hotpot'); } if ($empty_cache) { $DB->delete_records('hotpot_cache'); } return true; }
/** * Upgrade moodle core * @param float $version target version * @param bool $verbose * @return void, may throw exception */ function upgrade_core($version, $verbose) { global $CFG, $SITE, $DB, $COURSE; raise_memory_limit(MEMORY_EXTRA); require_once($CFG->libdir.'/db/upgrade.php'); // Defines upgrades try { // Reset caches before any output. cache_helper::purge_all(true); purge_all_caches(); // Upgrade current language pack if we can upgrade_language_pack(); print_upgrade_part_start('moodle', false, $verbose); // Pre-upgrade scripts for local hack workarounds. $preupgradefile = "$CFG->dirroot/local/preupgrade.php"; if (file_exists($preupgradefile)) { core_php_time_limit::raise(); require($preupgradefile); // Reset upgrade timeout to default. upgrade_set_timeout(); } $result = xmldb_main_upgrade($CFG->version); if ($version > $CFG->version) { // store version if not already there upgrade_main_savepoint($result, $version, false); } // In case structure of 'course' table has been changed and we forgot to update $SITE, re-read it from db. $SITE = $DB->get_record('course', array('id' => $SITE->id)); $COURSE = clone($SITE); // perform all other component upgrade routines update_capabilities('moodle'); log_update_descriptions('moodle'); external_update_descriptions('moodle'); events_update_definition('moodle'); \core\task\manager::reset_scheduled_tasks_for_component('moodle'); message_update_providers('moodle'); \core\message\inbound\manager::update_handlers_for_component('moodle'); // Update core definitions. cache_helper::update_definitions(true); // Purge caches again, just to be sure we arn't holding onto old stuff now. cache_helper::purge_all(true); purge_all_caches(); // Clean up contexts - more and more stuff depends on existence of paths and contexts context_helper::cleanup_instances(); context_helper::create_instances(null, false); context_helper::build_all_paths(false); $syscontext = context_system::instance(); $syscontext->mark_dirty(); print_upgrade_part_end('moodle', false, $verbose); } catch (Exception $ex) { upgrade_handle_exception($ex); } }
/** * Installs the roles system. * This function runs on a fresh install as well as on an upgrade from the old * hard-coded student/teacher/admin etc. roles to the new roles system. */ function moodle_install_roles() { global $CFG, $db; /// Create a system wide context for assignemnt. $systemcontext = $context = get_context_instance(CONTEXT_SYSTEM); /// Create default/legacy roles and capabilities. /// (1 legacy capability per legacy role at system level). $adminrole = create_role(addslashes(get_string('administrator')), 'admin', addslashes(get_string('administratordescription')), 'moodle/legacy:admin'); $coursecreatorrole = create_role(addslashes(get_string('coursecreators')), 'coursecreator', addslashes(get_string('coursecreatorsdescription')), 'moodle/legacy:coursecreator'); $editteacherrole = create_role(addslashes(get_string('defaultcourseteacher')), 'editingteacher', addslashes(get_string('defaultcourseteacherdescription')), 'moodle/legacy:editingteacher'); $noneditteacherrole = create_role(addslashes(get_string('noneditingteacher')), 'teacher', addslashes(get_string('noneditingteacherdescription')), 'moodle/legacy:teacher'); $studentrole = create_role(addslashes(get_string('defaultcoursestudent')), 'student', addslashes(get_string('defaultcoursestudentdescription')), 'moodle/legacy:student'); $guestrole = create_role(addslashes(get_string('guest')), 'guest', addslashes(get_string('guestdescription')), 'moodle/legacy:guest'); $userrole = create_role(addslashes(get_string('authenticateduser')), 'user', addslashes(get_string('authenticateduserdescription')), 'moodle/legacy:user'); /// Now is the correct moment to install capabilities - after creation of legacy roles, but before assigning of roles if (!assign_capability('moodle/site:doanything', CAP_ALLOW, $adminrole, $systemcontext->id)) { error('Could not assign moodle/site:doanything to the admin role'); } if (!update_capabilities()) { error('Had trouble upgrading the core capabilities for the Roles System'); } /// Look inside user_admin, user_creator, user_teachers, user_students and /// assign above new roles. If a user has both teacher and student role, /// only teacher role is assigned. The assignment should be system level. $dbtables = $db->MetaTables('TABLES'); /// Set up the progress bar $usertables = array('user_admins', 'user_coursecreators', 'user_teachers', 'user_students'); $totalcount = $progresscount = 0; foreach ($usertables as $usertable) { if (in_array($CFG->prefix . $usertable, $dbtables)) { $totalcount += count_records($usertable); } } print_progress(0, $totalcount, 5, 1, 'Processing role assignments'); /// Upgrade the admins. /// Sort using id ASC, first one is primary admin. if (in_array($CFG->prefix . 'user_admins', $dbtables)) { if ($rs = get_recordset_sql('SELECT * from ' . $CFG->prefix . 'user_admins ORDER BY ID ASC')) { while ($admin = rs_fetch_next_record($rs)) { role_assign($adminrole, $admin->userid, 0, $systemcontext->id); $progresscount++; print_progress($progresscount, $totalcount, 5, 1, 'Processing role assignments'); } rs_close($rs); } } else { // This is a fresh install. } /// Upgrade course creators. if (in_array($CFG->prefix . 'user_coursecreators', $dbtables)) { if ($rs = get_recordset('user_coursecreators')) { while ($coursecreator = rs_fetch_next_record($rs)) { role_assign($coursecreatorrole, $coursecreator->userid, 0, $systemcontext->id); $progresscount++; print_progress($progresscount, $totalcount, 5, 1, 'Processing role assignments'); } rs_close($rs); } } /// Upgrade editting teachers and non-editting teachers. if (in_array($CFG->prefix . 'user_teachers', $dbtables)) { if ($rs = get_recordset('user_teachers')) { while ($teacher = rs_fetch_next_record($rs)) { // removed code here to ignore site level assignments // since the contexts are separated now // populate the user_lastaccess table $access = new object(); $access->timeaccess = $teacher->timeaccess; $access->userid = $teacher->userid; $access->courseid = $teacher->course; insert_record('user_lastaccess', $access); // assign the default student role $coursecontext = get_context_instance(CONTEXT_COURSE, $teacher->course); // needs cache // hidden teacher if ($teacher->authority == 0) { $hiddenteacher = 1; } else { $hiddenteacher = 0; } if ($teacher->editall) { // editting teacher role_assign($editteacherrole, $teacher->userid, 0, $coursecontext->id, $teacher->timestart, $teacher->timeend, $hiddenteacher, $teacher->enrol, $teacher->timemodified); } else { role_assign($noneditteacherrole, $teacher->userid, 0, $coursecontext->id, $teacher->timestart, $teacher->timeend, $hiddenteacher, $teacher->enrol, $teacher->timemodified); } $progresscount++; print_progress($progresscount, $totalcount, 5, 1, 'Processing role assignments'); } rs_close($rs); } } /// Upgrade students. if (in_array($CFG->prefix . 'user_students', $dbtables)) { if ($rs = get_recordset('user_students')) { while ($student = rs_fetch_next_record($rs)) { // populate the user_lastaccess table $access = new object(); $access->timeaccess = $student->timeaccess; $access->userid = $student->userid; $access->courseid = $student->course; insert_record('user_lastaccess', $access); // assign the default student role $coursecontext = get_context_instance(CONTEXT_COURSE, $student->course); role_assign($studentrole, $student->userid, 0, $coursecontext->id, $student->timestart, $student->timeend, 0, $student->enrol, $student->time); $progresscount++; print_progress($progresscount, $totalcount, 5, 1, 'Processing role assignments'); } rs_close($rs); } } /// Upgrade guest (only 1 entry). if ($guestuser = get_record('user', 'username', 'guest')) { role_assign($guestrole, $guestuser->id, 0, $systemcontext->id); } print_progress($totalcount, $totalcount, 5, 1, 'Processing role assignments'); /// Insert the correct records for legacy roles allow_assign($adminrole, $adminrole); allow_assign($adminrole, $coursecreatorrole); allow_assign($adminrole, $noneditteacherrole); allow_assign($adminrole, $editteacherrole); allow_assign($adminrole, $studentrole); allow_assign($adminrole, $guestrole); allow_assign($coursecreatorrole, $noneditteacherrole); allow_assign($coursecreatorrole, $editteacherrole); allow_assign($coursecreatorrole, $studentrole); allow_assign($coursecreatorrole, $guestrole); allow_assign($editteacherrole, $noneditteacherrole); allow_assign($editteacherrole, $studentrole); allow_assign($editteacherrole, $guestrole); /// Set up default allow override matrix allow_override($adminrole, $adminrole); allow_override($adminrole, $coursecreatorrole); allow_override($adminrole, $noneditteacherrole); allow_override($adminrole, $editteacherrole); allow_override($adminrole, $studentrole); allow_override($adminrole, $guestrole); allow_override($adminrole, $userrole); //See MDL-15841 //allow_override($editteacherrole, $noneditteacherrole); //allow_override($editteacherrole, $studentrole); //allow_override($editteacherrole, $guestrole); /// Delete the old user tables when we are done $tables = array('user_students', 'user_teachers', 'user_coursecreators', 'user_admins'); foreach ($tables as $tablename) { $table = new XMLDBTable($tablename); if (table_exists($table)) { drop_table($table); } } }
/** * Setup the DB fixture data */ public function setup() { parent::setUp(); $tables = array('block_instance', 'cache_flags', 'capabilities', 'context', 'context_temp', 'course', 'course_modules', 'course_categories', 'course_sections', 'files', 'files_cleanup', 'grade_items', 'grade_categories', 'groups', 'groups_members', 'modules', 'role', 'role_names', 'role_context_levels', 'role_assignments', 'role_capabilities', 'user'); $this->create_test_tables($tables, 'lib'); $this->create_test_table('forum', 'mod/forum'); $this->switch_to_test_db(); global $DB, $CFG; // Insert needed capabilities $DB->insert_record('capabilities', array('id' => 45, 'name' => 'moodle/course:update', 'cattype' => 'write', 'contextlevel' => 50, 'component' => 'moodle', 'riskbitmask' => 4)); $DB->insert_record('capabilities', array('id' => 14, 'name' => 'moodle/site:backup', 'cattype' => 'write', 'contextlevel' => 50, 'component' => 'moodle', 'riskbitmask' => 28)); $DB->insert_record('capabilities', array('id' => 17, 'name' => 'moodle/site:restore', 'cattype' => 'write', 'contextlevel' => 50, 'component' => 'moodle', 'riskbitmask' => 28)); $DB->insert_record('capabilities', array('id' => 52, 'name' => 'moodle/course:managefiles', 'cattype' => 'write', 'contextlevel' => 50, 'component' => 'moodle', 'riskbitmask' => 4)); $DB->insert_record('capabilities', array('id' => 73, 'name' => 'moodle/user:editownprofile', 'cattype' => 'write', 'contextlevel' => 10, 'component' => 'moodle', 'riskbitmask' => 16)); // Insert system context $DB->insert_record('context', array('id' => 1, 'contextlevel' => 10, 'instanceid' => 0, 'path' => '/1', 'depth' => 1)); $DB->insert_record('context', array('id' => 2, 'contextlevel' => 50, 'instanceid' => 1, 'path' => '/1/2', 'depth' => 2)); // Insert site course $DB->insert_record('course', array('category' => 0, 'sortorder' => 1, 'fullname' => 'Test site', 'shortname' => 'test', 'format' => 'site', 'modinfo' => 'a:0:{}')); // User and capability stuff (stolen from testaccesslib.php) $syscontext = get_system_context(false); $adminrole = create_role(get_string('administrator'), 'admin', get_string('administratordescription'), 'moodle/legacy:admin'); /// Now is the correct moment to install capabilities - after creation of legacy roles, but before assigning of roles assign_capability('moodle/site:doanything', CAP_ALLOW, $adminrole, $syscontext->id); update_capabilities('moodle'); update_capabilities('mod/forum'); $contexts = $this->load_test_data('context', array('contextlevel', 'instanceid', 'path', 'depth'), array(1 => array(40, 666, '', 2))); $contexts[0] = $syscontext; $contexts[1]->path = $contexts[0]->path . '/' . $contexts[1]->id; $this->testdb->set_field('context', 'path', $contexts[1]->path, array('id' => $contexts[1]->id)); $users = $this->load_test_data('user', array('username', 'confirmed', 'deleted'), array('a' => array('a', 1, 0))); $admin = $this->testdb->get_record('role', array('shortname' => 'admin')); $ras = $this->load_test_data('role_assignments', array('userid', 'roleid', 'contextid'), array('a' => array($users['a']->id, $admin->id, $contexts[0]->id))); $this->switch_global_user_id(1); accesslib_clear_all_caches_for_unit_testing(); // Create a coursecat $newcategory = new stdClass(); $newcategory->name = 'test category'; $newcategory->sortorder = 999; if (!($newcategory->id = $DB->insert_record('course_categories', $newcategory))) { print_error('cannotcreatecategory', '', '', format_string($newcategory->name)); } $newcategory->context = get_context_instance(CONTEXT_COURSECAT, $newcategory->id); mark_context_dirty($newcategory->context->path); fix_course_sortorder(); // Required to build course_categories.depth and .path. $this->coursecat = $DB->get_record('course_categories', array('id' => $newcategory->id)); // Create a course $coursedata = new stdClass(); $coursedata->category = $newcategory->id; $coursedata->shortname = 'testcourse'; $coursedata->fullname = 'Test Course'; try { $this->course = create_course($coursedata); } catch (moodle_exception $e) { // Most likely the result of an aborted unit test: the test course was not correctly deleted $this->course = $DB->get_record('course', array('shortname' => $coursedata->shortname)); } // Create a user $this->user = new stdClass(); $this->user->username = '******'; $this->user->password = '******'; $this->user->firstname = 'TestUser'; $this->user->lastname = 'TestUser'; $this->user->email = '*****@*****.**'; try { $this->user->id = create_user($this->user); } catch (moodle_exception $e) { // Most likely the result of an aborted unit test: the test user was not correctly deleted $this->user->id = $DB->get_field('user', 'id', array('username' => $this->user->username)); } // Assign user to course // role_assign(5, $this->user->id, 0, get_context_instance(CONTEXT_COURSE, $this->course->id)->id); // Create a module $module = new stdClass(); $module->intro = 'Forum used for testing filelib API'; $module->type = 'general'; $module->forcesubscribe = 1; $module->format = 1; $module->name = 'Test Forum'; $module->module = $DB->get_field('modules', 'id', array('name' => 'forum')); $module->modulename = 'forum'; $module->add = 'forum'; $module->cmidnumber = ''; $module->course = $this->course->id; $module->instance = forum_add_instance($module, ''); $this->section = get_course_section(1, $this->course->id); $module->section = $this->section->id; $module->coursemodule = add_course_module($module); add_mod_to_section($module); $module->cmidnumber = set_coursemodule_idnumber($module->coursemodule, ''); rebuild_course_cache($this->course->id); $this->module = $DB->get_record('forum', array('id' => $module->instance)); $this->module->instance = $module->instance; // Update local copy of course $this->course = $DB->get_record('course', array('id' => $this->course->id)); }
/** * Upgrade moodle core * @param float $version target version * @param bool $verbose * @return void, may throw exception */ function upgrade_core($version, $verbose) { global $CFG; require_once $CFG->libdir . '/db/upgrade.php'; // Defines upgrades try { // Upgrade current language pack if we can if (empty($CFG->skiplangupgrade)) { upgrade_language_pack(false); } print_upgrade_part_start('moodle', false, $verbose); // one time special local migration pre 2.0 upgrade script if ($version < 2007101600) { $pre20upgradefile = "{$CFG->dirrot}/local/upgrade_pre20.php"; if (file_exists($pre20upgradefile)) { set_time_limit(0); require $pre20upgradefile; // reset upgrade timeout to default upgrade_set_timeout(); } } $result = xmldb_main_upgrade($CFG->version); if ($version > $CFG->version) { // store version if not already there upgrade_main_savepoint($result, $version, false); } // perform all other component upgrade routines update_capabilities('moodle'); events_update_definition('moodle'); message_update_providers('moodle'); remove_dir($CFG->dataroot . '/cache', true); // flush cache print_upgrade_part_end('moodle', false, $verbose); } catch (Exception $ex) { upgrade_handle_exception($ex); } }
/** * Main post-install tasks to be executed after the BD schema is available * * This function is automatically executed after Moodle core DB has been * created at initial install. It's in charge of perform the initial tasks * not covered by the {@link install.xml} file, like create initial users, * roles, templates, moving stuff from other plugins... * * Note that the function is only invoked once, at install time, so if new tasks * are needed in the future, they will need to be added both here (for new sites) * and in the corresponding {@link upgrade.php} file (for existing sites). * * All plugins within Moodle (modules, blocks, reports...) support the existence of * their own install.php file, using the "Frankenstyle" component name as * defined at {@link http://docs.moodle.org/dev/Frankenstyle}, for example: * - {@link xmldb_page_install()}. (modules don't require the plugintype ("mod_") to be used. * - {@link xmldb_enrol_meta_install()}. * - {@link xmldb_workshopform_accumulative_install()}. * - .... * * Finally, note that it's also supported to have one uninstall.php file that is * executed also once, each time one plugin is uninstalled (before the DB schema is * deleted). Those uninstall files will contain one function, using the "Frankenstyle" * naming conventions, like {@link xmldb_enrol_meta_uninstall()} or {@link xmldb_workshop_uninstall()}. */ function xmldb_main_install() { global $CFG, $DB, $SITE, $OUTPUT; // Make sure system context exists $syscontext = context_system::instance(0, MUST_EXIST, false); if ($syscontext->id != SYSCONTEXTID) { throw new moodle_exception('generalexceptionmessage', 'error', '', 'Unexpected new system context id!'); } // Create site course if ($DB->record_exists('course', array())) { throw new moodle_exception('generalexceptionmessage', 'error', '', 'Can not create frontpage course, courses already exist.'); } $newsite = new stdClass(); $newsite->fullname = ''; $newsite->shortname = ''; $newsite->summary = NULL; $newsite->newsitems = 3; $newsite->numsections = 1; $newsite->category = 0; $newsite->format = 'site'; // Only for this course $newsite->timecreated = time(); $newsite->timemodified = $newsite->timecreated; if (defined('SITEID')) { $newsite->id = SITEID; $DB->import_record('course', $newsite); $DB->get_manager()->reset_sequence('course'); } else { $newsite->id = $DB->insert_record('course', $newsite); define('SITEID', $newsite->id); } // set the field 'numsections'. We can not use format_site::update_format_options() because // the file is not loaded $DB->insert_record('course_format_options', array('courseid' => SITEID, 'format' => 'site', 'sectionid' => 0, 'name' => 'numsections', 'value' => $newsite->numsections)); $SITE = get_site(); if ($newsite->id != $SITE->id) { throw new moodle_exception('generalexceptionmessage', 'error', '', 'Unexpected new site course id!'); } // Make sure site course context exists context_course::instance($SITE->id); // Update the global frontpage cache $SITE = $DB->get_record('course', array('id' => $newsite->id), '*', MUST_EXIST); // Create default course category if ($DB->record_exists('course_categories', array())) { throw new moodle_exception('generalexceptionmessage', 'error', '', 'Can not create default course category, categories already exist.'); } $cat = new stdClass(); $cat->name = get_string('miscellaneous'); $cat->depth = 1; $cat->sortorder = MAX_COURSES_IN_CATEGORY; $cat->timemodified = time(); $catid = $DB->insert_record('course_categories', $cat); $DB->set_field('course_categories', 'path', '/' . $catid, array('id' => $catid)); // Make sure category context exists context_coursecat::instance($catid); $defaults = array('rolesactive' => '0', 'auth' => 'email', 'auth_pop3mailbox' => 'INBOX', 'enrol_plugins_enabled' => 'manual,guest,self,cohort', 'theme' => theme_config::DEFAULT_THEME, 'filter_multilang_converted' => 1, 'siteidentifier' => random_string(32) . get_host_from_url($CFG->wwwroot), 'backup_version' => 2008111700, 'backup_release' => '2.0 dev', 'mnet_dispatcher_mode' => 'off', 'sessiontimeout' => 7200, 'stringfilters' => '', 'filterall' => 0, 'texteditors' => 'atto,tinymce,textarea', 'upgrade_minmaxgradestepignored' => 1, 'upgrade_extracreditweightsstepignored' => 1, 'upgrade_calculatedgradeitemsignored' => 1); foreach ($defaults as $key => $value) { set_config($key, $value); } // Bootstrap mnet $mnethost = new stdClass(); $mnethost->wwwroot = $CFG->wwwroot; $mnethost->name = ''; $mnethost->name = ''; $mnethost->public_key = ''; if (empty($_SERVER['SERVER_ADDR'])) { // SERVER_ADDR is only returned by Apache-like webservers preg_match("@^(?:http[s]?://)?([A-Z0-9\\-\\.]+).*@i", $CFG->wwwroot, $matches); $my_hostname = $matches[1]; $my_ip = gethostbyname($my_hostname); // Returns unmodified hostname on failure. DOH! if ($my_ip == $my_hostname) { $mnethost->ip_address = 'UNKNOWN'; } else { $mnethost->ip_address = $my_ip; } } else { $mnethost->ip_address = $_SERVER['SERVER_ADDR']; } $mnetid = $DB->insert_record('mnet_host', $mnethost); set_config('mnet_localhost_id', $mnetid); // Initial insert of mnet applications info $mnet_app = new stdClass(); $mnet_app->name = 'moodle'; $mnet_app->display_name = 'Moodle'; $mnet_app->xmlrpc_server_url = '/mnet/xmlrpc/server.php'; $mnet_app->sso_land_url = '/auth/mnet/land.php'; $mnet_app->sso_jump_url = '/auth/mnet/jump.php'; $moodleapplicationid = $DB->insert_record('mnet_application', $mnet_app); $mnet_app = new stdClass(); $mnet_app->name = 'mahara'; $mnet_app->display_name = 'Mahara'; $mnet_app->xmlrpc_server_url = '/api/xmlrpc/server.php'; $mnet_app->sso_land_url = '/auth/xmlrpc/land.php'; $mnet_app->sso_jump_url = '/auth/xmlrpc/jump.php'; $DB->insert_record('mnet_application', $mnet_app); // Set up the probably-to-be-removed-soon 'All hosts' record $mnetallhosts = new stdClass(); $mnetallhosts->wwwroot = ''; $mnetallhosts->ip_address = ''; $mnetallhosts->public_key = ''; $mnetallhosts->public_key_expires = 0; $mnetallhosts->last_connect_time = 0; $mnetallhosts->last_log_id = 0; $mnetallhosts->deleted = 0; $mnetallhosts->name = 'All Hosts'; $mnetallhosts->applicationid = $moodleapplicationid; $mnetallhosts->id = $DB->insert_record('mnet_host', $mnetallhosts, true); set_config('mnet_all_hosts_id', $mnetallhosts->id); // Create guest record - do not assign any role, guest user gets the default guest role automatically on the fly if ($DB->record_exists('user', array())) { throw new moodle_exception('generalexceptionmessage', 'error', '', 'Can not create default users, users already exist.'); } $guest = new stdClass(); $guest->auth = 'manual'; $guest->username = '******'; $guest->password = hash_internal_user_password('guest'); $guest->firstname = get_string('guestuser'); $guest->lastname = ' '; $guest->email = 'root@localhost'; $guest->description = get_string('guestuserinfo'); $guest->mnethostid = $CFG->mnet_localhost_id; $guest->confirmed = 1; $guest->lang = $CFG->lang; $guest->timemodified = time(); $guest->id = $DB->insert_record('user', $guest); if ($guest->id != 1) { echo $OUTPUT->notification('Unexpected id generated for the Guest account. Your database configuration or clustering setup may not be fully supported', 'notifyproblem'); } // Store guest id set_config('siteguest', $guest->id); // Make sure user context exists context_user::instance($guest->id); // Now create admin user $admin = new stdClass(); $admin->auth = 'manual'; $admin->firstname = get_string('admin'); $admin->lastname = get_string('user'); $admin->username = '******'; $admin->password = '******'; $admin->email = ''; $admin->confirmed = 1; $admin->mnethostid = $CFG->mnet_localhost_id; $admin->lang = $CFG->lang; $admin->maildisplay = 1; $admin->timemodified = time(); $admin->lastip = CLI_SCRIPT ? '0.0.0.0' : getremoteaddr(); // installation hijacking prevention $admin->id = $DB->insert_record('user', $admin); if ($admin->id != 2) { echo $OUTPUT->notification('Unexpected id generated for the Admin account. Your database configuration or clustering setup may not be fully supported', 'notifyproblem'); } if ($admin->id != $guest->id + 1) { echo $OUTPUT->notification('Nonconsecutive id generated for the Admin account. Your database configuration or clustering setup may not be fully supported.', 'notifyproblem'); } // Store list of admins set_config('siteadmins', $admin->id); // Make sure user context exists context_user::instance($admin->id); // Install the roles system. $managerrole = create_role('', 'manager', '', 'manager'); $coursecreatorrole = create_role('', 'coursecreator', '', 'coursecreator'); $editteacherrole = create_role('', 'editingteacher', '', 'editingteacher'); $noneditteacherrole = create_role('', 'teacher', '', 'teacher'); $studentrole = create_role('', 'student', '', 'student'); $guestrole = create_role('', 'guest', '', 'guest'); $userrole = create_role('', 'user', '', 'user'); $frontpagerole = create_role('', 'frontpage', '', 'frontpage'); // Now is the correct moment to install capabilities - after creation of legacy roles, but before assigning of roles update_capabilities('moodle'); // Default allow role matrices. foreach ($DB->get_records('role') as $role) { foreach (array('assign', 'override', 'switch') as $type) { $function = 'allow_' . $type; $allows = get_default_role_archetype_allows($type, $role->archetype); foreach ($allows as $allowid) { $function($role->id, $allowid); } } } // Set up the context levels where you can assign each role. set_role_contextlevels($managerrole, get_default_contextlevels('manager')); set_role_contextlevels($coursecreatorrole, get_default_contextlevels('coursecreator')); set_role_contextlevels($editteacherrole, get_default_contextlevels('editingteacher')); set_role_contextlevels($noneditteacherrole, get_default_contextlevels('teacher')); set_role_contextlevels($studentrole, get_default_contextlevels('student')); set_role_contextlevels($guestrole, get_default_contextlevels('guest')); set_role_contextlevels($userrole, get_default_contextlevels('user')); // Init theme and JS revisions set_config('themerev', time()); set_config('jsrev', time()); // No admin setting for this any more, GD is now required, remove in Moodle 2.6. set_config('gdversion', 2); // Install licenses require_once $CFG->libdir . '/licenselib.php'; license_manager::install_licenses(); // Init profile pages defaults if ($DB->record_exists('my_pages', array())) { throw new moodle_exception('generalexceptionmessage', 'error', '', 'Can not create default profile pages, records already exist.'); } $mypage = new stdClass(); $mypage->userid = NULL; $mypage->name = '__default'; $mypage->private = 0; $mypage->sortorder = 0; $DB->insert_record('my_pages', $mypage); $mypage->private = 1; $DB->insert_record('my_pages', $mypage); // Set a sensible default sort order for the most-used question types. set_config('multichoice_sortorder', 1, 'question'); set_config('truefalse_sortorder', 2, 'question'); set_config('match_sortorder', 3, 'question'); set_config('shortanswer_sortorder', 4, 'question'); set_config('numerical_sortorder', 5, 'question'); set_config('essay_sortorder', 6, 'question'); }
function xmldb_block_curr_admin_upgrade($oldversion = 0) { global $CFG, $THEME, $db; $result = true; if ($oldversion < 2009010102) { $context = get_context_instance(CONTEXT_SYSTEM, SITEID); if ($role = get_record('role', 'shortname', 'curriculumadmin')) { if ($role->name == 'Bundle Administrator') { $role->name = 'Curriculum Administrator'; addslashes_object($role); update_record('role', $role); } } if (!empty($role->id)) { require_once dirname(__FILE__) . '/access.php'; if (!empty($block_curr_admin_capabilities)) { foreach ($block_curr_admin_capabilities as $capname => $caprules) { $result = $result && assign_capability($capname, CAP_ALLOW, $role->id, $context->id); } } } } if ($oldversion < 2009010103) { $table = new XMLDBTable('crlm_curriculum'); $field = new XMLDBField('timetocomplete'); $field->setAttributes(XMLDB_TYPE_CHAR, '64', NULL, XMLDB_NOTNULL, NULL, NULL, NULL, '0h, 0d, 0w, 0m, 0y', 'timemodified'); $result = $result && add_field($table, $field); $field = new XMLDBField('frequency'); $field->setAttributes(XMLDB_TYPE_CHAR, '64', NULL, XMLDB_NOTNULL, NULL, NULL, NULL, '0h, 0d, 0w, 0m, 0y', 'timetocomplete'); $result = $result && add_field($table, $field); } if ($oldversion < 2009010104) { $table = new XMLDBTable('crlm_config'); $table->comment = 'Curriculum management configuration values.'; // fields $f = $table->addFieldInfo('id', XMLDB_TYPE_INTEGER, '10', false, XMLDB_NOTNULL, XMLDB_SEQUENCE, null, null, null); $f = $table->addFieldInfo('name', XMLDB_TYPE_CHAR, '255', null, false, null, null, null, null); $f = $table->addFieldInfo('value', XMLDB_TYPE_TEXT, 'medium', null, false, null, null, null, null); // PK and indexes $table->addKeyInfo('primary', XMLDB_KEY_PRIMARY, array('id')); $table->addIndexInfo('name_ix', XMLDB_INDEX_UNIQUE, array('name')); $result = $result && create_table($table); } if ($oldversion < 2009010105) { $table = new XMLDBTable('crlm_coursetemplate'); $table->comment = 'Course templates'; // fields $f = $table->addFieldInfo('id', XMLDB_TYPE_INTEGER, '10', false, XMLDB_NOTNULL, XMLDB_SEQUENCE, null, null, null); $f = $table->addFieldInfo('courseid', XMLDB_TYPE_INTEGER, '10', false, XMLDB_NOTNULL, null, null, null, null); $f = $table->addFieldInfo('location', XMLDB_TYPE_CHAR, '255', null, false, null, null, null, null); $f = $table->addFieldInfo('templateclass', XMLDB_TYPE_CHAR, '255', null, false, null, null, null, null); // PK and indexes $table->addKeyInfo('primary', XMLDB_KEY_PRIMARY, array('id')); $table->addIndexInfo('courseid_ix', XMLDB_INDEX_UNIQUE, array('courseid')); $result = $result && create_table($table); } if ($oldversion < 2009010106) { $table = new XMLDBTable('crlm_cluster_curriculum'); $table->comment = 'Association between clusters and curricula'; // fields $f = $table->addFieldInfo('id', XMLDB_TYPE_INTEGER, '10', false, XMLDB_NOTNULL, XMLDB_SEQUENCE, null, null, null); $f = $table->addFieldInfo('clusterid', XMLDB_TYPE_INTEGER, '10', null, true, null, null, null, null, 'id'); $f->comment = 'Foreign key to cluster id'; $f = $table->addFieldInfo('curriculumid', XMLDB_TYPE_INTEGER, '10', null, true, null, null, null, null, 'clusterid'); $f->comment = 'Foreign key to curriculum id'; // PK and indexes $table->addKeyInfo('primary', XMLDB_KEY_PRIMARY, array('id')); $table->addIndexInfo('cluster_idx', XMLDB_INDEX_NOTUNIQUE, array('clusterid')); $result = $result && create_table($table); } if ($oldversion < 2009010108) { $table = new XMLDBTable('crlm_cluster_track'); $table->comment = 'Association between clusters and tracks'; // fields $f = $table->addFieldInfo('id', XMLDB_TYPE_INTEGER, '10', false, XMLDB_NOTNULL, XMLDB_SEQUENCE, null, null, null); $f = $table->addFieldInfo('clusterid', XMLDB_TYPE_INTEGER, '10', null, true, null, null, null, null, 'id'); $f->comment = 'Foreign key to cluster id'; $f = $table->addFieldInfo('trackid', XMLDB_TYPE_INTEGER, '10', null, true, null, null, null, null, 'clusterid'); $f->comment = 'Foreign key to track id'; $f = $table->addFieldInfo('autounenrol', XMLDB_TYPE_INTEGER, '1', null, true, null, null, null, null, 'trackid'); $f->comment = 'Whether or not to remove a user from classes when removed from cluster'; // PK and indexes $table->addKeyInfo('primary', XMLDB_KEY_PRIMARY, array('id')); $table->addIndexInfo('cluster_idx', XMLDB_INDEX_NOTUNIQUE, array('clusterid')); $result = $result && create_table($table); $table = new XMLDBTable('crlm_usercluster'); $f = new XMLDBField('autoenrol'); $f->setAttributes(XMLDB_TYPE_INTEGER, '1', null, true, null, null, null, 1, 'clusterid'); $f->comment = 'Whether users should be autoenrolled in tracks associated with this cluster.'; $result = $result && add_field($table, $f); } if ($oldversion < 2009010109) { /// Define table crlm_class_moodle to be created $table = new XMLDBTable('crlm_class_moodle'); /// Adding fields to table crlm_class_moodle $table->addFieldInfo('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null, null, null); $table->addFieldInfo('classid', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null, null, '0'); $table->addFieldInfo('moodlecourseid', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null, null, '0'); $table->addFieldInfo('enroltype', XMLDB_TYPE_INTEGER, '2', XMLDB_UNSIGNED, null, null, null, null, '0'); $table->addFieldInfo('enrolplugin', XMLDB_TYPE_CHAR, '20', null, null, null, null, null, 'crlm'); $table->addFieldInfo('timemodified', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null, null, '0'); /// Adding keys to table crlm_class_moodle $table->addKeyInfo('primary', XMLDB_KEY_PRIMARY, array('id')); $table->addKeyInfo('mdl_currclasmood_clamoo_uix', XMLDB_KEY_UNIQUE, array('classid', 'moodlecourseid')); /// Launch create table for crlm_class_moodle $result = $result && create_table($table); } if ($oldversion < 2009010110) { $table = new XMLDBTable('crlm_user_track'); $table->comment = 'User enrolment in tracks'; // fields $f = $table->addFieldInfo('id', XMLDB_TYPE_INTEGER, '10', false, XMLDB_NOTNULL, XMLDB_SEQUENCE, null, null, null); $f = $table->addFieldInfo('userid', XMLDB_TYPE_INTEGER, '10', null, true, null, null, null, null, 'id'); $f->comment = 'Foreign key to user id'; $f = $table->addFieldInfo('trackid', XMLDB_TYPE_INTEGER, '10', null, true, null, null, null, null, 'userid'); $f->comment = 'Foreign key to track id'; // PK and indexes $table->addKeyInfo('primary', XMLDB_KEY_PRIMARY, array('id')); $result = $result && create_table($table); } if ($result && $oldversion < 2009010112) { /// Define table crlm_notification_log to be created $table = new XMLDBTable('crlm_notification_log'); /// Adding fields to table crlm_notification_log $table->addFieldInfo('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null, null, null); $table->addFieldInfo('event', XMLDB_TYPE_CHAR, '166', null, null, null, null, null, null); $table->addFieldInfo('instance', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null, null, '0'); $table->addFieldInfo('userid', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null, null, '0'); $table->addFieldInfo('data', XMLDB_TYPE_CHAR, '255', null, null, null, null, null, null); $table->addFieldInfo('timecreated', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null, null, '0'); /// Adding keys to table crlm_notification_log $table->addKeyInfo('primary', XMLDB_KEY_PRIMARY, array('id')); /// Adding indexes to table crlm_notification_log $table->addIndexInfo('event_inst_user_ix', XMLDB_INDEX_NOTUNIQUE, array('event', 'instance', 'userid')); /// Launch create table for crlm_notification_log $result = $result && create_table($table); } if ($result && $oldversion < 2009010113) { /// Define index event_inst_user_ix (not unique) to be dropped from crlm_notification_log $table = new XMLDBTable('crlm_notification_log'); $index = new XMLDBIndex('event_inst_user_ix'); $index->setAttributes(XMLDB_INDEX_NOTUNIQUE, array('event', 'instance', 'userid')); /// Launch drop index event_inst_user_ix $result = $result && drop_index($table, $index); /// Define index event_inst_user_ix (not unique) to be added to crlm_notification_log $table = new XMLDBTable('crlm_notification_log'); $index = new XMLDBIndex('event_inst_user_ix'); $index->setAttributes(XMLDB_INDEX_NOTUNIQUE, array('userid', 'instance', 'event')); /// Launch add index event_inst_user_ix $result = $result && add_index($table, $index); } if ($result && $oldversion < 2009010114) { // Creating track table $table = new XMLDBTable('crlm_track'); $table->comment = 'Track table'; // fields $f = $table->addFieldInfo('id', XMLDB_TYPE_INTEGER, '10', false, XMLDB_NOTNULL, XMLDB_SEQUENCE, null, null, null); $f = $table->addFieldInfo('curid', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null, null, '0'); $f = $table->addFieldInfo('idnumber', XMLDB_TYPE_CHAR, '100', null, XMLDB_NOTNULL, null, null, null); $f = $table->addFieldInfo('name', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null, null); $f = $table->addFieldInfo('description', XMLDB_TYPE_TEXT, 'small', null, XMLDB_NOTNULL, null, null, null, null); $f = $table->addFieldInfo('startdate', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null, null, '0'); $f = $table->addFieldInfo('enddate', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null, null, '0'); $f = $table->addFieldInfo('timecreated', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null, null, '0'); $f = $table->addFieldInfo('timemodified', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null, null, '0'); // PK and indexes $table->addKeyInfo('primary', XMLDB_KEY_PRIMARY, array('id')); $table->addIndexInfo('track_curr_idx', XMLDB_INDEX_NOTUNIQUE, array('curid')); $result = $result && create_table($table); $table = new XMLDBTable('crlm_track_class'); $table->comment = 'Track class table'; $f = $table->addFieldInfo('id', XMLDB_TYPE_INTEGER, '10', false, XMLDB_NOTNULL, XMLDB_SEQUENCE, null, null, null); $f = $table->addFieldInfo('trackid', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null, null, '0'); $f = $table->addFieldInfo('classid', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null, null, '0'); $f = $table->addFieldInfo('courseid', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null, null, '0'); $f = $table->addFieldInfo('requried', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null, null, '0'); $f = $table->addFieldInfo('autoenrol', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null, null, '0'); $f = $table->addFieldInfo('default', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null, null, '0'); $f = $table->addFieldInfo('timecreated', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null, null, '0'); $f = $table->addFieldInfo('timemodified', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null, null, '0'); $table->addKeyInfo('primary', XMLDB_KEY_PRIMARY, array('id')); $table->addIndexInfo('trackid_idx', XMLDB_INDEX_NOTUNIQUE, array('trackid')); $table->addIndexInfo('track_classid_idx', XMLDB_INDEX_NOTUNIQUE, array('classid')); $table->addIndexInfo('track_courseid_idx', XMLDB_INDEX_NOTUNIQUE, array('courseid')); $result = $result && create_table($table); } if ($result && $oldversion < 2009010115) { /// Define table crlm_cluster_profile to be created $table = new XMLDBTable('crlm_cluster_profile'); /// Adding fields to table crlm_cluster_profile $table->addFieldInfo('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null, null, null); $table->addFieldInfo('clusterid', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null, null, null); $table->addFieldInfo('fieldid', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null, null, null); $table->addFieldInfo('value', XMLDB_TYPE_TEXT, 'big', null, XMLDB_NOTNULL, null, null, null, null); /// Adding keys to table crlm_cluster_profile $table->addKeyInfo('primary', XMLDB_KEY_PRIMARY, array('id')); /// Launch create table for crlm_cluster_profile $result = $result && create_table($table); /// Define table crlm_cluster_assignments to be created $table = new XMLDBTable('crlm_cluster_assignments'); /// Adding fields to table crlm_cluster_assignments $table->addFieldInfo('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null, null, null); $table->addFieldInfo('clusterid', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null, null, null); $table->addFieldInfo('userid', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null, null, null); $table->addFieldInfo('plugin', XMLDB_TYPE_CHAR, '32', null, XMLDB_NOTNULL, null, null, null, null); /// Adding keys to table crlm_cluster_assignments $table->addKeyInfo('primary', XMLDB_KEY_PRIMARY, array('id')); /// Launch create table for crlm_cluster_assignments $result = $result && create_table($table); } if ($result && $oldversion < 2009010116) { $table = new XMLDBTable('crlm_track_class'); $field = new XMLDBField('default'); $field->setAttributes(XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null, null, '0', 'autoenrol'); $result = $result && drop_field($table, $field); $field = new XMLDBField('defaulttrack'); $field->setAttributes(XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null, null, '0', 'autoenrol'); $result = $result && add_field($table, $field); } if ($result && $oldversion < 2009010117) { /// Remove obsolete job code tables if they exist. $table = new XMLDBTable('crlm_jobcode_list'); if (table_exists($table)) { drop_table($table); } $table = new XMLDBTable('crlm_curriculum_jobcode'); if (table_exists($table)) { drop_table($table); } } if ($result && $oldversion < 2009010118) { /// Removing defaulttrack column from table $table = new XMLDBTable('crlm_track_class'); $field = new XMLDBField('defaulttrack'); $field->setAttributes(XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null, null, '0', 'autoenrol'); $result = $result && drop_field($table, $field); /// Adding defaulttrack column to table $table = new XMLDBTable('crlm_track'); $field = new XMLDBField('defaulttrack'); $field->setAttributes(XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null, null, '0', 'enddate'); $result = $result && add_field($table, $field); } if ($result && $oldversion < 2009010119) { /// Define field completed to be added to crlm_curriculum_assignment $table = new XMLDBTable('crlm_curriculum_assignment'); $field = new XMLDBField('completed'); $field->setAttributes(XMLDB_TYPE_INTEGER, '2', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null, null, '0', 'curriculumid'); /// Launch add field completed $result = $result && add_field($table, $field); /// Define field completiontime to be added to crlm_curriculum_assignment $field = new XMLDBField('timecompleted'); $field->setAttributes(XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null, null, '0', 'completed'); /// Launch add field completiontime $result = $result && add_field($table, $field); /// Define field credits to be added to crlm_curriculum_assignment $field = new XMLDBField('credits'); $field->setAttributes(XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null, null, '0', 'timecompleted'); /// Launch add field credits $result = $result && add_field($table, $field); /// Define field locked to be added to crlm_curriculum_assignment $table = new XMLDBTable('crlm_curriculum_assignment'); $field = new XMLDBField('locked'); $field->setAttributes(XMLDB_TYPE_INTEGER, '2', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null, null, '0', 'credits'); /// Launch add field locked $result = $result && add_field($table, $field); /// Define key mdl_currcurrassi_usecur_uix (unique) to be dropped from crlm_curriculum_assignment $key = new XMLDBKey('mdl_currcurrassi_usecur_uix'); $key->setAttributes(XMLDB_KEY_UNIQUE, array('userid', 'curriculumid')); /// Launch drop key mdl_currcurrassi_usecur_uix $result = $result && drop_key($table, $key); /// Define index mdl_currcurrassi_usecurcom_ix (not unique) to be added to crlm_curriculum_assignment $index = new XMLDBIndex('mdl_currcurrassi_usecurcom_ix'); $index->setAttributes(XMLDB_INDEX_NOTUNIQUE, array('userid', 'curriculumid', 'completed')); /// Launch add index mdl_currcurrassi_usecurcom_ix $result = $result && add_index($table, $index); /// Define index completed_ix (not unique) to be added to crlm_curriculum_assignment $index = new XMLDBIndex('completed_ix'); $index->setAttributes(XMLDB_INDEX_NOTUNIQUE, array('completed')); /// Launch add index completed_ix $result = $result && add_index($table, $index); } if ($result && $oldversion < 2009010120) { /// Define field autoenrol to be added to crlm_cluster_assignments $table = new XMLDBTable('crlm_cluster_assignments'); $field = new XMLDBField('autoenrol'); $field->setAttributes(XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null, null, '1', 'plugin'); /// Launch add field autoenrol $result = $result && add_field($table, $field); } if ($result && $oldversion < 2009010121) { if (!record_exists('mnet_application', 'name', 'java')) { $application = new stdClass(); $application->name = 'java'; $application->display_name = 'Java servlet'; $application->xmlrpc_server_url = '/mnet/server'; $application->sso_land_url = '/mnet/land.jsp'; $result = $result && insert_record('mnet_application', $application, false); } } if ($result && $oldversion < 2009010122) { $table = new XMLDBTable('crlm_track_class'); $field = new XMLDBField('requried'); $field->setAttributes(XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null, null, '0', 'courseid'); $result = $result && drop_field($table, $field); } if ($result && $oldversion < 2009010125) { $result = $result && execute_sql('CREATE OR REPLACE VIEW `courseNforums` AS select `f`.`id` AS `forumid`,concat(`c`.`shortname`,_utf8\' | \',`f`.`name`) AS `courseNforumname` from (`mdl_forum` `f` join `mdl_course` `c` on((`c`.`id` = `f`.`course`))) order by `c`.`shortname`,`f`.`name`'); } if ($result && $oldversion < 2009010126) { $table = new XMLDBTable('crlm_cluster_curriculum'); $table->comment = 'Association between clusters and curricula'; // fields $f = $table->addFieldInfo('id', XMLDB_TYPE_INTEGER, '10', false, XMLDB_NOTNULL, XMLDB_SEQUENCE, null, null, null); $f = $table->addFieldInfo('clusterid', XMLDB_TYPE_INTEGER, '10', null, true, null, null, null, null, 'id'); $f->comment = 'Foreign key to cluster id'; $f = $table->addFieldInfo('curriculumid', XMLDB_TYPE_INTEGER, '10', null, true, null, null, null, null, 'clusterid'); $f->comment = 'Foreign key to curriculum id'; // PK and indexes $table->addKeyInfo('primary', XMLDB_KEY_PRIMARY, array('id')); $table->addIndexInfo('cluster_idx', XMLDB_INDEX_NOTUNIQUE, array('clusterid')); $result = $result && (table_exists($table) || create_table($table)); $table = new XMLDBTable('crlm_cluster_track'); $table->comment = 'Association between clusters and tracks'; // fields $f = $table->addFieldInfo('id', XMLDB_TYPE_INTEGER, '10', false, XMLDB_NOTNULL, XMLDB_SEQUENCE, null, null, null); $f = $table->addFieldInfo('clusterid', XMLDB_TYPE_INTEGER, '10', null, true, null, null, null, null, 'id'); $f->comment = 'Foreign key to cluster id'; $f = $table->addFieldInfo('trackid', XMLDB_TYPE_INTEGER, '10', null, true, null, null, null, null, 'clusterid'); $f->comment = 'Foreign key to track id'; $f = $table->addFieldInfo('autounenrol', XMLDB_TYPE_INTEGER, '1', null, true, null, null, null, null, 'trackid'); $f->comment = 'Whether or not to remove a user from classes when removed from cluster'; // PK and indexes $table->addKeyInfo('primary', XMLDB_KEY_PRIMARY, array('id')); $table->addIndexInfo('cluster_idx', XMLDB_INDEX_NOTUNIQUE, array('clusterid')); $result = $result && (table_exists($table) || create_table($table)); } if ($result && $oldversion < 2009010127) { // fix silly typos $newtable = new XMLDBTable('crlm_user_track'); $oldtable = new XMLDBTable('clrm_user_track'); $result = $result && (table_exists($newtable) || rename_table($oldtable, 'crlm_user_track')); $oldtable = new XMLDBTable('clrm_cluster_track'); $result = $result && (!table_exists($oldtable) || drop_table($oldtable)); $oldtable = new XMLDBTable('clrm_cluster_curriculum'); $result = $result && (!table_exists($oldtable) || drop_table($oldtable)); } if ($result && $oldversion < 2009010128) { require_once $CFG->dirroot . '/curriculum/lib/lib.php'; cm_migrate_moodle_users(); } if ($result && $oldversion < 2009010131) { /// Get rid of any outdated cluster data we might have lying around. if ($CFG->dbfamily == 'postgres') { $sql = "DELETE FROM {$CFG->prefix}crlm_cluster_assignments\n WHERE id IN (\n SELECT ca.clusterid\n FROM {$CFG->prefix}crlm_cluster_assignments ca\n LEFT JOIN {$CFG->prefix}crlm_cluster c ON c.id = ca.clusterid\n WHERE c.id IS NULL\n )"; $result = $result && execute_sql($sql); $sql = "DELETE FROM {$CFG->prefix}crlm_cluster_curriculum\n WHERE id IN (\n SELECT cc.clusterid\n FROM {$CFG->prefix}crlm_cluster_curriculum cc\n LEFT JOIN {$CFG->prefix}crlm_cluster c ON c.id = cc.clusterid\n WHERE c.id IS NULL\n )"; $result = $result && execute_sql($sql); $sql = "DELETE FROM {$CFG->prefix}crlm_cluster_profile\n WHERE id IN (\n SELECT cp.clusterid\n FROM {$CFG->prefix}crlm_cluster_profile cp\n LEFT JOIN {$CFG->prefix}crlm_cluster c ON c.id = cp.clusterid\n WHERE c.id IS NULL\n )"; $result = $result && execute_sql($sql); $sql = "DELETE FROM {$CFG->prefix}crlm_cluster_track\n WHERE id IN (\n SELECT ct.clusterid\n FROM {$CFG->prefix}crlm_cluster_track ct\n LEFT JOIN {$CFG->prefix}crlm_cluster c ON c.id = ct.clusterid\n WHERE c.id IS NULL\n )"; $result = $result && execute_sql($sql); $sql = "DELETE FROM {$CFG->prefix}crlm_usercluster\n WHERE id IN (\n SELECT uc.clusterid\n FROM {$CFG->prefix}crlm_usercluster uc\n LEFT JOIN {$CFG->prefix}crlm_cluster c ON c.id = uc.clusterid\n WHERE c.id IS NULL\n )"; $result = $result && execute_sql($sql); } else { $sql = "DELETE ca FROM {$CFG->prefix}crlm_cluster_assignments ca\n LEFT JOIN {$CFG->prefix}crlm_cluster c ON c.id = ca.clusterid\n WHERE c.id IS NULL"; $result = $result && execute_sql($sql); $sql = "DELETE cc FROM {$CFG->prefix}crlm_cluster_curriculum cc\n LEFT JOIN {$CFG->prefix}crlm_cluster c ON c.id = cc.clusterid\n WHERE c.id IS NULL"; $result = $result && execute_sql($sql); $sql = "DELETE cp FROM {$CFG->prefix}crlm_cluster_profile cp\n LEFT JOIN {$CFG->prefix}crlm_cluster c ON c.id = cp.clusterid\n WHERE c.id IS NULL"; $result = $result && execute_sql($sql); $sql = "DELETE ct FROM {$CFG->prefix}crlm_cluster_track ct\n LEFT JOIN {$CFG->prefix}crlm_cluster c ON c.id = ct.clusterid\n WHERE c.id IS NULL"; $result = $result && execute_sql($sql); $sql = "DELETE uc FROM {$CFG->prefix}crlm_usercluster uc\n LEFT JOIN {$CFG->prefix}crlm_cluster c ON c.id = uc.clusterid\n WHERE c.id IS NULL"; $result = $result && execute_sql($sql); } } if ($result && $oldversion < 2009010133) { /// Define field leader to be added to crlm_cluster_assignments $table = new XMLDBTable('crlm_cluster_assignments'); $field = new XMLDBField('leader'); $field->setAttributes(XMLDB_TYPE_INTEGER, '1', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null, null, '0', 'autoenrol'); /// Launch add field leader $result = $result && add_field($table, $field); /// Define field leader to be added to crlm_usercluster $table = new XMLDBTable('crlm_usercluster'); $field = new XMLDBField('leader'); $field->setAttributes(XMLDB_TYPE_INTEGER, '1', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null, null, '0', 'autoenrol'); /// Launch add field leader $result = $result && add_field($table, $field); } if ($result && $oldversion < 2009010134) { /// Define field inactive to be added to crlm_user $table = new XMLDBTable('crlm_user'); $field = new XMLDBField('inactive'); $field->setAttributes(XMLDB_TYPE_INTEGER, '1', XMLDB_UNSIGNED, null, null, null, null, '0', 'timemodified'); /// Launch add field inactive $result = $result && add_field($table, $field); } if ($result && $oldversion < 2009010137) { $roleid = get_field('role', 'id', 'shortname', 'curriculumadmin'); if (!empty($roleid)) { $context = get_context_instance(CONTEXT_SYSTEM, SITEID); require_once dirname(dirname(__FILE__)) . '/db/access.php'; if (!empty($block_curr_admin_capabilities)) { foreach ($block_curr_admin_capabilities as $capname => $caprules) { $result = $result && assign_capability($capname, CAP_ALLOW, $roleid, $context->id); } } } } if ($result && $oldversion < 2009010139) { global $CURMAN; require_once $CFG->dirroot . '/curriculum/lib/classmoodlecourse.class.php'; $moodleclasses = moodle_get_classes(); if (!empty($moodleclasses)) { foreach ($moodleclasses as $class) { $context = get_context_instance(CONTEXT_COURSE, $class->moodlecourseid); $sql = "DELETE cmce\n FROM {$CURMAN->db->prefix_table('user')} u\n JOIN {$CURMAN->db->prefix_table('role_assignments')} ra ON u.id = ra.userid\n JOIN {$CURMAN->db->prefix_table(STUTABLE)} cmce ON u.idnumber = cmce.user_idnumber\n WHERE ra.roleid NOT IN ({$CFG->gradebookroles})\n AND ra.contextid " . get_related_contexts_string($context) . "AND cmce.classid = {$class->classid}"; $result = $result && execute_sql($sql); } } } if ($result && $oldversion < 2009010140) { delete_records('crlm_cluster_profile', 'fieldid', 0); } if ($result && $oldversion < 2009010141) { set_config('field_lock_idnumber', 'locked', 'auth/manual'); } if ($result && $oldversion < 2009010143) { /// Define table crlm_wait_list to be created $table = new XMLDBTable('crlm_wait_list'); /// Adding fields to table crlm_wait_list $table->addFieldInfo('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null, null, null); $table->addFieldInfo('classid', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null, null, null); $table->addFieldInfo('userid', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null, null, null); $table->addFieldInfo('timecreated', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null, null, '0'); $table->addFieldInfo('timemodified', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null, null, '0'); $table->addFieldInfo('position', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, null, null, null, null, null); /// Adding keys to table crlm_wait_list $table->addKeyInfo('primary', XMLDB_KEY_PRIMARY, array('id')); /// Launch create table for crlm_wait_list $result = $result && create_table($table); } if ($result && $oldversion < 2009010145) { $table = new XMLDBTable('crlm_wait_list'); $field = new XMLDBField('enrolmenttime'); $field->setAttributes(XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null, null, '0'); $result = $result && add_field($table, $field); } if ($result && $oldversion < 2009010146) { // make sure trackclass's courseids are set // Let's just assume that all non-Postgres DB's use the same syntax as MySQL and call it a day. if ($CFG->dbfamily == 'postgres') { $sql = "UPDATE {$CFG->prefix}crlm_track_class\n SET courseid = c.courseid\n FROM {$CFG->prefix}crlm_track_class tc, {$CFG->prefix}crlm_class c\n WHERE tc.classid = c.id AND tc.courseid = 0"; } else { $sql = "UPDATE {$CFG->prefix}crlm_track_class tc, {$CFG->prefix}crlm_class c\n SET tc.courseid = c.courseid\n WHERE tc.classid = c.id AND tc.courseid = 0"; } $result = $result && execute_sql($sql); } if ($result && $oldversion < 2009010147) { // make sure all users have an idnumber $users = get_records('crlm_user', 'idnumber', ''); foreach ($users as $user) { $user = addslashes_recursive($user); $mu = addslashes_recursive(get_record('user', 'username', $user->username)); if (empty($mu->idnumber)) { $user->idnumber = $mu->idnumber = $mu->username; update_record('user', $mu); update_record('crlm_user', $user); } else { if (!get_record('crlm_user', 'idnumber', $mu->idnumber)) { $user->idnumber = $mu->idnumber; update_record('crlm_user', $user); } else { if (!get_record('crlm_user', 'idnumber', $user->username)) { $user->idnumber = $mu->idnumber; update_record('crlm_user', $user); } } } } } if ($result && $oldversion < 2009010149) { /// Define index clusterid_idx (not unique) to be added to crlm_cluster_assignments $table = new XMLDBTable('crlm_cluster_assignments'); $index = new XMLDBIndex('clusterid_idx'); $index->setAttributes(XMLDB_INDEX_NOTUNIQUE, array('clusterid')); /// Launch add index clusterid_idx $result = $result && add_index($table, $index); /// Define index userid_idx (not unique) to be added to crlm_cluster_assignments $table = new XMLDBTable('crlm_cluster_assignments'); $index = new XMLDBIndex('userid_idx'); $index->setAttributes(XMLDB_INDEX_NOTUNIQUE, array('userid')); /// Launch add index userid_idx $result = $result && add_index($table, $index); /// Define index clusterid_idx (not unique) to be added to crlm_cluster_profile $table = new XMLDBTable('crlm_cluster_profile'); $index = new XMLDBIndex('clusterid_idx'); $index->setAttributes(XMLDB_INDEX_NOTUNIQUE, array('clusterid')); /// Launch add index clusterid_idx $result = $result && add_index($table, $index); } if ($result && $oldversion < 2009010151) { $table = new XMLDBTable('crlm_curriculum'); $field = new XMLDBField('priority'); $field->setAttributes(XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null, null, '0'); $result = $result && add_field($table, $field); } if ($result && $oldversion < 2009010150) { require_once CURMAN_DIRLOCATION . '/lib/curriculumcourse.class.php'; $sql = "SELECT cp.id, cp.courseid, cc.curriculumid\n FROM {$CFG->prefix}crlm_course_prerequisite cp\n JOIN {$CFG->prefix}crlm_curriculum_course cc ON cc.id = cp.curriculumcourseid\n WHERE cp.courseid NOT IN (\n SELECT _cc.courseid\n FROM {$CFG->prefix}crlm_curriculum_course _cc\n WHERE _cc.curriculumid = cc.curriculumid\n )"; $students = get_records_sql($sql); $retval = 0; foreach ($students as $student) { $data = new object(); $data->curriculumid = $student->curriculumid; $data->courseid = $student->courseid; $data->timeperiod = 'year'; $currprereq = new curriculumcourse($data); $retval = $result && $currprereq->add(); } $results = $retval; } if ($result && $oldversion < 2009103001) { $table = new XMLDBTable('crlm_curriculum'); $field = new XMLDBField('priority'); $field->setAttributes(XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null, null, '0'); $result = $result && add_field($table, $field); /// Define table context_levels to be created $table = new XMLDBTable('context_levels'); /// Adding fields to table context_levels $table->addFieldInfo('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null, null, null); $table->addFieldInfo('name', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null, null, null); $table->addFieldInfo('component', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null, null, null); /// Adding keys to table context_levels $table->addKeyInfo('primary', XMLDB_KEY_PRIMARY, array('id')); /// Adding indexes to table context_levels $table->addIndexInfo('name', XMLDB_INDEX_NOTUNIQUE, array('name')); $table->addIndexInfo('component', XMLDB_INDEX_NOTUNIQUE, array('component')); /// Launch create table for context_levels $result = $result && create_table($table); } if ($result && $oldversion < 2009103003) { /// Define table crlm_field to be created $table = new XMLDBTable('crlm_field'); /// Adding fields to table crlm_field $table->addFieldInfo('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null, null, null); $table->addFieldInfo('shortname', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null, null, null); $table->addFieldInfo('name', XMLDB_TYPE_TEXT, 'big', null, XMLDB_NOTNULL, null, null, null, null); $table->addFieldInfo('datatype', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null, null, null); $table->addFieldInfo('description', XMLDB_TYPE_TEXT, 'big', null, null, null, null, null, null); $table->addFieldInfo('categoryid', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null, null, null); $table->addFieldInfo('sortorder', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null, null, null); $table->addFieldInfo('required', XMLDB_TYPE_INTEGER, '1', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null, null, null); $table->addFieldInfo('locked', XMLDB_TYPE_INTEGER, '1', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null, null, null); $table->addFieldInfo('visible', XMLDB_TYPE_INTEGER, '4', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null, null, null); $table->addFieldInfo('forceunique', XMLDB_TYPE_INTEGER, '1', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null, null, null); $table->addFieldInfo('defaultdata', XMLDB_TYPE_TEXT, 'big', null, null, null, null, null, null); $table->addFieldInfo('params', XMLDB_TYPE_TEXT, 'big', null, null, null, null, null, null); $table->addFieldInfo('syncwithmoodle', XMLDB_TYPE_INTEGER, '2', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null, null, null); /// Adding keys to table crlm_field $table->addKeyInfo('primary', XMLDB_KEY_PRIMARY, array('id')); /// Adding indexes to table crlm_field $table->addIndexInfo('shortname_idx', XMLDB_INDEX_NOTUNIQUE, array('shortname')); /// Launch create table for crlm_field $result = $result && create_table($table); /// Define table crlm_field_category to be created $table = new XMLDBTable('crlm_field_category'); /// Adding fields to table crlm_field_category $table->addFieldInfo('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null, null, null); $table->addFieldInfo('name', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null, null, null); $table->addFieldInfo('sortorder', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null, null, null); /// Adding keys to table crlm_field_category $table->addKeyInfo('primary', XMLDB_KEY_PRIMARY, array('id')); /// Launch create table for crlm_field_category $result = $result && create_table($table); /// Define table crlm_field_contextlevel to be created $table = new XMLDBTable('crlm_field_contextlevel'); /// Adding fields to table crlm_field_contextlevel $table->addFieldInfo('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null, null, null); $table->addFieldInfo('fieldid', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null, null, null); $table->addFieldInfo('contextlevel', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null, null, null); /// Adding keys to table crlm_field_contextlevel $table->addKeyInfo('primary', XMLDB_KEY_PRIMARY, array('id')); /// Launch create table for crlm_field_contextlevel $result = $result && create_table($table); /// Define table crlm_field_data to be created $table = new XMLDBTable('crlm_field_data'); /// Adding fields to table crlm_field_data $table->addFieldInfo('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null, null, null); $table->addFieldInfo('contextid', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null, null, null); $table->addFieldInfo('fieldid', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null, null, null); $table->addFieldInfo('data', XMLDB_TYPE_TEXT, 'big', null, XMLDB_NOTNULL, null, null, null, null); /// Adding keys to table crlm_field_data $table->addKeyInfo('primary', XMLDB_KEY_PRIMARY, array('id')); /// Adding indexes to table crlm_field_data $table->addIndexInfo('context_idx', XMLDB_INDEX_NOTUNIQUE, array('contextid')); /// Launch create table for crlm_field_data $result = $result && create_table($table); } //if ($result && $oldversion < 2010040501) { // require_once($CFG->dirroot . '/blocks/curr_admin/lib.php'); // $result = $result && create_views(); // create with default prefix // $result = $result && create_views(''); // create with no prefix //} if ($result && $oldversion < 2010040501) { $table = new XMLDBTable('crlm_field_map'); /// Adding fields to table crlm_field_data $table->addFieldInfo('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null, null, null); $table->addFieldInfo('context', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null, null, null); $table->addFieldInfo('type', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null, null, null); $table->addFieldInfo('elis_field', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null, null, null); $table->addFieldInfo('data_field', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null, null, null); /// Adding keys to table crlm_field_data $table->addKeyInfo('primary', XMLDB_KEY_PRIMARY, array('id')); /// Launch create table for crlm_field_data $result = $result && create_table($table); } if ($result && $oldversion < 2010040501) { require_once "{$CFG->dirroot}/curriculum/lib/customfield.class.php"; // make sure all ELIS users have a context update_capabilities('block/curr_admin'); $ctxlvl = context_level_base::get_custom_context_level('user', 'block_curr_admin'); $rs = get_recordset('crlm_user'); while ($rec = rs_fetch_next_record($rs)) { get_context_instance($ctxlvl, $rec->id); } // sync profile fields $fields = field::get_for_context_level($ctxlvl); $fields = $fields ? $fields : array(); require_once $CFG->dirroot . '/curriculum/plugins/moodle_profile/custom_fields.php'; foreach ($fields as $field) { $fieldobj = new field($field); $sync_profile_field_with_moodle(); } } if ($result && $oldversion < 2010040501) { require_once $CFG->dirroot . '/curriculum/lib/notifications.php'; if (!empty($CFG->coursemanager)) { $context_course = CONTEXT_COURSE; $sql = "SELECT role_assignments.* FROM {$CFG->prefix}role_assignments role_assignments\n JOIN {$CFG->prefix}context context\n ON role_assignments.contextid = context.id\n WHERE role_assignments.roleid IN ({$CFG->coursemanager})\n AND context.contextlevel = {$context_course}"; if ($records = get_records_sql($sql)) { foreach ($records as $record) { cm_assign_instructor_from_mdl($record); } } } } if ($result && $oldversion < 2010063001) { $table = new XMLDBTable('crlm_curriculum_assignment'); $field = new XMLDBField('user_idnumber'); $result = $result && drop_field($table, $field); $table = new XMLDBTable('crlm_class_enrolment'); $field = new XMLDBField('user_idnumber'); $result = $result && drop_field($table, $field); $table = new XMLDBTable('crlm_class_instructor'); $field = new XMLDBField('user_idnumber'); $result = $result && drop_field($table, $field); $table = new XMLDBTable('crlm_class_attendance'); $field = new XMLDBField('user_idnumber'); $result = $result && drop_field($table, $field); } //if ($result && $oldversion < 2010063002) { // require_once($CFG->dirroot . '/blocks/curr_admin/lib.php'); // $result = $result && create_views(); // create with default prefix // $result = $result && create_views(''); // create with no prefix //} if ($result && $oldversion < 2010040505) { require_once $CFG->dirroot . '/curriculum/lib/lib.php'; $result = $result && cm_notify_duplicate_user_info(true); } if ($result && $oldversion < 2010040506 && $oldversion >= 2010040501) { global $CFG, $CURMAN; // fix instructor assignments that were migrated incorrectly in the // 2010040501 upgrade code (ELIS-1171) // remove the obvious errors (instructors assigned to a non-existent class) $context_course = CONTEXT_COURSE; $sql = "DELETE\n FROM {$CFG->prefix}crlm_class_instructor\n WHERE NOT EXISTS (SELECT 'x' FROM {$CFG->prefix}crlm_class cmclass\n WHERE cmclass.id = {$CFG->prefix}crlm_class_instructor.classid)"; $result = $result && execute_sql($sql); // warn about other potentially incorrect instructor assignments require_once $CFG->dirroot . '/curriculum/lib/lib.php'; cm_notify_incorrect_instructor_assignment(true); // make sure the correct assignments are added if (!empty($CFG->coursemanager)) { require_once $CFG->dirroot . '/curriculum/lib/notifications.php'; $context_course = CONTEXT_COURSE; $sql = "SELECT role_assignments.* FROM {$CFG->prefix}role_assignments role_assignments\n JOIN {$CFG->prefix}context context\n ON role_assignments.contextid = context.id\n WHERE role_assignments.roleid IN ({$CFG->coursemanager})\n AND context.contextlevel = {$context_course}"; if ($records = get_records_sql($sql)) { foreach ($records as $record) { cm_assign_instructor_from_mdl($record); } } } } if ($result && $oldversion < 2010063002) { //get the class table $table = new XMLDBTable('crlm_class'); //add the auto enrol enabled flag $field = new XMLDBField('enrol_from_waitlist'); $field->setAttributes(XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, null, null, null, null, '0'); $result = $result && add_field($table, $field); } if ($result && $oldversion < 2010063005) { /// Define table crlm_field_data to be dropped $table = new XMLDBTable('crlm_field_map'); /// Launch drop table for crlm_field_data $result = $result && drop_table($table); } if ($result && $oldversion < 2010063006) { /// Define table crlm_field_data to be renamed to crlm_field_data_text $table = new XMLDBTable('crlm_field_data'); /// Define index context_idx (not unique) to be dropped form crlm_field_data_text $index = new XMLDBIndex('context_idx'); $index->setAttributes(XMLDB_INDEX_NOTUNIQUE, array('contextid')); /// Launch drop index context_idx $result = $result && drop_index($table, $index); /// Changing nullability of field contextid on table crlm_field_data_text to null $field = new XMLDBField('contextid'); $field->setAttributes(XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, null, null, null, null, null, 'id'); /// Define index context_idx (not unique) to be added to crlm_field_data_text $index = new XMLDBIndex('context_idx'); $index->setAttributes(XMLDB_INDEX_NOTUNIQUE, array('contextid')); /// Launch add index context_idx $result = $result && add_index($table, $index); /// Define index field_idx (not unique) to be added to crlm_field_data_text $index = new XMLDBIndex('field_idx'); $index->setAttributes(XMLDB_INDEX_NOTUNIQUE, array('fieldid')); /// Launch add index field_idx $result = $result && add_index($table, $index); /// Launch change of nullability for field contextid $result = $result && change_field_notnull($table, $field); /// Launch rename table for crlm_field_data $result = $result && rename_table($table, 'crlm_field_data_text'); /// Define table crlm_field_owner to be created $table = new XMLDBTable('crlm_field_owner'); /// Adding fields to table crlm_field_owner $table->addFieldInfo('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null, null, null); $table->addFieldInfo('fieldid', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, null, null, null, null, null); $table->addFieldInfo('plugin', XMLDB_TYPE_CHAR, '255', null, null, null, null, null, null); $table->addFieldInfo('exclude', XMLDB_TYPE_INTEGER, '1', XMLDB_UNSIGNED, null, null, null, null, '0'); $table->addFieldInfo('params', XMLDB_TYPE_TEXT, 'big', null, null, null, null, null, null); /// Adding keys to table crlm_field_owner $table->addKeyInfo('primary', XMLDB_KEY_PRIMARY, array('id')); /// Adding indexes to table crlm_field_owner $table->addIndexInfo('field_idx', XMLDB_INDEX_NOTUNIQUE, array('fieldid')); /// Launch create table for crlm_field_owner $result = $result && create_table($table); /// Define table crlm_field_category_context to be created $table = new XMLDBTable('crlm_field_category_context'); /// Adding fields to table crlm_field_category_context $table->addFieldInfo('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null, null, null); $table->addFieldInfo('categoryid', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, null, null, null, null, null); $table->addFieldInfo('contextlevel', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, null, null, null, null, null); /// Adding keys to table crlm_field_category_context $table->addKeyInfo('primary', XMLDB_KEY_PRIMARY, array('id')); /// Adding indexes to table crlm_field_category_context $table->addIndexInfo('contextlevel_idx', XMLDB_INDEX_NOTUNIQUE, array('contextlevel')); $table->addIndexInfo('category_idx', XMLDB_INDEX_NOTUNIQUE, array('categoryid')); /// Launch create table for crlm_field_category_context $result = $result && create_table($table); $usercontextid = context_level_base::get_custom_context_level('user', 'block_curr_admin'); if ($usercontextid) { $sql = "INSERT INTO {$CFG->prefix}crlm_field_category_context\n (categoryid, contextlevel)\n SELECT id, {$usercontextid}\n FROM {$CFG->prefix}crlm_field_category"; $result = $result && execute_sql($sql); } /// Define table crlm_field_data_int to be created $table = new XMLDBTable('crlm_field_data_int'); /// Adding fields to table crlm_field_data_int $table->addFieldInfo('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null, null, null); $table->addFieldInfo('contextid', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, null, null, null, null, null); $table->addFieldInfo('fieldid', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null, null, null); $table->addFieldInfo('data', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null, null, null); /// Adding keys to table crlm_field_data_int $table->addKeyInfo('primary', XMLDB_KEY_PRIMARY, array('id')); /// Adding indexes to table crlm_field_data_int $table->addIndexInfo('context_idx', XMLDB_INDEX_NOTUNIQUE, array('contextid')); $table->addIndexInfo('field_idx', XMLDB_INDEX_NOTUNIQUE, array('fieldid')); /// Launch create table for crlm_field_data_int $result = $result && create_table($table); /// Define table crlm_field_data_num to be created $table = new XMLDBTable('crlm_field_data_num'); /// Adding fields to table crlm_field_data_num $table->addFieldInfo('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null, null, null); $table->addFieldInfo('contextid', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, null, null, null, null, null); $table->addFieldInfo('fieldid', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null, null, null); $table->addFieldInfo('data', XMLDB_TYPE_NUMBER, '15, 5', null, XMLDB_NOTNULL, null, null, null, null); /// Adding keys to table crlm_field_data_num $table->addKeyInfo('primary', XMLDB_KEY_PRIMARY, array('id')); /// Adding indexes to table crlm_field_data_num $table->addIndexInfo('context_idx', XMLDB_INDEX_NOTUNIQUE, array('contextid')); $table->addIndexInfo('field_idx', XMLDB_INDEX_NOTUNIQUE, array('fieldid')); /// Launch create table for crlm_field_data_num $result = $result && create_table($table); /// Define table crlm_field_data_char to be created $table = new XMLDBTable('crlm_field_data_char'); /// Adding fields to table crlm_field_data_char $table->addFieldInfo('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null, null, null); $table->addFieldInfo('contextid', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, null, null, null, null, null); $table->addFieldInfo('fieldid', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null, null, null); $table->addFieldInfo('data', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null, null, null); /// Adding keys to table crlm_field_data_char $table->addKeyInfo('primary', XMLDB_KEY_PRIMARY, array('id')); /// Adding indexes to table crlm_field_data_char $table->addIndexInfo('context_idx', XMLDB_INDEX_NOTUNIQUE, array('contextid')); $table->addIndexInfo('field_idx', XMLDB_INDEX_NOTUNIQUE, array('fieldid')); /// Launch create table for crlm_field_data_char $result = $result && create_table($table); $records = get_records('crlm_field'); if ($records) { // FIXME: set data type based on old data type foreach ($records as $record) { unset($record->name); unset($record->shortname); unset($record->description); $record->defaultdata = addslashes($record->defaultdata); if (isset($record->syncwithmoodle)) { // make sure the crlm_field table hasn't been upgraded yet switch ($record->syncwithmoodle) { case 2: // sync from Moodle // create "moodle_profile" owner if (!record_exists('crlm_field_owner', 'fieldid', $record->id, 'plugin', 'moodle_profile')) { $owner = new stdClass(); $owner->fieldid = $record->id; $owner->plugin = 'moodle_profile'; $owner->exclude = true; $result = $result && insert_record('crlm_field_owner', $owner); } // create "manual" owner if (!record_exists('crlm_field_owner', 'fieldid', $record->id, 'plugin', 'manual')) { $owner = new stdClass(); $owner->fieldid = $record->id; $owner->plugin = 'manual'; $owner->exclude = false; $owner->params = array('edit_capability' => 'disabled'); if (!$record->visible) { $owner->params['view_capability'] = 'moodle/user:viewhiddendetails'; } $owner->params = serialize($owner->params); $result = $result && insert_record('crlm_field_owner', $owner); } $record->datatype = 'text'; break; case 1: // sync to Moodle // create "moodle_profile" owner if (!record_exists('crlm_field_owner', 'fieldid', $record->id, 'plugin', 'moodle_profile')) { $owner = new stdClass(); $owner->fieldid = $record->id; $owner->plugin = 'moodle_profile'; $owner->exclude = false; $result = $result && insert_record('crlm_field_owner', $owner); } // NOTE: fall through // NOTE: fall through default: // no sync or invalid user // create "manual" owner $controltype = $record->datatype; $record->datatype = 'text'; if (!record_exists('crlm_field_owner', 'fieldid', $record->id, 'plugin', 'manual')) { $owner = new stdClass(); $owner->fieldid = $record->id; $owner->plugin = 'manual'; $owner->exclude = false; $owner->params = array('control' => $controltype, 'required' => $record->required); if ($record->locked) { $owner->params['edit_capability'] = 'moodle/user:update'; } if (!$record->visible) { $owner->params['view_capability'] = 'moodle/user:viewhiddendetails'; } if (!empty($record->params)) { $owner->params += unserialize($record->params); } switch ($controltype) { case 'checkbox': // legacy checkboxes are all boolean $record->datatype = 'bool'; $data_recs = get_records('crlm_field_data_text', 'fieldid', $record->id); foreach ($data_recs as $data_rec) { delete_records('crlm_field_data_text', 'id', $data_rec->id); unset($data_rec->id); insert_record('crlm_field_data_int', $data_rec); } break; case 'menu': // menu items should be short text $record->datatype = 'char'; $data_recs = get_records('crlm_field_data_text', 'fieldid', $record->id); foreach ($data_recs as $data_rec) { delete_records('crlm_field_data_text', 'id', $data_rec->id); unset($data_rec->id); insert_record('crlm_field_data_char', $data_rec); } case 'text': $owner->params['columns'] = $owner->params['size']; unset($owner->params['size']); break; } $owner->params = addslashes(serialize($owner->params)); $result = $result && insert_record('crlm_field_owner', $owner); } break; } $record->params = ''; $result = $result && update_record('crlm_field', $record); if (!empty($record->defaultdata)) { if (!record_exists_select('crlm_field_data_text', "fieldid = {$record->id} AND contextid IS NULL")) { $defaultdata = new stdClass(); $defaultdata->fieldid = $record->id; $defaultdata->data = $record->defaultdata; $result = $result && insert_record('crlm_field_data_text', $defaultdata); } } } } } $table = new XMLDBTable('crlm_field'); /// Define field required to be dropped from crlm_field $field = new XMLDBField('required'); /// Launch drop field required $result = $result && drop_field($table, $field); /// Define field locked to be dropped from crlm_field $field = new XMLDBField('locked'); /// Launch drop field locked $result = $result && drop_field($table, $field); /// Define field visible to be dropped from crlm_field $field = new XMLDBField('visible'); /// Launch drop field visible $result = $result && drop_field($table, $field); /// Define field defaultdata to be dropped from crlm_field $field = new XMLDBField('defaultdata'); /// Launch drop field defaultdata $result = $result && drop_field($table, $field); /// Define field syncwithmoodle to be dropped from crlm_field $field = new XMLDBField('syncwithmoodle'); /// Launch drop field syncwithmoodle $result = $result && drop_field($table, $field); /// Define field multivalued to be added to crlm_field $field = new XMLDBField('multivalued'); $field->setAttributes(XMLDB_TYPE_INTEGER, '1', XMLDB_UNSIGNED, null, null, null, null, '0', 'sortorder'); /// Launch add field multivalued $result = $result && add_field($table, $field); } if ($result && $oldversion < 2010063007) { // install.xml accidentally had the char table use an integer data field /// Changing type of field data on table crlm_field_data_char to char $table = new XMLDBTable('crlm_field_data_char'); $field = new XMLDBField('data'); $field->setAttributes(XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null, null, null, 'fieldid'); /// Launch change of type for field data $result = $result && change_field_type($table, $field); } if ($result && $oldversion < 2010063008) { $table = new XMLDBTable('crlm_cluster_curriculum'); $field = new XMLDBField('autoenrol'); $field->setAttributes(XMLDB_TYPE_INTEGER, '1', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null, null, '1', 'curriculumid'); $result = $result && add_field($table, $field); $table = new XMLDBTable('crlm_cluster_track'); $field = new XMLDBField('autoenrol'); $field->setAttributes(XMLDB_TYPE_INTEGER, '1', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null, null, '1', 'trackid'); $result = $result && add_field($table, $field); /// Define field parent to be added to crlm_cluster $table = new XMLDBTable('crlm_cluster'); $field = new XMLDBField('parent'); $field->setAttributes(XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null, null, '0', 'display'); /// Launch add field parent $result = $result && add_field($table, $field); /// Define field depth to be added to crlm_cluster $field = new XMLDBField('depth'); $field->setAttributes(XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null, null, '1', 'parent'); /// Launch add field depth $result = $result && add_field($table, $field); } if ($result && $oldversion < 2010063013) { /* * Curriculum */ $table = new XMLDBTable('crlm_curriculum'); //name field $index = new XMLDBIndex('name_ix'); $index->setAttributes(XMLDB_INDEX_NOTUNIQUE, array('name')); if (!index_exists($table, $index)) { $result = $result && add_index($table, $index); } /* * Course */ $table = new XMLDBTable('crlm_course'); //name field $index = new XMLDBIndex('name_ix'); $index->setAttributes(XMLDB_INDEX_NOTUNIQUE, array('name')); if (!index_exists($table, $index)) { $result = $result && add_index($table, $index); } //credits field $index = new XMLDBIndex('credits_ix'); $index->setAttributes(XMLDB_INDEX_NOTUNIQUE, array('credits')); if (!index_exists($table, $index)) { $result = $result && add_index($table, $index); } /* * Class */ $table = new XMLDBTable('crlm_class'); //idnumber field $index = new XMLDBIndex('idnumber_ix'); $index->setAttributes(XMLDB_INDEX_NOTUNIQUE, array('idnumber')); if (!index_exists($table, $index)) { $result = $result && add_index($table, $index); } //enddate field $index = new XMLDBIndex('enddate_ix'); $index->setAttributes(XMLDB_INDEX_NOTUNIQUE, array('enddate')); if (!index_exists($table, $index)) { $result = $result && add_index($table, $index); } /* * Class enrolment */ $table = new XMLDBTable('crlm_class_enrolment'); //completetime field $index = new XMLDBIndex('completetime_ix'); $index->setAttributes(XMLDB_INDEX_NOTUNIQUE, array('completetime')); if (!index_exists($table, $index)) { $result = $result && add_index($table, $index); } //completestatusid field $index = new XMLDBIndex('completestatusid_ix'); $index->setAttributes(XMLDB_INDEX_NOTUNIQUE, array('completestatusid')); if (!index_exists($table, $index)) { $result = $result && add_index($table, $index); } /* * CM user */ $table = new XMLDBTable('crlm_user'); //lastname field $index = new XMLDBIndex('lastname_ix'); $index->setAttributes(XMLDB_INDEX_NOTUNIQUE, array('lastname')); if (!index_exists($table, $index)) { $result = $result && add_index($table, $index); } //firstname field $index = new XMLDBIndex('firstname_ix'); $index->setAttributes(XMLDB_INDEX_NOTUNIQUE, array('firstname')); if (!index_exists($table, $index)) { $result = $result && add_index($table, $index); } } if ($result && $oldversion < 2010063015) { /// Define field autocreated to be added to crlm_class_moodle $table = new XMLDBTable('crlm_class_moodle'); $field = new XMLDBField('autocreated'); $field->setAttributes(XMLDB_TYPE_INTEGER, '2', null, XMLDB_NOTNULL, null, null, null, '-1', 'timemodified'); /// Launch add field autocreated $result = $result && add_field($table, $field); } if ($result && $oldversion < 2010111300) { $table = new XMLDBTable('crlm_curriculum_assignment'); $field = new XMLDBField('timeexpired'); $field->setAttributes(XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null, null, '0', 'timecompleted'); // Launch add field multivalued $result = $result && add_field($table, $field); } if ($result && $oldversion < 2011050200) { /// Define index startdate_ix (not unique) to be added to crlm_class $table = new XMLDBTable('crlm_class'); $index = new XMLDBIndex('startdate_ix'); $index->setAttributes(XMLDB_INDEX_NOTUNIQUE, array('startdate')); $result = $result && add_index($table, $index); /// Define index enrolmenttime_ix (not unique) to be added to crlm_class_enrolment $table = new XMLDBTable('crlm_class_enrolment'); $index = new XMLDBIndex('enrolmenttime_ix'); $index->setAttributes(XMLDB_INDEX_NOTUNIQUE, array('enrolmenttime')); $result = $result && add_index($table, $index); /// Define index locked_ix (not unique) to be added to crlm_class_graded $table = new XMLDBTable('crlm_class_graded'); $index = new XMLDBIndex('locked_ix'); $index->setAttributes(XMLDB_INDEX_NOTUNIQUE, array('locked')); $result = $result && add_index($table, $index); /// Define index timegraded_ix (not unique) to be added to crlm_class_graded $table = new XMLDBTable('crlm_class_graded'); $index = new XMLDBIndex('timegraded_ix'); $index->setAttributes(XMLDB_INDEX_NOTUNIQUE, array('timegraded')); $result = $result && add_index($table, $index); /// Define index classid_ix (not unique) to be added to crlm_class_moodle $table = new XMLDBTable('crlm_class_moodle'); $index = new XMLDBIndex('classid_ix'); $index->setAttributes(XMLDB_INDEX_NOTUNIQUE, array('classid')); $result = $result && add_index($table, $index); /// Define index curriculumid_ix (not unique) to be added to crlm_cluster_curriculum $table = new XMLDBTable('crlm_cluster_curriculum'); $index = new XMLDBIndex('curriculumid_ix'); $index->setAttributes(XMLDB_INDEX_NOTUNIQUE, array('curriculumid')); $result = $result && add_index($table, $index); /// Define index fieldid_ix (not unique) to be added to crlm_cluster_profile $table = new XMLDBTable('crlm_cluster_profile'); $index = new XMLDBIndex('fieldid_ix'); $index->setAttributes(XMLDB_INDEX_NOTUNIQUE, array('fieldid')); $result = $result && add_index($table, $index); /// Define index trackid_ix (not unique) to be added to crlm_cluster_track $table = new XMLDBTable('crlm_cluster_track'); $index = new XMLDBIndex('trackid_ix'); $index->setAttributes(XMLDB_INDEX_NOTUNIQUE, array('trackid')); $result = $result && add_index($table, $index); /// Define index idnumber_ix (not unique) to be added to crlm_course_completion $table = new XMLDBTable('crlm_course_completion'); $index = new XMLDBIndex('idnumber_ix'); $index->setAttributes(XMLDB_INDEX_NOTUNIQUE, array('idnumber')); $result = $result && add_index($table, $index); /// Define index sortorder_ix (not unique) to be added to crlm_field $table = new XMLDBTable('crlm_field'); $index = new XMLDBIndex('sortorder_ix'); $index->setAttributes(XMLDB_INDEX_NOTUNIQUE, array('sortorder')); $result = $result && add_index($table, $index); /// Define index username_ix (not unique) to be added to crlm_user $table = new XMLDBTable('crlm_user'); $index = new XMLDBIndex('username_ix'); $index->setAttributes(XMLDB_INDEX_NOTUNIQUE, array('username')); $result = $result && add_index($table, $index); /// Define index inactive_ix (not unique) to be added to crlm_user $table = new XMLDBTable('crlm_user'); $index = new XMLDBIndex('inactive_ix'); $index->setAttributes(XMLDB_INDEX_NOTUNIQUE, array('inactive')); $result = $result && add_index($table, $index); /// Define index userid_ix (not unique) to be added to crlm_user_track $table = new XMLDBTable('crlm_user_track'); $index = new XMLDBIndex('userid_ix'); $index->setAttributes(XMLDB_INDEX_NOTUNIQUE, array('userid')); $result = $result && add_index($table, $index); /// Define index trackid_ix (not unique) to be added to crlm_user_track $table = new XMLDBTable('crlm_user_track'); $index = new XMLDBIndex('trackid_ix'); $index->setAttributes(XMLDB_INDEX_NOTUNIQUE, array('trackid')); $result = $result && add_index($table, $index); /// Define index classid_ix (not unique) to be added to crlm_wait_list $table = new XMLDBTable('crlm_wait_list'); $index = new XMLDBIndex('classid_ix'); $index->setAttributes(XMLDB_INDEX_NOTUNIQUE, array('classid')); $result = $result && add_index($table, $index); /// Define index userid_ix (not unique) to be added to crlm_wait_list $table = new XMLDBTable('crlm_wait_list'); $index = new XMLDBIndex('userid_ix'); $index->setAttributes(XMLDB_INDEX_NOTUNIQUE, array('userid')); $result = $result && add_index($table, $index); } if ($result && $oldversion < 2011050201) { // make sure that hours are within 24 hours $sql = "UPDATE {$CFG->prefix}crlm_class\n SET starttimehour = MOD(starttimehour, 24),\n endtimehour = MOD(endtimehour, 24)"; $result = $result && execute_sql($sql); } if ($result && $oldversion < 2011050202) { /// Changing type of field credits on table crlm_class_enrolment to number $table = new XMLDBTable('crlm_class_enrolment'); $field = new XMLDBField('credits'); $field->setAttributes(XMLDB_TYPE_NUMBER, '10, 2', XMLDB_UNSIGNED, null, null, null, null, '0', 'grade'); /// Launch change of type for field credits $result = $result && change_field_type($table, $field); /// Changing type of field credits on table crlm_curriculum_assignment to number $table = new XMLDBTable('crlm_curriculum_assignment'); $field = new XMLDBField('credits'); $field->setAttributes(XMLDB_TYPE_NUMBER, '10, 2', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null, null, '0', 'timeexpired'); /// Launch change of type for field credits $result = $result && change_field_type($table, $field); /// Changing type of field reqcredits on table crlm_curriculum to number $table = new XMLDBTable('crlm_curriculum'); $field = new XMLDBField('reqcredits'); $field->setAttributes(XMLDB_TYPE_NUMBER, '10, 2', XMLDB_UNSIGNED, null, null, null, null, null, 'description'); /// Launch change of type for field reqcredits $result = $result && change_field_type($table, $field); // update student class credits with decimal credits if ($CFG->dbfamily == 'postgres') { $sql = "UPDATE {$CFG->prefix}crlm_class_enrolment\n SET credits = CAST(c.credits AS numeric)\n FROM {$CFG->prefix}crlm_class_enrolment e, {$CFG->prefix}crlm_class cls, {$CFG->prefix}crlm_course c\n WHERE e.classid = cls.id\n AND cls.courseid = c.id\n AND e.credits = CAST(c.credits AS integer)"; } else { $sql = "UPDATE {$CFG->prefix}crlm_class_enrolment e, {$CFG->prefix}crlm_class cls, {$CFG->prefix}crlm_course c\n SET e.credits = c.credits\n WHERE e.classid = cls.id\n AND cls.courseid = c.id\n AND e.credits = CAST(c.credits AS unsigned)"; } $result = $result && execute_sql($sql); } if ($result && $oldversion < 2011050203) { //create a new column in the notification log table //to store the user who triggered the notification $table = new XMLDBTable('crlm_notification_log'); $field = new XMLDBField('fromuserid'); $field->setAttributes(XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null, null, 0, 'userid'); $field->comment = 'CM user id that triggered the notification.'; $result = $result && add_field($table, $field); //populate data, assuming that the user who received the notification is the one whose //criteria spawned it //NOTE: this fudges data and the side-effect implies that if someone had received a notification //for another user and satisfy the same criteria for the same instance for themself, they will not //receive a similar notification $sql = "UPDATE {$CFG->prefix}crlm_notification_log\n SET fromuserid = userid"; $result = $result && execute_sql($sql); if ($result) { /// Define field certificatecode to be added to crlm_curriculum_assignment $table = new XMLDBTable('crlm_curriculum_assignment'); $field = new XMLDBField('certificatecode'); $field->setAttributes(XMLDB_TYPE_CHAR, '40', null, null, null, null, null, null, 'locked'); /// Launch add field autocreated $result = $result && add_field($table, $field); /// Define index userid_ix (not unique) to be added to crlm_wait_list $index = new XMLDBIndex('certificatecode_ix'); $index->setAttributes(XMLDB_INDEX_NOTUNIQUE, array('certificatecode')); $result = $result && add_index($table, $index); } } if ($result && $oldversion < 2011050204) { $table = new XMLDBTable('crlm_notification_log'); $index = new XMLDBIndex('event_inst_fuser_ix'); $index->setAttributes(XMLDB_INDEX_NOTUNIQUE, array('fromuserid', 'instance', 'event')); $result = add_index($table, $index); } if ($result && $oldversion < 2011050205) { // Update the ELIS class enrolment grade value and completion score grade values so they store float // (decimal) values $table = new XMLDBTable('crlm_class_enrolment'); $field = new XMLDBField('grade'); $field->setAttributes(XMLDB_TYPE_NUMBER, '10', null, XMLDB_NOTNULL, null, null, null, '0'); $field->setDecimals(5); $result = change_field_type($table, $field); $table = new XMLDBTable('crlm_class_graded'); $result = $result && change_field_type($table, $field); /* * Find all of the completion grades that are synchronised from Moodle grade items that are not locked and * where the ELIS completion score does not match the value in the Moodle gradebook and delete those * completion scores so they can be re-synchronised from Moodle with the correct float values stored. */ // Attempt to handle different DBs in the most efficient way possible if ($CFG->dbfamily == 'postgres') { $sql = "DELETE FROM {$CFG->prefix}crlm_class_graded\n WHERE id IN (\n SELECT ccg.id\n FROM mdl_crlm_user cu\n INNER JOIN {$CFG->prefix}crlm_class_enrolment cce ON cce.userid = cu.id\n INNER JOIN {$CFG->prefix}crlm_class_graded ccg ON (ccg.userid = cce.userid AND ccg.classid = cce.classid)\n INNER JOIN {$CFG->prefix}crlm_course_completion ccc ON ccc.id = ccg.completionid\n INNER JOIN {$CFG->prefix}crlm_class_moodle ccm ON ccm.classid = ccg.classid\n INNER JOIN {$CFG->prefix}user u ON u.idnumber = cu.idnumber\n INNER JOIN {$CFG->prefix}course c ON c.id = ccm.moodlecourseid\n INNER JOIN {$CFG->prefix}grade_items gi ON (gi.courseid = c.id AND gi.idnumber = ccc.idnumber)\n INNER JOIN {$CFG->prefix}grade_grades gg ON (gg.itemid = gi.id AND gg.userid = u.id)\n WHERE ccg.locked = 0\n AND ccc.idnumber != ''\n AND gi.itemtype != 'course'\n AND ccg.grade != gg.finalgrade\n AND gg.finalgrade IS NOT NULL\n )"; $result = $result && execute_sql($sql); } else { if ($CFG->dbfamily == 'mysql') { $sql = "DELETE ccg\n FROM mdl_crlm_user cu\n INNER JOIN {$CFG->prefix}crlm_class_enrolment cce ON cce.userid = cu.id\n INNER JOIN {$CFG->prefix}crlm_class_graded ccg ON (ccg.userid = cce.userid AND ccg.classid = cce.classid)\n INNER JOIN {$CFG->prefix}crlm_course_completion ccc ON ccc.id = ccg.completionid\n INNER JOIN {$CFG->prefix}crlm_class_moodle ccm ON ccm.classid = ccg.classid\n INNER JOIN {$CFG->prefix}user u ON u.idnumber = cu.idnumber\n INNER JOIN {$CFG->prefix}course c ON c.id = ccm.moodlecourseid\n INNER JOIN {$CFG->prefix}grade_items gi ON (gi.courseid = c.id AND gi.idnumber = ccc.idnumber)\n INNER JOIN {$CFG->prefix}grade_grades gg ON (gg.itemid = gi.id AND gg.userid = u.id)\n WHERE ccg.locked = 0\n AND ccc.idnumber != ''\n AND gi.itemtype != 'course'\n AND ccg.grade != gg.finalgrade\n AND gg.finalgrade IS NOT NULL"; $result = $result && execute_sql($sql); } else { $sql = "SELECT ccg.id, ccg.grade\n FROM mdl_crlm_user cu\n INNER JOIN {$CFG->prefix}crlm_class_enrolment cce ON cce.userid = cu.id\n INNER JOIN {$CFG->prefix}crlm_class_graded ccg ON (ccg.userid = cce.userid AND ccg.classid = cce.classid)\n INNER JOIN {$CFG->prefix}crlm_course_completion ccc ON ccc.id = ccg.completionid\n INNER JOIN {$CFG->prefix}crlm_class_moodle ccm ON ccm.classid = ccg.classid\n INNER JOIN {$CFG->prefix}user u ON u.idnumber = cu.idnumber\n INNER JOIN {$CFG->prefix}course c ON c.id = ccm.moodlecourseid\n INNER JOIN {$CFG->prefix}grade_items gi ON (gi.courseid = c.id AND gi.idnumber = ccc.idnumber)\n INNER JOIN {$CFG->prefix}grade_grades gg ON (gg.itemid = gi.id AND gg.userid = u.id)\n WHERE ccg.locked = 0\n AND ccc.idnumber != ''\n AND gi.itemtype != 'course'\n AND ccg.grade != gg.finalgrade\n AND gg.finalgrade IS NOT NULL"; if ($rs = get_recordset_sql($sql)) { while ($cg = rs_fetch_next_record($rs)) { $result = $result && delete_records('crlm_class_graded', 'id', $cg->id); } rs_close($rs); } } } // Force a re-synchronization of ELIS class grade data require_once $CFG->dirroot . '/curriculum/lib/lib.php'; cm_synchronize_moodle_class_grades(); } if ($result && $oldversion < 2011050206) { /// Define table crlm_field_data to be dropped $table = new XMLDBTable('crlm_field_map'); if (table_exists($table)) { /// Launch drop table for crlm_field_data $result = drop_table($table); } } if ($result && $oldversion < 2011050207) { // Delete duplicate class completion element grades $xmldbtable = new XMLDBTable('crlm_class_graded_temp'); if (table_exists($xmldbtable)) { drop_table($xmldbtable); } // Create a temporary table $result = $result && execute_sql("CREATE TABLE {$CFG->prefix}crlm_class_graded_temp LIKE {$CFG->prefix}crlm_class_graded"); // Store the unique values in the temporary table $sql = "INSERT INTO {$CFG->prefix}crlm_class_graded_temp\n SELECT MAX(id) AS id, classid, userid, completionid, grade, locked, timegraded, timemodified\n FROM {$CFG->prefix}crlm_class_graded\n GROUP BY classid, userid, completionid, locked"; $result = $result && execute_sql($sql); // Detect if there are still duplicates in the temporary table $sql = "SELECT COUNT(*) AS count, classid, userid, completionid, grade, locked, timegraded, timemodified\n FROM {$CFG->prefix}crlm_class_graded_temp\n GROUP BY classid, userid, completionid\n ORDER BY count DESC, classid ASC, userid ASC, completionid ASC"; if ($result && ($dupcount = get_record_sql($sql, true))) { if ($dupcount->count > 1) { if ($rs = get_recordset_sql($sql)) { while ($result && ($dupe = rs_fetch_next_record($rs))) { if ($dupe->count <= 1) { continue; } $classid = $dupe->classid; $userid = $dupe->userid; $goodid = 0; // The ID of the record we will keep // Look for the earliest locked grade record for this user and keep that (if any are locked) $sql2 = "SELECT id, grade, locked, timegraded\n FROM mdl_crlm_class_graded\n WHERE classid = {$classid}\n AND userid = {$userid}\n ORDER BY timegraded ASC"; if ($rs2 = get_recordset_sql($sql2)) { while ($rec = rs_fetch_next_record($rs2)) { // Store the last record ID just in case we need it for cleanup $lastid = $rec->id; // Don't bother looking at remaining records if we have found a record to keep if (!empty($goodid)) { continue; } if ($rec->locked = 1) { $goodid = $rec->id; } } rs_close($rs2); // We need to make sure we have a record ID to keep, if we found no "complete" and locked // records, let's just keep the last record we saw if (empty($goodid)) { $goodid = $lastid; } $select = 'classid = ' . $classid . ' AND userid = ' . $userid . ' AND id != ' . $goodid; } if (!empty($select)) { $result = $result && delete_records_select('crlm_class_graded_temp', $select); } } } } } // Drop the real table $result = $result && execute_sql("DROP TABLE {$CFG->prefix}crlm_class_graded"); // Replace the real table with the temporary table that now only contains unique values. $result = $result && execute_sql("ALTER TABLE {$CFG->prefix}crlm_class_graded_temp RENAME TO {$CFG->prefix}crlm_class_graded"); } return $result; }