See Release Notes
Long Term Support Release
Differences Between: [Versions 39 and 401] [Versions 401 and 402] [Versions 401 and 403]
1 <?php 2 // This file is part of Moodle - http://moodle.org/ 3 // 4 // Moodle is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // Moodle is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU General Public License for more details. 13 // 14 // You should have received a copy of the GNU General Public License 15 // along with Moodle. If not, see <http://www.gnu.org/licenses/>. 16 17 /** 18 * Contains class core_user\output\user_roles_editable 19 * 20 * @package core_user 21 * @copyright 2017 Damyon Wiese 22 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 */ 24 25 namespace core_user\output; 26 27 use context_course; 28 use core_user; 29 use core_external; 30 use coding_exception; 31 32 defined('MOODLE_INTERNAL') || die(); 33 34 /** 35 * Class to display list of user roles. 36 * 37 * @package core_user 38 * @copyright 2017 Damyon Wiese 39 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 40 */ 41 class user_roles_editable extends \core\output\inplace_editable { 42 43 /** @var $context */ 44 private $context = null; 45 46 /** @var \stdClass[] $courseroles */ 47 private $courseroles; 48 49 /** @var \stdClass[] $profileroles */ 50 private $profileroles; 51 52 /** @var \stdClass[] $viewableroles */ 53 private $viewableroles; 54 55 /** @var \stdClass[] $assignableroles */ 56 private $assignableroles; 57 58 /** 59 * Constructor. 60 * 61 * @param \stdClass $course The current course 62 * @param \context $context The course context 63 * @param \stdClass $user The current user 64 * @param \stdClass[] $courseroles The list of course roles. 65 * @param \stdClass[] $assignableroles The list of assignable roles in this course. 66 * @param \stdClass[] $profileroles The list of roles that should be visible in a users profile. 67 * @param \stdClass[] $userroles The list of user roles. 68 */ 69 public function __construct($course, $context, $user, $courseroles, $assignableroles, $profileroles, $userroles, $viewableroles = null) { 70 if ($viewableroles === null) { 71 debugging('Constructor for user_roles_editable now needs the result of get_viewable_roles passed as viewableroles'); 72 } 73 74 // Check capabilities to get editable value. 75 $editable = has_capability('moodle/role:assign', $context); 76 77 // Invent an itemid. 78 $itemid = $course->id . ':' . $user->id; 79 80 $getrole = function($role) { 81 return $role->roleid; 82 }; 83 $ids = array_values(array_unique(array_map($getrole, $userroles))); 84 85 $value = json_encode($ids); 86 87 // Remember these for the display value. 88 $this->courseroles = $courseroles; 89 $this->profileroles = $profileroles; 90 $this->viewableroles = array_keys($viewableroles); 91 $this->assignableroles = array_keys($assignableroles); 92 $this->context = $context; 93 94 parent::__construct('core_user', 'user_roles', $itemid, $editable, $value, $value); 95 96 // Removed the roles that were assigned to the user at a different context. 97 $options = $assignableroles; 98 foreach ($userroles as $role) { 99 if (isset($assignableroles[$role->roleid])) { 100 if ($role->contextid != $context->id) { 101 unset($options[$role->roleid]); 102 } 103 } 104 } 105 $this->edithint = get_string('xroleassignments', 'role', fullname($user)); 106 $this->editlabel = get_string('xroleassignments', 'role', fullname($user)); 107 108 $attributes = ['multiple' => true]; 109 $this->set_type_autocomplete($options, $attributes); 110 } 111 112 /** 113 * Export this data so it can be used as the context for a mustache template. 114 * 115 * @param \renderer_base $output 116 * @return array 117 */ 118 public function export_for_template(\renderer_base $output) { 119 $listofroles = []; 120 $roleids = json_decode($this->value); 121 $viewableroleids = array_intersect($roleids, array_merge($this->viewableroles, $this->assignableroles)); 122 123 foreach ($viewableroleids as $id) { 124 // If this is a student, we only show a subset of the roles. 125 if ($this->editable || array_key_exists($id, $this->profileroles)) { 126 $listofroles[] = format_string($this->courseroles[$id]->localname, true, ['context' => $this->context]); 127 } 128 } 129 130 if (!empty($listofroles)) { 131 $this->displayvalue = implode(', ', $listofroles); 132 } else if (!empty($roleids) && empty($viewableroleids)) { 133 $this->displayvalue = get_string('novisibleroles', 'role'); 134 } else { 135 $this->displayvalue = get_string('noroles', 'role'); 136 } 137 return parent::export_for_template($output); 138 } 139 140 /** 141 * Updates the value in database and returns itself, called from inplace_editable callback 142 * 143 * @param int $itemid 144 * @param mixed $newvalue 145 * @return \self 146 */ 147 public static function update($itemid, $newvalue) { 148 global $DB, $CFG; 149 150 require_once($CFG->libdir . '/external/externallib.php'); 151 // Check caps. 152 // Do the thing. 153 // Return one of me. 154 // Validate the inputs. 155 list($courseid, $userid) = explode(':', $itemid, 2); 156 157 $courseid = clean_param($courseid, PARAM_INT); 158 $userid = clean_param($userid, PARAM_INT); 159 $roleids = json_decode($newvalue); 160 foreach ($roleids as $index => $roleid) { 161 $roleids[$index] = clean_param($roleid, PARAM_INT); 162 } 163 164 // Check user is enrolled in the course. 165 $context = context_course::instance($courseid); 166 core_external::validate_context($context); 167 168 // Check permissions. 169 require_capability('moodle/role:assign', $context); 170 171 if (!is_enrolled($context, $userid)) { 172 throw new coding_exception('User does not belong to the course'); 173 } 174 175 // Check that all the groups belong to the course. 176 $allroles = role_fix_names(get_all_roles($context), $context, ROLENAME_BOTH); 177 $assignableroles = get_assignable_roles($context, ROLENAME_BOTH, false); 178 $viewableroles = get_viewable_roles($context); 179 $userrolesbyid = get_user_roles($context, $userid, true, 'c.contextlevel DESC, r.sortorder ASC'); 180 $profileroles = get_profile_roles($context); 181 182 // Set an array where the index is the roleid. 183 $userroles = array(); 184 foreach ($userrolesbyid as $id => $role) { 185 $userroles[$role->roleid] = $role; 186 } 187 188 $rolestoprocess = []; 189 foreach ($roleids as $roleid) { 190 if (!isset($assignableroles[$roleid])) { 191 throw new coding_exception('Role cannot be assigned in this course.'); 192 } 193 $rolestoprocess[$roleid] = $roleid; 194 } 195 196 // Process adds. 197 foreach ($rolestoprocess as $roleid) { 198 if (!isset($userroles[$roleid])) { 199 // Add them. 200 $id = role_assign($roleid, $userid, $context); 201 // Keep this variable in sync. 202 $role = new \stdClass(); 203 $role->id = $id; 204 $role->roleid = $roleid; 205 $role->contextid = $context->id; 206 $userroles[$role->roleid] = $role; 207 } 208 } 209 210 // Process removals. 211 foreach ($assignableroles as $roleid => $rolename) { 212 if (isset($userroles[$roleid]) && !isset($rolestoprocess[$roleid])) { 213 // Do not remove the role if we are not in the same context. 214 if ($userroles[$roleid]->contextid != $context->id) { 215 continue; 216 } 217 $ras = $DB->get_records('role_assignments', ['contextid' => $context->id, 'userid' => $userid, 218 'roleid' => $roleid]); 219 $allremoved = true; 220 foreach ($ras as $ra) { 221 if ($ra->component) { 222 if (strpos($ra->component, 'enrol_') !== 0) { 223 continue; 224 } 225 if (!$plugin = enrol_get_plugin(substr($ra->component, 6))) { 226 continue; 227 } 228 if ($plugin->roles_protected()) { 229 $allremoved = false; 230 continue; 231 } 232 } 233 role_unassign($ra->roleid, $ra->userid, $ra->contextid, $ra->component, $ra->itemid); 234 } 235 if ($allremoved) { 236 unset($userroles[$roleid]); 237 } 238 } 239 } 240 241 $course = get_course($courseid); 242 $user = core_user::get_user($userid); 243 return new self($course, $context, $user, $allroles, $assignableroles, $profileroles, $userroles, $viewableroles); 244 } 245 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body