Proyectos de Subversion Moodle

Rev

Rev 1 | | Comparar con el anterior | Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 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
     */
1441 ariadna 164
    protected static function get_roles_select(?context $context = null, bool $onlyviewableroles = true) {
1 efrain 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'),
1441 ariadna 222
            'children' => [],
1 efrain 223
        ];
1441 ariadna 224
 
225
        if (empty($bbactivity)) {
226
            return $data;
227
        }
228
 
229
        $data['user']['children'] = self::get_users_array($context, $bbactivity);
230
 
1 efrain 231
        return $data;
232
    }
233
 
234
    /**
235
     * Returns an array to populate a list of participants used in mod_form.php.
236
     *
237
     * @param stdClass|null $bigbluebuttonbn
238
     * @param context $context
239
     *
240
     * @return array
241
     */
242
    public static function get_participant_list(?stdClass $bigbluebuttonbn, context $context): array {
243
        global $USER;
244
        if ($bigbluebuttonbn == null) {
245
            return self::get_participant_rules_encoded(
246
                self::get_participant_list_default($context, $USER->id)
247
            );
248
        }
249
        if (empty($bigbluebuttonbn->participants)) {
250
            $bigbluebuttonbn->participants = "[]";
251
        }
252
        $rules = json_decode($bigbluebuttonbn->participants, true);
253
        if (empty($rules)) {
254
            $rules = self::get_participant_list_default($context,
255
                bigbluebutton_proxy::get_instance_ownerid($bigbluebuttonbn));
256
        }
257
        return self::get_participant_rules_encoded($rules);
258
    }
259
 
260
    /**
261
     * Returns an array to populate a list of participants used in mod_form.php with default values.
262
     *
263
     * @param context $context
264
     * @param int|null $ownerid
265
     *
266
     * @return array
267
     */
268
    protected static function get_participant_list_default(context $context, ?int $ownerid = null) {
269
        $participantlist = [];
270
        $participantlist[] = [
271
            'selectiontype' => 'all',
272
            'selectionid' => 'all',
273
            'role' => self::ROLE_VIEWER,
274
        ];
275
        $defaultrules = explode(',', \mod_bigbluebuttonbn\local\config::get('participant_moderator_default'));
276
        foreach ($defaultrules as $defaultrule) {
277
            if ($defaultrule == '0') {
278
                if (!empty($ownerid) && is_enrolled($context, $ownerid)) {
279
                    $participantlist[] = [
280
                        'selectiontype' => 'user',
281
                        'selectionid' => (string) $ownerid,
282
                        'role' => self::ROLE_MODERATOR];
283
                }
284
                continue;
285
            }
286
            $participantlist[] = [
287
                'selectiontype' => 'role',
288
                'selectionid' => $defaultrule,
289
                'role' => self::ROLE_MODERATOR];
290
        }
291
        return $participantlist;
292
    }
293
 
294
    /**
295
     * Returns an array to populate a list of participants used in mod_form.php with bigbluebuttonbn values.
296
     *
297
     * @param array $rules
298
     *
299
     * @return array
300
     */
301
    protected static function get_participant_rules_encoded(array $rules): array {
302
        foreach ($rules as $key => $rule) {
303
            if ($rule['selectiontype'] !== 'role' || is_numeric($rule['selectionid'])) {
304
                continue;
305
            }
306
            $role = self::get_role($rule['selectionid']);
307
            if ($role == null) {
308
                unset($rules[$key]);
309
                continue;
310
            }
311
            $rule['selectionid'] = $role->id;
312
            $rules[$key] = $rule;
313
        }
314
        return $rules;
315
    }
316
 
317
    /**
318
     * Returns an array to populate a list of participant_selection used in mod_form.php.
319
     *
320
     * @return array
321
     */
322
    public static function get_participant_selection_data(): array {
323
        return [
324
            'type_options' => [
325
                'all' => get_string('mod_form_field_participant_list_type_all', 'bigbluebuttonbn'),
326
                'role' => get_string('mod_form_field_participant_list_type_role', 'bigbluebuttonbn'),
327
                'user' => get_string('mod_form_field_participant_list_type_user', 'bigbluebuttonbn'),
328
            ],
329
            'type_selected' => 'all',
330
            'options' => ['all' => '---------------'],
331
            'selected' => 'all',
332
        ];
333
    }
334
 
335
    /**
336
     * Evaluate if a user in a context is moderator based on roles and participation rules.
337
     *
338
     * @param context $context
339
     * @param array $participantlist
340
     * @param int $userid
341
     *
342
     * @return bool
343
     */
344
    public static function is_moderator(context $context, array $participantlist, ?int $userid = null): bool {
345
        global $USER;
346
        // If an admin, then also a moderator.
347
        if (has_capability('moodle/site:config', $context)) {
348
            return true;
349
        }
350
        if (!is_array($participantlist)) {
351
            return false;
352
        }
353
        if (empty($userid)) {
354
            $userid = $USER->id;
355
        }
356
        $userroles = self::get_guest_role();
357
        if (!isguestuser()) {
358
            $userroles = self::get_user_roles($context, $userid);
359
        }
360
        return self::is_moderator_validator($participantlist, $userid, $userroles);
361
    }
362
 
363
    /**
364
     * Iterates participant list rules to evaluate if a user is moderator.
365
     *
366
     * @param array $participantlist
367
     * @param int $userid
368
     * @param array $userroles
369
     *
370
     * @return bool
371
     */
372
    protected static function is_moderator_validator(array $participantlist, int $userid, array $userroles): bool {
373
        // Iterate participant rules.
374
        foreach ($participantlist as $participant) {
375
            if (self::is_moderator_validate_rule($participant, $userid, $userroles)) {
376
                return true;
377
            }
378
        }
379
        return false;
380
    }
381
 
382
    /**
383
     * Evaluate if a user is moderator based on roles and a particular participation rule.
384
     *
385
     * @param array $participant
386
     * @param int $userid
387
     * @param array $userroles
388
     *
389
     * @return bool
390
     */
391
    protected static function is_moderator_validate_rule(array $participant, int $userid, array $userroles): bool {
392
        if ($participant['role'] == self::ROLE_VIEWER) {
393
            return false;
394
        }
395
        // Validation for the 'all' rule.
396
        if ($participant['selectiontype'] == 'all') {
397
            return true;
398
        }
399
        // Validation for a 'user' rule.
400
        if ($participant['selectiontype'] == 'user') {
401
            if ($participant['selectionid'] == $userid) {
402
                return true;
403
            }
404
            return false;
405
        }
406
        // Validation for a 'role' rule.
407
        $role = self::get_role($participant['selectionid']);
408
        if ($role != null && array_key_exists($role->id, $userroles)) {
409
            return true;
410
        }
411
        return false;
412
    }
413
 
414
    /**
415
     * Updates the meeting info cached object when a participant has joined.
416
     *
417
     * @param string $meetingid
418
     * @param bool $ismoderator
419
     *
420
     * @return void
421
     */
422
    public static function participant_joined(string $meetingid, bool $ismoderator): void {
423
        $cache = cache::make_from_params(cache_store::MODE_APPLICATION, 'mod_bigbluebuttonbn', 'meetings_cache');
424
        $result = $cache->get($meetingid);
425
        $meetinginfo = json_decode($result['meeting_info']);
426
        $meetinginfo->participantCount += 1;
427
        if ($ismoderator) {
428
            $meetinginfo->moderatorCount += 1;
429
        }
430
        $cache->set($meetingid, ['creation_time' => $result['creation_time'],
431
            'meeting_info' => json_encode($meetinginfo)]);
432
    }
433
 
434
    /**
435
     * Helper function returns a list of courses a user has access to, wrapped in an array that can be used
436
     * by a html select.
437
     *
438
     * @param instance $instance
439
     * @return array
440
     */
441
    public static function import_get_courses_for_select(instance $instance): array {
442
        if ($instance->is_admin()) {
443
            $courses = get_courses('all', 'c.fullname ASC');
444
            // It includes the name of the site as a course (category 0), so remove the first one.
445
            unset($courses['1']);
446
        } else {
447
            $courses = enrol_get_users_courses($instance->get_user_id(), false, 'id,shortname,fullname');
448
        }
449
        $courses = array_filter($courses, function($course) {
450
            $modules = get_fast_modinfo($course->id);
451
            return !empty($modules->instances['bigbluebuttonbn']);
452
        });
453
        $coursesforselect = [];
454
        foreach ($courses as $course) {
455
            $coursesforselect[$course->id] = $course->fullname . " (" . $course->shortname . ")";
456
        }
457
        return $coursesforselect;
458
    }
459
}