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;
}
Example #2
0
/**
 * 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');
}
Example #3
0
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();
}
Example #4
0
     $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');
Example #5
0
/**
 * 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);
    }
}
Example #6
0
/**
 * 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, '&nbsp;', '&nbsp;');
                    }
                    $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, '&nbsp;', '&nbsp;');
            }
            $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;
    }
}
Example #8
0
 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)));
 }
Example #9
0
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);
 }
Example #11
0
/**
 * 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);
            }
        }
    }
}
Example #12
0
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'));
}
Example #13
0
/**
 * 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);
    }
}
Example #14
0
/**
 * 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);
    }
}
Example #15
0
/**
 * 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, '&nbsp;', '&nbsp;');
                }
                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, '&nbsp;', '&nbsp;');
                    }
                    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, '&nbsp;', '&nbsp;');
            }
            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);
                    }
                }
            }
        }
    }
}
Example #17
0
/**
 * 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();
}
Example #18
0
            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!");
    }
Example #19
0
    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);
    }
Example #20
0
/**
 * 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;
}
Example #21
0
/**
 * 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);
        }
    }
}
Example #23
0
 /**
  * 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));
 }
Example #24
0
/**
 * 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);
    }
}
Example #25
0
/**
 * 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');
}
Example #26
0
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;
}