/** * Defines the form fields. */ public function definition() { global $USER, $CFG, $DB; $mform = $this->_form; $course = $this->_customdata['course']; // Overall criteria aggregation. $context = context_course::instance($course->id); $roles = array(); $assumedrole = -1; if (is_role_switched($course->id)) { $roles[0] = get_string('switchrolereturn'); $assumedrole = $USER->access['rsw'][$context->path]; } $availableroles = get_switchable_roles($context); if (is_array($availableroles)) { foreach ($availableroles as $key => $role) { if ($assumedrole == (int) $key) { continue; } $roles[$key] = $role; } } $mform->addElement('select', 'switchrole', get_string('role'), $roles); // Add common action buttons. $this->add_action_buttons(); // Add hidden fields. $mform->addElement('hidden', 'id', $course->id); $mform->setType('id', PARAM_INT); }
/** * This function loads the course settings that are available for the user * * @param bool $forceopen If set to true the course node will be forced open * @return navigation_node|false */ protected function load_course_settings($forceopen = false) { global $CFG; $course = $this->page->course; $coursecontext = get_context_instance(CONTEXT_COURSE, $course->id); // note: do not test if enrolled or viewing here because we need the enrol link in Course administration section $coursenode = $this->add(get_string('courseadministration'), null, self::TYPE_COURSE, null, 'courseadmin'); if ($forceopen) { $coursenode->force_open(); } if (has_capability('moodle/course:update', $coursecontext)) { // Add the turn on/off settings if ($this->page->url->compare(new moodle_url('/course/view.php'), URL_MATCH_BASE)) { // We are on the course page, retain the current page params e.g. section. $baseurl = clone $this->page->url; $baseurl->param('sesskey', sesskey()); } else { // Edit on the main course page. $baseurl = new moodle_url('/course/view.php', array('id' => $course->id, 'return' => $this->page->url->out_as_local_url(false), 'sesskey' => sesskey())); } $editurl = clone $baseurl; if ($this->page->user_is_editing()) { $editurl->param('edit', 'off'); $editstring = get_string('turneditingoff'); } else { $editurl->param('edit', 'on'); $editstring = get_string('turneditingon'); } $coursenode->add($editstring, $editurl, self::TYPE_SETTING, null, null, new pix_icon('i/edit', '')); // Add the module chooser toggle $modchoosertoggleurl = clone $baseurl; if ($this->page->user_is_editing() && course_ajax_enabled($course)) { if ($usemodchooser = get_user_preferences('usemodchooser', $CFG->modchooserdefault)) { $modchoosertogglestring = get_string('modchooserdisable', 'moodle'); $modchoosertoggleurl->param('modchooser', 'off'); } else { $modchoosertogglestring = get_string('modchooserenable', 'moodle'); $modchoosertoggleurl->param('modchooser', 'on'); } $modchoosertoggle = $coursenode->add($modchoosertogglestring, $modchoosertoggleurl, self::TYPE_SETTING); $modchoosertoggle->add_class('modchoosertoggle'); $modchoosertoggle->add_class('visibleifjs'); user_preference_allow_ajax_update('usemodchooser', PARAM_BOOL); } if ($this->page->user_is_editing()) { // Removed as per MDL-22732 // $this->add_course_editing_links($course); } // Add the course settings link $url = new moodle_url('/course/edit.php', array('id' => $course->id)); $coursenode->add(get_string('editsettings'), $url, self::TYPE_SETTING, null, null, new pix_icon('i/settings', '')); // Add the course completion settings link if ($CFG->enablecompletion && $course->enablecompletion) { $url = new moodle_url('/course/completion.php', array('id' => $course->id)); $coursenode->add(get_string('completion', 'completion'), $url, self::TYPE_SETTING, null, null, new pix_icon('i/settings', '')); } } // add enrol nodes enrol_add_course_navigation($coursenode, $course); // Manage filters if (has_capability('moodle/filter:manage', $coursecontext) && count(filter_get_available_in_context($coursecontext)) > 0) { $url = new moodle_url('/filter/manage.php', array('contextid' => $coursecontext->id)); $coursenode->add(get_string('filters', 'admin'), $url, self::TYPE_SETTING, null, null, new pix_icon('i/filter', '')); } // Add view grade report is permitted $reportavailable = false; if (has_capability('moodle/grade:viewall', $coursecontext)) { $reportavailable = true; } else { if (!empty($course->showgrades)) { $reports = get_plugin_list('gradereport'); if (is_array($reports) && count($reports) > 0) { // Get all installed reports arsort($reports); // user is last, we want to test it first foreach ($reports as $plugin => $plugindir) { if (has_capability('gradereport/' . $plugin . ':view', $coursecontext)) { //stop when the first visible plugin is found $reportavailable = true; break; } } } } } if ($reportavailable) { $url = new moodle_url('/grade/report/index.php', array('id' => $course->id)); $gradenode = $coursenode->add(get_string('grades'), $url, self::TYPE_SETTING, null, 'grades', new pix_icon('i/grades', '')); } // Add outcome if permitted if (!empty($CFG->enableoutcomes) && has_capability('moodle/course:update', $coursecontext)) { $url = new moodle_url('/grade/edit/outcome/course.php', array('id' => $course->id)); $coursenode->add(get_string('outcomes', 'grades'), $url, self::TYPE_SETTING, null, 'outcomes', new pix_icon('i/outcomes', '')); } // Backup this course if (has_capability('moodle/backup:backupcourse', $coursecontext)) { $url = new moodle_url('/backup/backup.php', array('id' => $course->id)); $coursenode->add(get_string('backup'), $url, self::TYPE_SETTING, null, 'backup', new pix_icon('i/backup', '')); } // Restore to this course if (has_capability('moodle/restore:restorecourse', $coursecontext)) { $url = new moodle_url('/backup/restorefile.php', array('contextid' => $coursecontext->id)); $coursenode->add(get_string('restore'), $url, self::TYPE_SETTING, null, 'restore', new pix_icon('i/restore', '')); } // Import data from other courses if (has_capability('moodle/restore:restoretargetimport', $coursecontext)) { $url = new moodle_url('/backup/import.php', array('id' => $course->id)); $coursenode->add(get_string('import'), $url, self::TYPE_SETTING, null, 'import', new pix_icon('i/restore', '')); } // Publish course on a hub if (has_capability('moodle/course:publish', $coursecontext)) { $url = new moodle_url('/course/publish/index.php', array('id' => $course->id)); $coursenode->add(get_string('publish'), $url, self::TYPE_SETTING, null, 'publish', new pix_icon('i/publish', '')); } // Reset this course if (has_capability('moodle/course:reset', $coursecontext)) { $url = new moodle_url('/course/reset.php', array('id' => $course->id)); $coursenode->add(get_string('reset'), $url, self::TYPE_SETTING, null, null, new pix_icon('i/return', '')); } // Questions require_once $CFG->libdir . '/questionlib.php'; question_extend_settings_navigation($coursenode, $coursecontext)->trim_if_empty(); if (has_capability('moodle/course:update', $coursecontext)) { // Repository Instances if (!$this->cache->cached('contexthasrepos' . $coursecontext->id)) { require_once $CFG->dirroot . '/repository/lib.php'; $editabletypes = repository::get_editable_types($coursecontext); $haseditabletypes = !empty($editabletypes); unset($editabletypes); $this->cache->set('contexthasrepos' . $coursecontext->id, $haseditabletypes); } else { $haseditabletypes = $this->cache->{'contexthasrepos' . $coursecontext->id}; } if ($haseditabletypes) { $url = new moodle_url('/repository/manage_instances.php', array('contextid' => $coursecontext->id)); $coursenode->add(get_string('repositories'), $url, self::TYPE_SETTING, null, null, new pix_icon('i/repository', '')); } } // Manage files if ($course->legacyfiles == 2 and has_capability('moodle/course:managefiles', $coursecontext)) { // hidden in new courses and courses where legacy files were turned off $url = new moodle_url('/files/index.php', array('contextid' => $coursecontext->id)); $coursenode->add(get_string('courselegacyfiles'), $url, self::TYPE_SETTING, null, 'coursefiles', new pix_icon('i/files', '')); } // Switch roles $roles = array(); $assumedrole = $this->in_alternative_role(); if ($assumedrole !== false) { $roles[0] = get_string('switchrolereturn'); } if (has_capability('moodle/role:switchroles', $coursecontext)) { $availableroles = get_switchable_roles($coursecontext); if (is_array($availableroles)) { foreach ($availableroles as $key => $role) { if ($assumedrole == (int) $key) { continue; } $roles[$key] = $role; } } } if (is_array($roles) && count($roles) > 0) { $switchroles = $this->add(get_string('switchroleto')); if (count($roles) == 1 && array_key_exists(0, $roles) || $assumedrole !== false) { $switchroles->force_open(); } $returnurl = $this->page->url; $returnurl->param('sesskey', sesskey()); foreach ($roles as $key => $name) { $url = new moodle_url('/course/switchrole.php', array('id' => $course->id, 'sesskey' => sesskey(), 'switchrole' => $key, 'returnurl' => $returnurl->out(false))); $switchroles->add($name, $url, self::TYPE_SETTING, null, $key, new pix_icon('i/roles', '')); } } // Return we are done return $coursenode; }
// Defined here to avoid notices on errors etc // Prevent caching of this page to stop confusion when changing page after making AJAX changes $PAGE->set_cacheable(false); preload_course_contexts($course->id); $context = context_course::instance($course->id, MUST_EXIST); // Remove any switched roles before checking login if ($switchrole == 0 && confirm_sesskey()) { role_switch($switchrole, $context); } require_login($course); // Switchrole - sanity check in cost-order... $reset_user_allowed_editing = false; if ($switchrole > 0 && confirm_sesskey() && has_capability('moodle/role:switchroles', $context)) { // is this role assignable in this context? // inquiring minds want to know... $aroles = get_switchable_roles($context); if (is_array($aroles) && isset($aroles[$switchrole])) { role_switch($switchrole, $context); // Double check that this role is allowed here require_login($course); } // reset course page state - this prevents some weird problems ;-) $USER->activitycopy = false; $USER->activitycopycourse = NULL; unset($USER->activitycopyname); unset($SESSION->modform); $USER->editing = 0; $reset_user_allowed_editing = true; } //If course is hosted on an external server, redirect to corresponding //url with appropriate authentication attached as parameter
/** * This function loads the course settings that are available for the user * * @param bool $forceopen If set to true the course node will be forced open * @return navigation_node|false */ protected function load_course_settings($forceopen = false) { global $CFG; $course = $this->page->course; $coursecontext = context_course::instance($course->id); // note: do not test if enrolled or viewing here because we need the enrol link in Course administration section $coursenode = $this->add(get_string('courseadministration'), null, self::TYPE_COURSE, null, 'courseadmin'); if ($forceopen) { $coursenode->force_open(); } if ($this->page->user_allowed_editing()) { // Add the turn on/off settings if ($this->page->url->compare(new moodle_url('/course/view.php'), URL_MATCH_BASE)) { // We are on the course page, retain the current page params e.g. section. $baseurl = clone $this->page->url; $baseurl->param('sesskey', sesskey()); } else { // Edit on the main course page. $baseurl = new moodle_url('/course/view.php', array('id' => $course->id, 'return' => $this->page->url->out_as_local_url(false), 'sesskey' => sesskey())); } $editurl = clone $baseurl; if ($this->page->user_is_editing()) { $editurl->param('edit', 'off'); $editstring = get_string('turneditingoff'); } else { $editurl->param('edit', 'on'); $editstring = get_string('turneditingon'); } $coursenode->add($editstring, $editurl, self::TYPE_SETTING, null, 'turneditingonoff', new pix_icon('i/edit', '')); } if (has_capability('moodle/course:update', $coursecontext)) { // Add the course settings link $url = new moodle_url('/course/edit.php', array('id' => $course->id)); $coursenode->add(get_string('editsettings'), $url, self::TYPE_SETTING, null, 'editsettings', new pix_icon('i/settings', '')); // Add the course completion settings link if ($CFG->enablecompletion && $course->enablecompletion) { $url = new moodle_url('/course/completion.php', array('id' => $course->id)); $coursenode->add(get_string('coursecompletion', 'completion'), $url, self::TYPE_SETTING, null, null, new pix_icon('i/settings', '')); } } else { if (has_capability('moodle/course:tag', $coursecontext)) { $url = new moodle_url('/course/tags.php', array('id' => $course->id)); $coursenode->add(get_string('coursetags', 'tag'), $url, self::TYPE_SETTING, null, 'coursetags', new pix_icon('i/settings', '')); } } // add enrol nodes enrol_add_course_navigation($coursenode, $course); // Manage filters if (has_capability('moodle/filter:manage', $coursecontext) && count(filter_get_available_in_context($coursecontext)) > 0) { $url = new moodle_url('/filter/manage.php', array('contextid' => $coursecontext->id)); $coursenode->add(get_string('filters', 'admin'), $url, self::TYPE_SETTING, null, null, new pix_icon('i/filter', '')); } // View course reports. if (has_capability('moodle/site:viewreports', $coursecontext)) { // Basic capability for listing of reports. $reportnav = $coursenode->add(get_string('reports'), null, self::TYPE_CONTAINER, null, 'coursereports', new pix_icon('i/stats', '')); $coursereports = core_component::get_plugin_list('coursereport'); foreach ($coursereports as $report => $dir) { $libfile = $CFG->dirroot . '/course/report/' . $report . '/lib.php'; if (file_exists($libfile)) { require_once $libfile; $reportfunction = $report . '_report_extend_navigation'; if (function_exists($report . '_report_extend_navigation')) { $reportfunction($reportnav, $course, $coursecontext); } } } $reports = get_plugin_list_with_function('report', 'extend_navigation_course', 'lib.php'); foreach ($reports as $reportfunction) { $reportfunction($reportnav, $course, $coursecontext); } } // Add view grade report is permitted $reportavailable = false; if (has_capability('moodle/grade:viewall', $coursecontext)) { $reportavailable = true; } else { if (!empty($course->showgrades)) { $reports = core_component::get_plugin_list('gradereport'); if (is_array($reports) && count($reports) > 0) { // Get all installed reports arsort($reports); // user is last, we want to test it first foreach ($reports as $plugin => $plugindir) { if (has_capability('gradereport/' . $plugin . ':view', $coursecontext)) { //stop when the first visible plugin is found $reportavailable = true; break; } } } } } if ($reportavailable) { $url = new moodle_url('/grade/report/index.php', array('id' => $course->id)); $gradenode = $coursenode->add(get_string('grades'), $url, self::TYPE_SETTING, null, 'grades', new pix_icon('i/grades', '')); } // Check if we can view the gradebook's setup page. if (has_capability('moodle/grade:manage', $coursecontext)) { $url = new moodle_url('/grade/edit/tree/index.php', array('id' => $course->id)); $coursenode->add(get_string('gradebooksetup', 'grades'), $url, self::TYPE_SETTING, null, 'gradebooksetup', new pix_icon('i/settings', '')); } // Add outcome if permitted if (!empty($CFG->enableoutcomes) && has_capability('moodle/course:update', $coursecontext)) { $url = new moodle_url('/grade/edit/outcome/course.php', array('id' => $course->id)); $coursenode->add(get_string('outcomes', 'grades'), $url, self::TYPE_SETTING, null, 'outcomes', new pix_icon('i/outcomes', '')); } //Add badges navigation if (!empty($CFG->enablebadges)) { require_once $CFG->libdir . '/badgeslib.php'; badges_add_course_navigation($coursenode, $course); } // Backup this course if (has_capability('moodle/backup:backupcourse', $coursecontext)) { $url = new moodle_url('/backup/backup.php', array('id' => $course->id)); $coursenode->add(get_string('backup'), $url, self::TYPE_SETTING, null, 'backup', new pix_icon('i/backup', '')); } // Restore to this course if (has_capability('moodle/restore:restorecourse', $coursecontext)) { $url = new moodle_url('/backup/restorefile.php', array('contextid' => $coursecontext->id)); $coursenode->add(get_string('restore'), $url, self::TYPE_SETTING, null, 'restore', new pix_icon('i/restore', '')); } // Import data from other courses if (has_capability('moodle/restore:restoretargetimport', $coursecontext)) { $url = new moodle_url('/backup/import.php', array('id' => $course->id)); $coursenode->add(get_string('import'), $url, self::TYPE_SETTING, null, 'import', new pix_icon('i/import', '')); } // Publish course on a hub if (has_capability('moodle/course:publish', $coursecontext)) { $url = new moodle_url('/course/publish/index.php', array('id' => $course->id)); $coursenode->add(get_string('publish'), $url, self::TYPE_SETTING, null, 'publish', new pix_icon('i/publish', '')); } // Reset this course if (has_capability('moodle/course:reset', $coursecontext)) { $url = new moodle_url('/course/reset.php', array('id' => $course->id)); $coursenode->add(get_string('reset'), $url, self::TYPE_SETTING, null, 'reset', new pix_icon('i/return', '')); } // Questions require_once $CFG->libdir . '/questionlib.php'; question_extend_settings_navigation($coursenode, $coursecontext)->trim_if_empty(); if (has_capability('moodle/course:update', $coursecontext)) { // Repository Instances if (!$this->cache->cached('contexthasrepos' . $coursecontext->id)) { require_once $CFG->dirroot . '/repository/lib.php'; $editabletypes = repository::get_editable_types($coursecontext); $haseditabletypes = !empty($editabletypes); unset($editabletypes); $this->cache->set('contexthasrepos' . $coursecontext->id, $haseditabletypes); } else { $haseditabletypes = $this->cache->{'contexthasrepos' . $coursecontext->id}; } if ($haseditabletypes) { $url = new moodle_url('/repository/manage_instances.php', array('contextid' => $coursecontext->id)); $coursenode->add(get_string('repositories'), $url, self::TYPE_SETTING, null, null, new pix_icon('i/repository', '')); } } // Manage files if ($course->legacyfiles == 2 and has_capability('moodle/course:managefiles', $coursecontext)) { // hidden in new courses and courses where legacy files were turned off $url = new moodle_url('/files/index.php', array('contextid' => $coursecontext->id)); $coursenode->add(get_string('courselegacyfiles'), $url, self::TYPE_SETTING, null, 'coursefiles', new pix_icon('i/folder', '')); } // Switch roles $roles = array(); $assumedrole = $this->in_alternative_role(); if ($assumedrole !== false) { $roles[0] = get_string('switchrolereturn'); } if (has_capability('moodle/role:switchroles', $coursecontext)) { $availableroles = get_switchable_roles($coursecontext); if (is_array($availableroles)) { foreach ($availableroles as $key => $role) { if ($assumedrole == (int) $key) { continue; } $roles[$key] = $role; } } } if (is_array($roles) && count($roles) > 0) { $switchroles = $this->add(get_string('switchroleto'), null, self::TYPE_CONTAINER, null, 'switchroleto'); if (count($roles) == 1 && array_key_exists(0, $roles) || $assumedrole !== false) { $switchroles->force_open(); } foreach ($roles as $key => $name) { $url = new moodle_url('/course/switchrole.php', array('id' => $course->id, 'sesskey' => sesskey(), 'switchrole' => $key, 'returnurl' => $this->page->url->out_as_local_url(false))); $switchroles->add($name, $url, self::TYPE_SETTING, null, $key, new pix_icon('i/switchrole', '')); } } // Let plugins hook into course navigation. $pluginsfunction = get_plugins_with_function('extend_navigation_course', 'lib.php'); foreach ($pluginsfunction as $plugintype => $plugins) { // Ignore the report plugin as it was already loaded above. if ($plugintype == 'report') { continue; } foreach ($plugins as $pluginfunction) { $pluginfunction($coursenode, $course, $coursecontext); } } // Return we are done return $coursenode; }
function test_get_switchable_roles() { global $USER; $tablenames = array('role', 'role_capabilities', 'role_assignments', 'role_allow_switch', 'capabilities', 'context', 'role_names'); $this->create_test_tables($tablenames, 'lib'); $this->switch_to_test_db(); $this->switch_to_test_cfg(); // Ensure SYSCONTEXTID is set. get_context_instance(CONTEXT_SYSTEM); $contexts = $this->load_test_data('context', array('contextlevel', 'instanceid', 'path', 'depth'), array('sys' => array(CONTEXT_SYSTEM, 0, '/' . SYSCONTEXTID, 1), 'cat' => array(CONTEXT_COURSECAT, 66, '/' . SYSCONTEXTID . '/' . (SYSCONTEXTID + 1), 2), 'cou' => array(CONTEXT_COURSE, 666, '/' . SYSCONTEXTID . '/' . (SYSCONTEXTID + 1) . '/' . (SYSCONTEXTID + 2), 3), 'fp' => array(CONTEXT_COURSE, SITEID, '/' . SYSCONTEXTID . '/' . SITEID, 2))); $this->testdb->set_field('context', 'id', SYSCONTEXTID, array('id' => $contexts['sys']->id)); $this->testdb->set_field('context', 'id', SYSCONTEXTID + 1, array('id' => $contexts['cat']->id)); $this->testdb->set_field('context', 'id', SYSCONTEXTID + 2, array('id' => $contexts['cou']->id)); $syscontext = $contexts['sys']; $syscontext->id = SYSCONTEXTID; $context = $contexts['cou']; $context->id = SYSCONTEXTID + 2; $roles = $this->load_test_data('role', array('name', 'shortname', 'description', 'sortorder'), array('r1' => array('r1', 'r1', 'not null', 2), 'r2' => array('r2', 'r2', 'not null', 3), 'funny' => array('funny', 'funny', 'not null', 4))); $r1id = $roles['r1']->id; $r2id = $roles['r2']->id; $funnyid = $roles['funny']->id; // strange role // Note that get_switchable_roles requires at least one capability for // each role. I am not really clear why it was implemented that way // but this makes the test work. $roles = $this->load_test_data('role_capabilities', array('roleid', 'capability'), array(array($r1id, 'moodle/say:hello'), array($r2id, 'moodle/say:hello'), array($funnyid, 'moodle/say:hello'))); $this->load_test_data('role_assignments', array('userid', 'contextid', 'roleid'), array(array(2, SYSCONTEXTID + 1, $r1id), array(3, SYSCONTEXTID + 2, $r2id))); $this->load_test_data('role_allow_switch', array('roleid', 'allowswitch'), array(array($r1id, $r2id), array($r2id, $r1id), array($r2id, $r2id), array($r2id, $funnyid))); // r1 should be able to switch to r2, but this user only has r1 in $context, not $syscontext. $this->switch_global_user_id(2); accesslib_clear_all_caches_for_unit_testing(); $this->assert(new ArraysHaveSameValuesExpectation(array()), array_keys(get_switchable_roles($syscontext))); $this->assert(new ArraysHaveSameValuesExpectation(array($r2id)), array_keys(get_switchable_roles($context))); $this->revert_global_user_id(); // The table says r2 should be able to switch to all of r1, r2 and funny; // this used to be restricted further beyond the switch table (for example // to prevent you switching to roles with doanything) but is not any more // (for example because doanything does not exist). $this->switch_global_user_id(3); accesslib_clear_all_caches_for_unit_testing(); $this->assert(new ArraysHaveSameValuesExpectation(array()), array_keys(get_switchable_roles($syscontext))); $this->assert(new ArraysHaveSameValuesExpectation(array($r2id, $r1id, $funnyid)), array_keys(get_switchable_roles($context))); }
/** * Test getting of all switchable roles. */ public function test_get_switchable_roles() { global $DB; $this->resetAfterTest(); $course = $this->getDataGenerator()->create_course(); $coursecontext = context_course::instance($course->id); $teacherrole = $DB->get_record('role', array('shortname' => 'editingteacher'), '*', MUST_EXIST); $teacher = $this->getDataGenerator()->create_user(); role_assign($teacherrole->id, $teacher->id, $coursecontext); $teacherename = (object) array('roleid' => $teacherrole->id, 'name' => 'Učitel', 'contextid' => $coursecontext->id); $DB->insert_record('role_names', $teacherename); $contexts = $DB->get_records('context'); $users = $DB->get_records('user'); $allroles = $DB->get_records('role'); // Evaluate all results for all users in all contexts. foreach ($users as $user) { $this->setUser($user); foreach ($contexts as $contextid => $unused) { $context = context_helper::instance_by_id($contextid); $roles = get_switchable_roles($context); foreach ($allroles as $roleid => $role) { if (is_siteadmin()) { $this->assertTrue(isset($roles[$roleid])); } else { $parents = $context->get_parent_context_ids(true); $pcontexts = implode(',', $parents); $allowed = $DB->record_exists_sql("SELECT r.id\n FROM {role} r\n JOIN {role_allow_switch} ras ON ras.allowswitch = r.id\n JOIN {role_assignments} ra ON ra.roleid = ras.roleid\n WHERE ra.userid = :userid AND ra.contextid IN ({$pcontexts}) AND r.id = :roleid\n ", array('userid' => $user->id, 'roleid' => $roleid)); if (isset($roles[$roleid])) { $this->assertTrue($allowed); } else { $this->assertFalse($allowed); } } if (isset($roles[$roleid])) { $coursecontext = $context->get_course_context(false); $this->assertSame(role_get_name($role, $coursecontext), $roles[$roleid]); } } } } }
/** * Returns a little popup menu for switching roles * * @uses $CFG * @uses $USER * @param int $courseid The course to update by id as found in 'course' table * @return string */ function switchroles_form($courseid) { global $CFG, $USER; if (!($context = get_context_instance(CONTEXT_COURSE, $courseid))) { return ''; } if (!empty($USER->access['rsw'][$context->path])) { // Just a button to return to normal $options = array(); $options['id'] = $courseid; $options['sesskey'] = sesskey(); $options['switchrole'] = 0; return print_single_button($CFG->wwwroot . '/course/view.php', $options, get_string('switchrolereturn'), 'post', '_self', true); } if (has_capability('moodle/role:switchroles', $context)) { if (!($roles = get_switchable_roles($context))) { return ''; // Nothing to show! } // unset default user role - it would not work unset($roles[$CFG->guestroleid]); return popup_form($CFG->wwwroot . '/course/view.php?id=' . $courseid . '&sesskey=' . sesskey() . '&switchrole=', $roles, 'switchrole', '', get_string('switchroleto'), 'switchrole', get_string('switchroleto'), true); } return ''; }
function test_get_switchable_roles() { global $USER; $tablenames = array('role', 'role_capabilities', 'role_assignments', 'role_allow_switch', 'capabilities', 'context', 'role_names'); $this->create_test_tables($tablenames, 'lib'); $this->switch_to_test_db(); // Ensure SYSCONTEXTID is set. get_context_instance(CONTEXT_SYSTEM); $contexts = $this->load_test_data('context', array('contextlevel', 'instanceid', 'path', 'depth'), array('sys' => array(CONTEXT_SYSTEM, 0, '/' . SYSCONTEXTID, 1), 'cat' => array(CONTEXT_COURSECAT, 66, '/' . SYSCONTEXTID . '/' . (SYSCONTEXTID + 1), 2), 'cou' => array(CONTEXT_COURSE, 666, '/' . SYSCONTEXTID . '/' . (SYSCONTEXTID + 1) . '/' . (SYSCONTEXTID + 2), 3), 'fp' => array(CONTEXT_COURSE, SITEID, '/' . SYSCONTEXTID . '/' . SITEID, 2))); $this->testdb->set_field('context', 'id', SYSCONTEXTID, array('id' => $contexts['sys']->id)); $this->testdb->set_field('context', 'id', SYSCONTEXTID + 1, array('id' => $contexts['cat']->id)); $this->testdb->set_field('context', 'id', SYSCONTEXTID + 2, array('id' => $contexts['cou']->id)); $syscontext = $contexts['sys']; $syscontext->id = SYSCONTEXTID; $context = $contexts['cou']; $context->id = SYSCONTEXTID + 2; $this->load_test_data('capabilities', array('name'), array(array('moodle/site:doanything'), array('moodle/course:view'))); $roles = $this->load_test_data('role', array('name', 'shortname', 'description', 'sortorder'), array('admin' => array('admin', 'admin', 'not null', 1), 'r1' => array('r1', 'r1', 'not null', 2), 'r2' => array('r2', 'r2', 'not null', 3), 'funny' => array('funny', 'funny', 'not null', 4))); $adminid = $roles['admin']->id; $r1id = $roles['r1']->id; $r2id = $roles['r2']->id; $funnyid = $roles['funny']->id; // strange role to test that roles with 'moodle/site:doanything' and 'moodle/course:view' are not returned. $this->load_test_data('role_capabilities', array('roleid', 'capability', 'contextid', 'permission'), array(array($adminid, 'moodle/site:doanything', SYSCONTEXTID, CAP_ALLOW), array($r1id, 'moodle/course:view', SYSCONTEXTID + 1, CAP_ALLOW), array($r2id, 'moodle/course:view', SYSCONTEXTID, CAP_ALLOW), array($funnyid, 'moodle/site:doanything', SYSCONTEXTID, CAP_ALLOW), array($funnyid, 'moodle/course:view', SYSCONTEXTID, CAP_ALLOW))); $this->load_test_data('role_assignments', array('userid', 'contextid', 'roleid'), array(array(1, SYSCONTEXTID, $adminid), array(2, SYSCONTEXTID + 1, $r1id), array(3, SYSCONTEXTID + 2, $r2id))); $this->load_test_data('role_allow_switch', array('roleid', 'allowswitch'), array(array($r1id, $r2id), array($r2id, $r1id), array($r2id, $r2id), array($r2id, $funnyid))); // Admin should be able to switch to any role with 'moodle/course:view' in any context. $this->switch_global_user_id(1); accesslib_clear_all_caches_for_unit_testing(); $this->assert(new ArraysHaveSameValuesExpectation(array($r2id)), array_keys(get_switchable_roles($syscontext))); $this->assert(new ArraysHaveSameValuesExpectation(array($r2id)), array_keys(get_switchable_roles($context))); $this->revert_global_user_id(); // r1 should be able to switch to r2, but this user only has r1 in $context, not $syscontext. $this->switch_global_user_id(2); accesslib_clear_all_caches_for_unit_testing(); $this->assert(new ArraysHaveSameValuesExpectation(array()), array_keys(get_switchable_roles($syscontext))); $this->assert(new ArraysHaveSameValuesExpectation(array($r2id)), array_keys(get_switchable_roles($context))); $this->revert_global_user_id(); // The table says r2 should be able to switch to all of r1, r2 and funny, however, only r2 passes the tests on which roles can be returnd.. $this->switch_global_user_id(3); accesslib_clear_all_caches_for_unit_testing(); $this->assert(new ArraysHaveSameValuesExpectation(array()), array_keys(get_switchable_roles($syscontext))); $this->assert(new ArraysHaveSameValuesExpectation(array($r2id)), array_keys(get_switchable_roles($context))); }
/** * Returns a little popup menu for switching roles * * @global object * @global object * @uses CONTEXT_COURSE * @param int $courseid The course to update by id as found in 'course' table * @return string */ function switchroles_form($courseid) { global $CFG, $USER, $OUTPUT; if (!($context = get_context_instance(CONTEXT_COURSE, $courseid))) { return ''; } if (!empty($USER->access['rsw'][$context->path])) { // Just a button to return to normal $options = array(); $options['id'] = $courseid; $options['sesskey'] = sesskey(); $options['switchrole'] = 0; return $OUTPUT->button(html_form::make_button($CFG->wwwroot . '/course/view.php', $options, get_string('switchrolereturn'))); } if (has_capability('moodle/role:switchroles', $context)) { if (!($roles = get_switchable_roles($context))) { return ''; // Nothing to show! } // unset default user role - it would not work unset($roles[$CFG->guestroleid]); $popupurl = $CFG->wwwroot . '/course/view.php?id=' . $courseid . '&sesskey=' . sesskey(); $select = html_select::make_popup_form($popupurl, 'switchrole', $roles, 'switchrole', ''); $select->nothinglabel = get_string('switchroleto'); $select->set_help_icon('switchrole', get_string('switchroleto')); return $OUTPUT->select($select); } return ''; }
/** * Get a list of essential user navigation items. * * @param stdclass $user user object. * @param moodle_page $page page object. * @param array $options associative array. * options are: * - avatarsize=35 (size of avatar image) * @return stdClass $returnobj navigation information object, where: * * $returnobj->navitems array array of links where each link is a * stdClass with fields url, title, and * pix * $returnobj->metadata array array of useful user metadata to be * used when constructing navigation; * fields include: * * ROLE FIELDS * asotherrole bool whether viewing as another role * rolename string name of the role * * USER FIELDS * These fields are for the currently-logged in user, or for * the user that the real user is currently logged in as. * * userid int the id of the user in question * userfullname string the user's full name * userprofileurl moodle_url the url of the user's profile * useravatar string a HTML fragment - the rendered * user_picture for this user * userloginfail string an error string denoting the number * of login failures since last login * * "REAL USER" FIELDS * These fields are for when asotheruser is true, and * correspond to the underlying "real user". * * asotheruser bool whether viewing as another user * realuserid int the id of the user in question * realuserfullname string the user's full name * realuserprofileurl moodle_url the url of the user's profile * realuseravatar string a HTML fragment - the rendered * user_picture for this user * * MNET PROVIDER FIELDS * asmnetuser bool whether viewing as a user from an * MNet provider * mnetidprovidername string name of the MNet provider * mnetidproviderwwwroot string URL of the MNet provider */ function user_get_user_navigation_info($user, $page, $options = array()) { global $OUTPUT, $DB, $SESSION, $CFG; $returnobject = new stdClass(); $returnobject->navitems = array(); $returnobject->metadata = array(); $course = $page->course; // Query the environment. $context = context_course::instance($course->id); // Get basic user metadata. $returnobject->metadata['userid'] = $user->id; $returnobject->metadata['userfullname'] = fullname($user, true); $returnobject->metadata['userprofileurl'] = new moodle_url('/user/profile.php', array( 'id' => $user->id )); $avataroptions = array('link' => false, 'visibletoscreenreaders' => false); if (!empty($options['avatarsize'])) { $avataroptions['size'] = $options['avatarsize']; } $returnobject->metadata['useravatar'] = $OUTPUT->user_picture ( $user, $avataroptions ); // Build a list of items for a regular user. // Query MNet status. if ($returnobject->metadata['asmnetuser'] = is_mnet_remote_user($user)) { $mnetidprovider = $DB->get_record('mnet_host', array('id' => $user->mnethostid)); $returnobject->metadata['mnetidprovidername'] = $mnetidprovider->name; $returnobject->metadata['mnetidproviderwwwroot'] = $mnetidprovider->wwwroot; } // Did the user just log in? if (isset($SESSION->justloggedin)) { // Don't unset this flag as login_info still needs it. if (!empty($CFG->displayloginfailures)) { // Don't reset the count either, as login_info() still needs it too. if ($count = user_count_login_failures($user, false)) { // Get login failures string. $a = new stdClass(); $a->attempts = html_writer::tag('span', $count, array('class' => 'value')); $returnobject->metadata['userloginfail'] = get_string('failedloginattempts', '', $a); } } } // Links: Dashboard. $myhome = new stdClass(); $myhome->itemtype = 'link'; $myhome->url = new moodle_url('/my/'); $myhome->title = get_string('mymoodle', 'admin'); $myhome->titleidentifier = 'mymoodle,admin'; $myhome->pix = "i/course"; $returnobject->navitems[] = $myhome; // Links: My Profile. $myprofile = new stdClass(); $myprofile->itemtype = 'link'; $myprofile->url = new moodle_url('/user/profile.php', array('id' => $user->id)); $myprofile->title = get_string('profile'); $myprofile->titleidentifier = 'profile,moodle'; $myprofile->pix = "i/user"; $returnobject->navitems[] = $myprofile; $returnobject->metadata['asotherrole'] = false; // Before we add the last items (usually a logout + switch role link), add any // custom-defined items. $customitems = user_convert_text_to_menu_items($CFG->customusermenuitems, $page); foreach ($customitems as $item) { $returnobject->navitems[] = $item; } if ($returnobject->metadata['asotheruser'] = \core\session\manager::is_loggedinas()) { $realuser = \core\session\manager::get_realuser(); // Save values for the real user, as $user will be full of data for the // user the user is disguised as. $returnobject->metadata['realuserid'] = $realuser->id; $returnobject->metadata['realuserfullname'] = fullname($realuser, true); $returnobject->metadata['realuserprofileurl'] = new moodle_url('/user/profile.php', array( 'id' => $realuser->id )); $returnobject->metadata['realuseravatar'] = $OUTPUT->user_picture($realuser, $avataroptions); // Build a user-revert link. $userrevert = new stdClass(); $userrevert->itemtype = 'link'; $userrevert->url = new moodle_url('/course/loginas.php', array( 'id' => $course->id, 'sesskey' => sesskey() )); $userrevert->pix = "a/logout"; $userrevert->title = get_string('logout'); $userrevert->titleidentifier = 'logout,moodle'; $returnobject->navitems[] = $userrevert; } else { // Build a logout link. $logout = new stdClass(); $logout->itemtype = 'link'; $logout->url = new moodle_url('/login/logout.php', array('sesskey' => sesskey())); $logout->pix = "a/logout"; $logout->title = get_string('logout'); $logout->titleidentifier = 'logout,moodle'; $returnobject->navitems[] = $logout; } if (is_role_switched($course->id)) { if ($role = $DB->get_record('role', array('id' => $user->access['rsw'][$context->path]))) { // Build role-return link instead of logout link. $rolereturn = new stdClass(); $rolereturn->itemtype = 'link'; $rolereturn->url = new moodle_url('/course/switchrole.php', array( 'id' => $course->id, 'sesskey' => sesskey(), 'switchrole' => 0, 'returnurl' => $page->url->out_as_local_url(false) )); $rolereturn->pix = "a/logout"; $rolereturn->title = get_string('switchrolereturn'); $rolereturn->titleidentifier = 'switchrolereturn,moodle'; $returnobject->navitems[] = $rolereturn; $returnobject->metadata['asotherrole'] = true; $returnobject->metadata['rolename'] = role_get_name($role, $context); } } else { // Build switch role link. $roles = get_switchable_roles($context); if (is_array($roles) && (count($roles) > 0)) { $switchrole = new stdClass(); $switchrole->itemtype = 'link'; $switchrole->url = new moodle_url('/course/switchrole.php', array( 'id' => $course->id, 'switchrole' => -1, 'returnurl' => $page->url->out_as_local_url(false) )); $switchrole->pix = "i/switchrole"; $switchrole->title = get_string('switchroleto'); $switchrole->titleidentifier = 'switchroleto,moodle'; $returnobject->navitems[] = $switchrole; } } return $returnobject; }
} } else { if ($switchrole < 0) { $PAGE->set_title(get_string('switchroleto')); $PAGE->set_heading($course->fullname); $PAGE->set_pagelayout('incourse'); echo $OUTPUT->header(); echo $OUTPUT->heading(get_string('switchroleto')); // Overall criteria aggregation. $roles = array(); $assumedrole = -1; if (is_role_switched($course->id)) { $roles[0] = get_string('switchrolereturn'); $assumedrole = $USER->access['rsw'][$context->path]; } $availableroles = get_switchable_roles($context); if (is_array($availableroles)) { foreach ($availableroles as $key => $role) { if ($assumedrole == (int) $key) { continue; } $roles[$key] = $role; } } echo $OUTPUT->box(markdown_to_html(get_string('switchroleto_help'))); foreach ($roles as $key => $role) { $url = new moodle_url('/course/switchrole.php', array('id' => $id, 'switchrole' => $key, 'returnurl' => $returnurl)); echo $OUTPUT->container($OUTPUT->single_button($url, $role), 'm-x-3 m-b-1'); } $url = new moodle_url($returnurl); echo $OUTPUT->container($OUTPUT->action_link($url, get_string('cancel')), 'm-x-3 m-b-1');