See Release Notes
Long Term Support Release
Differences Between: [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 * The mod_bigbluebuttonbn roles helper 18 * 19 * @package mod_bigbluebuttonbn 20 * @copyright 2021 onwards, Blindside Networks Inc 21 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 22 * @author Laurent David (laurent [at] call-learning [dt] fr) 23 */ 24 25 namespace mod_bigbluebuttonbn\local\helpers; 26 27 use cache; 28 use cache_store; 29 use context; 30 use context_course; 31 use mod_bigbluebuttonbn\instance; 32 use mod_bigbluebuttonbn\local\proxy\bigbluebutton_proxy; 33 use stdClass; 34 35 /** 36 * Utility class for all roles routines helper 37 * 38 * @package mod_bigbluebuttonbn 39 * @copyright 2021 onwards, Blindside Networks Inc 40 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 41 */ 42 class roles { 43 44 /** @var int The bigbluebutton viewer role */ 45 public const ROLE_VIEWER = 'viewer'; 46 47 /** @var string The bigbluebutton moderator role */ 48 public const ROLE_MODERATOR = 'moderator'; 49 50 /** 51 * Returns user roles in a context. 52 * 53 * @param context $context 54 * @param int $userid 55 * 56 * @return array $userroles 57 */ 58 public static function get_user_roles(context $context, int $userid) { 59 global $DB; 60 $userroles = get_user_roles($context, $userid); 61 if ($userroles) { 62 $where = ''; 63 foreach ($userroles as $userrole) { 64 $where .= (empty($where) ? ' WHERE' : ' OR') . ' id=' . $userrole->roleid; 65 } 66 $userroles = $DB->get_records_sql('SELECT * FROM {role}' . $where); 67 } 68 return $userroles; 69 } 70 71 /** 72 * Returns guest role wrapped in an array. 73 * 74 * @return array 75 */ 76 protected static function get_guest_role() { 77 $guestrole = get_guest_role(); 78 return [$guestrole->id => $guestrole]; 79 } 80 81 /** 82 * Returns an array containing all the users in a context wrapped for html select element. 83 * 84 * @param context_course $context 85 * @param null $bbactivity 86 * @return array $users 87 */ 88 public static function get_users_array(context_course $context, $bbactivity = null) { 89 // CONTRIB-7972, check the group of current user and course group mode. 90 $groups = null; 91 $users = (array) get_enrolled_users($context, '', 0, 'u.*', null, 0, 0, true); 92 $course = get_course($context->instanceid); 93 $groupmode = groups_get_course_groupmode($course); 94 if ($bbactivity) { 95 list($bbcourse, $cm) = get_course_and_cm_from_instance($bbactivity->id, 'bigbluebuttonbn'); 96 $groupmode = groups_get_activity_groupmode($cm); 97 98 } 99 if ($groupmode == SEPARATEGROUPS && !has_capability('moodle/site:accessallgroups', $context)) { 100 global $USER; 101 $groups = groups_get_all_groups($course->id, $USER->id); 102 $users = []; 103 foreach ($groups as $g) { 104 $users += (array) get_enrolled_users($context, '', $g->id, 'u.*', null, 0, 0, true); 105 } 106 } 107 return array_map( 108 function($u) { 109 return ['id' => $u->id, 'name' => fullname($u)]; 110 }, 111 $users); 112 } 113 114 /** 115 * Can do some administration in this course, likely manage recordings 116 * 117 * @param int $courseid 118 * @param string $capability 119 */ 120 public static function has_capability_in_course(int $courseid, string $capability) { 121 global $DB; 122 if (empty($courseid) || $DB->record_exists('course', ['id' => $courseid])) { 123 return has_capability('moodle/site:config', \context_system::instance()); 124 } 125 126 $coursecontext = context_course::instance($courseid); 127 return has_capability($capability, $coursecontext); 128 } 129 130 /** 131 * Returns an array containing all the roles in a context. 132 * 133 * @param context|null $context $context 134 * @param bool|null $onlyviewableroles 135 * 136 * @return array $roles 137 */ 138 public static function get_roles(?context $context = null, ?bool $onlyviewableroles = true) { 139 global $CFG; 140 141 if ($onlyviewableroles == true && $CFG->branch >= 35) { 142 $roles = (array) get_viewable_roles($context); 143 foreach ($roles as $key => $value) { 144 $roles[$key] = $value; 145 } 146 } else { 147 $roles = (array) role_get_names($context); 148 foreach ($roles as $key => $value) { 149 $roles[$key] = $value->localname; 150 } 151 } 152 153 return $roles; 154 } 155 156 /** 157 * Returns an array containing all the roles in a context wrapped for html select element. 158 * 159 * @param context|null $context $context 160 * @param bool $onlyviewableroles 161 * 162 * @return array $users 163 */ 164 protected static function get_roles_select(context $context = null, bool $onlyviewableroles = true) { 165 global $CFG; 166 167 if ($onlyviewableroles == true && $CFG->branch >= 35) { 168 $roles = (array) get_viewable_roles($context); 169 foreach ($roles as $key => $value) { 170 $roles[$key] = ['id' => $key, 'name' => $value]; 171 } 172 } else { 173 $roles = (array) role_get_names($context); 174 foreach ($roles as $key => $value) { 175 $roles[$key] = ['id' => $value->id, 'name' => $value->localname]; 176 } 177 } 178 179 return $roles; 180 } 181 182 /** 183 * Returns role that corresponds to an id. 184 * 185 * @param string|integer $id 186 * 187 * @return stdClass|null $role 188 */ 189 protected static function get_role($id): ?stdClass { 190 $roles = (array) role_get_names(); 191 if (is_numeric($id) && isset($roles[$id])) { 192 return (object) $roles[$id]; 193 } 194 foreach ($roles as $role) { 195 if ($role->shortname == $id) { 196 return $role; 197 } 198 } 199 return null; 200 } 201 202 /** 203 * Returns an array to populate a list of participants used in mod_form.js. 204 * 205 * @param context $context 206 * @param null|stdClass $bbactivity 207 * @return array $data 208 */ 209 public static function get_participant_data(context $context, ?stdClass $bbactivity = null) { 210 $data = [ 211 'all' => [ 212 'name' => get_string('mod_form_field_participant_list_type_all', 'bigbluebuttonbn'), 213 'children' => [] 214 ], 215 ]; 216 $data['role'] = [ 217 'name' => get_string('mod_form_field_participant_list_type_role', 'bigbluebuttonbn'), 218 'children' => self::get_roles_select($context, true) 219 ]; 220 $data['user'] = [ 221 'name' => get_string('mod_form_field_participant_list_type_user', 'bigbluebuttonbn'), 222 'children' => self::get_users_array($context, $bbactivity), 223 ]; 224 return $data; 225 } 226 227 /** 228 * Returns an array to populate a list of participants used in mod_form.php. 229 * 230 * @param stdClass|null $bigbluebuttonbn 231 * @param context $context 232 * 233 * @return array 234 */ 235 public static function get_participant_list(?stdClass $bigbluebuttonbn, context $context): array { 236 global $USER; 237 if ($bigbluebuttonbn == null) { 238 return self::get_participant_rules_encoded( 239 self::get_participant_list_default($context, $USER->id) 240 ); 241 } 242 if (empty($bigbluebuttonbn->participants)) { 243 $bigbluebuttonbn->participants = "[]"; 244 } 245 $rules = json_decode($bigbluebuttonbn->participants, true); 246 if (empty($rules)) { 247 $rules = self::get_participant_list_default($context, 248 bigbluebutton_proxy::get_instance_ownerid($bigbluebuttonbn)); 249 } 250 return self::get_participant_rules_encoded($rules); 251 } 252 253 /** 254 * Returns an array to populate a list of participants used in mod_form.php with default values. 255 * 256 * @param context $context 257 * @param int|null $ownerid 258 * 259 * @return array 260 */ 261 protected static function get_participant_list_default(context $context, ?int $ownerid = null) { 262 $participantlist = []; 263 $participantlist[] = [ 264 'selectiontype' => 'all', 265 'selectionid' => 'all', 266 'role' => self::ROLE_VIEWER, 267 ]; 268 $defaultrules = explode(',', \mod_bigbluebuttonbn\local\config::get('participant_moderator_default')); 269 foreach ($defaultrules as $defaultrule) { 270 if ($defaultrule == '0') { 271 if (!empty($ownerid) && is_enrolled($context, $ownerid)) { 272 $participantlist[] = [ 273 'selectiontype' => 'user', 274 'selectionid' => (string) $ownerid, 275 'role' => self::ROLE_MODERATOR]; 276 } 277 continue; 278 } 279 $participantlist[] = [ 280 'selectiontype' => 'role', 281 'selectionid' => $defaultrule, 282 'role' => self::ROLE_MODERATOR]; 283 } 284 return $participantlist; 285 } 286 287 /** 288 * Returns an array to populate a list of participants used in mod_form.php with bigbluebuttonbn values. 289 * 290 * @param array $rules 291 * 292 * @return array 293 */ 294 protected static function get_participant_rules_encoded(array $rules): array { 295 foreach ($rules as $key => $rule) { 296 if ($rule['selectiontype'] !== 'role' || is_numeric($rule['selectionid'])) { 297 continue; 298 } 299 $role = self::get_role($rule['selectionid']); 300 if ($role == null) { 301 unset($rules[$key]); 302 continue; 303 } 304 $rule['selectionid'] = $role->id; 305 $rules[$key] = $rule; 306 } 307 return $rules; 308 } 309 310 /** 311 * Returns an array to populate a list of participant_selection used in mod_form.php. 312 * 313 * @return array 314 */ 315 public static function get_participant_selection_data(): array { 316 return [ 317 'type_options' => [ 318 'all' => get_string('mod_form_field_participant_list_type_all', 'bigbluebuttonbn'), 319 'role' => get_string('mod_form_field_participant_list_type_role', 'bigbluebuttonbn'), 320 'user' => get_string('mod_form_field_participant_list_type_user', 'bigbluebuttonbn'), 321 ], 322 'type_selected' => 'all', 323 'options' => ['all' => '---------------'], 324 'selected' => 'all', 325 ]; 326 } 327 328 /** 329 * Evaluate if a user in a context is moderator based on roles and participation rules. 330 * 331 * @param context $context 332 * @param array $participantlist 333 * @param int $userid 334 * 335 * @return bool 336 */ 337 public static function is_moderator(context $context, array $participantlist, ?int $userid = null): bool { 338 global $USER; 339 // If an admin, then also a moderator. 340 if (has_capability('moodle/site:config', $context)) { 341 return true; 342 } 343 if (!is_array($participantlist)) { 344 return false; 345 } 346 if (empty($userid)) { 347 $userid = $USER->id; 348 } 349 $userroles = self::get_guest_role(); 350 if (!isguestuser()) { 351 $userroles = self::get_user_roles($context, $userid); 352 } 353 return self::is_moderator_validator($participantlist, $userid, $userroles); 354 } 355 356 /** 357 * Iterates participant list rules to evaluate if a user is moderator. 358 * 359 * @param array $participantlist 360 * @param int $userid 361 * @param array $userroles 362 * 363 * @return bool 364 */ 365 protected static function is_moderator_validator(array $participantlist, int $userid, array $userroles): bool { 366 // Iterate participant rules. 367 foreach ($participantlist as $participant) { 368 if (self::is_moderator_validate_rule($participant, $userid, $userroles)) { 369 return true; 370 } 371 } 372 return false; 373 } 374 375 /** 376 * Evaluate if a user is moderator based on roles and a particular participation rule. 377 * 378 * @param array $participant 379 * @param int $userid 380 * @param array $userroles 381 * 382 * @return bool 383 */ 384 protected static function is_moderator_validate_rule(array $participant, int $userid, array $userroles): bool { 385 if ($participant['role'] == self::ROLE_VIEWER) { 386 return false; 387 } 388 // Validation for the 'all' rule. 389 if ($participant['selectiontype'] == 'all') { 390 return true; 391 } 392 // Validation for a 'user' rule. 393 if ($participant['selectiontype'] == 'user') { 394 if ($participant['selectionid'] == $userid) { 395 return true; 396 } 397 return false; 398 } 399 // Validation for a 'role' rule. 400 $role = self::get_role($participant['selectionid']); 401 if ($role != null && array_key_exists($role->id, $userroles)) { 402 return true; 403 } 404 return false; 405 } 406 407 /** 408 * Updates the meeting info cached object when a participant has joined. 409 * 410 * @param string $meetingid 411 * @param bool $ismoderator 412 * 413 * @return void 414 */ 415 public static function participant_joined(string $meetingid, bool $ismoderator): void { 416 $cache = cache::make_from_params(cache_store::MODE_APPLICATION, 'mod_bigbluebuttonbn', 'meetings_cache'); 417 $result = $cache->get($meetingid); 418 $meetinginfo = json_decode($result['meeting_info']); 419 $meetinginfo->participantCount += 1; 420 if ($ismoderator) { 421 $meetinginfo->moderatorCount += 1; 422 } 423 $cache->set($meetingid, ['creation_time' => $result['creation_time'], 424 'meeting_info' => json_encode($meetinginfo)]); 425 } 426 427 /** 428 * Helper function returns a list of courses a user has access to, wrapped in an array that can be used 429 * by a html select. 430 * 431 * @param instance $instance 432 * @return array 433 */ 434 public static function import_get_courses_for_select(instance $instance): array { 435 if ($instance->is_admin()) { 436 $courses = get_courses('all', 'c.fullname ASC'); 437 // It includes the name of the site as a course (category 0), so remove the first one. 438 unset($courses['1']); 439 } else { 440 $courses = enrol_get_users_courses($instance->get_user_id(), false, 'id,shortname,fullname'); 441 } 442 $courses = array_filter($courses, function($course) { 443 $modules = get_fast_modinfo($course->id); 444 return !empty($modules->instances['bigbluebuttonbn']); 445 }); 446 $coursesforselect = []; 447 foreach ($courses as $course) { 448 $coursesforselect[$course->id] = $course->fullname . " (" . $course->shortname . ")"; 449 } 450 return $coursesforselect; 451 } 452 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body