public function __construct($actionurl, $companyid, $departmentid) { global $CFG, $USER; $this->selectedcompany = $companyid; $this->departmentid = $departmentid; $company = new company($this->selectedcompany); $parentlevel = company::get_company_parentnode($company->id); $this->companydepartment = $parentlevel->id; if (iomad::has_capability('block/iomad_company_admin:edit_all_departments', context_system::instance())) { $userhierarchylevel = $parentlevel->id; } else { $userlevel = company::get_userlevel($USER); $userhierarchylevel = $userlevel->id; } $this->subhierarchieslist = company::get_all_subdepartments($userhierarchylevel); if ($this->departmentid == 0) { $departmentid = $userhierarchylevel; } else { $departmentid = $this->departmentid; } $this->userdepartment = $userhierarchylevel; $options = array('context' => $this->context, 'multiselect' => true, 'companyid' => $this->selectedcompany, 'departmentid' => $departmentid, 'subdepartments' => $this->subhierarchieslist, 'parentdepartmentid' => $parentlevel, 'showopenshared' => true, 'license' => false); $this->currentcourses = new potential_subdepartment_course_selector('currentcourses', $options); $this->currentcourses->set_rows(20); $this->context = context_coursecat::instance($CFG->defaultrequestcategory); parent::moodleform($actionurl); }
public function __construct($actionurl, $invoiceid) { global $CFG; $this->invoiceid = $invoiceid; $this->context = context_coursecat::instance($CFG->defaultrequestcategory); parent::__construct($actionurl); }
public function __construct($actionurl, $companyid, $editoroptions) { global $CFG; $this->selectedcompany = $companyid; $this->context = context_coursecat::instance($CFG->defaultrequestcategory); $this->editoroptions = $editoroptions; parent::__construct($actionurl); }
/** * Validate that class instance-moodle course associations * can be created during a class instance create action * * @param string $link The link attribute to use in the import, or 'auto' to auto-create * from template * @dataProvider link_course_provider */ public function test_associate_moodle_course_during_class_create($link) { global $CFG, $DB, $USER; require_once $CFG->dirroot . '/course/lib.php'; require_once $CFG->dirroot . '/local/elisprogram/lib/setup.php'; require_once elispm::lib('data/classmoodlecourse.class.php'); require_once elispm::lib('data/coursetemplate.class.php'); require_once elispm::lib('data/course.class.php'); // Make sure $USER is set up for backup/restore. $USER = $DB->get_record_select('user', "username != 'guest' and DELETED = 0", array(), '*', IGNORE_MULTIPLE); $GLOBAL['USER'] = $USER; // Need the moodle/backup:backupcourse capability. $guestroleid = create_role('guestrole', 'guestrole', 'guestrole'); set_config('guestroleid', $guestroleid); set_config('siteguest', ''); $systemcontext = context_system::instance(); $roleid = create_role('testrole', 'testrole', 'testrole'); assign_capability('moodle/backup:backupcourse', CAP_ALLOW, $roleid, $systemcontext->id); role_assign($roleid, $USER->id, $systemcontext->id); set_config('siteadmins', $USER->id); $coursecategory = new stdClass(); $coursecategory->name = 'testcoursecategoryname'; $coursecategory->id = $DB->insert_record('course_categories', $coursecategory); context_coursecat::instance($coursecategory->id); $moodlecourse = new stdClass(); $moodlecourse->category = $coursecategory->id; $moodlecourse->shortname = 'testcourseshortname'; $moodlecourse->fullname = 'testcoursefullname'; $moodlecourse = create_course($moodlecourse); $course = new course(array('name' => 'testcoursename', 'idnumber' => 'testcourseidnumber', 'syllabus' => '')); $course->save(); // Need this for the 'auto' case, at the very least. $coursetemplate = new coursetemplate(array('courseid' => $course->id, 'location' => $moodlecourse->id, 'templateclass' => 'moodlecourseurl')); $coursetemplate->save(); // Run the class instance create action. $record = new stdClass(); $record->idnumber = 'testclassidnumber'; $record->assignment = 'testcourseidnumber'; $record->link = $link; $importplugin = rlip_dataplugin_factory::factory('dhimport_version1elis'); $importplugin->fslogger = new silent_fslogger(null); $importplugin->class_create($record, 'bogus'); $classid = $DB->get_field(pmclass::TABLE, 'id', array('idnumber' => 'testclassidnumber')); // Validation. if ($record->link == 'auto') { $moodlecourseid = $moodlecourse->id + 1; } else { $moodlecourseid = $moodlecourse->id; } $dbautocreated = $record->link == 'auto' ? 1 : 0; $this->assertTrue($DB->record_exists(classmoodlecourse::TABLE, array('classid' => $classid, 'moodlecourseid' => $moodlecourseid, 'enroltype' => 0, 'enrolplugin' => 'crlm', 'autocreated' => $dbautocreated))); ini_set('max_execution_time', '0'); }
/** * Initialize a test category and course, including their context records. * * @return object the course's context object * @uses $DB */ private function init_category_and_course() { global $DB; // Category. $category = new stdClass(); $category->name = 'category'; $category->id = $DB->insert_record('course_categories', $category); context_coursecat::instance($category->id); // Course. $coursedata = new stdClass(); $coursedata->category = $category->id; $coursedata->fullname = 'fullname'; $course = create_course($coursedata); return context_course::instance($course->id); }
public function __construct($actionurl, $isadding, $shopsettingsid, $course, $priceblocks, $editoroptions) { global $CFG; $this->isadding = $isadding; $this->shopsettingsid = $shopsettingsid; $this->course = $course; $this->priceblocks = $priceblocks; $this->context = context_coursecat::instance($CFG->defaultrequestcategory); $this->editoroptions = $editoroptions; if ($isadding) { $options = array('context' => $this->context, 'multiselect' => false, 'selectedid' => $shopsettingsid, 'searchanywhere' => true, 'file' => '/blocks/iomad_commerce/lib/course_selectors.php'); $this->currentcourses = new nonshopcourse_selector('currentcourses', $options); $this->currentcourses->set_rows(1); } parent::__construct($actionurl); }
/** * Validate that appropriate fields are synched over to Moodle when PM user is enrolled in a class instance during an import. */ public function test_user_sync_on_pm_user_create() { global $CFG, $DB; require_once $CFG->dirroot . '/course/lib.php'; require_once $CFG->dirroot . '/local/elisprogram/lib/setup.php'; require_once elispm::lib('data/classmoodlecourse.class.php'); require_once elispm::lib('data/course.class.php'); require_once elispm::lib('data/pmclass.class.php'); require_once elispm::lib('data/user.class.php'); // Configure the elis enrolment plugin. $roleid = $DB->get_field('role', 'id', array(), IGNORE_MULTIPLE); set_config('roleid', $roleid, 'enrol_elis'); $user = new user(array('idnumber' => 'testuseridnumber', 'username' => 'testuserusername', 'firstname' => 'testuserfirstname', 'lastname' => 'testuserlastname', 'email' => '*****@*****.**', 'country' => 'CA')); $user->save(); $course = new course(array('name' => 'testcoursename', 'idnumber' => 'testcourseidnumber', 'syllabus' => '')); $course->save(); $class = new pmclass(array('courseid' => $course->id, 'idnumber' => 'testclassidnumber')); $class->save(); $category = new stdClass(); $category->name = 'testcategoryname'; $category->id = $DB->insert_record('course_categories', $category); // Create the associated context. context_coursecat::instance($category->id); $mdlcourse = new stdClass(); $mdlcourse->category = $category->id; $mdlcourse->fullname = 'testcoursefullname'; $mdlcourse = create_course($mdlcourse); // Associate class instance to Moodle course. $classmoodlecourse = new classmoodlecourse(array('classid' => $class->id, 'moodlecourseid' => $mdlcourse->id)); $classmoodlecourse->save(); // Run the enrolment create action. $record = new stdClass(); $record->context = 'class_testclassidnumber'; $record->user_username = '******'; $importplugin = rlip_dataplugin_factory::factory('dhimport_version1elis'); $importplugin->fslogger = new silent_fslogger(null); $importplugin->class_enrolment_create($record, 'bogus', 'testclassidnumber'); // Validate the enrolment. $enrolid = $DB->get_field('enrol', 'id', array('enrol' => 'elis', 'courseid' => $mdlcourse->id)); $this->assertNotEquals(false, $enrolid); $mdluserid = $DB->get_field('user', 'id', array('username' => 'testuserusername')); $this->assertNotEquals(false, $mdluserid); $this->assertTrue($DB->record_exists('user_enrolments', array('enrolid' => $enrolid, 'userid' => $mdluserid))); // Validate the role assignment. $mdlcoursecontext = context_course::instance($mdlcourse->id); $this->assertTrue($DB->record_exists('role_assignments', array('roleid' => $roleid, 'contextid' => $mdlcoursecontext->id, 'userid' => $mdluserid))); }
/** * Create one or more cohorts * * @param array $cohorts An array of cohorts to create. * @return array An array of arrays * @since Moodle 2.5 */ public static function create_cohorts($cohorts) { global $CFG, $DB; require_once "{$CFG->dirroot}/cohort/lib.php"; $params = self::validate_parameters(self::create_cohorts_parameters(), array('cohorts' => $cohorts)); $transaction = $DB->start_delegated_transaction(); $syscontext = context_system::instance(); $cohortids = array(); foreach ($params['cohorts'] as $cohort) { $cohort = (object) $cohort; // Category type (context id). $categorytype = $cohort->categorytype; if (!in_array($categorytype['type'], array('idnumber', 'id', 'system'))) { throw new invalid_parameter_exception('category type must be id, idnumber or system:' . $categorytype['type']); } if ($categorytype['type'] === 'system') { $cohort->contextid = $syscontext->id; } else { if ($catid = $DB->get_field('course_categories', 'id', array($categorytype['type'] => $categorytype['value']))) { $catcontext = context_coursecat::instance($catid); $cohort->contextid = $catcontext->id; } else { throw new invalid_parameter_exception('category not exists: category ' . $categorytype['type'] . ' = ' . $categorytype['value']); } } // Make sure that the idnumber doesn't already exist. if ($DB->record_exists('cohort', array('idnumber' => $cohort->idnumber))) { throw new invalid_parameter_exception('record already exists: idnumber=' . $cohort->idnumber); } $context = context::instance_by_id($cohort->contextid, MUST_EXIST); if ($context->contextlevel != CONTEXT_COURSECAT and $context->contextlevel != CONTEXT_SYSTEM) { throw new invalid_parameter_exception('Invalid context'); } self::validate_context($context); require_capability('moodle/cohort:manage', $context); // Validate format. $cohort->descriptionformat = external_validate_format($cohort->descriptionformat); $cohort->id = cohort_add_cohort($cohort); list($cohort->description, $cohort->descriptionformat) = external_format_text($cohort->description, $cohort->descriptionformat, $context->id, 'cohort', 'description', $cohort->id); $cohortids[] = (array) $cohort; } $transaction->allow_commit(); return $cohortids; }
/** * Returns the jmail context * * @param int $context The context * @param int $id The context id * @param int $flags The flags to be used * @return stdClass An object instance */ function block_jmail_get_context($context, $id = null, $flags = null) { if ($context == CONTEXT_SYSTEM) { if (class_exists('context_system')) { return context_system::instance(); } else { return get_context_instance(CONTEXT_SYSTEM); } } else { if ($context == CONTEXT_COURSE) { if (class_exists('context_course')) { return context_course::instance($id, $flags); } else { return get_context_instance($context, $id, $flags); } } else { if ($context == CONTEXT_COURSECAT) { if (class_exists('context_coursecat')) { return context_coursecat::instance($id, $flags); } else { return get_context_instance($context, $id, $flags); } } else { if ($context == CONTEXT_BLOCK) { if (class_exists('context_block')) { return context_block::instance($id, $flags); } else { return get_context_instance($context, $id, $flags); } } else { if ($context == CONTEXT_USER) { if (class_exists('context_user')) { return context_user::instance($id, $flags); } else { return get_context_instance($context, $id, $flags); } } } } } } }
/** * Create EQUELLA single sign on token for current user * * @return string */ function equella_getssotoken($course = null) { global $USER, $CFG, $COURSE; if (empty($course)) { $course = $COURSE; } $context_sys = context_system::instance(); $context_cc = null; if (!empty($course->category) && is_int($course->category)) { $context_cc = context_coursecat::instance($course->category); } $context_c = context_course::instance($course->id); // roles are ordered by shortname $editingroles = get_all_editing_roles(); foreach ($editingroles as $role) { $hassystemrole = false; if (!empty($context_sys)) { $hassystemrole = user_has_role_assignment($USER->id, $role->id, $context_sys->id); } $hascategoryrole = false; if (!empty($context_cc)) { $hascategoryrole = user_has_role_assignment($USER->id, $role->id, $context_cc->id); } $hascourserole = false; if (!empty($context_c)) { $hascourserole = user_has_role_assignment($USER->id, $role->id, $context_c->id); } if ($hassystemrole || $hascategoryrole || $hascourserole) { // see if the user has a role that is linked to an equella role $shareid = $CFG->{"equella_{$role->shortname}_shareid"}; if (!empty($shareid)) { return equella_getssotoken_raw($USER->username, $shareid, $CFG->{"equella_{$role->shortname}_sharedsecret"}); } } } // no roles found, use the default shareid and secret $shareid = $CFG->equella_shareid; if (!empty($shareid)) { return equella_getssotoken_raw($USER->username, $shareid, $CFG->equella_sharedsecret); } }
protected function get_category_options($currentcontextid) { $displaylist = array(); $parentlist = array(); make_categories_list($displaylist, $parentlist, 'moodle/cohort:manage'); $options = array(); $syscontext = context_system::instance(); if (has_capability('moodle/cohort:manage', $syscontext)) { $options[$syscontext->id] = $syscontext->get_context_name(); } foreach ($displaylist as $cid => $name) { $context = context_coursecat::instance($cid); $options[$context->id] = $name; } // Always add current - this is not likely, but if the logic gets changed it might be a problem. if (!isset($options[$currentcontextid])) { $context = context::instance_by_id($currentcontextid, MUST_EXIST); $options[$context->id] = $syscontext->get_context_name(); } return $options; }
/** * Test that a new group with the name of the cohort is created. */ public function test_enrol_cohort_create_new_group() { global $DB; $this->resetAfterTest(); // Create a category. $category = $this->getDataGenerator()->create_category(); // Create two courses. $course = $this->getDataGenerator()->create_course(array('category' => $category->id)); $course2 = $this->getDataGenerator()->create_course(array('category' => $category->id)); // Create a cohort. $cohort = $this->getDataGenerator()->create_cohort(array('context' => context_coursecat::instance($category->id)->id)); // Run the function. $groupid = enrol_cohort_create_new_group($course->id, $cohort->id); // Check the results. $group = $DB->get_record('groups', array('id' => $groupid)); // The group name should match the cohort name. $this->assertEquals($cohort->name . ' cohort', $group->name); // Group course id should match the course id. $this->assertEquals($course->id, $group->courseid); // Create a group that will have the same name as the cohort. $groupdata = new stdClass(); $groupdata->courseid = $course2->id; $groupdata->name = $cohort->name . ' cohort'; groups_create_group($groupdata); // Create a group for the cohort in course 2. $groupid = enrol_cohort_create_new_group($course2->id, $cohort->id); $groupinfo = $DB->get_record('groups', array('id' => $groupid)); // Check that the group name has been changed. $this->assertEquals($cohort->name . ' cohort (2)', $groupinfo->name); // Create another group that will have the same name as a generated cohort. $groupdata = new stdClass(); $groupdata->courseid = $course2->id; $groupdata->name = $cohort->name . ' cohort (2)'; groups_create_group($groupdata); // Create a group for the cohort in course 2. $groupid = enrol_cohort_create_new_group($course2->id, $cohort->id); $groupinfo = $DB->get_record('groups', array('id' => $groupid)); // Check that the group name has been changed. $this->assertEquals($cohort->name . ' cohort (3)', $groupinfo->name); }
/** * 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'); }
/** * Adds a structured category to the navigation in the correct order/place * * @param stdClass $category * @param navigation_node $parent */ protected function add_category(stdClass $category, navigation_node $parent) { if (array_key_exists($category->id, $this->addedcategories)) { return; } $url = new moodle_url('/course/category.php', array('id' => $category->id)); $context = context_coursecat::instance($category->id); $categoryname = format_string($category->name, true, array('context' => $context)); $categorynode = $parent->add($categoryname, $url, self::TYPE_CATEGORY, $categoryname, $category->id); if (empty($category->visible)) { if (has_capability('moodle/category:viewhiddencategories', get_system_context())) { $categorynode->hidden = true; } else { $categorynode->display = false; } } $this->addedcategories[$category->id] = $categorynode; }
/** * Delete categories * * @param array $categories A list of category ids * @return array * @since Moodle 2.3 */ public static function delete_categories($categories) { global $CFG, $DB; require_once($CFG->dirroot . "/course/lib.php"); require_once($CFG->libdir . "/coursecatlib.php"); // Validate parameters. $params = self::validate_parameters(self::delete_categories_parameters(), array('categories' => $categories)); $transaction = $DB->start_delegated_transaction(); foreach ($params['categories'] as $category) { $deletecat = coursecat::get($category['id'], MUST_EXIST); $context = context_coursecat::instance($deletecat->id); require_capability('moodle/category:manage', $context); self::validate_context($context); self::validate_context(get_category_or_system_context($deletecat->parent)); if ($category['recursive']) { // If recursive was specified, then we recursively delete the category's contents. if ($deletecat->can_delete_full()) { $deletecat->delete_full(false); } else { throw new moodle_exception('youcannotdeletecategory', '', '', $deletecat->get_formatted_name()); } } else { // In this situation, we don't delete the category's contents, we either move it to newparent or parent. // If the parent is the root, moving is not supported (because a course must always be inside a category). // We must move to an existing category. if (!empty($category['newparent'])) { $newparentcat = coursecat::get($category['newparent']); } else { $newparentcat = coursecat::get($deletecat->parent); } // This operation is not allowed. We must move contents to an existing category. if (!$newparentcat->id) { throw new moodle_exception('movecatcontentstoroot'); } self::validate_context(context_coursecat::instance($newparentcat->id)); if ($deletecat->can_move_content_to($newparentcat->id)) { $deletecat->delete_move($newparentcat->id, false); } else { throw new moodle_exception('youcannotdeletecategory', '', '', $deletecat->get_formatted_name()); } } } $transaction->allow_commit(); }
/** * Delete categories * * @param array $categories A list of category ids * @return array * @since Moodle 2.3 */ public static function delete_categories($categories) { global $CFG, $DB; require_once $CFG->dirroot . "/course/lib.php"; // Validate parameters. $params = self::validate_parameters(self::delete_categories_parameters(), array('categories' => $categories)); $transaction = $DB->start_delegated_transaction(); foreach ($params['categories'] as $category) { if (!($deletecat = $DB->get_record('course_categories', array('id' => $category['id'])))) { throw new moodle_exception('unknowcategory'); } $context = context_coursecat::instance($deletecat->id); require_capability('moodle/category:manage', $context); self::validate_context($context); self::validate_context(get_category_or_system_context($deletecat->parent)); if ($category['recursive']) { // If recursive was specified, then we recursively delete the category's contents. category_delete_full($deletecat, false); } else { // In this situation, we don't delete the category's contents, we either move it to newparent or parent. // If the parent is the root, moving is not supported (because a course must always be inside a category). // We must move to an existing category. if (!empty($category['newparent'])) { if (!$DB->record_exists('course_categories', array('id' => $category['newparent']))) { throw new moodle_exception('unknowcategory'); } $newparent = $category['newparent']; } else { $newparent = $deletecat->parent; } // This operation is not allowed. We must move contents to an existing category. if ($newparent == 0) { throw new moodle_exception('movecatcontentstoroot'); } $parentcontext = get_category_or_system_context($newparent); require_capability('moodle/category:manage', $parentcontext); self::validate_context($parentcontext); category_delete_move($deletecat, $newparent, false); } } $transaction->allow_commit(); }
/** * @global object * @uses CONTEXT_COURSECAT * @return boolean Whether the user can create courses in any category in the system. */ function user_can_create_courses() { global $DB; $catsrs = $DB->get_recordset('course_categories'); foreach ($catsrs as $cat) { if (has_capability('moodle/course:create', context_coursecat::instance($cat->id))) { $catsrs->close(); return true; } } $catsrs->close(); return false; }
/** * Initialises the navigation object. * * This causes the navigation object to look at the current state of the page * that it is associated with and then load the appropriate content. * * This should only occur the first time that the navigation structure is utilised * which will normally be either when the navbar is called to be displayed or * when a block makes use of it. * * @return bool */ public function initialise() { global $CFG, $SITE, $USER, $DB; // Check if it has alread been initialised if ($this->initialised || during_initial_install()) { return true; } $this->initialised = true; // Set up the five base root nodes. These are nodes where we will put our // content and are as follows: // site: Navigation for the front page. // myprofile: User profile information goes here. // mycourses: The users courses get added here. // courses: Additional courses are added here. // users: Other users information loaded here. $this->rootnodes = array(); if (get_home_page() == HOMEPAGE_SITE) { // The home element should be my moodle because the root element is the site if (isloggedin() && !isguestuser()) { // Makes no sense if you aren't logged in $this->rootnodes['home'] = $this->add(get_string('myhome'), new moodle_url('/my/'), self::TYPE_SETTING, null, 'home'); } } else { // The home element should be the site because the root node is my moodle $this->rootnodes['home'] = $this->add(get_string('sitehome'), new moodle_url('/'), self::TYPE_SETTING, null, 'home'); if (!empty($CFG->defaulthomepage) && $CFG->defaulthomepage == HOMEPAGE_MY) { // We need to stop automatic redirection $this->rootnodes['home']->action->param('redirect', '0'); } } $this->rootnodes['site'] = $this->add_course($SITE); $this->rootnodes['myprofile'] = $this->add(get_string('myprofile'), null, self::TYPE_USER, null, 'myprofile'); $this->rootnodes['mycourses'] = $this->add(get_string('mycourses'), null, self::TYPE_ROOTNODE, null, 'mycourses'); $this->rootnodes['courses'] = $this->add(get_string('courses'), new moodle_url('/course/index.php'), self::TYPE_ROOTNODE, null, 'courses'); $this->rootnodes['users'] = $this->add(get_string('users'), null, self::TYPE_ROOTNODE, null, 'users'); // We always load the frontpage course to ensure it is available without // JavaScript enabled. $this->add_front_page_course_essentials($this->rootnodes['site'], $SITE); $this->load_course_sections($SITE, $this->rootnodes['site']); // Fetch all of the users courses. $mycourses = enrol_get_my_courses(); // We need to show categories if we can show categories and the user isn't enrolled in any courses or we're not showing all courses $showcategories = $this->show_categories() && (count($mycourses) == 0 || !empty($CFG->navshowallcourses)); // $issite gets set to true if the current pages course is the sites frontpage course $issite = $this->page->course->id == $SITE->id; // $ismycourse gets set to true if the user is enrolled in the current pages course. $ismycourse = !$issite && array_key_exists($this->page->course->id, $mycourses); // Check if any courses were returned. if (count($mycourses) > 0) { // Check if categories should be displayed within the my courses branch if (!empty($CFG->navshowmycoursecategories)) { // Find the category of each mycourse $categories = array(); foreach ($mycourses as $course) { $categories[] = $course->category; } // Do a single DB query to get the categories immediately associated with // courses the user is enrolled in. $categories = $DB->get_records_list('course_categories', 'id', array_unique($categories), 'depth ASC, sortorder ASC'); // Work out the parent categories that we need to load that we havn't // already got. $categoryids = array(); foreach ($categories as $category) { $categoryids = array_merge($categoryids, explode('/', trim($category->path, '/'))); } $categoryids = array_unique($categoryids); $categoryids = array_diff($categoryids, array_keys($categories)); if (count($categoryids)) { // Fetch any other categories we need. $allcategories = $DB->get_records_list('course_categories', 'id', $categoryids, 'depth ASC, sortorder ASC'); if (is_array($allcategories) && count($allcategories) > 0) { $categories = array_merge($categories, $allcategories); } } // We ONLY want the categories, we need to get rid of the keys $categories = array_values($categories); $addedcategories = array(); while (($category = array_shift($categories)) !== null) { if ($category->parent == '0') { $categoryparent = $this->rootnodes['mycourses']; } else { if (array_key_exists($category->parent, $addedcategories)) { $categoryparent = $addedcategories[$category->parent]; } else { // Prepare to count iterations. We don't want to loop forever // accidentally if for some reason a category can't be placed. if (!isset($category->loopcount)) { $category->loopcount = 0; } $category->loopcount++; if ($category->loopcount > 5) { // This is a pretty serious problem and this should never happen. // If it does then for some reason a category has been loaded but // its parents have now. It could be data corruption. debugging('Category ' . $category->id . ' could not be placed within the navigation', DEBUG_DEVELOPER); } else { // Add it back to the end of the categories array array_push($categories, $category); } continue; } } $url = new moodle_url('/course/category.php', array('id' => $category->id)); $addedcategories[$category->id] = $categoryparent->add($category->name, $url, self::TYPE_CATEGORY, $category->name, $category->id); if (!$category->visible) { // Let's decide the context where viewhidden cap checks will happen. if ($category->parent == '0') { $contexttocheck = context_system::instance(); } else { $contexttocheck = context_coursecat::instance($category->parent); } if (!has_capability('moodle/category:viewhiddencategories', $contexttocheck)) { $addedcategories[$category->id]->display = false; } else { $addedcategories[$category->id]->hidden = true; } } } } // Add all of the users courses to the navigation. // First up we need to add to the mycourses section. foreach ($mycourses as $course) { $course->coursenode = $this->add_course($course, false, true); } if (!empty($CFG->navshowallcourses)) { // Load all courses $this->load_all_courses(); } // Next if nasvshowallcourses is enabled then we need to add courses // to the courses branch as well. if (!empty($CFG->navshowallcourses)) { foreach ($mycourses as $course) { if (!empty($course->category) && !$this->can_add_more_courses_to_category($course->category)) { continue; } $genericcoursenode = $this->add_course($course, true); if ($genericcoursenode->isactive) { // We don't want this node to be active because we want the // node in the mycourses branch to be active. $genericcoursenode->make_inactive(); $genericcoursenode->collapse = true; if ($genericcoursenode->parent && $genericcoursenode->parent->type == self::TYPE_CATEGORY) { $parent = $genericcoursenode->parent; while ($parent && $parent->type == self::TYPE_CATEGORY) { $parent->collapse = true; $parent = $parent->parent; } } } } } } else { if (!empty($CFG->navshowallcourses) || !$this->show_categories()) { // Load all courses $this->load_all_courses(); } } $canviewcourseprofile = true; // Next load context specific content into the navigation switch ($this->page->context->contextlevel) { case CONTEXT_SYSTEM: // This has already been loaded we just need to map the variable if ($showcategories) { $this->load_all_categories(self::LOAD_ROOT_CATEGORIES, true); } break; case CONTEXT_COURSECAT: // This has already been loaded we just need to map the variable if ($this->show_categories()) { $this->load_all_categories($this->page->context->instanceid, true); } break; case CONTEXT_BLOCK: case CONTEXT_COURSE: if ($issite) { // If it is the front page course, or a block on it then // all we need to do is load the root categories if required if ($showcategories) { $this->load_all_categories(self::LOAD_ROOT_CATEGORIES, true); } break; } // Load the course associated with the page into the navigation $course = $this->page->course; if ($this->show_categories() && !$ismycourse) { // The user isn't enrolled in the course and we need to show categories in which case we need // to load the category relating to the course and depending up $showcategories all of the root categories as well. $this->load_all_categories($course->category, $showcategories); } $coursenode = $this->load_course($course); // If the course wasn't added then don't try going any further. if (!$coursenode) { $canviewcourseprofile = false; break; } // If the user is not enrolled then we only want to show the // course node and not populate it. // Not enrolled, can't view, and hasn't switched roles if (!can_access_course($course)) { // TODO: very ugly hack - do not force "parents" to enrol into course their child is enrolled in, // this hack has been propagated from user/view.php to display the navigation node. (MDL-25805) $isparent = false; if ($this->useridtouseforparentchecks) { if ($this->useridtouseforparentchecks != $USER->id) { $usercontext = get_context_instance(CONTEXT_USER, $this->useridtouseforparentchecks, MUST_EXIST); if ($DB->record_exists('role_assignments', array('userid' => $USER->id, 'contextid' => $usercontext->id)) and has_capability('moodle/user:viewdetails', $usercontext)) { $isparent = true; } } } if (!$isparent) { $coursenode->make_active(); $canviewcourseprofile = false; break; } } // Add the essentials such as reports etc... $this->add_course_essentials($coursenode, $course); if ($this->format_display_course_content($course->format)) { // Load the course sections $sections = $this->load_course_sections($course, $coursenode); } if (!$coursenode->contains_active_node() && !$coursenode->search_for_active_node()) { $coursenode->make_active(); } break; case CONTEXT_MODULE: if ($issite) { // If this is the site course then most information will have // already been loaded. // However we need to check if there is more content that can // yet be loaded for the specific module instance. $activitynode = $this->rootnodes['site']->get($this->page->cm->id, navigation_node::TYPE_ACTIVITY); if ($activitynode) { $this->load_activity($this->page->cm, $this->page->course, $activitynode); } break; } $course = $this->page->course; $cm = $this->page->cm; if ($this->show_categories() && !$ismycourse) { $this->load_all_categories($course->category, $showcategories); } // Load the course associated with the page into the navigation $coursenode = $this->load_course($course); // If the course wasn't added then don't try going any further. if (!$coursenode) { $canviewcourseprofile = false; break; } // If the user is not enrolled then we only want to show the // course node and not populate it. if (!can_access_course($course)) { $coursenode->make_active(); $canviewcourseprofile = false; break; } $this->add_course_essentials($coursenode, $course); // Get section number from $cm (if provided) - we need this // before loading sections in order to tell it to load this section // even if it would not normally display (=> it contains only // a label, which we are now editing) $sectionnum = isset($cm->sectionnum) ? $cm->sectionnum : 0; if ($sectionnum) { // This value has to be stored in a member variable because // otherwise we would have to pass it through a public API // to course formats and they would need to change their // functions to pass it along again... $this->includesectionnum = $sectionnum; } else { $this->includesectionnum = false; } // Load the course sections into the page $sections = $this->load_course_sections($course, $coursenode); if ($course->id != $SITE->id) { // Find the section for the $CM associated with the page and collect // its section number. if ($sectionnum) { $cm->sectionnumber = $sectionnum; } else { foreach ($sections as $section) { if ($section->id == $cm->section) { $cm->sectionnumber = $section->section; break; } } } // Load all of the section activities for the section the cm belongs to. if (isset($cm->sectionnumber) and !empty($sections[$cm->sectionnumber])) { list($sectionarray, $activityarray) = $this->generate_sections_and_activities($course); $activities = $this->load_section_activities($sections[$cm->sectionnumber]->sectionnode, $cm->sectionnumber, $activityarray); } else { $activities = array(); if ($activity = $this->load_stealth_activity($coursenode, get_fast_modinfo($course))) { // "stealth" activity from unavailable section $activities[$cm->id] = $activity; } } } else { $activities = array(); $activities[$cm->id] = $coursenode->get($cm->id, navigation_node::TYPE_ACTIVITY); } if (!empty($activities[$cm->id])) { // Finally load the cm specific navigaton information $this->load_activity($cm, $course, $activities[$cm->id]); // Check if we have an active ndoe if (!$activities[$cm->id]->contains_active_node() && !$activities[$cm->id]->search_for_active_node()) { // And make the activity node active. $activities[$cm->id]->make_active(); } } else { //TODO: something is wrong, what to do? (Skodak) } break; case CONTEXT_USER: if ($issite) { // The users profile information etc is already loaded // for the front page. break; } $course = $this->page->course; if ($this->show_categories() && !$ismycourse) { $this->load_all_categories($course->category, $showcategories); } // Load the course associated with the user into the navigation $coursenode = $this->load_course($course); // If the course wasn't added then don't try going any further. if (!$coursenode) { $canviewcourseprofile = false; break; } // If the user is not enrolled then we only want to show the // course node and not populate it. if (!can_access_course($course)) { $coursenode->make_active(); $canviewcourseprofile = false; break; } $this->add_course_essentials($coursenode, $course); $sections = $this->load_course_sections($course, $coursenode); break; } // Look for all categories which have been loaded if ($showcategories) { $categories = $this->find_all_of_type(self::TYPE_CATEGORY); if (count($categories) !== 0) { $categoryids = array(); foreach ($categories as $category) { $categoryids[] = $category->key; } list($categoriessql, $params) = $DB->get_in_or_equal($categoryids, SQL_PARAMS_NAMED); $params['limit'] = !empty($CFG->navcourselimit) ? $CFG->navcourselimit : 20; $sql = "SELECT cc.id, COUNT(c.id) AS coursecount\n FROM {course_categories} cc\n JOIN {course} c ON c.category = cc.id\n WHERE cc.id {$categoriessql}\n GROUP BY cc.id\n HAVING COUNT(c.id) > :limit"; $excessivecategories = $DB->get_records_sql($sql, $params); foreach ($categories as &$category) { if (array_key_exists($category->key, $excessivecategories) && !$this->can_add_more_courses_to_category($category)) { $url = new moodle_url('/course/category.php', array('id' => $category->key)); $category->add(get_string('viewallcourses'), $url, self::TYPE_SETTING); } } } } else { if ((!empty($CFG->navshowallcourses) || empty($mycourses)) && !$this->can_add_more_courses_to_category($this->rootnodes['courses'])) { $this->rootnodes['courses']->add(get_string('viewallcoursescategories'), new moodle_url('/course/index.php'), self::TYPE_SETTING); } } // Load for the current user $this->load_for_user(); if ($this->page->context->contextlevel >= CONTEXT_COURSE && $this->page->context->instanceid != $SITE->id && $canviewcourseprofile) { $this->load_for_user(null, true); } // Load each extending user into the navigation. foreach ($this->extendforuser as $user) { if ($user->id != $USER->id) { $this->load_for_user($user); } } // Give the local plugins a chance to include some navigation if they want. foreach (get_plugin_list_with_file('local', 'lib.php', true) as $plugin => $file) { $function = "local_{$plugin}_extends_navigation"; $oldfunction = "{$plugin}_extends_navigation"; if (function_exists($function)) { // This is the preferred function name as there is less chance of conflicts $function($this); } else { if (function_exists($oldfunction)) { // We continue to support the old function name to ensure backwards compatability $oldfunction($this); } } } // Remove any empty root nodes foreach ($this->rootnodes as $node) { // Dont remove the home node if ($node->key !== 'home' && !$node->has_children()) { $node->remove(); } } if (!$this->contains_active_node()) { $this->search_for_active_node(); } // If the user is not logged in modify the navigation structure as detailed // in {@link http://docs.moodle.org/dev/Navigation_2.0_structure} if (!isloggedin()) { $activities = clone $this->rootnodes['site']->children; $this->rootnodes['site']->remove(); $children = clone $this->children; $this->children = new navigation_node_collection(); foreach ($activities as $child) { $this->children->add($child); } foreach ($children as $child) { $this->children->add($child); } } return true; }
* @package eclass-local-contextadmin * @author joshstagg * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ require_once '../../config.php'; require_once $CFG->dirroot . '/course/lib.php'; require_once $CFG->libdir . '/adminlib.php'; require_once $CFG->libdir . '/coursecatlib.php'; require_once 'categoryroles_form.php'; require_login(); $id = required_param('id', PARAM_INT); $forum = optional_param('rolerenaming', 0, PARAM_INT); $itemid = 0; // Initalise itemid, as all files in category description has item id 0. $PAGE->set_url('/local/contextadmin/categoryroles.php', array('id' => $id)); $categorycontext = context_coursecat::instance($id); $PAGE->set_context($categorycontext); require_capability('moodle/category:manage', $categorycontext); if (!($category = $DB->get_record('course_categories', array('id' => $id)))) { print_error('unknowcategory'); } $strtitle = get_string('roleedit_title', 'local_contextadmin'); $editorcontext = $categorycontext; $title = $strtitle; $fullname = $category->name; $PAGE->set_pagelayout('admin'); $mform = new categoryroles_form('categoryroles.php', array('category' => $category)); if ($mform->is_cancelled()) { if ($id) { redirect($CFG->wwwroot . '/course/index.php?categoryid=' . $id . '&categoryedit=on'); } else {
/** * Returns the category context. * @return context_coursecat */ public function get_context() { if ($this->id === 0) { // This is the special top level category object. return context_system::instance(); } else { return context_coursecat::instance($this->id); } }
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ require_once dirname(__FILE__) . '/../config.php'; require_once $CFG->dirroot . '/course/lib.php'; $id = required_param('id', PARAM_INT); // Course ID. $delete = optional_param('delete', '', PARAM_ALPHANUM); // Confirmation hash. $course = $DB->get_record('course', array('id' => $id), '*', MUST_EXIST); $coursecontext = context_course::instance($course->id); require_login(); if ($SITE->id == $course->id || !can_delete_course($id)) { // Can not delete frontpage or don't have permission to delete the course. print_error('cannotdeletecourse'); } $categorycontext = context_coursecat::instance($course->category); $PAGE->set_url('/course/delete.php', array('id' => $id)); $PAGE->set_context($categorycontext); $PAGE->set_pagelayout('admin'); navigation_node::override_active_url(new moodle_url('/course/management.php', array('categoryid' => $course->category))); $courseshortname = format_string($course->shortname, true, array('context' => $coursecontext)); $coursefullname = format_string($course->fullname, true, array('context' => $coursecontext)); $categoryurl = new moodle_url('/course/management.php', array('categoryid' => $course->category)); // Check if we've got confirmation. if ($delete === md5($course->timemodified)) { // We do - time to delete the course. require_sesskey(); $strdeletingcourse = get_string("deletingcourse", "", $courseshortname); $PAGE->navbar->add($strdeletingcourse); $PAGE->set_title("{$SITE->shortname}: {$strdeletingcourse}"); $PAGE->set_heading($SITE->fullname);
/** * Update a course. * * Please note this functions does not verify any access control, * the calling code is responsible for all validation (usually it is the form definition). * * @param object $data - all the data needed for an entry in the 'course' table * @param array $editoroptions course description editor options * @return void */ function update_course($data, $editoroptions = NULL) { global $DB; $data->timemodified = time(); $oldcourse = course_get_format($data->id)->get_course(); $context = context_course::instance($oldcourse->id); if ($editoroptions) { $data = file_postupdate_standard_editor($data, 'summary', $editoroptions, $context, 'course', 'summary', 0); } if ($overviewfilesoptions = course_overviewfiles_options($data->id)) { $data = file_postupdate_standard_filemanager($data, 'overviewfiles', $overviewfilesoptions, $context, 'course', 'overviewfiles', 0); } // Check we don't have a duplicate shortname. if (!empty($data->shortname) && $oldcourse->shortname != $data->shortname) { if ($DB->record_exists_sql('SELECT id from {course} WHERE shortname = ? AND id <> ?', array($data->shortname, $data->id))) { throw new moodle_exception('shortnametaken', '', '', $data->shortname); } } // Check we don't have a duplicate idnumber. if (!empty($data->idnumber) && $oldcourse->idnumber != $data->idnumber) { if ($DB->record_exists_sql('SELECT id from {course} WHERE idnumber = ? AND id <> ?', array($data->idnumber, $data->id))) { throw new moodle_exception('courseidnumbertaken', '', '', $data->idnumber); } } if (!isset($data->category) or empty($data->category)) { // prevent nulls and 0 in category field unset($data->category); } $changesincoursecat = $movecat = (isset($data->category) and $oldcourse->category != $data->category); if (!isset($data->visible)) { // data not from form, add missing visibility info $data->visible = $oldcourse->visible; } if ($data->visible != $oldcourse->visible) { // reset the visibleold flag when manually hiding/unhiding course $data->visibleold = $data->visible; $changesincoursecat = true; } else { if ($movecat) { $newcategory = $DB->get_record('course_categories', array('id' => $data->category)); if (empty($newcategory->visible)) { // make sure when moving into hidden category the course is hidden automatically $data->visible = 0; } } } // Update with the new data $DB->update_record('course', $data); // make sure the modinfo cache is reset rebuild_course_cache($data->id); // update course format options with full course data course_get_format($data->id)->update_course_format_options($data, $oldcourse); $course = $DB->get_record('course', array('id' => $data->id)); if ($movecat) { $newparent = context_coursecat::instance($course->category); $context->update_moved($newparent); } $fixcoursesortorder = $movecat || isset($data->sortorder) && $oldcourse->sortorder != $data->sortorder; if ($fixcoursesortorder) { fix_course_sortorder(); } // purge appropriate caches in case fix_course_sortorder() did not change anything cache_helper::purge_by_event('changesincourse'); if ($changesincoursecat) { cache_helper::purge_by_event('changesincoursecat'); } // Test for and remove blocks which aren't appropriate anymore blocks_remove_inappropriate($course); // Save any custom role names. save_local_role_names($course->id, $data); // update enrol settings enrol_course_updated(false, $course, $data); // Trigger a course updated event. $event = \core\event\course_updated::create(array('objectid' => $course->id, 'context' => context_course::instance($course->id), 'other' => array('shortname' => $course->shortname, 'fullname' => $course->fullname))); $event->set_legacy_logdata(array($course->id, 'course', 'update', 'edit.php?id=' . $course->id, $course->id)); $event->trigger(); if ($oldcourse->format !== $course->format) { // Remove all options stored for the previous format // We assume that new course format migrated everything it needed watching trigger // 'course_updated' and in method format_XXX::update_course_format_options() $DB->delete_records('course_format_options', array('courseid' => $course->id, 'format' => $oldcourse->format)); } }
/** * Test update_cohorts without permission on the src category. */ public function test_update_cohorts_missing_src() { global $USER, $CFG, $DB; $this->resetAfterTest(true); $category1 = self::getDataGenerator()->create_category(array('name' => 'Test category 1')); $category2 = self::getDataGenerator()->create_category(array('name' => 'Test category 2')); $context1 = context_coursecat::instance($category1->id); $context2 = context_coursecat::instance($category2->id); $cohort = array('contextid' => $context1->id, 'name' => 'cohortnametest1', 'idnumber' => 'idnumbertest1', 'description' => 'This is a description for cohort 1'); $cohort1 = self::getDataGenerator()->create_cohort($cohort); $roleid = $this->assignUserCapability('moodle/cohort:manage', $context2->id); $cohortupdate = array('id' => $cohort1->id, 'categorytype' => array('type' => 'id', 'value' => $category2->id), 'name' => 'cohort update', 'idnumber' => 'idnumber update', 'description' => 'This is a description update'); // Call the external function. // Should fail because we don't have permission on the src category $this->setExpectedException('required_capability_exception'); core_cohort_external::update_cohorts(array($cohortupdate)); }
/** * Get the list of categories leading to this course. * * This function is used by {@link navbar::get_items()} to add back the "courses" * node and category chain leading to the current course. Note that this is only ever * called for the current course, so we don't need to bother taking in any parameters. * * @return array */ private function get_course_categories() { global $CFG; require_once $CFG->dirroot . '/course/lib.php'; require_once $CFG->libdir . '/coursecatlib.php'; $categories = array(); $cap = 'moodle/category:viewhiddencategories'; $showcategories = coursecat::count_all() > 1; if ($showcategories) { foreach ($this->page->categories as $category) { if (!$category->visible && !has_capability($cap, get_category_or_system_context($category->parent))) { continue; } $url = new moodle_url('/course/index.php', array('categoryid' => $category->id)); $name = format_string($category->name, true, array('context' => context_coursecat::instance($category->id))); $categorynode = breadcrumb_navigation_node::create($name, $url, self::TYPE_CATEGORY, null, $category->id); if (!$category->visible) { $categorynode->hidden = true; } $categories[] = $categorynode; } } // Don't show the 'course' node if enrolled in this course. if (!is_enrolled(context_course::instance($this->page->course->id, null, '', true))) { $courses = $this->page->navigation->get('courses'); if (!$courses) { // Courses node may not be present. $courses = breadcrumb_navigation_node::create(get_string('courses'), new moodle_url('/course/index.php'), self::TYPE_CONTAINER); } $categories[] = $courses; } return $categories; }
/** * This function tests that the functions responsible for moving questions to * different contexts also updates the tag instances associated with the questions. */ public function test_altering_tag_instance_context() { global $CFG, $DB; // Set to admin user. $this->setAdminUser(); // Create two course categories - we are going to delete one of these later and will expect // all the questions belonging to the course in the deleted category to be moved. $coursecat1 = $this->getDataGenerator()->create_category(); $coursecat2 = $this->getDataGenerator()->create_category(); // Create a couple of categories and questions. $context1 = context_coursecat::instance($coursecat1->id); $context2 = context_coursecat::instance($coursecat2->id); $questiongenerator = $this->getDataGenerator()->get_plugin_generator('core_question'); $questioncat1 = $questiongenerator->create_question_category(array('contextid' => $context1->id)); $questioncat2 = $questiongenerator->create_question_category(array('contextid' => $context2->id)); $question1 = $questiongenerator->create_question('shortanswer', null, array('category' => $questioncat1->id)); $question2 = $questiongenerator->create_question('shortanswer', null, array('category' => $questioncat1->id)); $question3 = $questiongenerator->create_question('shortanswer', null, array('category' => $questioncat2->id)); $question4 = $questiongenerator->create_question('shortanswer', null, array('category' => $questioncat2->id)); // Now lets tag these questions. core_tag_tag::set_item_tags('core_question', 'question', $question1->id, $context1, array('tag 1', 'tag 2')); core_tag_tag::set_item_tags('core_question', 'question', $question2->id, $context1, array('tag 3', 'tag 4')); core_tag_tag::set_item_tags('core_question', 'question', $question3->id, $context2, array('tag 5', 'tag 6')); core_tag_tag::set_item_tags('core_question', 'question', $question4->id, $context2, array('tag 7', 'tag 8')); // Test moving the questions to another category. question_move_questions_to_category(array($question1->id, $question2->id), $questioncat2->id); // Test that all tag_instances belong to one context. $this->assertEquals(8, $DB->count_records('tag_instance', array('component' => 'core_question', 'contextid' => $questioncat2->contextid))); // Test moving them back. question_move_questions_to_category(array($question1->id, $question2->id), $questioncat1->id); // Test that all tag_instances are now reset to how they were initially. $this->assertEquals(4, $DB->count_records('tag_instance', array('component' => 'core_question', 'contextid' => $questioncat1->contextid))); $this->assertEquals(4, $DB->count_records('tag_instance', array('component' => 'core_question', 'contextid' => $questioncat2->contextid))); // Now test moving a whole question category to another context. question_move_category_to_context($questioncat1->id, $questioncat1->contextid, $questioncat2->contextid); // Test that all tag_instances belong to one context. $this->assertEquals(8, $DB->count_records('tag_instance', array('component' => 'core_question', 'contextid' => $questioncat2->contextid))); // Now test moving them back. question_move_category_to_context($questioncat1->id, $questioncat2->contextid, context_coursecat::instance($coursecat1->id)->id); // Test that all tag_instances are now reset to how they were initially. $this->assertEquals(4, $DB->count_records('tag_instance', array('component' => 'core_question', 'contextid' => $questioncat1->contextid))); $this->assertEquals(4, $DB->count_records('tag_instance', array('component' => 'core_question', 'contextid' => $questioncat2->contextid))); // Now we want to test deleting the course category and moving the questions to another category. question_delete_course_category($coursecat1, $coursecat2, false); // Test that all tag_instances belong to one context. $this->assertEquals(8, $DB->count_records('tag_instance', array('component' => 'core_question', 'contextid' => $questioncat2->contextid))); // Create a course. $course = $this->getDataGenerator()->create_course(); // Create some question categories and questions in this course. $coursecontext = context_course::instance($course->id); $questioncat = $questiongenerator->create_question_category(array('contextid' => $coursecontext->id)); $question1 = $questiongenerator->create_question('shortanswer', null, array('category' => $questioncat->id)); $question2 = $questiongenerator->create_question('shortanswer', null, array('category' => $questioncat->id)); // Add some tags to these questions. core_tag_tag::set_item_tags('core_question', 'question', $question1->id, $coursecontext, array('tag 1', 'tag 2')); core_tag_tag::set_item_tags('core_question', 'question', $question2->id, $coursecontext, array('tag 1', 'tag 2')); // Create a course that we are going to restore the other course to. $course2 = $this->getDataGenerator()->create_course(); // Create backup file and save it to the backup location. $bc = new backup_controller(backup::TYPE_1COURSE, $course->id, backup::FORMAT_MOODLE, backup::INTERACTIVE_NO, backup::MODE_GENERAL, 2); $bc->execute_plan(); $results = $bc->get_results(); $file = $results['backup_destination']; $fp = get_file_packer('application/vnd.moodle.backup'); $filepath = $CFG->dataroot . '/temp/backup/test-restore-course'; $file->extract_to_pathname($fp, $filepath); $bc->destroy(); // Now restore the course. $rc = new restore_controller('test-restore-course', $course2->id, backup::INTERACTIVE_NO, backup::MODE_GENERAL, 2, backup::TARGET_NEW_COURSE); $rc->execute_precheck(); $rc->execute_plan(); // Get the created question category. $restoredcategory = $DB->get_record('question_categories', array('contextid' => context_course::instance($course2->id)->id), '*', MUST_EXIST); // Check that there are two questions in the restored to course's context. $this->assertEquals(2, $DB->count_records('question', array('category' => $restoredcategory->id))); $rc->destroy(); }
function get_content() { global $CFG, $USER, $DB, $OUTPUT; if ($this->content !== NULL) { return $this->content; } $this->content = new stdClass(); $this->content->items = array(); $this->content->icons = array(); $this->content->footer = ''; $icon = '<img src="' . $OUTPUT->pix_url('i/course') . '" class="icon" alt="" />'; $adminseesall = true; if (isset($CFG->block_course_list_adminview)) { if ($CFG->block_course_list_adminview == 'own') { $adminseesall = false; } } if (empty($CFG->disablemycourses) and isloggedin() and !isguestuser() and !(has_capability('moodle/course:update', context_system::instance()) and $adminseesall)) { // Just print My Courses if ($courses = enrol_get_my_courses(NULL, 'visible DESC, fullname ASC')) { foreach ($courses as $course) { $coursecontext = context_course::instance($course->id); $linkcss = $course->visible ? "" : " class=\"dimmed\" "; $this->content->items[] = "<a {$linkcss} title=\"" . format_string($course->shortname, true, array('context' => $coursecontext)) . "\" " . "href=\"{$CFG->wwwroot}/course/view.php?id={$course->id}\">" . $icon . format_string(get_course_display_name_for_list($course)) . "</a>"; } $this->title = get_string('mycourses'); /// If we can update any course of the view all isn't hidden, show the view all courses link if (has_capability('moodle/course:update', context_system::instance()) || empty($CFG->block_course_list_hideallcourseslink)) { $this->content->footer = "<a href=\"{$CFG->wwwroot}/course/index.php\">" . get_string("fulllistofcourses") . "</a> ..."; } } $this->get_remote_courses(); if ($this->content->items) { // make sure we don't return an empty list return $this->content; } } $categories = coursecat::get(0)->get_children(); // Parent = 0 ie top-level categories only if ($categories) { //Check we have categories if (count($categories) > 1 || count($categories) == 1 && $DB->count_records('course') > 200) { // Just print top level category links foreach ($categories as $category) { $categoryname = $category->get_formatted_name(); $linkcss = $category->visible ? "" : " class=\"dimmed\" "; $this->content->items[] = "<a {$linkcss} href=\"{$CFG->wwwroot}/course/index.php?categoryid={$category->id}\">" . $icon . $categoryname . "</a>"; } /// If we can update any course of the view all isn't hidden, show the view all courses link if (has_capability('moodle/course:update', context_system::instance()) || empty($CFG->block_course_list_hideallcourseslink)) { $this->content->footer .= "<a href=\"{$CFG->wwwroot}/course/index.php\">" . get_string('fulllistofcourses') . '</a> ...'; } $this->title = get_string('categories'); } else { // Just print course names of single category $category = array_shift($categories); $courses = get_courses($category->id); if ($courses) { foreach ($courses as $course) { $coursecontext = context_course::instance($course->id); $linkcss = $course->visible ? "" : " class=\"dimmed\" "; $this->content->items[] = "<a {$linkcss} title=\"" . format_string($course->shortname, true, array('context' => $coursecontext)) . "\" " . "href=\"{$CFG->wwwroot}/course/view.php?id={$course->id}\">" . $icon . format_string(get_course_display_name_for_list($course), true, array('context' => context_course::instance($course->id))) . "</a>"; } /// If we can update any course of the view all isn't hidden, show the view all courses link if (has_capability('moodle/course:update', context_system::instance()) || empty($CFG->block_course_list_hideallcourseslink)) { $this->content->footer .= "<a href=\"{$CFG->wwwroot}/course/index.php\">" . get_string('fulllistofcourses') . '</a> ...'; } $this->get_remote_courses(); } else { $this->content->icons[] = ''; $this->content->items[] = get_string('nocoursesyet'); if (has_capability('moodle/course:create', context_coursecat::instance($category->id))) { $this->content->footer = '<a href="' . $CFG->wwwroot . '/course/edit.php?category=' . $category->id . '">' . get_string("addnewcourse") . '</a> ...'; } $this->get_remote_courses(); } $this->title = get_string('courses'); } } return $this->content; }
/** * Returns course context instance. * * @static * @param int $instanceid * @param int $strictness * @return context_course context instance */ public static function instance($instanceid, $strictness = MUST_EXIST) { global $DB; if ($context = context::cache_get(CONTEXT_COURSE, $instanceid)) { return $context; } if (!($record = $DB->get_record('context', array('contextlevel' => CONTEXT_COURSE, 'instanceid' => $instanceid)))) { if ($course = $DB->get_record('course', array('id' => $instanceid), 'id,category', $strictness)) { if ($course->category) { $parentcontext = context_coursecat::instance($course->category); $record = context::insert_context_record(CONTEXT_COURSE, $course->id, $parentcontext->path); } else { $record = context::insert_context_record(CONTEXT_COURSE, $course->id, '/' . SYSCONTEXTID, 0); } } } if ($record) { $context = new context_course($record); context::cache_add($context); return $context; } return false; }
/** * Renders a restore category search object * * @param restore_category_search $component * @return string */ public function render_restore_category_search(restore_category_search $component) { $url = $component->get_url(); $output = html_writer::start_tag('div', array('class' => 'restore-course-search')); $output .= html_writer::start_tag('div', array('class' => 'rcs-results')); $table = new html_table(); $table->head = array('', get_string('name'), get_string('description')); $table->data = array(); if ($component->get_count() !== 0) { foreach ($component->get_results() as $category) { $row = new html_table_row(); $row->attributes['class'] = 'rcs-course'; if (!$category->visible) { $row->attributes['class'] .= ' dimmed'; } $row->cells = array(html_writer::empty_tag('input', array('type' => 'radio', 'name' => 'targetid', 'value' => $category->id)), format_string($category->name, true, array('context' => context_coursecat::instance($category->id))), format_text($category->description, $category->descriptionformat, array('overflowdiv' => true))); $table->data[] = $row; } if ($component->has_more_results()) { $cell = new html_table_cell(get_string('moreresults', 'backup')); $cell->attributes['class'] = 'notifyproblem'; $cell->colspan = 3; $row = new html_table_row(array($cell)); $row->attributes['class'] = 'rcs-course'; $table->data[] = $row; } } else { $cell = new html_table_cell(get_string('nomatchingcourses', 'backup')); $cell->colspan = 3; $cell->attributes['class'] = 'notifyproblem'; $row = new html_table_row(array($cell)); $row->attributes['class'] = 'rcs-course'; $table->data[] = $row; } $output .= html_writer::table($table); $output .= html_writer::end_tag('div'); $output .= html_writer::start_tag('div', array('class' => 'rcs-search')); $output .= html_writer::empty_tag('input', array('type' => 'text', 'name' => restore_category_search::$VAR_SEARCH, 'value' => $component->get_search())); $output .= html_writer::empty_tag('input', array('type' => 'submit', 'name' => 'searchcourses', 'value' => get_string('search'))); $output .= html_writer::end_tag('div'); $output .= html_writer::end_tag('div'); return $output; }
/** * Set the course category this page belongs to manually. * * This automatically sets $PAGE->course to be the site course. You cannot * use this method if you have already set $PAGE->course - in that case, * the category must be the one that the course belongs to. This also * automatically sets the page context to the category context. * * @param int $categoryid The id of the category to set. * @throws coding_exception */ public function set_category_by_id($categoryid) { global $SITE; if (!is_null($this->_course)) { throw new coding_exception('Course has already been set. You cannot change the category now.'); } if (is_array($this->_categories)) { throw new coding_exception('Course category has already been set. You cannot to change it now.'); } $this->ensure_theme_not_set(); $this->set_course($SITE); $this->load_category($categoryid); $this->set_context(context_coursecat::instance($categoryid)); }
/** * Create a test course category * @param array|stdClass $record * @param array $options * @return stdClass course category record */ function create_category($record = null, array $options = null) { global $DB, $CFG; require_once "{$CFG->dirroot}/course/lib.php"; $this->categorycount++; $i = $this->categorycount; $record = (array) $record; if (!isset($record['name'])) { $record['name'] = 'Course category ' . $i; } if (!isset($record['idnumber'])) { $record['idnumber'] = ''; } if (!isset($record['description'])) { $record['description'] = "Test course category {$i}\n{$this->loremipsum}"; } if (!isset($record['descriptionformat'])) { $record['descriptionformat'] = FORMAT_MOODLE; } if (!isset($record['parent'])) { $record['parent'] = 0; } if (empty($record['parent'])) { $parent = new stdClass(); $parent->path = ''; $parent->depth = 0; } else { $parent = $DB->get_record('course_categories', array('id' => $record['parent']), '*', MUST_EXIST); } $record['depth'] = $parent->depth + 1; $record['sortorder'] = 0; $record['timemodified'] = time(); $record['timecreated'] = $record['timemodified']; $catid = $DB->insert_record('course_categories', $record); $path = $parent->path . '/' . $catid; $DB->set_field('course_categories', 'path', $path, array('id' => $catid)); context_coursecat::instance($catid); fix_course_sortorder(); return $DB->get_record('course_categories', array('id' => $catid), '*', MUST_EXIST); }