Completed
Pull Request — master (#289)
by
unknown
04:06 queued 01:23
created

locallib.php ➔ bigbluebuttonbn_join_meeting()   B

Complexity

Conditions 6
Paths 3

Size

Total Lines 27

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 6
nc 3
nop 3
dl 0
loc 27
rs 8.8657
c 0
b 0
f 0
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
 * Internal library of functions for module BigBlueButtonBN.
19
 *
20
 * @package   mod_bigbluebuttonbn
21
 * @copyright 2010 onwards, Blindside Networks Inc
22
 * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
23
 * @author    Jesus Federico  (jesus [at] blindsidenetworks [dt] com)
24
 * @author    Fred Dixon  (ffdixon [at] blindsidenetworks [dt] com)
25
 */
26
27
use mod_bigbluebuttonbn\locallib;
28
use mod_bigbluebuttonbn\plugin;
29
use mod_bigbluebuttonbn\task;
30
31
defined('MOODLE_INTERNAL') || die;
32
33
global $CFG;
34
35
require_once(__DIR__ . '/lib.php');
36
37
/** @var BIGBLUEBUTTONBN_UPDATE_CACHE boolean set to true indicates that cache has to be updated */
38
const BIGBLUEBUTTONBN_UPDATE_CACHE = true;
39
/** @var BIGBLUEBUTTONBN_TYPE_ALL integer set to 0 defines an instance type that inclueds room and recordings */
40
const BIGBLUEBUTTONBN_TYPE_ALL = 0;
41
/** @var BIGBLUEBUTTONBN_TYPE_ROOM_ONLY integer set to 1 defines an instance type that inclueds only room */
42
const BIGBLUEBUTTONBN_TYPE_ROOM_ONLY = 1;
43
/** @var BIGBLUEBUTTONBN_TYPE_RECORDING_ONLY integer set to 2 defines an instance type that inclueds only recordings */
44
const BIGBLUEBUTTONBN_TYPE_RECORDING_ONLY = 2;
45
/** @var BIGBLUEBUTTONBN_ROLE_VIEWER string defines the bigbluebutton viewer role */
46
const BIGBLUEBUTTONBN_ROLE_VIEWER = 'viewer';
47
/** @var BIGBLUEBUTTONBN_ROLE_MODERATOR string defines the bigbluebutton moderator role */
48
const BIGBLUEBUTTONBN_ROLE_MODERATOR = 'moderator';
49
/** @var BIGBLUEBUTTON_EVENT_ACTIVITY_VIEWED string defines the bigbluebuttonbn activity_viewed event */
50
const BIGBLUEBUTTON_EVENT_ACTIVITY_VIEWED = 'activity_viewed';
51
/** @var BIGBLUEBUTTON_EVENT_ACTIVITY_MANAGEMENT_VIEWED string defines the bigbluebuttonbn activity_management_viewed event */
52
const BIGBLUEBUTTON_EVENT_ACTIVITY_MANAGEMENT_VIEWED = 'activity_management_viewed';
53
/** @var BIGBLUEBUTTON_EVENT_LIVE_SESSION string defines the bigbluebuttonbn live_session event */
54
const BIGBLUEBUTTON_EVENT_LIVE_SESSION = 'live_session';
55
/** @var BIGBLUEBUTTON_EVENT_MEETING_CREATED string defines the bigbluebuttonbn meeting_created event */
56
const BIGBLUEBUTTON_EVENT_MEETING_CREATED = 'meeting_created';
57
/** @var BIGBLUEBUTTON_EVENT_MEETING_ENDED string defines the bigbluebuttonbn meeting_ended event */
58
const BIGBLUEBUTTON_EVENT_MEETING_ENDED = 'meeting_ended';
59
/** @var BIGBLUEBUTTON_EVENT_MEETING_JOINED string defines the bigbluebuttonbn meeting_joined event */
60
const BIGBLUEBUTTON_EVENT_MEETING_JOINED = 'meeting_joined';
61
/** @var BIGBLUEBUTTON_EVENT_MEETING_LEFT string defines the bigbluebuttonbn meeting_left event */
62
const BIGBLUEBUTTON_EVENT_MEETING_LEFT = 'meeting_left';
63
/** @var BIGBLUEBUTTON_EVENT_RECORDING_DELETED string defines the bigbluebuttonbn recording_deleted event */
64
const BIGBLUEBUTTON_EVENT_RECORDING_DELETED = 'recording_deleted';
65
/** @var BIGBLUEBUTTON_EVENT_RECORDING_IMPORTED string defines the bigbluebuttonbn recording_imported event */
66
const BIGBLUEBUTTON_EVENT_RECORDING_IMPORTED = 'recording_imported';
67
/** @var BIGBLUEBUTTON_EVENT_RECORDING_PROTECTED string defines the bigbluebuttonbn recording_protected event */
68
const BIGBLUEBUTTON_EVENT_RECORDING_PROTECTED = 'recording_protected';
69
/** @var BIGBLUEBUTTON_EVENT_RECORDING_PUBLISHED string defines the bigbluebuttonbn recording_published event */
70
const BIGBLUEBUTTON_EVENT_RECORDING_PUBLISHED = 'recording_published';
71
/** @var BIGBLUEBUTTON_EVENT_RECORDING_UNPROTECTED string defines the bigbluebuttonbn recording_unprotected event */
72
const BIGBLUEBUTTON_EVENT_RECORDING_UNPROTECTED = 'recording_unprotected';
73
/** @var BIGBLUEBUTTON_EVENT_RECORDING_UNPUBLISHED string defines the bigbluebuttonbn recording_unpublished event */
74
const BIGBLUEBUTTON_EVENT_RECORDING_UNPUBLISHED = 'recording_unpublished';
75
/** @var BIGBLUEBUTTON_EVENT_RECORDING_EDITED string defines the bigbluebuttonbn recording_edited event */
76
const BIGBLUEBUTTON_EVENT_RECORDING_EDITED = 'recording_edited';
77
/** @var BIGBLUEBUTTON_EVENT_RECORDING_VIEWED string defines the bigbluebuttonbn recording_viewed event */
78
const BIGBLUEBUTTON_EVENT_RECORDING_VIEWED = 'recording_viewed';
79
/** @var BIGBLUEBUTTON_EVENT_MEETING_START string defines the bigbluebuttonbn meeting_start event */
80
const BIGBLUEBUTTON_EVENT_MEETING_START = 'meeting_start';
81
/** @var BIGBLUEBUTTON_CLIENTTYPE_FLASH integer that defines the bigbluebuttonbn default web client based on Adobe FLASH */
82
const BIGBLUEBUTTON_CLIENTTYPE_FLASH = 0;
83
/** @var BIGBLUEBUTTON_CLIENTTYPE_HTML5 integer that defines the bigbluebuttonbn default web client based on HTML5 */
84
const BIGBLUEBUTTON_CLIENTTYPE_HTML5 = 1;
85
/** @var BIGBLUEBUTTON_ORIGIN_BASE integer set to 0 defines that the user acceded the session from activity page */
86
const BIGBLUEBUTTON_ORIGIN_BASE = 0;
87
/** @var BIGBLUEBUTTON_ORIGIN_TIMELINE integer set to 1 defines that the user acceded the session from Timeline */
88
const BIGBLUEBUTTON_ORIGIN_TIMELINE = 1;
89
/** @var BIGBLUEBUTTON_ORIGIN_INDEX integer set to 2 defines that the user acceded the session from Index */
90
const BIGBLUEBUTTON_ORIGIN_INDEX = 2;
91
92
/**
93
 * Builds and retunrs a url for joining a bigbluebutton meeting.
94
 *
95
 * @param string $meetingid
96
 * @param string $username
97
 * @param string $pw
98
 * @param string $logouturl
99
 * @param string $configtoken
100
 * @param string $userid
101
 * @param string $clienttype
102
 *
103
 * @return string
104
 */
105
function bigbluebuttonbn_get_join_url(
106
    $meetingid,
107
    $username,
108
    $pw,
109
    $logouturl,
110
    $configtoken = null,
111
    $userid = null,
112
    $clienttype = BIGBLUEBUTTON_CLIENTTYPE_FLASH
113
) {
114
    $data = ['meetingID' => $meetingid,
115
        'fullName' => $username,
116
        'password' => $pw,
117
        'logoutURL' => $logouturl,
118
    ];
119
    // Choose between Adobe Flash or HTML5 Client.
120
    if ($clienttype == BIGBLUEBUTTON_CLIENTTYPE_HTML5) {
121
        $data['joinViaHtml5'] = 'true';
122
    }
123
    if (!is_null($configtoken)) {
124
        $data['configToken'] = $configtoken;
125
    }
126
    if (!is_null($userid)) {
127
        $data['userID'] = $userid;
128
    }
129
    return \mod_bigbluebuttonbn\locallib\bigbluebutton::action_url('join', $data);
130
}
131
132
/**
133
 * Creates a bigbluebutton meeting and returns the response in an array.
134
 *
135
 * @param array  $data
136
 * @param array  $metadata
137
 * @param string $pname
138
 * @param string $purl
139
 *
140
 * @return array
141
 */
142
function bigbluebuttonbn_get_create_meeting_array($data, $metadata = array(), $pname = null, $purl = null) {
143
    $createmeetingurl = \mod_bigbluebuttonbn\locallib\bigbluebutton::action_url('create', $data, $metadata);
144
    $method = 'GET';
145
    $payload = null;
146
    if (!is_null($pname) && !is_null($purl)) {
147
        $method = 'POST';
148
        $payload = "<?xml version='1.0' encoding='UTF-8'?><modules><module name='presentation'><document url='".
149
            $purl."' /></module></modules>";
150
    }
151
    $xml = bigbluebuttonbn_wrap_xml_load_file($createmeetingurl, $method, $payload);
152
    if ($xml) {
153
        $response = array('returncode' => $xml->returncode, 'message' => $xml->message, 'messageKey' => $xml->messageKey);
154
        if ($xml->meetingID) {
155
            $response += array('meetingID' => $xml->meetingID, 'attendeePW' => $xml->attendeePW,
156
                'moderatorPW' => $xml->moderatorPW, 'hasBeenForciblyEnded' => $xml->hasBeenForciblyEnded);
157
        }
158
        return $response;
159
    }
160
    return array('returncode' => 'FAILED', 'message' => 'unreachable', 'messageKey' => 'Server is unreachable');
161
}
162
163
/**
164
 * Fetch meeting info and wrap response in array.
165
 *
166
 * @param string $meetingid
167
 *
168
 * @return array
169
 */
170
function bigbluebuttonbn_get_meeting_info_array($meetingid) {
171
    $xml = bigbluebuttonbn_wrap_xml_load_file(
172
        \mod_bigbluebuttonbn\locallib\bigbluebutton::action_url('getMeetingInfo', ['meetingID' => $meetingid])
173
    );
174
    if ($xml && $xml->returncode == 'SUCCESS' && empty($xml->messageKey)) {
175
        // Meeting info was returned.
176
        return array('returncode' => $xml->returncode,
177
            'meetingID' => $xml->meetingID,
178
            'moderatorPW' => $xml->moderatorPW,
179
            'attendeePW' => $xml->attendeePW,
180
            'hasBeenForciblyEnded' => $xml->hasBeenForciblyEnded,
181
            'running' => $xml->running,
182
            'recording' => $xml->recording,
183
            'startTime' => $xml->startTime,
184
            'endTime' => $xml->endTime,
185
            'participantCount' => $xml->participantCount,
186
            'moderatorCount' => $xml->moderatorCount,
187
            'attendees' => $xml->attendees,
188
            'metadata' => $xml->metadata,
189
        );
190
    }
191
    if ($xml) {
192
        // Either failure or success without meeting info.
193
        return (array) $xml;
194
    }
195
    // If the server is unreachable, then prompts the user of the necessary action.
196
    return array('returncode' => 'FAILED', 'message' => 'unreachable', 'messageKey' => 'Server is unreachable');
197
}
198
199
/**
200
 * Helper function to retrieve recordings from a BigBlueButton server.
201
 *
202
 * @param string|array $meetingids   list of meetingIDs "mid1,mid2,mid3" or array("mid1","mid2","mid3")
203
 * @param string|array $recordingids list of $recordingids "rid1,rid2,rid3" or array("rid1","rid2","rid3") for filtering
204
 *
205
 * @return associative array with recordings indexed by recordID, each recording is a non sequential associative array
206
 */
207
function bigbluebuttonbn_get_recordings_array($meetingids, $recordingids = []) {
208
    $meetingidsarray = $meetingids;
209
    if (!is_array($meetingids)) {
210
        $meetingidsarray = explode(',', $meetingids);
211
    }
212
    // If $meetingidsarray is empty there is no need to go further.
213
    if (empty($meetingidsarray)) {
214
        return array();
215
    }
216
    $recordings = bigbluebuttonbn_get_recordings_array_fetch($meetingidsarray);
0 ignored issues
show
Bug introduced by
It seems like $meetingidsarray defined by $meetingids on line 208 can also be of type string; however, bigbluebuttonbn_get_recordings_array_fetch() does only seem to accept array, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
217
    // Sort recordings.
218
    uasort($recordings, 'bigbluebuttonbn_recording_build_sorter');
219
    // Filter recordings based on recordingIDs.
220
    $recordingidsarray = $recordingids;
221
    if (!is_array($recordingids)) {
222
        $recordingidsarray = explode(',', $recordingids);
223
    }
224
    if (empty($recordingidsarray)) {
225
        // No recording ids, no need to filter.
226
        return $recordings;
227
    }
228
    return bigbluebuttonbn_get_recordings_array_filter($recordingidsarray, $recordings);
0 ignored issues
show
Bug introduced by
It seems like $recordingidsarray defined by $recordingids on line 220 can also be of type string; however, bigbluebuttonbn_get_recordings_array_filter() does only seem to accept array, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
229
}
230
231
/**
232
 * Helper function to fetch recordings from a BigBlueButton server.
233
 *
234
 * @param array $meetingidsarray array with meeting ids in the form array("mid1","mid2","mid3")
235
 *
236
 * @return array (associative) with recordings indexed by recordID, each recording is a non sequential associative array
237
 */
238
function bigbluebuttonbn_get_recordings_array_fetch($meetingidsarray) {
239
    if ((defined('PHPUNIT_TEST') && PHPUNIT_TEST)
240
            || defined('BEHAT_SITE_RUNNING')
241
            || defined('BEHAT_TEST')
242
            || defined('BEHAT_UTIL')) {
243
        // Just return the fake recording.
244
        global $CFG;
245
        require_once($CFG->libdir . '/testing/generator/lib.php');
246
        require_once(__DIR__ . '/tests/generator/lib.php');
247
        return mod_bigbluebuttonbn_generator::bigbluebuttonbn_get_recordings_array_fetch($meetingidsarray);
248
    }
249
    $recordings = array();
250
    // Execute a paginated getRecordings request.
251
    $pagecount = 25;
252
    $pages = floor(count($meetingidsarray) / $pagecount) + 1;
253
    if (count($meetingidsarray) > 0 && count($meetingidsarray) % $pagecount == 0) {
254
        $pages--;
255
    }
256
    for ($page = 1; $page <= $pages; ++$page) {
257
        $mids = array_slice($meetingidsarray, ($page - 1) * $pagecount, $pagecount);
258
        $recordings += bigbluebuttonbn_get_recordings_array_fetch_page($mids);
259
    }
260
    return $recordings;
261
}
262
263
/**
264
 * Helper function to fetch one page of upto 25 recordings from a BigBlueButton server.
265
 *
266
 * @param array  $mids
267
 *
268
 * @return array
269
 */
270
function bigbluebuttonbn_get_recordings_array_fetch_page($mids) {
271
    $recordings = array();
272
    // Do getRecordings is executed using a method GET (supported by all versions of BBB).
273
    $url = \mod_bigbluebuttonbn\locallib\bigbluebutton::action_url('getRecordings', ['meetingID' => implode(',', $mids)]);
274
    $xml = bigbluebuttonbn_wrap_xml_load_file($url);
275
    if ($xml && $xml->returncode == 'SUCCESS' && isset($xml->recordings)) {
276
        // If there were meetings already created.
277
        foreach ($xml->recordings->recording as $recordingxml) {
278
            $recording = bigbluebuttonbn_get_recording_array_value($recordingxml);
279
            $recordings[$recording['recordID']] = $recording;
280
281
            // Check if there is childs.
282
            if (isset($recordingxml->breakoutRooms->breakoutRoom)) {
283
                foreach ($recordingxml->breakoutRooms->breakoutRoom as $breakoutroom) {
284
                    $url = \mod_bigbluebuttonbn\locallib\bigbluebutton::action_url(
285
                        'getRecordings',
286
                        ['recordID' => implode(',', (array) $breakoutroom)]
287
                    );
288
                    $xml = bigbluebuttonbn_wrap_xml_load_file($url);
289
                    if ($xml && $xml->returncode == 'SUCCESS' && isset($xml->recordings)) {
290
                        // If there were meetings already created.
291
                        foreach ($xml->recordings->recording as $recordingxml) {
292
                            $recording = bigbluebuttonbn_get_recording_array_value($recordingxml);
293
                            $recordings[$recording['recordID']] = $recording;
294
                        }
295
                    }
296
                }
297
            }
298
        }
299
    }
300
    return $recordings;
301
}
302
303
/**
304
 * Helper function to remove a set of recordings from an array.
305
 *
306
 * @param array  $rids
307
 * @param array  $recordings
308
 *
309
 * @return array
310
 */
311
function bigbluebuttonbn_get_recordings_array_filter($rids, &$recordings) {
312
    foreach ($recordings as $key => $recording) {
313
        if (!in_array($recording['recordID'], $rids)) {
314
            unset($recordings[$key]);
315
        }
316
    }
317
    return $recordings;
318
}
319
320
/**
321
 * Helper function to retrieve imported recordings from the Moodle database.
322
 * The references are stored as events in bigbluebuttonbn_logs.
323
 *
324
 * @param string $courseid
325
 * @param string $bigbluebuttonbnid
326
 * @param bool   $subset
327
 *
328
 * @return associative array with imported recordings indexed by recordID, each recording
329
 * is a non sequential associative array that corresponds to the actual recording in BBB
330
 */
331
function bigbluebuttonbn_get_recordings_imported_array($courseid = 0, $bigbluebuttonbnid = null, $subset = true) {
332
    global $DB;
333
    $select = bigbluebuttonbn_get_recordings_imported_sql_select($courseid, $bigbluebuttonbnid, $subset);
334
    $recordsimported = $DB->get_records_select('bigbluebuttonbn_logs', $select);
335
    $recordsimportedarray = array();
336
    foreach ($recordsimported as $recordimported) {
337
        $meta = json_decode($recordimported->meta, true);
338
        $recording = $meta['recording'];
339
        // Override imported flag with actual ID.
340
        $recording['imported'] = $recordimported->id;
341
        if (isset($recordimported->protected)) {
342
            $recording['protected'] = (string) $recordimported->protected;
343
        }
344
        $recordsimportedarray[$recording['recordID']] = $recording;
345
    }
346
    return $recordsimportedarray;
347
}
348
349
/**
350
 * Helper function to retrive the default config.xml file.
351
 *
352
 * @return string
353
 */
354
function bigbluebuttonbn_get_default_config_xml() {
355
    $xml = bigbluebuttonbn_wrap_xml_load_file(
356
        \mod_bigbluebuttonbn\locallib\bigbluebutton::action_url('getDefaultConfigXML')
357
    );
358
    return $xml;
359
}
360
361
/**
362
 * Helper function to convert an xml recording object to an array in the format used by the plugin.
363
 *
364
 * @param object $recording
365
 *
366
 * @return array
367
 */
368
function bigbluebuttonbn_get_recording_array_value($recording) {
369
    // Add formats.
370
    $playbackarray = array();
371
    foreach ($recording->playback->format as $format) {
372
        $playbackarray[(string) $format->type] = array('type' => (string) $format->type,
373
            'url' => trim((string) $format->url), 'length' => (string) $format->length);
374
        // Add preview per format when existing.
375
        if ($format->preview) {
376
            $playbackarray[(string) $format->type]['preview'] = bigbluebuttonbn_get_recording_preview_images($format->preview);
377
        }
378
    }
379
    // Add the metadata to the recordings array.
380
    $metadataarray = bigbluebuttonbn_get_recording_array_meta(get_object_vars($recording->metadata));
381
    $recordingarray = array('recordID' => (string) $recording->recordID,
382
        'meetingID' => (string) $recording->meetingID, 'meetingName' => (string) $recording->name,
383
        'published' => (string) $recording->published, 'startTime' => (string) $recording->startTime,
384
        'endTime' => (string) $recording->endTime, 'playbacks' => $playbackarray);
385
    if (isset($recording->protected)) {
386
        $recordingarray['protected'] = (string) $recording->protected;
387
    }
388
    return $recordingarray + $metadataarray;
389
}
390
391
/**
392
 * Helper function to convert an xml recording preview images to an array in the format used by the plugin.
393
 *
394
 * @param object $preview
395
 *
396
 * @return array
397
 */
398
function bigbluebuttonbn_get_recording_preview_images($preview) {
399
    $imagesarray = array();
400
    foreach ($preview->images->image as $image) {
401
        $imagearray = array('url' => trim((string) $image));
402
        foreach ($image->attributes() as $attkey => $attvalue) {
403
            $imagearray[$attkey] = (string) $attvalue;
404
        }
405
        array_push($imagesarray, $imagearray);
406
    }
407
    return $imagesarray;
408
}
409
410
/**
411
 * Helper function to convert an xml recording metadata object to an array in the format used by the plugin.
412
 *
413
 * @param array $metadata
414
 *
415
 * @return array
416
 */
417
function bigbluebuttonbn_get_recording_array_meta($metadata) {
418
    $metadataarray = array();
419
    foreach ($metadata as $key => $value) {
420
        if (is_object($value)) {
421
            $value = '';
422
        }
423
        $metadataarray['meta_' . $key] = $value;
424
    }
425
    return $metadataarray;
426
}
427
428
/**
429
 * Helper function to sort an array of recordings. It compares the startTime in two recording objecs.
430
 *
431
 * @param object $a
432
 * @param object $b
433
 *
434
 * @return array
435
 */
436
function bigbluebuttonbn_recording_build_sorter($a, $b) {
437
    global $CFG;
438
    $resultless = !empty($CFG->bigbluebuttonbn_recordings_sortorder) ? -1 : 1;
439
    $resultmore = !empty($CFG->bigbluebuttonbn_recordings_sortorder) ? 1 : -1;
440
    if ($a['startTime'] < $b['startTime']) {
441
        return $resultless;
442
    }
443
    if ($a['startTime'] == $b['startTime']) {
444
        return 0;
445
    }
446
    return $resultmore;
447
}
448
449
/**
450
 * Perform deleteRecordings on BBB.
451
 *
452
 * @param string $recordids
453
 *
454
 * @return boolean
455
 */
456 View Code Duplication
function bigbluebuttonbn_delete_recordings($recordids) {
0 ignored issues
show
Duplication introduced by
This function seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
457
    $ids = explode(',', $recordids);
458
    foreach ($ids as $id) {
459
        $xml = bigbluebuttonbn_wrap_xml_load_file(
460
            \mod_bigbluebuttonbn\locallib\bigbluebutton::action_url('deleteRecordings', ['recordID' => $id])
461
        );
462
        if ($xml && $xml->returncode != 'SUCCESS') {
463
            return false;
464
        }
465
    }
466
    return true;
467
}
468
469
/**
470
 * Perform publishRecordings on BBB.
471
 *
472
 * @param string $recordids
473
 * @param string $publish
474
 */
475 View Code Duplication
function bigbluebuttonbn_publish_recordings($recordids, $publish = 'true') {
0 ignored issues
show
Duplication introduced by
This function seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
476
    $ids = explode(',', $recordids);
477
    foreach ($ids as $id) {
478
        $xml = bigbluebuttonbn_wrap_xml_load_file(
479
            \mod_bigbluebuttonbn\locallib\bigbluebutton::action_url('publishRecordings', ['recordID' => $id, 'publish' => $publish])
480
        );
481
        if ($xml && $xml->returncode != 'SUCCESS') {
482
            return false;
483
        }
484
    }
485
    return true;
486
}
487
488
/**
489
 * Perform updateRecordings on BBB.
490
 *
491
 * @param string $recordids
492
 * @param array $params ['key'=>param_key, 'value']
493
 */
494 View Code Duplication
function bigbluebuttonbn_update_recordings($recordids, $params) {
0 ignored issues
show
Duplication introduced by
This function seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
495
    $ids = explode(',', $recordids);
496
    foreach ($ids as $id) {
497
        $xml = bigbluebuttonbn_wrap_xml_load_file(
498
            \mod_bigbluebuttonbn\locallib\bigbluebutton::action_url('updateRecordings', ['recordID' => $id] + (array) $params)
499
        );
500
        if ($xml && $xml->returncode != 'SUCCESS') {
501
            return false;
502
        }
503
    }
504
    return true;
505
}
506
507
/**
508
 * Perform end on BBB.
509
 *
510
 * @param string $meetingid
511
 * @param string $modpw
512
 */
513
function bigbluebuttonbn_end_meeting($meetingid, $modpw) {
514
    $xml = bigbluebuttonbn_wrap_xml_load_file(
515
        \mod_bigbluebuttonbn\locallib\bigbluebutton::action_url('end', ['meetingID' => $meetingid, 'password' => $modpw])
516
    );
517
    if ($xml) {
518
        // If the xml packet returned failure it displays the message to the user.
519
        return array('returncode' => $xml->returncode, 'message' => $xml->message, 'messageKey' => $xml->messageKey);
520
    }
521
    // If the server is unreachable, then prompts the user of the necessary action.
522
    return null;
523
}
524
525
/**
526
 * Perform api request on BBB.
527
 *
528
 * @return string
529
 */
530
function bigbluebuttonbn_get_server_version() {
531
    $xml = bigbluebuttonbn_wrap_xml_load_file(
532
        \mod_bigbluebuttonbn\locallib\bigbluebutton::action_url()
533
    );
534
    if ($xml && $xml->returncode == 'SUCCESS') {
535
        return $xml->version;
536
    }
537
    return null;
538
}
539
540
/**
541
 * Perform api request on BBB and wraps the response in an XML object
542
 *
543
 * @param string $url
544
 * @param string $method
545
 * @param string $data
546
 * @param string $contenttype
547
 *
548
 * @return object
549
 */
550
function bigbluebuttonbn_wrap_xml_load_file($url, $method = 'GET', $data = null, $contenttype = 'text/xml') {
551
    if (extension_loaded('curl')) {
552
        $response = bigbluebuttonbn_wrap_xml_load_file_curl_request($url, $method, $data, $contenttype);
553
        if (!$response) {
554
            debugging('No response on wrap_simplexml_load_file', DEBUG_DEVELOPER);
555
            return null;
556
        }
557
        $previous = libxml_use_internal_errors(true);
558
        try {
559
            $xml = simplexml_load_string($response, 'SimpleXMLElement', LIBXML_NOCDATA | LIBXML_NOBLANKS);
560
            return $xml;
561
        } catch (Exception $e) {
562
            libxml_use_internal_errors($previous);
563
            $error = 'Caught exception: ' . $e->getMessage();
564
            debugging($error, DEBUG_DEVELOPER);
565
            return null;
566
        }
567
    }
568
    // Alternative request non CURL based.
569
    $previous = libxml_use_internal_errors(true);
570
    try {
571
        $response = simplexml_load_file($url, 'SimpleXMLElement', LIBXML_NOCDATA | LIBXML_NOBLANKS);
572
        return $response;
573
    } catch (Exception $e) {
574
        $error = 'Caught exception: ' . $e->getMessage();
575
        debugging($error, DEBUG_DEVELOPER);
576
        libxml_use_internal_errors($previous);
577
        return null;
578
    }
579
}
580
581
/**
582
 * Perform api request on BBB using CURL and wraps the response in an XML object
583
 *
584
 * @param string $url
585
 * @param string $method
586
 * @param string $data
587
 * @param string $contenttype
588
 *
589
 * @return object
590
 */
591
function bigbluebuttonbn_wrap_xml_load_file_curl_request($url, $method = 'GET', $data = null, $contenttype = 'text/xml') {
592
    global $CFG;
593
    require_once($CFG->libdir . '/filelib.php');
594
    $c = new curl();
595
    $c->setopt(array('SSL_VERIFYPEER' => true));
596
    if ($method == 'POST') {
597
        if (is_null($data) || is_array($data)) {
598
            return $c->post($url);
599
        }
600
        $options = array();
601
        $options['CURLOPT_HTTPHEADER'] = array(
602
            'Content-Type: ' . $contenttype,
603
            'Content-Length: ' . strlen($data),
604
            'Content-Language: en-US',
605
        );
606
607
        return $c->post($url, $data, $options);
608
    }
609
    if ($method == 'HEAD') {
610
        $c->head($url, array('followlocation' => true, 'timeout' => 1));
611
        return $c->get_info();
612
    }
613
    return $c->get($url);
614
}
615
616
/**
617
 * End the session associated with this instance (if it's running).
618
 *
619
 * @param object $bigbluebuttonbn
620
 *
621
 * @return void
622
 */
623
function bigbluebuttonbn_end_meeting_if_running($bigbluebuttonbn) {
624
    $meetingid = $bigbluebuttonbn->meetingid . '-' . $bigbluebuttonbn->course . '-' . $bigbluebuttonbn->id;
625
    if (bigbluebuttonbn_is_meeting_running($meetingid)) {
626
        bigbluebuttonbn_end_meeting($meetingid, $bigbluebuttonbn->moderatorpass);
627
    }
628
}
629
630
/**
631
 * Returns user roles in a context.
632
 *
633
 * @param object $context
634
 * @param integer $userid
635
 *
636
 * @return array $userroles
637
 */
638
function bigbluebuttonbn_get_user_roles($context, $userid) {
639
    global $DB;
640
    $userroles = get_user_roles($context, $userid);
641
    if ($userroles) {
642
        $where = '';
643
        foreach ($userroles as $userrole) {
644
            $where .= (empty($where) ? ' WHERE' : ' OR') . ' id=' . $userrole->roleid;
645
        }
646
        $userroles = $DB->get_records_sql('SELECT * FROM {role}' . $where);
647
    }
648
    return $userroles;
649
}
650
651
/**
652
 * Returns guest role wrapped in an array.
653
 *
654
 * @return array
655
 */
656
function bigbluebuttonbn_get_guest_role() {
657
    $guestrole = get_guest_role();
658
    return array($guestrole->id => $guestrole);
659
}
660
661
/**
662
 * Returns an array containing all the users in a context.
663
 *
664
 * @param context $context
665
 *
666
 * @return array $users
667
 */
668
function bigbluebuttonbn_get_users(context $context = null) {
669
    $users = (array) get_enrolled_users($context, '', 0, 'u.*', null, 0, 0, true);
670
    foreach ($users as $key => $value) {
671
        $users[$key] = fullname($value);
672
    }
673
    return $users;
674
}
675
676
/**
677
 * Returns an array containing all the users in a context wrapped for html select element.
678
 *
679
 * @param context_course $context
680
 * @param null $bbactivity
681
 * @return array $users
682
 * @throws coding_exception
683
 * @throws moodle_exception
684
 */
685
function bigbluebuttonbn_get_users_select(context_course $context, $bbactivity = null) {
686
    // CONTRIB-7972, check the group of current user and course group mode.
687
    $groups = null;
0 ignored issues
show
Unused Code introduced by
$groups is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
688
    $users = (array) get_enrolled_users($context, '', 0, 'u.*', null, 0, 0, true);
689
    $course = get_course($context->instanceid);
690
    $groupmode = groups_get_course_groupmode($course);
691
    if ($bbactivity) {
692
        list($bbcourse, $cm) = get_course_and_cm_from_instance($bbactivity->id, 'bigbluebuttonbn');
0 ignored issues
show
Unused Code introduced by
The assignment to $bbcourse is unused. Consider omitting it like so list($first,,$third).

This checks looks for assignemnts to variables using the list(...) function, where not all assigned variables are subsequently used.

Consider the following code example.

<?php

function returnThreeValues() {
    return array('a', 'b', 'c');
}

list($a, $b, $c) = returnThreeValues();

print $a . " - " . $c;

Only the variables $a and $c are used. There was no need to assign $b.

Instead, the list call could have been.

list($a,, $c) = returnThreeValues();
Loading history...
693
        $groupmode = groups_get_activity_groupmode($cm);
694
695
    }
696
    if ($groupmode == SEPARATEGROUPS && !has_capability('moodle/site:accessallgroups', $context)) {
697
        global $USER;
698
        $groups = groups_get_all_groups($course->id, $USER->id);
699
        $users = [];
700
        foreach ($groups as $g) {
701
            $users += (array) get_enrolled_users($context, '', $g->id, 'u.*', null, 0, 0, true);
702
        }
703
    }
704
    return array_map(
705
            function($u) {
706
                return array('id' => $u->id, 'name' => fullname($u));
707
            },
708
            $users);
709
}
710
711
/**
712
 * Returns an array containing all the roles in a context.
713
 *
714
 * @param context $context
715
 * @param bool $onlyviewableroles
716
 *
717
 * @return array $roles
718
 */
719
function bigbluebuttonbn_get_roles(context $context = null, bool $onlyviewableroles = true) {
720
    global $CFG;
721
722
    if ($onlyviewableroles == true && $CFG->branch >= 35) {
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison === instead.

When comparing two booleans, it is generally considered safer to use the strict comparison operator.

Loading history...
723
        $roles = (array) get_viewable_roles($context);
724
        foreach ($roles as $key => $value) {
725
            $roles[$key] = $value;
726
        }
727
    } else {
728
        $roles = (array) role_get_names($context);
729
        foreach ($roles as $key => $value) {
730
            $roles[$key] = $value->localname;
731
        }
732
    }
733
734
    return $roles;
735
}
736
737
/**
738
 * Returns an array containing all the roles in a context wrapped for html select element.
739
 *
740
 * @param context $context
741
 * @param bool $onlyviewableroles
742
 *
743
 * @return array $users
744
 */
745
function bigbluebuttonbn_get_roles_select(context $context = null, bool $onlyviewableroles = true) {
746
    global $CFG;
747
748
    if ($onlyviewableroles == true && $CFG->branch >= 35) {
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison === instead.

When comparing two booleans, it is generally considered safer to use the strict comparison operator.

Loading history...
749
        $roles = (array) get_viewable_roles($context);
750
        foreach ($roles as $key => $value) {
751
            $roles[$key] = array('id' => $key, 'name' => $value);
752
        }
753
    } else {
754
        $roles = (array) role_get_names($context);
755
        foreach ($roles as $key => $value) {
756
            $roles[$key] = array('id' => $value->id, 'name' => $value->localname);
757
        }
758
    }
759
760
    return $roles;
761
}
762
763
/**
764
 * Returns role that corresponds to an id.
765
 *
766
 * @param string|integer $id
767
 *
768
 * @return object $role
769
 */
770
function bigbluebuttonbn_get_role($id) {
771
    $roles = (array) role_get_names();
772
    if (is_numeric($id) && isset($roles[$id])) {
773
        return (object) $roles[$id];
774
    }
775
    foreach ($roles as $role) {
776
        if ($role->shortname == $id) {
777
            return $role;
778
        }
779
    }
780
}
781
782
/**
783
 * Returns an array to populate a list of participants used in mod_form.js.
784
 *
785
 * @param context $context
786
 * @param null|object $bbactivity
787
 * @return array $data
788
 */
789
function bigbluebuttonbn_get_participant_data($context, $bbactivity = null) {
790
    $data = array(
791
        'all' => array(
792
            'name' => get_string('mod_form_field_participant_list_type_all', 'bigbluebuttonbn'),
793
            'children' => []
794
        ),
795
    );
796
    $data['role'] = array(
797
        'name' => get_string('mod_form_field_participant_list_type_role', 'bigbluebuttonbn'),
798
        'children' => bigbluebuttonbn_get_roles_select($context, true)
799
      );
800
    $data['user'] = array(
801
        'name' => get_string('mod_form_field_participant_list_type_user', 'bigbluebuttonbn'),
802
        'children' => bigbluebuttonbn_get_users_select($context, $bbactivity),
0 ignored issues
show
Bug introduced by
It seems like $bbactivity defined by parameter $bbactivity on line 789 can also be of type object; however, bigbluebuttonbn_get_users_select() does only seem to accept null, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
803
    );
804
    return $data;
805
}
806
807
/**
808
 * Returns an array to populate a list of participants used in mod_form.php.
809
 *
810
 * @param object $bigbluebuttonbn
811
 * @param context $context
812
 *
813
 * @return array
814
 */
815
function bigbluebuttonbn_get_participant_list($bigbluebuttonbn, $context) {
816
    global $USER;
817
    if ($bigbluebuttonbn == null) {
818
        return bigbluebuttonbn_get_participant_rules_encoded(
819
            bigbluebuttonbn_get_participant_list_default($context, $USER->id)
820
        );
821
    }
822
    if (empty($bigbluebuttonbn->participants)) {
823
        $bigbluebuttonbn->participants = "[]";
824
    }
825
    $rules = json_decode($bigbluebuttonbn->participants, true);
826
    if (empty($rules)) {
827
        $rules = bigbluebuttonbn_get_participant_list_default($context, bigbluebuttonbn_instance_ownerid($bigbluebuttonbn));
828
    }
829
    return bigbluebuttonbn_get_participant_rules_encoded($rules);
830
}
831
832
/**
833
 * Returns an array to populate a list of participants used in mod_form.php with default values.
834
 *
835
 * @param context $context
836
 * @param integer $ownerid
837
 *
838
 * @return array
839
 */
840
function bigbluebuttonbn_get_participant_list_default($context, $ownerid = null) {
841
    $participantlist = array();
842
    $participantlist[] = array(
843
        'selectiontype' => 'all',
844
        'selectionid' => 'all',
845
        'role' => BIGBLUEBUTTONBN_ROLE_VIEWER,
846
    );
847
    $defaultrules = explode(',', \mod_bigbluebuttonbn\locallib\config::get('participant_moderator_default'));
848
    foreach ($defaultrules as $defaultrule) {
849
        if ($defaultrule == '0') {
850
            if (!empty($ownerid) && is_enrolled($context, $ownerid)) {
851
                $participantlist[] = array(
852
                    'selectiontype' => 'user',
853
                    'selectionid' => (string) $ownerid,
854
                    'role' => BIGBLUEBUTTONBN_ROLE_MODERATOR);
855
            }
856
            continue;
857
        }
858
        $participantlist[] = array(
859
            'selectiontype' => 'role',
860
            'selectionid' => $defaultrule,
861
            'role' => BIGBLUEBUTTONBN_ROLE_MODERATOR);
862
    }
863
    return $participantlist;
864
}
865
866
/**
867
 * Returns an array to populate a list of participants used in mod_form.php with bigbluebuttonbn values.
868
 *
869
 * @param array $rules
870
 *
871
 * @return array
872
 */
873
function bigbluebuttonbn_get_participant_rules_encoded($rules) {
874
    foreach ($rules as $key => $rule) {
875
        if ($rule['selectiontype'] !== 'role' || is_numeric($rule['selectionid'])) {
876
            continue;
877
        }
878
        $role = bigbluebuttonbn_get_role($rule['selectionid']);
879
        if ($role == null) {
880
            unset($rules[$key]);
881
            continue;
882
        }
883
        $rule['selectionid'] = $role->id;
884
        $rules[$key] = $rule;
885
    }
886
    return $rules;
887
}
888
889
/**
890
 * Returns an array to populate a list of participant_selection used in mod_form.php.
891
 *
892
 * @return array
893
 */
894
function bigbluebuttonbn_get_participant_selection_data() {
895
    return [
896
        'type_options' => [
897
            'all' => get_string('mod_form_field_participant_list_type_all', 'bigbluebuttonbn'),
898
            'role' => get_string('mod_form_field_participant_list_type_role', 'bigbluebuttonbn'),
899
            'user' => get_string('mod_form_field_participant_list_type_user', 'bigbluebuttonbn'),
900
        ],
901
        'type_selected' => 'all',
902
        'options' => ['all' => '---------------'],
903
        'selected' => 'all',
904
    ];
905
}
906
907
/**
908
 * Evaluate if a user in a context is moderator based on roles and participation rules.
909
 *
910
 * @param context $context
911
 * @param array $participantlist
912
 * @param integer $userid
913
 *
914
 * @return boolean
915
 */
916
function bigbluebuttonbn_is_moderator($context, $participantlist, $userid = null) {
917
    global $USER;
918
    if (!is_array($participantlist)) {
919
        return false;
920
    }
921
    if (empty($userid)) {
922
        $userid = $USER->id;
923
    }
924
    $userroles = bigbluebuttonbn_get_guest_role();
925
    if (!isguestuser()) {
926
        $userroles = bigbluebuttonbn_get_user_roles($context, $userid);
927
    }
928
    return bigbluebuttonbn_is_moderator_validator($participantlist, $userid, $userroles);
929
}
930
931
/**
932
 * Iterates participant list rules to evaluate if a user is moderator.
933
 *
934
 * @param array $participantlist
935
 * @param integer $userid
936
 * @param array $userroles
937
 *
938
 * @return boolean
939
 */
940
function bigbluebuttonbn_is_moderator_validator($participantlist, $userid, $userroles) {
941
    // Iterate participant rules.
942
    foreach ($participantlist as $participant) {
943
        if (bigbluebuttonbn_is_moderator_validate_rule($participant, $userid, $userroles)) {
944
            return true;
945
        }
946
    }
947
    return false;
948
}
949
950
/**
951
 * Evaluate if a user is moderator based on roles and a particular participation rule.
952
 *
953
 * @param object $participant
954
 * @param integer $userid
955
 * @param array $userroles
956
 *
957
 * @return boolean
958
 */
959
function bigbluebuttonbn_is_moderator_validate_rule($participant, $userid, $userroles) {
960
    if ($participant['role'] == BIGBLUEBUTTONBN_ROLE_VIEWER) {
961
        return false;
962
    }
963
    // Validation for the 'all' rule.
964
    if ($participant['selectiontype'] == 'all') {
965
        return true;
966
    }
967
    // Validation for a 'user' rule.
968
    if ($participant['selectiontype'] == 'user') {
969
        if ($participant['selectionid'] == $userid) {
970
            return true;
971
        }
972
        return false;
973
    }
974
    // Validation for a 'role' rule.
975
    $role = bigbluebuttonbn_get_role($participant['selectionid']);
976
    if ($role != null && array_key_exists($role->id, $userroles)) {
977
        return true;
978
    }
979
    return false;
980
}
981
982
/**
983
 * Helper returns error message key for the language file that corresponds to a bigbluebutton error key.
984
 *
985
 * @param string $messagekey
986
 * @param string $defaultkey
987
 *
988
 * @return string
989
 */
990
function bigbluebuttonbn_get_error_key($messagekey, $defaultkey = null) {
991
    if ($messagekey == 'checksumError') {
992
        return 'index_error_checksum';
993
    }
994
    if ($messagekey == 'maxConcurrent') {
995
        return 'view_error_max_concurrent';
996
    }
997
    return $defaultkey;
998
}
999
1000
/**
1001
 * Helper evaluates if a voicebridge number is unique.
1002
 *
1003
 * @param integer $instance
1004
 * @param integer $voicebridge
1005
 *
1006
 * @return string
1007
 */
1008
function bigbluebuttonbn_voicebridge_unique($instance, $voicebridge) {
1009
    global $DB;
1010
    if ($voicebridge == 0) {
1011
        return true;
1012
    }
1013
    $select = 'voicebridge = ' . $voicebridge;
1014
    if ($instance != 0) {
1015
        $select .= ' AND id <>' . $instance;
1016
    }
1017
    if (!$DB->get_records_select('bigbluebuttonbn', $select)) {
1018
        return true;
1019
    }
1020
    return false;
1021
}
1022
1023
/**
1024
 * Helper estimate a duration for the meeting based on the closingtime.
1025
 *
1026
 * @param integer $closingtime
1027
 *
1028
 * @return integer
1029
 */
1030
function bigbluebuttonbn_get_duration($closingtime) {
1031
    $duration = 0;
1032
    $now = time();
1033
    if ($closingtime > 0 && $now < $closingtime) {
1034
        $duration = ceil(($closingtime - $now) / 60);
1035
        $compensationtime = intval((int) \mod_bigbluebuttonbn\locallib\config::get('scheduled_duration_compensation'));
1036
        $duration = intval($duration) + $compensationtime;
1037
    }
1038
    return $duration;
1039
}
1040
1041
/**
1042
 * Helper return array containing the file descriptor for a preuploaded presentation.
1043
 *
1044
 * @param context $context
1045
 * @param string $presentation
1046
 * @param integer $id
1047
 *
1048
 * @return array
1049
 */
1050
function bigbluebuttonbn_get_presentation_array($context, $presentation, $id = null) {
1051
    global $CFG;
1052
    if (empty($presentation)) {
1053
        if ($CFG->bigbluebuttonbn_preuploadpresentation_enabled) {
1054
            // Item has not presentation but presentation is enabled..
1055
            // Check if exist some file by default in general mod setting ("presentationdefault").
1056
            $fs = get_file_storage();
1057
            $files = $fs->get_area_files(
1058
                context_system::instance()->id,
1059
                'mod_bigbluebuttonbn',
1060
                'presentationdefault',
1061
                0,
1062
                "filename",
1063
                false
1064
            );
1065
1066 View Code Duplication
            if (count($files) == 0) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1067
                // Not exist file by default in "presentationbydefault" setting.
1068
                return array('url' => null, 'name' => null, 'icon' => null, 'mimetype_description' => null);
1069
            }
1070
1071
            // Exists file in general setting to use as default for presentation. Cache image for temp public access.
1072
            $file = reset($files);
1073
            unset($files);
1074
            $pnoncevalue = null;
1075 View Code Duplication
            if (!is_null($id)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1076
                // Create the nonce component for granting a temporary public access.
1077
                $cache = cache::make_from_params(
1078
                    cache_store::MODE_APPLICATION,
1079
                    'mod_bigbluebuttonbn',
1080
                    'presentationdefault_cache'
1081
                );
1082
                $pnoncekey = sha1(context_system::instance()->id);
1083
                /* The item id was adapted for granting public access to the presentation once in order
1084
                 * to allow BigBlueButton to gather the file. */
1085
                $pnoncevalue = bigbluebuttonbn_generate_nonce();
1086
                $cache->set($pnoncekey, array('value' => $pnoncevalue, 'counter' => 0));
1087
            }
1088
1089
            $url = moodle_url::make_pluginfile_url(
1090
                $file->get_contextid(),
1091
                $file->get_component(),
1092
                $file->get_filearea(),
1093
                $pnoncevalue,
1094
                $file->get_filepath(),
1095
                $file->get_filename()
1096
            );
1097
            return (array('name' => $file->get_filename(), 'icon' => file_file_icon($file, 24),
1098
                'url' => $url->out(false), 'mimetype_description' => get_mimetype_description($file)));
1099
        }
1100
1101
        return array('url' => null, 'name' => null, 'icon' => null, 'mimetype_description' => null);
1102
    }
1103
    $fs = get_file_storage();
1104
    $files = $fs->get_area_files(
1105
        $context->id,
1106
        'mod_bigbluebuttonbn',
1107
        'presentation',
1108
        0,
1109
        'itemid, filepath, filename',
1110
        false
1111
    );
1112 View Code Duplication
    if (count($files) == 0) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1113
        return array('url' => null, 'name' => null, 'icon' => null, 'mimetype_description' => null);
1114
    }
1115
    $file = reset($files);
1116
    unset($files);
1117
    $pnoncevalue = null;
1118 View Code Duplication
    if (!is_null($id)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1119
        // Create the nonce component for granting a temporary public access.
1120
        $cache = cache::make_from_params(
1121
            cache_store::MODE_APPLICATION,
1122
            'mod_bigbluebuttonbn',
1123
            'presentation_cache'
1124
        );
1125
        $pnoncekey = sha1($id);
1126
        /* The item id was adapted for granting public access to the presentation once in order
1127
         * to allow BigBlueButton to gather the file. */
1128
        $pnoncevalue = bigbluebuttonbn_generate_nonce();
1129
        $cache->set($pnoncekey, array('value' => $pnoncevalue, 'counter' => 0));
1130
    }
1131
    $url = moodle_url::make_pluginfile_url(
1132
        $file->get_contextid(),
1133
        $file->get_component(),
1134
        $file->get_filearea(),
1135
        $pnoncevalue,
1136
        $file->get_filepath(),
1137
        $file->get_filename()
1138
    );
1139
    return array('name' => $file->get_filename(), 'icon' => file_file_icon($file, 24),
1140
        'url' => $url->out(false), 'mimetype_description' => get_mimetype_description($file));
1141
}
1142
1143
/**
1144
 * Helper generates a nonce used for the preuploaded presentation callback url.
1145
 *
1146
 * @return string
1147
 */
1148
function bigbluebuttonbn_generate_nonce() {
1149
    $mt = microtime();
1150
    $rand = mt_rand();
1151
    return md5($mt . $rand);
1152
}
1153
1154
/**
1155
 * Helper generates a random password.
1156
 *
1157
 * @param integer $length
1158
 * @param string $unique
1159
 *
1160
 * @return string
1161
 */
1162
function bigbluebuttonbn_random_password($length = 8, $unique = "") {
1163
    $chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
1164
    do {
1165
        $password = substr(str_shuffle($chars), 0, $length);
1166
    } while ($unique == $password);
1167
    return $password;
1168
}
1169
1170
/**
1171
 * Helper register a bigbluebuttonbn event.
1172
 *
1173
 * @param string $type
1174
 * @param object $bigbluebuttonbn
1175
 * @param array $options [timecreated, userid, other]
1176
 *
1177
 * @return void
1178
 */
1179
function bigbluebuttonbn_event_log($type, $bigbluebuttonbn, $options = []) {
1180
    global $DB;
1181
    if (!in_array($type, \mod_bigbluebuttonbn\event\events::$events)) {
1182
        // No log will be created.
1183
        return;
1184
    }
1185
    $course = $DB->get_record('course', array('id' => $bigbluebuttonbn->course), '*', MUST_EXIST);
1186
    $cm = get_coursemodule_from_instance('bigbluebuttonbn', $bigbluebuttonbn->id, $course->id, false, MUST_EXIST);
1187
    $context = context_module::instance($cm->id);
1188
    $params = array('context' => $context, 'objectid' => $bigbluebuttonbn->id);
1189
    if (array_key_exists('timecreated', $options)) {
1190
        $params['timecreated'] = $options['timecreated'];
1191
    }
1192
    if (array_key_exists('userid', $options)) {
1193
        $params['userid'] = $options['userid'];
1194
    }
1195
    if (array_key_exists('other', $options)) {
1196
        $params['other'] = $options['other'];
1197
    }
1198
    $event = call_user_func_array(
1199
        '\mod_bigbluebuttonbn\event\\' . $type . '::create',
1200
        array($params)
1201
    );
1202
    $event->add_record_snapshot('course_modules', $cm);
1203
    $event->add_record_snapshot('course', $course);
1204
    $event->add_record_snapshot('bigbluebuttonbn', $bigbluebuttonbn);
1205
    $event->trigger();
1206
}
1207
1208
/**
1209
 * Updates the meeting info cached object when a participant has joined.
1210
 *
1211
 * @param string $meetingid
1212
 * @param bool $ismoderator
1213
 *
1214
 * @return void
1215
 */
1216
function bigbluebuttonbn_participant_joined($meetingid, $ismoderator) {
1217
    $cache = cache::make_from_params(cache_store::MODE_APPLICATION, 'mod_bigbluebuttonbn', 'meetings_cache');
1218
    $result = $cache->get($meetingid);
1219
    $meetinginfo = json_decode($result['meeting_info']);
1220
    $meetinginfo->participantCount += 1;
1221
    if ($ismoderator) {
1222
        $meetinginfo->moderatorCount += 1;
1223
    }
1224
    $cache->set($meetingid, array('creation_time' => $result['creation_time'],
1225
        'meeting_info' => json_encode($meetinginfo)));
1226
}
1227
1228
/**
1229
 * Gets a meeting info object cached or fetched from the live session.
1230
 *
1231
 * @param string $meetingid
1232
 * @param boolean $updatecache
1233
 *
1234
 * @return array
1235
 */
1236
function bigbluebuttonbn_get_meeting_info($meetingid, $updatecache = false) {
1237
    $cachettl = (int) \mod_bigbluebuttonbn\locallib\config::get('waitformoderator_cache_ttl');
1238
    $cache = cache::make_from_params(cache_store::MODE_APPLICATION, 'mod_bigbluebuttonbn', 'meetings_cache');
1239
    $result = $cache->get($meetingid);
1240
    $now = time();
1241
    if (!$updatecache && !empty($result) && $now < ($result['creation_time'] + $cachettl)) {
1242
        // Use the value in the cache.
1243
        return (array) json_decode($result['meeting_info']);
1244
    }
1245
    // Ping again and refresh the cache.
1246
    $meetinginfo = (array) bigbluebuttonbn_wrap_xml_load_file(
1247
        \mod_bigbluebuttonbn\locallib\bigbluebutton::action_url('getMeetingInfo', ['meetingID' => $meetingid])
1248
    );
1249
    $cache->set($meetingid, array('creation_time' => time(), 'meeting_info' => json_encode($meetinginfo)));
1250
    return $meetinginfo;
1251
}
1252
1253
/**
1254
 * Perform isMeetingRunning on BBB.
1255
 *
1256
 * @param string $meetingid
1257
 * @param boolean $updatecache
1258
 *
1259
 * @return boolean
1260
 */
1261
function bigbluebuttonbn_is_meeting_running($meetingid, $updatecache = false) {
1262
    /* As a workaround to isMeetingRunning that always return SUCCESS but only returns true
1263
     * when at least one user is in the session, we use getMeetingInfo instead.
1264
     */
1265
    $meetinginfo = bigbluebuttonbn_get_meeting_info($meetingid, $updatecache);
1266
    return ($meetinginfo['returncode'] === 'SUCCESS');
1267
}
1268
1269
/**
1270
 * Publish an imported recording.
1271
 *
1272
 * @param string $id
1273
 * @param boolean $publish
1274
 *
1275
 * @return boolean
1276
 */
1277 View Code Duplication
function bigbluebuttonbn_publish_recording_imported($id, $publish = true) {
0 ignored issues
show
Duplication introduced by
This function seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1278
    global $DB;
1279
    // Locate the record to be updated.
1280
    $record = $DB->get_record('bigbluebuttonbn_logs', array('id' => $id));
1281
    $meta = json_decode($record->meta, true);
1282
    // Prepare data for the update.
1283
    $meta['recording']['published'] = ($publish) ? 'true' : 'false';
1284
    $record->meta = json_encode($meta);
1285
    // Proceed with the update.
1286
    $DB->update_record('bigbluebuttonbn_logs', $record);
1287
    return true;
1288
}
1289
1290
/**
1291
 * Delete an imported recording.
1292
 *
1293
 * @param string $id
1294
 *
1295
 * @return boolean
1296
 */
1297
function bigbluebuttonbn_delete_recording_imported($id) {
1298
    global $DB;
1299
    // Execute delete.
1300
    $DB->delete_records('bigbluebuttonbn_logs', array('id' => $id));
1301
    return true;
1302
}
1303
1304
/**
1305
 * Update an imported recording.
1306
 *
1307
 * @param string $id
1308
 * @param array $params ['key'=>param_key, 'value']
1309
 *
1310
 * @return boolean
1311
 */
1312
function bigbluebuttonbn_update_recording_imported($id, $params) {
1313
    global $DB;
1314
    // Locate the record to be updated.
1315
    $record = $DB->get_record('bigbluebuttonbn_logs', array('id' => $id));
1316
    $meta = json_decode($record->meta, true);
1317
    // Prepare data for the update.
1318
    $meta['recording'] = $params + $meta['recording'];
1319
    $record->meta = json_encode($meta);
1320
    // Proceed with the update.
1321
    if (!$DB->update_record('bigbluebuttonbn_logs', $record)) {
1322
        return false;
1323
    }
1324
    return true;
1325
}
1326
1327
/**
1328
 * Protect/Unprotect an imported recording.
1329
 *
1330
 * @param string $id
1331
 * @param boolean $protect
1332
 *
1333
 * @return boolean
1334
 */
1335 View Code Duplication
function bigbluebuttonbn_protect_recording_imported($id, $protect = true) {
0 ignored issues
show
Duplication introduced by
This function seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1336
    global $DB;
1337
    // Locate the record to be updated.
1338
    $record = $DB->get_record('bigbluebuttonbn_logs', array('id' => $id));
1339
    $meta = json_decode($record->meta, true);
1340
    // Prepare data for the update.
1341
    $meta['recording']['protected'] = ($protect) ? 'true' : 'false';
1342
    $record->meta = json_encode($meta);
1343
    // Proceed with the update.
1344
    $DB->update_record('bigbluebuttonbn_logs', $record);
1345
    return true;
1346
}
1347
1348
/**
1349
 * Sets a custom config.xml file for being used on create.
1350
 *
1351
 * @param string $meetingid
1352
 * @param string $configxml
1353
 *
1354
 * @return object
1355
 */
1356
function bigbluebuttonbn_set_config_xml($meetingid, $configxml) {
1357
    $urldefaultconfig = \mod_bigbluebuttonbn\locallib\config::get('server_url') . 'api/setConfigXML?';
1358
    $configxmlparams = bigbluebuttonbn_set_config_xml_params($meetingid, $configxml);
1359
    $xml = bigbluebuttonbn_wrap_xml_load_file(
1360
        $urldefaultconfig,
1361
        'POST',
1362
        $configxmlparams,
1363
        'application/x-www-form-urlencoded'
1364
    );
1365
    return $xml;
1366
}
1367
1368
/**
1369
 * Sets qs used with a custom config.xml file request.
1370
 *
1371
 * @param string $meetingid
1372
 * @param string $configxml
1373
 *
1374
 * @return string
1375
 */
1376
function bigbluebuttonbn_set_config_xml_params($meetingid, $configxml) {
1377
    $params = 'configXML=' . urlencode($configxml) . '&meetingID=' . urlencode($meetingid);
1378
    $sharedsecret = \mod_bigbluebuttonbn\locallib\config::get('shared_secret');
1379
    $configxmlparams = $params . '&checksum=' . sha1('setConfigXML' . $params . $sharedsecret);
1380
    return $configxmlparams;
1381
}
1382
1383
/**
1384
 * Sets a custom config.xml file for being used on create.
1385
 *
1386
 * @param string $meetingid
1387
 * @param string $configxml
1388
 *
1389
 * @return array
1390
 */
1391
function bigbluebuttonbn_set_config_xml_array($meetingid, $configxml) {
1392
    $configxml = bigbluebuttonbn_set_config_xml($meetingid, $configxml);
1393
    $configxmlarray = (array) $configxml;
1394
    if ($configxmlarray['returncode'] != 'SUCCESS') {
1395
        debugging('BigBlueButton was not able to set the custom config.xml file', DEBUG_DEVELOPER);
1396
        return '';
1397
    }
1398
    return $configxmlarray['configToken'];
1399
}
1400
1401
/**
1402
 * Helper function builds a row for the data used by the recording table.
1403
 *
1404
 * @param array $bbbsession
1405
 * @param array $recording
1406
 * @param array $tools
1407
 *
1408
 * @return array
1409
 */
1410
function bigbluebuttonbn_get_recording_data_row($bbbsession, $recording, $tools = ['protect', 'publish', 'delete']) {
1411
    if (!bigbluebuttonbn_include_recording_table_row($bbbsession, $recording)) {
1412
        return;
1413
    }
1414
    $rowdata = new stdClass();
1415
    // Set recording_types.
1416
    $rowdata->playback = bigbluebuttonbn_get_recording_data_row_types($recording, $bbbsession);
1417
    // Set activity name.
1418
    $rowdata->recording = bigbluebuttonbn_get_recording_data_row_meta_activity($recording, $bbbsession);
1419
    // Set activity description.
1420
    $rowdata->description = bigbluebuttonbn_get_recording_data_row_meta_description($recording, $bbbsession);
1421
    if (bigbluebuttonbn_get_recording_data_preview_enabled($bbbsession)) {
1422
        // Set recording_preview.
1423
        $rowdata->preview = bigbluebuttonbn_get_recording_data_row_preview($recording);
1424
    }
1425
    // Set date.
1426
    $rowdata->date = bigbluebuttonbn_get_recording_data_row_date($recording);
1427
    // Set formatted date.
1428
    $rowdata->date_formatted = bigbluebuttonbn_get_recording_data_row_date_formatted($rowdata->date);
1429
    // Set formatted duration.
1430
    $rowdata->duration_formatted = $rowdata->duration = bigbluebuttonbn_get_recording_data_row_duration($recording);
1431
    // Set actionbar, if user is allowed to manage recordings.
1432
    if ($bbbsession['managerecordings']) {
1433
        $rowdata->actionbar = bigbluebuttonbn_get_recording_data_row_actionbar($recording, $tools);
1434
    }
1435
    return $rowdata;
1436
}
1437
1438
/**
1439
 * Helper function evaluates if a row for the data used by the recording table is editable.
1440
 *
1441
 * @param array $bbbsession
1442
 *
1443
 * @return boolean
1444
 */
1445
function bigbluebuttonbn_get_recording_data_row_editable($bbbsession) {
1446
    return ($bbbsession['managerecordings'] && ((double) $bbbsession['serverversion'] >= 1.0 || $bbbsession['bnserver']));
1447
}
1448
1449
/**
1450
 * Helper function evaluates if recording preview should be included.
1451
 *
1452
 * @param array $bbbsession
1453
 *
1454
 * @return boolean
1455
 */
1456
function bigbluebuttonbn_get_recording_data_preview_enabled($bbbsession) {
1457
    return ((double) $bbbsession['serverversion'] >= 1.0 && $bbbsession['bigbluebuttonbn']->recordings_preview == '1');
1458
}
1459
1460
/**
1461
 * Helper function converts recording date used in row for the data used by the recording table.
1462
 *
1463
 * @param array $recording
1464
 *
1465
 * @return integer
1466
 */
1467
function bigbluebuttonbn_get_recording_data_row_date($recording) {
1468
    if (!isset($recording['startTime'])) {
1469
        return 0;
1470
    }
1471
    return floatval($recording['startTime']);
1472
}
1473
1474
/**
1475
 * Helper function format recording date used in row for the data used by the recording table.
1476
 *
1477
 * @param integer $starttime
1478
 *
1479
 * @return string
1480
 */
1481
function bigbluebuttonbn_get_recording_data_row_date_formatted($starttime) {
1482
    global $USER;
1483
    $starttime = $starttime - ($starttime % 1000);
1484
    // Set formatted date.
1485
    $dateformat = get_string('strftimerecentfull', 'langconfig') . ' %Z';
1486
    return userdate($starttime / 1000, $dateformat, usertimezone($USER->timezone));
1487
}
1488
1489
/**
1490
 * Helper function converts recording duration used in row for the data used by the recording table.
1491
 *
1492
 * @param array $recording
1493
 *
1494
 * @return integer
1495
 */
1496
function bigbluebuttonbn_get_recording_data_row_duration($recording) {
1497
    foreach (array_values($recording['playbacks']) as $playback) {
1498
        // Ignore restricted playbacks.
1499
        if (array_key_exists('restricted', $playback) && strtolower($playback['restricted']) == 'true') {
1500
            continue;
1501
        }
1502
        // Take the lenght form the fist playback with an actual value.
1503
        if (!empty($playback['length'])) {
1504
            return intval($playback['length']);
1505
        }
1506
    }
1507
    return 0;
1508
}
1509
1510
/**
1511
 * Helper function builds recording actionbar used in row for the data used by the recording table.
1512
 *
1513
 * @param array $recording
1514
 * @param array $tools
1515
 *
1516
 * @return string
1517
 */
1518
function bigbluebuttonbn_get_recording_data_row_actionbar($recording, $tools) {
1519
    $actionbar = '';
1520
    foreach ($tools as $tool) {
1521
        $buttonpayload = bigbluebuttonbn_get_recording_data_row_actionbar_payload($recording, $tool);
1522
        if ($tool == 'protect') {
1523
            if (isset($recording['imported'])) {
1524
                $buttonpayload['disabled'] = 'disabled';
1525
            }
1526
            if (!isset($recording['protected'])) {
1527
                $buttonpayload['disabled'] = 'invisible';
1528
            }
1529
        }
1530
        $actionbar .= bigbluebuttonbn_actionbar_render_button($recording, $buttonpayload);
1531
    }
1532
    $head = html_writer::start_tag('div', array(
1533
        'id' => 'recording-actionbar-' . $recording['recordID'],
1534
        'data-recordingid' => $recording['recordID'],
1535
        'data-meetingid' => $recording['meetingID']));
1536
    $tail = html_writer::end_tag('div');
1537
    return $head . $actionbar . $tail;
1538
}
1539
1540
/**
1541
 * Helper function returns the corresponding payload for an actionbar button used in row
1542
 * for the data used by the recording table.
1543
 *
1544
 * @param array $recording
1545
 * @param array $tool
1546
 *
1547
 * @return array
1548
 */
1549
function bigbluebuttonbn_get_recording_data_row_actionbar_payload($recording, $tool) {
1550
    if ($tool == 'protect') {
1551
        $protected = 'false';
1552
        if (isset($recording['protected'])) {
1553
            $protected = $recording['protected'];
1554
        }
1555
        return bigbluebuttonbn_get_recording_data_row_action_protect($protected);
1556
    }
1557
    if ($tool == 'publish') {
1558
        return bigbluebuttonbn_get_recording_data_row_action_publish($recording['published']);
1559
    }
1560
    return array('action' => $tool, 'tag' => $tool);
1561
}
1562
1563
/**
1564
 * Helper function returns the payload for protect action button used in row
1565
 * for the data used by the recording table.
1566
 *
1567
 * @param string $protected
1568
 *
1569
 * @return array
1570
 */
1571
function bigbluebuttonbn_get_recording_data_row_action_protect($protected) {
1572
    if ($protected == 'true') {
1573
        return array('action' => 'unprotect', 'tag' => 'lock');
1574
    }
1575
    return array('action' => 'protect', 'tag' => 'unlock');
1576
}
1577
1578
/**
1579
 * Helper function returns the payload for publish action button used in row
1580
 * for the data used by the recording table.
1581
 *
1582
 * @param string $published
1583
 *
1584
 * @return array
1585
 */
1586
function bigbluebuttonbn_get_recording_data_row_action_publish($published) {
1587
    if ($published == 'true') {
1588
        return array('action' => 'unpublish', 'tag' => 'hide');
1589
    }
1590
    return array('action' => 'publish', 'tag' => 'show');
1591
}
1592
1593
/**
1594
 * Helper function builds recording preview used in row for the data used by the recording table.
1595
 *
1596
 * @param array $recording
1597
 *
1598
 * @return string
1599
 */
1600
function bigbluebuttonbn_get_recording_data_row_preview($recording) {
1601
    $options = array('id' => 'preview-' . $recording['recordID']);
1602
    if ($recording['published'] === 'false') {
1603
        $options['hidden'] = 'hidden';
1604
    }
1605
    $recordingpreview = html_writer::start_tag('div', $options);
1606
    foreach ($recording['playbacks'] as $playback) {
1607
        if (isset($playback['preview'])) {
1608
            $recordingpreview .= bigbluebuttonbn_get_recording_data_row_preview_images($playback);
1609
            break;
1610
        }
1611
    }
1612
    $recordingpreview .= html_writer::end_tag('div');
1613
    return $recordingpreview;
1614
}
1615
1616
/**
1617
 * Helper function builds element with actual images used in recording preview row based on a selected playback.
1618
 *
1619
 * @param array $playback
1620
 *
1621
 * @return string
1622
 */
1623
function bigbluebuttonbn_get_recording_data_row_preview_images($playback) {
1624
    global $CFG;
1625
    $recordingpreview  = html_writer::start_tag('div', array('class' => 'container-fluid'));
1626
    $recordingpreview .= html_writer::start_tag('div', array('class' => 'row'));
1627
    foreach ($playback['preview'] as $image) {
1628
        if ($CFG->bigbluebuttonbn_recordings_validate_url && !bigbluebuttonbn_is_valid_resource(trim($image['url']))) {
1629
            return '';
1630
        }
1631
        $recordingpreview .= html_writer::start_tag('div', array('class' => ''));
1632
        $recordingpreview .= html_writer::empty_tag(
1633
            'img',
1634
            array('src' => trim($image['url']) . '?' . time(), 'class' => 'recording-thumbnail pull-left')
1635
        );
1636
        $recordingpreview .= html_writer::end_tag('div');
1637
    }
1638
    $recordingpreview .= html_writer::end_tag('div');
1639
    $recordingpreview .= html_writer::start_tag('div', array('class' => 'row'));
1640
    $recordingpreview .= html_writer::tag(
1641
        'div',
1642
        get_string('view_recording_preview_help', 'bigbluebuttonbn'),
1643
        array('class' => 'text-center text-muted small')
1644
    );
1645
    $recordingpreview .= html_writer::end_tag('div');
1646
    $recordingpreview .= html_writer::end_tag('div');
1647
    return $recordingpreview;
1648
}
1649
1650
/**
1651
 * Helper function renders recording types to be used in row for the data used by the recording table.
1652
 *
1653
 * @param array $recording
1654
 * @param array $bbbsession
1655
 *
1656
 * @return string
1657
 */
1658
function bigbluebuttonbn_get_recording_data_row_types($recording, $bbbsession) {
1659
    $dataimported = 'false';
1660
    $title = '';
1661
    if (isset($recording['imported'])) {
1662
        $dataimported = 'true';
1663
        $title = get_string('view_recording_link_warning', 'bigbluebuttonbn');
1664
    }
1665
    $visibility = '';
1666
    if ($recording['published'] === 'false') {
1667
        $visibility = 'hidden ';
1668
    }
1669
    $id = 'playbacks-' . $recording['recordID'];
1670
    $recordingtypes = html_writer::start_tag('div', array('id' => $id, 'data-imported' => $dataimported,
1671
        'data-meetingid' => $recording['meetingID'], 'data-recordingid' => $recording['recordID'],
1672
        'title' => $title, $visibility => $visibility));
1673
    foreach ($recording['playbacks'] as $playback) {
1674
        $recordingtypes .= bigbluebuttonbn_get_recording_data_row_type($recording, $bbbsession, $playback);
1675
    }
1676
    $recordingtypes .= html_writer::end_tag('div');
1677
    return $recordingtypes;
1678
}
1679
1680
/**
1681
 * Helper function renders the link used for recording type in row for the data used by the recording table.
1682
 *
1683
 * @param array $recording
1684
 * @param array $bbbsession
1685
 * @param array $playback
1686
 *
1687
 * @return string
1688
 */
1689
function bigbluebuttonbn_get_recording_data_row_type($recording, $bbbsession, $playback) {
1690
    global $CFG, $OUTPUT;
1691
    if (!bigbluebuttonbn_include_recording_data_row_type($recording, $bbbsession, $playback)) {
1692
        return '';
1693
    }
1694
    $text = bigbluebuttonbn_get_recording_type_text($playback['type']);
1695
    $href = $CFG->wwwroot . '/mod/bigbluebuttonbn/bbb_view.php?action=play&bn=' . $bbbsession['bigbluebuttonbn']->id .
1696
        '&mid=' . $recording['meetingID'] . '&rid=' . $recording['recordID'] . '&rtype=' . $playback['type'];
1697
    if (!isset($recording['imported']) || !isset($recording['protected']) || $recording['protected'] === 'false') {
1698
        $href .= '&href=' . urlencode(trim($playback['url']));
1699
    }
1700
    $linkattributes = array(
1701
        'id' => 'recording-play-' . $playback['type'] . '-' . $recording['recordID'],
1702
        'class' => 'btn btn-sm btn-default',
1703
        'onclick' => 'M.mod_bigbluebuttonbn.recordings.recordingPlay(this);',
1704
        'data-action' => 'play',
1705
        'data-target' => $playback['type'],
1706
        'data-href' => $href,
1707
      );
1708
    if ($CFG->bigbluebuttonbn_recordings_validate_url && !bigbluebuttonbn_is_bn_server()
1709
            && !bigbluebuttonbn_is_valid_resource(trim($playback['url']))) {
1710
        $linkattributes['class'] = 'btn btn-sm btn-warning';
1711
        $linkattributes['title'] = get_string('view_recording_format_errror_unreachable', 'bigbluebuttonbn');
1712
        unset($linkattributes['data-href']);
1713
    }
1714
    return $OUTPUT->action_link('#', $text, null, $linkattributes) . '&#32;';
1715
}
1716
1717
/**
1718
 * Helper function to handle yet unknown recording types
1719
 *
1720
 * @param string $playbacktype : for now presentation, video, statistics, capture, notes, podcast
1721
 *
1722
 * @return string the matching language string or a capitalised version of the provided string
1723
 */
1724
function bigbluebuttonbn_get_recording_type_text($playbacktype) {
1725
    // Check first if string exists, and if it does'nt just default to the capitalised version of the string.
1726
    $text = ucwords($playbacktype);
1727
    $typestringid = 'view_recording_format_' . $playbacktype;
1728
    if (get_string_manager()->string_exists($typestringid, 'bigbluebuttonbn')) {
1729
        $text = get_string($typestringid, 'bigbluebuttonbn');
1730
    }
1731
    return $text;
1732
}
1733
1734
/**
1735
 * Helper function validates a remote resource.
1736
 *
1737
 * @param string $url
1738
 *
1739
 * @return boolean
1740
 */
1741
function bigbluebuttonbn_is_valid_resource($url) {
1742
    $urlhost = parse_url($url, PHP_URL_HOST);
1743
    $serverurlhost = parse_url(\mod_bigbluebuttonbn\locallib\config::get('server_url'), PHP_URL_HOST);
1744
    // Skip validation when the recording URL host is the same as the configured BBB server.
1745
    if ($urlhost == $serverurlhost) {
1746
        return true;
1747
    }
1748
    // Skip validation when the recording URL was already validated.
1749
    $validatedurls = bigbluebuttonbn_cache_get('recordings_cache', 'validated_urls', array());
0 ignored issues
show
Documentation introduced by
array() is of type array, but the function expects a integer|null.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
1750
    if (array_key_exists($urlhost, $validatedurls)) {
1751
        return $validatedurls[$urlhost];
1752
    }
1753
    // Validate the recording URL.
1754
    $validatedurls[$urlhost] = true;
1755
    $curlinfo = bigbluebuttonbn_wrap_xml_load_file_curl_request($url, 'HEAD');
1756
    if (!isset($curlinfo['http_code']) || $curlinfo['http_code'] != 200) {
1757
        $error = "Resources hosted by " . $urlhost . " are unreachable. Server responded with code " . $curlinfo['http_code'];
1758
        debugging($error, DEBUG_DEVELOPER);
1759
        $validatedurls[$urlhost] = false;
1760
    }
1761
    bigbluebuttonbn_cache_set('recordings_cache', 'validated_urls', $validatedurls);
1762
    return $validatedurls[$urlhost];
1763
}
1764
1765
/**
1766
 * Helper function renders the name for meeting used in row for the data used by the recording table.
1767
 *
1768
 * @param array $recording
1769
 * @param array $bbbsession
1770
 *
1771
 * @return string
1772
 */
1773
function bigbluebuttonbn_get_recording_data_row_meeting($recording, $bbbsession) {
0 ignored issues
show
Unused Code introduced by
The parameter $bbbsession is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
1774
    $payload = array();
1775
    $source = 'meetingName';
1776
    $metaname = trim($recording['meetingName']);
1777
    return bigbluebuttonbn_get_recording_data_row_text($recording, $metaname, $source, $payload);
1778
}
1779
1780
/**
1781
 * Helper function renders the name for recording used in row for the data used by the recording table.
1782
 *
1783
 * @param array $recording
1784
 * @param array $bbbsession
1785
 *
1786
 * @return string
1787
 */
1788
function bigbluebuttonbn_get_recording_data_row_meta_activity($recording, $bbbsession) {
1789
    $payload = array();
1790 View Code Duplication
    if (bigbluebuttonbn_get_recording_data_row_editable($bbbsession)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1791
        $payload = array('recordingid' => $recording['recordID'], 'meetingid' => $recording['meetingID'],
1792
            'action' => 'edit', 'tag' => 'edit',
1793
            'target' => 'name');
1794
    }
1795
    $oldsource = 'meta_contextactivity';
1796
    if (isset($recording[$oldsource])) {
1797
        $metaname = trim($recording[$oldsource]);
1798
        return bigbluebuttonbn_get_recording_data_row_text($recording, $metaname, $oldsource, $payload);
1799
    }
1800
    $newsource = 'meta_bbb-recording-name';
1801 View Code Duplication
    if (isset($recording[$newsource])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1802
        $metaname = trim($recording[$newsource]);
1803
        return bigbluebuttonbn_get_recording_data_row_text($recording, $metaname, $newsource, $payload);
1804
    }
1805
    $metaname = trim($recording['meetingName']);
1806
    return bigbluebuttonbn_get_recording_data_row_text($recording, $metaname, $newsource, $payload);
1807
}
1808
1809
/**
1810
 * Helper function renders the description for recording used in row for the data used by the recording table.
1811
 *
1812
 * @param array $recording
1813
 * @param array $bbbsession
1814
 *
1815
 * @return string
1816
 */
1817
function bigbluebuttonbn_get_recording_data_row_meta_description($recording, $bbbsession) {
1818
    $payload = array();
1819 View Code Duplication
    if (bigbluebuttonbn_get_recording_data_row_editable($bbbsession)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1820
        $payload = array('recordingid' => $recording['recordID'], 'meetingid' => $recording['meetingID'],
1821
            'action' => 'edit', 'tag' => 'edit',
1822
            'target' => 'description');
1823
    }
1824
    $oldsource = 'meta_contextactivitydescription';
1825 View Code Duplication
    if (isset($recording[$oldsource])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1826
        $metadescription = trim($recording[$oldsource]);
1827
        return bigbluebuttonbn_get_recording_data_row_text($recording, $metadescription, $oldsource, $payload);
1828
    }
1829
    $newsource = 'meta_bbb-recording-description';
1830 View Code Duplication
    if (isset($recording[$newsource])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1831
        $metadescription = trim($recording[$newsource]);
1832
        return bigbluebuttonbn_get_recording_data_row_text($recording, $metadescription, $newsource, $payload);
1833
    }
1834
    return bigbluebuttonbn_get_recording_data_row_text($recording, '', $newsource, $payload);
1835
}
1836
1837
/**
1838
 * Helper function renders text element for recording used in row for the data used by the recording table.
1839
 *
1840
 * @param array $recording
1841
 * @param string $text
1842
 * @param string $source
1843
 * @param array $data
1844
 *
1845
 * @return string
1846
 */
1847
function bigbluebuttonbn_get_recording_data_row_text($recording, $text, $source, $data) {
1848
    $htmltext = '<span>' . htmlentities($text) . '</span>';
1849
    if (empty($data)) {
1850
        return $htmltext;
1851
    }
1852
    $target = $data['action'] . '-' . $data['target'];
1853
    $id = 'recording-' . $target . '-' . $data['recordingid'];
1854
    $attributes = array('id' => $id, 'class' => 'quickeditlink col-md-20',
1855
        'data-recordingid' => $data['recordingid'], 'data-meetingid' => $data['meetingid'],
1856
        'data-target' => $data['target'], 'data-source' => $source);
1857
    $head = html_writer::start_tag('div', $attributes);
1858
    $tail = html_writer::end_tag('div');
1859
    $payload = array('action' => $data['action'], 'tag' => $data['tag'], 'target' => $data['target']);
1860
    $htmllink = bigbluebuttonbn_actionbar_render_button($recording, $payload);
1861
    return $head . $htmltext . $htmllink . $tail;
1862
}
1863
1864
/**
1865
 * Helper function render a button for the recording action bar
1866
 *
1867
 * @param array $recording
1868
 * @param array $data
1869
 *
1870
 * @return string
1871
 */
1872
function bigbluebuttonbn_actionbar_render_button($recording, $data) {
1873
    global $OUTPUT;
1874
    if (empty($data)) {
1875
        return '';
1876
    }
1877
    $target = $data['action'];
1878
    if (isset($data['target'])) {
1879
        $target .= '-' . $data['target'];
1880
    }
1881
    $id = 'recording-' . $target . '-' . $recording['recordID'];
1882
    $onclick = 'M.mod_bigbluebuttonbn.recordings.recording' . ucfirst($data['action']) . '(this); return false;';
1883
    if ((boolean) \mod_bigbluebuttonbn\locallib\config::get('recording_icons_enabled')) {
1884
        // With icon for $manageaction.
1885
        $iconattributes = array('id' => $id, 'class' => 'iconsmall');
1886
        $linkattributes = array(
1887
            'id' => $id,
1888
            'onclick' => $onclick,
1889
            'data-action' => $data['action'],
1890
        );
1891
        if (!isset($recording['imported'])) {
1892
            $linkattributes['data-links'] = bigbluebuttonbn_count_recording_imported_instances(
1893
                $recording['recordID']
1894
            );
1895
        }
1896
        if (isset($data['disabled'])) {
1897
            $iconattributes['class'] .= ' fa-' . $data['disabled'];
1898
            $linkattributes['class'] = 'disabled';
1899
            unset($linkattributes['onclick']);
1900
        }
1901
        $icon = new pix_icon(
1902
            'i/' . $data['tag'],
1903
            get_string('view_recording_list_actionbar_' . $data['action'], 'bigbluebuttonbn'),
1904
            'moodle',
1905
            $iconattributes
1906
        );
1907
        return $OUTPUT->action_icon('#', $icon, null, $linkattributes, false);
1908
    }
1909
    // With text for $manageaction.
1910
    $linkattributes = array('title' => get_string($data['tag']), 'class' => 'btn btn-xs btn-danger',
1911
        'onclick' => $onclick);
1912
    return $OUTPUT->action_link('#', get_string($data['action']), null, $linkattributes);
1913
}
1914
1915
/**
1916
 * Helper function builds the recording table.
1917
 *
1918
 * @param array $bbbsession
1919
 * @param array $recordings
1920
 * @param array $tools
1921
 *
1922
 * @return object
1923
 */
1924
function bigbluebuttonbn_get_recording_table($bbbsession, $recordings, $tools = ['protect', 'publish', 'delete']) {
1925
    global $DB;
1926
    // Declare the table.
1927
    $table = new html_table();
1928
    $table->data = array();
1929
    // Initialize table headers.
1930
    $table->head[] = get_string('view_recording_playback', 'bigbluebuttonbn');
1931
    $table->head[] = get_string('view_recording_name', 'bigbluebuttonbn');
1932
    $table->head[] = get_string('view_recording_description', 'bigbluebuttonbn');
1933
    if (bigbluebuttonbn_get_recording_data_preview_enabled($bbbsession)) {
1934
        $table->head[] = get_string('view_recording_preview', 'bigbluebuttonbn');
1935
    }
1936
    $table->head[] = get_string('view_recording_date', 'bigbluebuttonbn');
1937
    $table->head[] = get_string('view_recording_duration', 'bigbluebuttonbn');
1938
    $table->align = array('left', 'left', 'left', 'left', 'left', 'center');
1939
    $table->size = array('', '', '', '', '', '');
1940
    if ($bbbsession['managerecordings']) {
1941
        $table->head[] = get_string('view_recording_actionbar', 'bigbluebuttonbn');
1942
        $table->align[] = 'left';
1943
        $table->size[] = (count($tools) * 40) . 'px';
1944
    }
1945
    // Get the groups of the user.
1946
    $usergroups = groups_get_all_groups($bbbsession['course']->id, $bbbsession['userID']);
1947
1948
    // Build table content.
1949
    foreach ($recordings as $recording) {
1950
        $meetingid = $recording['meetingID'];
0 ignored issues
show
Unused Code introduced by
$meetingid is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
1951
        $shortmeetingid = explode('-', $recording['meetingID']);
1952
        if (isset($shortmeetingid[0])) {
1953
            $meetingid = $shortmeetingid[0];
0 ignored issues
show
Unused Code introduced by
$meetingid is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
1954
        }
1955
        // Check if the record belongs to a Visible Group type.
1956
        list($course, $cm) = get_course_and_cm_from_cmid($bbbsession['cm']->id);
0 ignored issues
show
Unused Code introduced by
The assignment to $course is unused. Consider omitting it like so list($first,,$third).

This checks looks for assignemnts to variables using the list(...) function, where not all assigned variables are subsequently used.

Consider the following code example.

<?php

function returnThreeValues() {
    return array('a', 'b', 'c');
}

list($a, $b, $c) = returnThreeValues();

print $a . " - " . $c;

Only the variables $a and $c are used. There was no need to assign $b.

Instead, the list call could have been.

list($a,, $c) = returnThreeValues();
Loading history...
1957
        $groupmode = groups_get_activity_groupmode($cm);
1958
        $displayrow = true;
1959
        if (($groupmode != VISIBLEGROUPS)
1960
                && !$bbbsession['administrator'] && !$bbbsession['moderator']) {
1961
            $groupid = explode('[', $recording['meetingID']);
1962
            if (isset($groupid[1])) {
1963
                // It is a group recording and the user is not moderator/administrator. Recording should not be included by default.
1964
                $displayrow = false;
1965
                $groupid = explode(']', $groupid[1]);
1966
                if (isset($groupid[0])) {
1967
                    foreach ($usergroups as $usergroup) {
1968
                        if ($usergroup->id == $groupid[0]) {
1969
                            // Include recording if the user is in the same group.
1970
                            $displayrow = true;
1971
                        }
1972
                    }
1973
                }
1974
            }
1975
        }
1976
        if ($displayrow) {
1977
            $rowdata = bigbluebuttonbn_get_recording_data_row($bbbsession, $recording, $tools);
1978
            if (!empty($rowdata)) {
1979
                $row = bigbluebuttonbn_get_recording_table_row($bbbsession, $recording, $rowdata);
1980
                array_push($table->data, $row);
1981
            }
1982
        }
1983
    }
1984
    return $table;
1985
}
1986
1987
/**
1988
 * Helper function builds the recording table row and insert into table.
1989
 *
1990
 * @param array $bbbsession
1991
 * @param array $recording
1992
 * @param object $rowdata
1993
 *
1994
 * @return object
1995
 */
1996
function bigbluebuttonbn_get_recording_table_row($bbbsession, $recording, $rowdata) {
1997
    $row = new html_table_row();
1998
    $row->id = 'recording-tr-' . $recording['recordID'];
1999
    $row->attributes['data-imported'] = 'false';
2000
    $texthead = '';
2001
    $texttail = '';
2002
    if (isset($recording['imported'])) {
2003
        $row->attributes['title'] = get_string('view_recording_link_warning', 'bigbluebuttonbn');
2004
        $row->attributes['data-imported'] = 'true';
2005
        $texthead = '<em>';
2006
        $texttail = '</em>';
2007
    }
2008
    $rowdata->date_formatted = str_replace(' ', '&nbsp;', $rowdata->date_formatted);
2009
    $row->cells = array();
2010
    $row->cells[] = $texthead . $rowdata->playback . $texttail;
2011
    $row->cells[] = $texthead . $rowdata->recording . $texttail;
2012
    $row->cells[] = $texthead . $rowdata->description . $texttail;
2013
    if (bigbluebuttonbn_get_recording_data_preview_enabled($bbbsession)) {
2014
        $row->cells[] = $rowdata->preview;
2015
    }
2016
    $row->cells[] = $texthead . $rowdata->date_formatted . $texttail;
2017
    $row->cells[] = $rowdata->duration_formatted;
2018
    if ($bbbsession['managerecordings']) {
2019
        $row->cells[] = $rowdata->actionbar;
2020
    }
2021
    return $row;
2022
}
2023
2024
/**
2025
 * Get the basic data to display in the table view
2026
 *
2027
 * @param array $bbbsession the current session
2028
 * @param array $enabledfeatures feature enabled for this activity
2029
 * @return associative array containing the recordings indexed by recordID, each recording is also a
2030
 * non sequential associative array itself that corresponds to the actual recording in BBB
2031
 */
2032
function bigbluebutton_get_recordings_for_table_view($bbbsession, $enabledfeatures) {
2033
    $bigbluebuttonbnid = null;
2034
    if ($enabledfeatures['showroom']) {
2035
        $bigbluebuttonbnid = $bbbsession['bigbluebuttonbn']->id;
2036
    }
2037
    // Get recordings.
2038
    $recordings = bigbluebuttonbn_get_recordings(
2039
        $bbbsession['course']->id, $bigbluebuttonbnid, $enabledfeatures['showroom'],
2040
        $bbbsession['bigbluebuttonbn']->recordings_deleted
2041
    );
2042
    if ($enabledfeatures['importrecordings']) {
2043
        // Get recording links.
2044
        $bigbluebuttonbnid = $bbbsession['bigbluebuttonbn']->id;
2045
        $recordingsimported = bigbluebuttonbn_get_recordings_imported_array(
2046
            $bbbsession['course']->id, $bigbluebuttonbnid, true
2047
        );
2048
        /* Perform aritmetic addition instead of merge so the imported recordings corresponding to existent
2049
         * recordings are not included. */
2050
        if ($bbbsession['bigbluebuttonbn']->recordings_imported) {
2051
            $recordings = $recordingsimported;
2052
        } else {
2053
            $recordings += $recordingsimported;
2054
        }
2055
    }
2056
    return $recordings;
2057
}
2058
2059
/**
2060
 * Helper function evaluates if recording row should be included in the table.
2061
 *
2062
 * @param array $bbbsession
2063
 * @param array $recording
2064
 *
2065
 * @return boolean
2066
 */
2067
function bigbluebuttonbn_include_recording_table_row($bbbsession, $recording) {
2068
    // Exclude unpublished recordings, only if user has no rights to manage them.
2069
    if ($recording['published'] != 'true' && !$bbbsession['managerecordings']) {
2070
        return false;
2071
    }
2072
    // Imported recordings are always shown as long as they are published.
2073
    if (isset($recording['imported'])) {
2074
        return true;
2075
    }
2076
    // Administrators and moderators are always allowed.
2077
    if ($bbbsession['administrator'] || $bbbsession['moderator']) {
2078
        return true;
2079
    }
2080
    // When groups are enabled, exclude those to which the user doesn't have access to.
2081
    if (isset($bbbsession['group']) && $recording['meetingID'] != $bbbsession['meetingid']) {
2082
        return false;
2083
    }
2084
    return true;
2085
}
2086
2087
/**
2088
 * Helper function triggers a send notification when the recording is ready.
2089
 *
2090
 * @param object $bigbluebuttonbn
2091
 *
2092
 * @return void
2093
 */
2094
function bigbluebuttonbn_send_notification_recording_ready($bigbluebuttonbn) {
2095
    \mod_bigbluebuttonbn\locallib\notifier::notify_recording_ready($bigbluebuttonbn);
2096
}
2097
2098
/**
2099
 * Helper function enqueues list of meeting events to be stored and processed as for completion.
2100
 *
2101
 * @param object $bigbluebuttonbn
2102
 * @param object $jsonobj
2103
 *
2104
 * @return void
2105
 */
2106
function bigbluebuttonbn_process_meeting_events($bigbluebuttonbn, $jsonobj) {
2107
    $meetingid = $jsonobj->{'meeting_id'};
2108
    $recordid = $jsonobj->{'internal_meeting_id'};
2109
    $attendees = $jsonobj->{'data'}->{'attendees'};
2110
    foreach ($attendees as $attendee) {
2111
        $userid = $attendee->{'ext_user_id'};
2112
        $overrides['meetingid'] = $meetingid;
0 ignored issues
show
Coding Style Comprehensibility introduced by
$overrides was never initialized. Although not strictly required by PHP, it is generally a good practice to add $overrides = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
2113
        $overrides['userid'] = $userid;
0 ignored issues
show
Bug introduced by
The variable $overrides does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
2114
        $meta['recordid'] = $recordid;
0 ignored issues
show
Coding Style Comprehensibility introduced by
$meta was never initialized. Although not strictly required by PHP, it is generally a good practice to add $meta = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
2115
        $meta['data'] = $attendee;
2116
        // Stores the log.
2117
        bigbluebuttonbn_log($bigbluebuttonbn, BIGBLUEBUTTON_LOG_EVENT_SUMMARY, $overrides, json_encode($meta));
2118
        // Enqueue a task for processing the completion.
2119
        bigbluebuttonbn_enqueue_completion_update($bigbluebuttonbn, $userid);
2120
    }
2121
}
2122
2123
/**
2124
 * Helper function enqueues one user for being validated as for completion.
2125
 *
2126
 * @param object $bigbluebuttonbn
2127
 * @param string $userid
2128
 *
2129
 * @return void
2130
 */
2131
function bigbluebuttonbn_enqueue_completion_update($bigbluebuttonbn, $userid) {
2132
    try {
2133
        // Create the instance of completion_update_state task.
2134
        $task = new \mod_bigbluebuttonbn\task\completion_update_state();
2135
        // Add custom data.
2136
        $data = array(
2137
            'bigbluebuttonbn' => $bigbluebuttonbn,
2138
            'userid' => $userid,
2139
        );
2140
        $task->set_custom_data($data);
2141
        // CONTRIB-7457: Task should be executed by a user, maybe Teacher as Student won't have rights for overriding.
2142
        // $ task -> set_userid ( $ user -> id );.
2143
        // Enqueue it.
2144
        \core\task\manager::queue_adhoc_task($task);
2145
    } catch (Exception $e) {
2146
        mtrace("Error while enqueuing completion_update_state task. " . (string) $e);
2147
    }
2148
}
2149
2150
/**
2151
 * Helper function enqueues completion trigger.
2152
 *
2153
 * @param object $bigbluebuttonbn
2154
 * @param string $userid
2155
 *
2156
 * @return void
2157
 */
2158
function bigbluebuttonbn_completion_update_state($bigbluebuttonbn, $userid) {
2159
    global $CFG;
2160
    require_once($CFG->libdir.'/completionlib.php');
2161
    list($course, $cm) = get_course_and_cm_from_instance($bigbluebuttonbn, 'bigbluebuttonbn');
2162
    $completion = new completion_info($course);
2163
    if (!$completion->is_enabled($cm)) {
2164
        mtrace("Completion not enabled");
2165
        return;
2166
    }
2167
    if (bigbluebuttonbn_get_completion_state($course, $cm, $userid, COMPLETION_AND)) {
2168
        mtrace("Completion succeeded for user $userid");
2169
        $completion->update_state($cm, COMPLETION_COMPLETE, $userid, true);
2170
    } else {
2171
        mtrace("Completion did not succeed for user $userid");
2172
    }
2173
}
2174
2175
/**
2176
 * Helper evaluates if the bigbluebutton server used belongs to blindsidenetworks domain.
2177
 *
2178
 * @return boolean
2179
 */
2180
function bigbluebuttonbn_is_bn_server() {
2181
    if (\mod_bigbluebuttonbn\locallib\config::get('bn_server')) {
2182
        return true;
2183
    }
2184
    $parsedurl = parse_url(\mod_bigbluebuttonbn\locallib\config::get('server_url'));
2185
    if (!isset($parsedurl['host'])) {
2186
        return false;
2187
    }
2188
    $h = $parsedurl['host'];
2189
    $hends = explode('.', $h);
2190
    $hendslength = count($hends);
2191
    return ($hends[$hendslength - 1] == 'com' && $hends[$hendslength - 2] == 'blindsidenetworks');
2192
}
2193
2194
/**
2195
 * Helper function returns a list of courses a user has access to, wrapped in an array that can be used
2196
 * by a html select.
2197
 *
2198
 * @param array $bbbsession
2199
 *
2200
 * @return array
2201
 */
2202
function bigbluebuttonbn_import_get_courses_for_select(array $bbbsession) {
2203
    if ($bbbsession['administrator']) {
2204
        $courses = get_courses('all', 'c.fullname ASC');
2205
        // It includes the name of the site as a course (category 0), so remove the first one.
2206
        unset($courses['1']);
2207
    } else {
2208
        $courses = enrol_get_users_courses($bbbsession['userID'], false, 'id,shortname,fullname');
2209
    }
2210
    $coursesforselect = [];
2211
    foreach ($courses as $course) {
2212
        $coursesforselect[$course->id] = $course->fullname . " (" . $course->shortname . ")";
2213
    }
2214
    return $coursesforselect;
2215
}
2216
2217
/**
2218
 * Helper function renders recording table.
2219
 *
2220
 * @param array $bbbsession
2221
 * @param array $recordings
2222
 * @param array $tools
2223
 *
2224
 * @return array
2225
 */
2226
function bigbluebuttonbn_output_recording_table($bbbsession, $recordings, $tools = ['protect', 'publish', 'delete']) {
2227
    if (isset($recordings) && !empty($recordings)) {
2228
        // There are recordings for this meeting.
2229
        $table = bigbluebuttonbn_get_recording_table($bbbsession, $recordings, $tools);
2230
    }
2231
    if (!isset($table) || !isset($table->data)) {
2232
        // Render a table with "No recordings".
2233
        return html_writer::div(
2234
            get_string('view_message_norecordings', 'bigbluebuttonbn'),
2235
            '',
2236
            array('id' => 'bigbluebuttonbn_recordings_table')
2237
        );
2238
    }
2239
    // Render the table.
2240
    return html_writer::div(html_writer::table($table), '', array('id' => 'bigbluebuttonbn_recordings_table'));
2241
}
2242
2243
/**
2244
 * Helper function to convert an html string to plain text.
2245
 *
2246
 * @param string $html
2247
 * @param integer $len
2248
 *
2249
 * @return string
2250
 */
2251
function bigbluebuttonbn_html2text($html, $len = 0) {
2252
    $text = strip_tags($html);
2253
    $text = str_replace('&nbsp;', ' ', $text);
2254
    $textlen = strlen($text);
2255
    $text = mb_substr($text, 0, $len);
2256
    if ($textlen > $len) {
2257
        $text .= '...';
2258
    }
2259
    return $text;
2260
}
2261
2262
/**
2263
 * Helper function to obtain the tags linked to a bigbluebuttonbn activity
2264
 *
2265
 * @param string $id
2266
 *
2267
 * @return string containing the tags separated by commas
2268
 */
2269
function bigbluebuttonbn_get_tags($id) {
2270
    if (class_exists('core_tag_tag')) {
2271
        return implode(',', core_tag_tag::get_item_tags_array('core', 'course_modules', $id));
2272
    }
2273
    return implode(',', tag_get_tags('bigbluebuttonbn', $id));
2274
}
2275
2276
/**
2277
 * Helper function to define the sql used for gattering the bigbluebuttonbnids whose meetingids should be included
2278
 * in the getRecordings request
2279
 *
2280
 * @param string $courseid
2281
 * @param string $bigbluebuttonbnid
2282
 * @param bool   $subset
2283
 *
2284
 * @return string containing the sql used for getting the target bigbluebuttonbn instances
2285
 */
2286
function bigbluebuttonbn_get_recordings_sql_select($courseid, $bigbluebuttonbnid = null, $subset = true) {
2287
    if (empty($courseid)) {
2288
        $courseid = 0;
2289
    }
2290
    if (empty($bigbluebuttonbnid)) {
2291
        return "course = '{$courseid}'";
2292
    }
2293
    if ($subset) {
2294
        return "id = '{$bigbluebuttonbnid}'";
2295
    }
2296
    return "id <> '{$bigbluebuttonbnid}' AND course = '{$courseid}'";
2297
}
2298
2299
/**
2300
 * Helper function to define the sql used for gattering the bigbluebuttonbnids whose meetingids should be included
2301
 * in the getRecordings request considering only those that belong to deleted activities.
2302
 *
2303
 * @param string $courseid
2304
 * @param string $bigbluebuttonbnid
2305
 * @param bool   $subset
2306
 *
2307
 * @return string containing the sql used for getting the target bigbluebuttonbn instances
2308
 */
2309 View Code Duplication
function bigbluebuttonbn_get_recordings_deleted_sql_select($courseid = 0, $bigbluebuttonbnid = null, $subset = true) {
0 ignored issues
show
Duplication introduced by
This function seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
2310
    $sql = "log = '" . BIGBLUEBUTTONBN_LOG_EVENT_DELETE . "' AND meta like '%has_recordings%' AND meta like '%true%'";
2311
    if (empty($courseid)) {
2312
        $courseid = 0;
2313
    }
2314
    if (empty($bigbluebuttonbnid)) {
2315
        return $sql . " AND courseid = {$courseid}";
2316
    }
2317
    if ($subset) {
2318
        return $sql . " AND bigbluebuttonbnid = '{$bigbluebuttonbnid}'";
2319
    }
2320
    return $sql . " AND courseid = {$courseid} AND bigbluebuttonbnid <> '{$bigbluebuttonbnid}'";
2321
}
2322
2323
/**
2324
 * Helper function to define the sql used for gattering the bigbluebuttonbnids whose meetingids should be included
2325
 * in the getRecordings request considering only those that belong to imported recordings.
2326
 *
2327
 * @param string $courseid
2328
 * @param string $bigbluebuttonbnid
2329
 * @param bool   $subset
2330
 *
2331
 * @return string containing the sql used for getting the target bigbluebuttonbn instances
2332
 */
2333 View Code Duplication
function bigbluebuttonbn_get_recordings_imported_sql_select($courseid = 0, $bigbluebuttonbnid = null, $subset = true) {
0 ignored issues
show
Duplication introduced by
This function seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
2334
    $sql = "log = '" . BIGBLUEBUTTONBN_LOG_EVENT_IMPORT . "'";
2335
    if (empty($courseid)) {
2336
        $courseid = 0;
2337
    }
2338
    if (empty($bigbluebuttonbnid)) {
2339
        return $sql . " AND courseid = '{$courseid}'";
2340
    }
2341
    if ($subset) {
2342
        return $sql . " AND bigbluebuttonbnid = '{$bigbluebuttonbnid}'";
2343
    }
2344
    return $sql . " AND courseid = '{$courseid}' AND bigbluebuttonbnid <> '{$bigbluebuttonbnid}'";
2345
}
2346
2347
/**
2348
 * Helper function to get recordings and imported recordings together.
2349
 *
2350
 * @param string $courseid
2351
 * @param string $bigbluebuttonbnid
2352
 * @param bool   $subset
2353
 * @param bool   $includedeleted
2354
 *
2355
 * @return associative array containing the recordings indexed by recordID, each recording is also a
2356
 * non sequential associative array itself that corresponds to the actual recording in BBB
2357
 */
2358
function bigbluebuttonbn_get_allrecordings($courseid = 0, $bigbluebuttonbnid = null, $subset = true, $includedeleted = false) {
2359
    $recordings = bigbluebuttonbn_get_recordings($courseid, $bigbluebuttonbnid, $subset, $includedeleted);
2360
    $recordingsimported = bigbluebuttonbn_get_recordings_imported_array($courseid, $bigbluebuttonbnid, $subset);
2361
    return ($recordings + $recordingsimported);
2362
}
2363
2364
/**
2365
 * Helper function to retrieve recordings from the BigBlueButton. The references are stored as events
2366
 * in bigbluebuttonbn_logs.
2367
 *
2368
 * @param string $courseid
2369
 * @param string $bigbluebuttonbnid
2370
 * @param bool   $subset
2371
 * @param bool   $includedeleted
2372
 *
2373
 * @return associative array containing the recordings indexed by recordID, each recording is also a
2374
 * non sequential associative array itself that corresponds to the actual recording in BBB
2375
 */
2376
function bigbluebuttonbn_get_recordings($courseid = 0, $bigbluebuttonbnid = null, $subset = true, $includedeleted = false) {
2377
    global $DB;
2378
    $select = bigbluebuttonbn_get_recordings_sql_select($courseid, $bigbluebuttonbnid, $subset);
2379
    $bigbluebuttonbns = $DB->get_records_select_menu('bigbluebuttonbn', $select, null, 'id', 'id, meetingid');
2380
    /* Consider logs from deleted bigbluebuttonbn instances whose meetingids should be included in
2381
     * the getRecordings request. */
2382
    if ($includedeleted) {
2383
        $selectdeleted = bigbluebuttonbn_get_recordings_deleted_sql_select($courseid, $bigbluebuttonbnid, $subset);
2384
        $bigbluebuttonbnsdel = $DB->get_records_select_menu(
2385
            'bigbluebuttonbn_logs',
2386
            $selectdeleted,
2387
            null,
2388
            'bigbluebuttonbnid',
2389
            'bigbluebuttonbnid, meetingid'
2390
        );
2391
        if (!empty($bigbluebuttonbnsdel)) {
2392
            // Merge bigbluebuttonbnis from deleted instances, only keys are relevant.
2393
            // Artimetic merge is used in order to keep the keys.
2394
            $bigbluebuttonbns += $bigbluebuttonbnsdel;
2395
        }
2396
    }
2397
    // Gather the meetingids from bigbluebuttonbn logs that include a create with record=true.
2398
    if (empty($bigbluebuttonbns)) {
2399
        return array();
2400
    }
2401
    // Prepare select for loading records based on existent bigbluebuttonbns.
2402
    $sql = 'SELECT DISTINCT meetingid, bigbluebuttonbnid FROM {bigbluebuttonbn_logs} WHERE ';
2403
    $sql .= '(bigbluebuttonbnid=' . implode(' OR bigbluebuttonbnid=', array_keys($bigbluebuttonbns)) . ')';
2404
    // Include only Create events and exclude those with record not true.
2405
    $sql .= ' AND log = ? AND meta LIKE ? AND meta LIKE ?';
2406
    // Execute select for loading records based on existent bigbluebuttonbns.
2407
    $records = $DB->get_records_sql_menu($sql, array(BIGBLUEBUTTONBN_LOG_EVENT_CREATE, '%record%', '%true%'));
2408
    // Get actual recordings.
2409
    return bigbluebuttonbn_get_recordings_array(array_keys($records));
2410
}
2411
2412
/**
2413
 * Helper function iterates an array with recordings and unset those already imported.
2414
 *
2415
 * @param array $recordings
2416
 * @param integer $courseid
2417
 * @param integer $bigbluebuttonbnid
2418
 *
2419
 * @return array
2420
 */
2421
function bigbluebuttonbn_unset_existent_recordings_already_imported($recordings, $courseid, $bigbluebuttonbnid) {
2422
    $recordingsimported = bigbluebuttonbn_get_recordings_imported_array($courseid, $bigbluebuttonbnid, true);
2423
    foreach ($recordings as $key => $recording) {
2424
        if (isset($recordingsimported[$recording['recordID']])) {
2425
            unset($recordings[$key]);
2426
        }
2427
    }
2428
    return $recordings;
2429
}
2430
2431
/**
2432
 * Helper function to count the imported recordings for a recordingid.
2433
 *
2434
 * @param string $recordid
2435
 *
2436
 * @return integer
2437
 */
2438
function bigbluebuttonbn_count_recording_imported_instances($recordid) {
2439
    global $DB;
2440
    $sql = 'SELECT COUNT(DISTINCT id) FROM {bigbluebuttonbn_logs} WHERE log = ? AND meta LIKE ? AND meta LIKE ?';
2441
    return $DB->count_records_sql($sql, array(BIGBLUEBUTTONBN_LOG_EVENT_IMPORT, '%recordID%', "%{$recordid}%"));
2442
}
2443
2444
/**
2445
 * Helper function returns an array with all the instances of imported recordings for a recordingid.
2446
 *
2447
 * @param string $recordid
2448
 *
2449
 * @return array
2450
 */
2451
function bigbluebuttonbn_get_recording_imported_instances($recordid) {
2452
    global $DB;
2453
    $sql = 'SELECT * FROM {bigbluebuttonbn_logs} WHERE log = ? AND meta LIKE ? AND meta LIKE ?';
2454
    $recordingsimported = $DB->get_records_sql($sql, array(BIGBLUEBUTTONBN_LOG_EVENT_IMPORT, '%recordID%',
2455
        "%{$recordid}%"));
2456
    return $recordingsimported;
2457
}
2458
2459
/**
2460
 * Helper function to get how much callback events are logged.
2461
 *
2462
 * @param string $recordid
2463
 * @param string $callbacktype
2464
 *
2465
 * @return integer
2466
 */
2467
function bigbluebuttonbn_get_count_callback_event_log($recordid, $callbacktype = 'recording_ready') {
2468
    global $DB;
2469
    $sql = 'SELECT count(DISTINCT id) FROM {bigbluebuttonbn_logs} WHERE log = ? AND meta LIKE ? AND meta LIKE ?';
2470
    // Callback type added on version 2.4, validate recording_ready first or assume it on records with no callback.
2471
    if ($callbacktype == 'recording_ready') {
2472
        $sql .= ' AND (meta LIKE ? OR meta NOT LIKE ? )';
2473
        $count = $DB->count_records_sql($sql, array(BIGBLUEBUTTON_LOG_EVENT_CALLBACK, '%recordid%', "%$recordid%",
2474
            $callbacktype, 'callback'));
2475
        return $count;
2476
    }
2477
    $sql .= ' AND meta LIKE ?;';
2478
    $count = $DB->count_records_sql($sql, array(BIGBLUEBUTTON_LOG_EVENT_CALLBACK, '%recordid%', "%$recordid%", "%$callbacktype%"));
2479
    return $count;
2480
}
2481
2482
/**
2483
 * Helper function returns an array with the profiles (with features per profile) for the different types
2484
 * of bigbluebuttonbn instances.
2485
 *
2486
 * @return array
2487
 */
2488
function bigbluebuttonbn_get_instance_type_profiles() {
2489
    $instanceprofiles = array(
2490
        BIGBLUEBUTTONBN_TYPE_ALL => array('id' => BIGBLUEBUTTONBN_TYPE_ALL,
2491
            'name' => get_string('instance_type_default', 'bigbluebuttonbn'),
2492
            'features' => array('all')),
2493
        BIGBLUEBUTTONBN_TYPE_ROOM_ONLY => array('id' => BIGBLUEBUTTONBN_TYPE_ROOM_ONLY,
2494
            'name' => get_string('instance_type_room_only', 'bigbluebuttonbn'),
2495
            'features' => array('showroom', 'welcomemessage', 'voicebridge', 'waitformoderator', 'userlimit',
2496
                'recording', 'sendnotifications', 'preuploadpresentation', 'permissions', 'schedule', 'groups',
2497
                'modstandardelshdr', 'availabilityconditionsheader', 'tagshdr', 'competenciessection',
2498
                'clienttype', 'completionattendance', 'completionengagement', 'availabilityconditionsheader',
2499
                'viewguestlink', 'changeguestlinkpass')),
2500
        BIGBLUEBUTTONBN_TYPE_RECORDING_ONLY => array('id' => BIGBLUEBUTTONBN_TYPE_RECORDING_ONLY,
2501
            'name' => get_string('instance_type_recording_only', 'bigbluebuttonbn'),
2502
            'features' => array('showrecordings', 'importrecordings', 'availabilityconditionsheader')),
2503
    );
2504
    return $instanceprofiles;
2505
}
2506
2507
/**
2508
 * Helper function returns an array with enabled features for an specific profile type.
2509
 *
2510
 * @param array $typeprofiles
2511
 * @param string $type
2512
 *
2513
 * @return array
2514
 */
2515
function bigbluebuttonbn_get_enabled_features($typeprofiles, $type = null) {
2516
    $enabledfeatures = array();
2517
    $features = $typeprofiles[BIGBLUEBUTTONBN_TYPE_ALL]['features'];
2518
    if (!is_null($type) && key_exists($type, $typeprofiles)) {
2519
        $features = $typeprofiles[$type]['features'];
2520
    }
2521
    $enabledfeatures['showroom'] = (in_array('all', $features) || in_array('showroom', $features));
2522
    if (\mod_bigbluebuttonbn\locallib\config::guestlinks_enabled()) {
2523
        $enabledfeatures['viewguestlink'] = (in_array('all', $features) || in_array('viewguestlink', $features));
2524
        $enabledfeatures['changeguestlinkpass'] = (in_array('all', $features) || in_array('changeguestlinkpass', $features));
2525
    }
2526
    // Evaluates if recordings are enabled for the Moodle site.
2527
    $enabledfeatures['showrecordings'] = false;
2528
    if (\mod_bigbluebuttonbn\locallib\config::recordings_enabled()) {
2529
        $enabledfeatures['showrecordings'] = (in_array('all', $features) || in_array('showrecordings', $features));
2530
    }
2531
    $enabledfeatures['importrecordings'] = false;
2532
    if (\mod_bigbluebuttonbn\locallib\config::importrecordings_enabled()) {
2533
        $enabledfeatures['importrecordings'] = (in_array('all', $features) || in_array('importrecordings', $features));
2534
    }
2535
    // Evaluates if clienttype is enabled for the Moodle site.
2536
    $enabledfeatures['clienttype'] = false;
2537
    if (\mod_bigbluebuttonbn\locallib\config::clienttype_enabled()) {
2538
        $enabledfeatures['clienttype'] = (in_array('all', $features) || in_array('clienttype', $features));
2539
    }
2540
    return $enabledfeatures;
2541
}
2542
2543
/**
2544
 * Helper function returns an array with the profiles (with features per profile) for the different types
2545
 * of bigbluebuttonbn instances that the user is allowed to create.
2546
 *
2547
 * @param boolean $room
2548
 * @param boolean $recording
2549
 *
2550
 * @return array
2551
 */
2552
function bigbluebuttonbn_get_instance_type_profiles_create_allowed($room, $recording) {
2553
    $profiles = bigbluebuttonbn_get_instance_type_profiles();
2554
    if (!$room) {
2555
        unset($profiles[BIGBLUEBUTTONBN_TYPE_ROOM_ONLY]);
2556
        unset($profiles[BIGBLUEBUTTONBN_TYPE_ALL]);
2557
    }
2558
    if (!$recording) {
2559
        unset($profiles[BIGBLUEBUTTONBN_TYPE_RECORDING_ONLY]);
2560
        unset($profiles[BIGBLUEBUTTONBN_TYPE_ALL]);
2561
    }
2562
    return $profiles;
2563
}
2564
2565
/**
2566
 * Helper function returns an array with the profiles (with features per profile) for the different types
2567
 * of bigbluebuttonbn instances.
2568
 *
2569
 * @param array $profiles
2570
 *
2571
 * @return array
2572
 */
2573
function bigbluebuttonbn_get_instance_profiles_array($profiles = []) {
2574
    $profilesarray = array();
2575
    foreach ($profiles as $key => $profile) {
2576
        $profilesarray[$profile['id']] = $profile['name'];
2577
    }
2578
    return $profilesarray;
2579
}
2580
2581
/**
2582
 * Helper function returns time in a formatted string.
2583
 *
2584
 * @param integer $time
2585
 *
2586
 * @return string
2587
 */
2588
function bigbluebuttonbn_format_activity_time($time) {
2589
    global $CFG;
2590
    require_once($CFG->dirroot.'/calendar/lib.php');
2591
    $activitytime = '';
2592
    if ($time) {
2593
        $activitytime = calendar_day_representation($time) . ' ' .
2594
        get_string('mod_form_field_notification_msg_at', 'bigbluebuttonbn') . ' ' .
2595
        calendar_time_representation($time);
2596
    }
2597
    return $activitytime;
2598
}
2599
2600
/**
2601
 * Helper function returns array with all the strings to be used in javascript.
2602
 *
2603
 * @return array
2604
 */
2605
function bigbluebuttonbn_get_strings_for_js() {
2606
    $locale = bigbluebuttonbn_get_locale();
2607
    $stringman = get_string_manager();
2608
    $strings = $stringman->load_component_strings('bigbluebuttonbn', $locale);
2609
    return $strings;
2610
}
2611
2612
/**
2613
 * Helper function returns the locale set by moodle.
2614
 *
2615
 * @return string
2616
 */
2617
function bigbluebuttonbn_get_locale() {
2618
    $lang = get_string('locale', 'core_langconfig');
2619
    return substr($lang, 0, strpos($lang, '.'));
2620
}
2621
2622
/**
2623
 * Helper function returns the locale code based on the locale set by moodle.
2624
 *
2625
 * @return string
2626
 */
2627
function bigbluebuttonbn_get_localcode() {
2628
    $locale = bigbluebuttonbn_get_locale();
2629
    return substr($locale, 0, strpos($locale, '_'));
2630
}
2631
2632
/**
2633
 * Helper function returns array with the instance settings used in views.
2634
 *
2635
 * @param string $id
2636
 * @param object $bigbluebuttonbnid
2637
 *
2638
 * @return array
2639
 */
2640
function bigbluebuttonbn_view_validator($id, $bigbluebuttonbnid) {
2641
    if ($id) {
2642
        return bigbluebuttonbn_view_instance_id($id);
2643
    }
2644
    if ($bigbluebuttonbnid) {
2645
        return bigbluebuttonbn_view_instance_bigbluebuttonbn($bigbluebuttonbnid);
2646
    }
2647
}
2648
2649
/**
2650
 * Helper function returns array with the instance settings used in views based on id.
2651
 *
2652
 * @param string $id
2653
 *
2654
 * @return array
2655
 */
2656 View Code Duplication
function bigbluebuttonbn_view_instance_id($id) {
0 ignored issues
show
Duplication introduced by
This function seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
2657
    global $DB;
2658
    $cm = get_coursemodule_from_id('bigbluebuttonbn', $id, 0, false, MUST_EXIST);
2659
    $course = $DB->get_record('course', array('id' => $cm->course), '*', MUST_EXIST);
2660
    $bigbluebuttonbn = $DB->get_record('bigbluebuttonbn', array('id' => $cm->instance), '*', MUST_EXIST);
2661
    return array('cm' => $cm, 'course' => $course, 'bigbluebuttonbn' => $bigbluebuttonbn);
2662
}
2663
2664
/**
2665
 * Helper function returns array with the instance settings used in views based on bigbluebuttonbnid.
2666
 *
2667
 * @param object $bigbluebuttonbnid
2668
 *
2669
 * @return array
2670
 */
2671 View Code Duplication
function bigbluebuttonbn_view_instance_bigbluebuttonbn($bigbluebuttonbnid) {
0 ignored issues
show
Duplication introduced by
This function seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
2672
    global $DB;
2673
    $bigbluebuttonbn = $DB->get_record('bigbluebuttonbn', array('id' => $bigbluebuttonbnid), '*', MUST_EXIST);
2674
    $course = $DB->get_record('course', array('id' => $bigbluebuttonbn->course), '*', MUST_EXIST);
2675
    $cm = get_coursemodule_from_instance('bigbluebuttonbn', $bigbluebuttonbn->id, $course->id, false, MUST_EXIST);
2676
    return array('cm' => $cm, 'course' => $course, 'bigbluebuttonbn' => $bigbluebuttonbn);
2677
}
2678
2679
/**
2680
 * Helper function renders general settings if the feature is enabled.
2681
 *
2682
 * @param object $renderer
2683
 *
2684
 * @return void
2685
 */
2686
function bigbluebuttonbn_settings_general(&$renderer) {
2687
    // Configuration for BigBlueButton.
2688
    if ((boolean) \mod_bigbluebuttonbn\settings\validator::section_general_shown()) {
2689
        $renderer->render_group_header('general');
2690
        $renderer->render_group_element(
2691
            'server_url',
2692
            $renderer->render_group_element_text('server_url', BIGBLUEBUTTONBN_DEFAULT_SERVER_URL)
2693
        );
2694
        $renderer->render_group_element(
2695
            'shared_secret',
2696
            $renderer->render_group_element_text('shared_secret', BIGBLUEBUTTONBN_DEFAULT_SHARED_SECRET)
2697
        );
2698
    }
2699
}
2700
2701
/**
2702
 * Helper function renders record settings if the feature is enabled.
2703
 *
2704
 * @param object $renderer
2705
 *
2706
 * @return void
2707
 */
2708
function bigbluebuttonbn_settings_record(&$renderer) {
2709
    // Configuration for 'recording' feature.
2710
    if ((boolean) \mod_bigbluebuttonbn\settings\validator::section_record_meeting_shown()) {
2711
        $renderer->render_group_header('recording');
2712
        $renderer->render_group_element(
2713
            'recording_default',
2714
            $renderer->render_group_element_checkbox('recording_default', 1)
2715
        );
2716
        $renderer->render_group_element(
2717
            'recording_editable',
2718
            $renderer->render_group_element_checkbox('recording_editable', 1)
2719
        );
2720
        $renderer->render_group_element(
2721
            'recording_icons_enabled',
2722
            $renderer->render_group_element_checkbox('recording_icons_enabled', 1)
2723
        );
2724
2725
        // Add recording start to load and allow/hide stop/pause.
2726
        $renderer->render_group_element(
2727
            'recording_all_from_start_default',
2728
            $renderer->render_group_element_checkbox('recording_all_from_start_default', 0)
2729
        );
2730
        $renderer->render_group_element(
2731
            'recording_all_from_start_editable',
2732
            $renderer->render_group_element_checkbox('recording_all_from_start_editable', 0)
2733
        );
2734
        $renderer->render_group_element(
2735
            'recording_hide_button_default',
2736
            $renderer->render_group_element_checkbox('recording_hide_button_default', 0)
2737
        );
2738
        $renderer->render_group_element(
2739
            'recording_hide_button_editable',
2740
            $renderer->render_group_element_checkbox('recording_hide_button_editable', 0)
2741
        );
2742
    }
2743
}
2744
2745
/**
2746
 * Helper function renders import recording settings if the feature is enabled.
2747
 *
2748
 * @param object $renderer
2749
 *
2750
 * @return void
2751
 */
2752 View Code Duplication
function bigbluebuttonbn_settings_importrecordings(&$renderer) {
0 ignored issues
show
Duplication introduced by
This function seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
2753
    // Configuration for 'import recordings' feature.
2754
    if ((boolean) \mod_bigbluebuttonbn\settings\validator::section_import_recordings_shown()) {
2755
        $renderer->render_group_header('importrecordings');
2756
        $renderer->render_group_element(
2757
            'importrecordings_enabled',
2758
            $renderer->render_group_element_checkbox('importrecordings_enabled', 0)
2759
        );
2760
        $renderer->render_group_element(
2761
            'importrecordings_from_deleted_enabled',
2762
            $renderer->render_group_element_checkbox('importrecordings_from_deleted_enabled', 0)
2763
        );
2764
    }
2765
}
2766
2767
/**
2768
 * Helper function renders show recording settings if the feature is enabled.
2769
 *
2770
 * @param object $renderer
2771
 *
2772
 * @return void
2773
 */
2774
function bigbluebuttonbn_settings_showrecordings(&$renderer) {
2775
    // Configuration for 'show recordings' feature.
2776
    if ((boolean) \mod_bigbluebuttonbn\settings\validator::section_show_recordings_shown()) {
2777
        $renderer->render_group_header('recordings');
2778
        $renderer->render_group_element(
2779
            'recordings_html_default',
2780
            $renderer->render_group_element_checkbox('recordings_html_default', 1)
2781
        );
2782
        $renderer->render_group_element(
2783
            'recordings_html_editable',
2784
            $renderer->render_group_element_checkbox('recordings_html_editable', 0)
2785
        );
2786
        $renderer->render_group_element(
2787
            'recordings_deleted_default',
2788
            $renderer->render_group_element_checkbox('recordings_deleted_default', 1)
2789
        );
2790
        $renderer->render_group_element(
2791
            'recordings_deleted_editable',
2792
            $renderer->render_group_element_checkbox('recordings_deleted_editable', 0)
2793
        );
2794
        $renderer->render_group_element(
2795
            'recordings_imported_default',
2796
            $renderer->render_group_element_checkbox('recordings_imported_default', 0)
2797
        );
2798
        $renderer->render_group_element(
2799
            'recordings_imported_editable',
2800
            $renderer->render_group_element_checkbox('recordings_imported_editable', 1)
2801
        );
2802
        $renderer->render_group_element(
2803
            'recordings_preview_default',
2804
            $renderer->render_group_element_checkbox('recordings_preview_default', 1)
2805
        );
2806
        $renderer->render_group_element(
2807
            'recordings_preview_editable',
2808
            $renderer->render_group_element_checkbox('recordings_preview_editable', 0)
2809
        );
2810
        $renderer->render_group_element(
2811
            'recordings_sortorder',
2812
            $renderer->render_group_element_checkbox('recordings_sortorder', 0)
2813
        );
2814
        $renderer->render_group_element(
2815
            'recordings_validate_url',
2816
            $renderer->render_group_element_checkbox('recordings_validate_url', 1)
2817
        );
2818
    }
2819
}
2820
2821
/**
2822
 * Helper function renders wait for moderator settings if the feature is enabled.
2823
 *
2824
 * @param object $renderer
2825
 *
2826
 * @return void
2827
 */
2828
function bigbluebuttonbn_settings_waitmoderator(&$renderer) {
2829
    // Configuration for wait for moderator feature.
2830
    if ((boolean) \mod_bigbluebuttonbn\settings\validator::section_wait_moderator_shown()) {
2831
        $renderer->render_group_header('waitformoderator');
2832
        $renderer->render_group_element(
2833
            'waitformoderator_default',
2834
            $renderer->render_group_element_checkbox('waitformoderator_default', 0)
2835
        );
2836
        $renderer->render_group_element(
2837
            'waitformoderator_editable',
2838
            $renderer->render_group_element_checkbox('waitformoderator_editable', 1)
2839
        );
2840
        $renderer->render_group_element(
2841
            'waitformoderator_ping_interval',
2842
            $renderer->render_group_element_text('waitformoderator_ping_interval', 10, PARAM_INT)
2843
        );
2844
        $renderer->render_group_element(
2845
            'waitformoderator_cache_ttl',
2846
            $renderer->render_group_element_text('waitformoderator_cache_ttl', 60, PARAM_INT)
2847
        );
2848
    }
2849
}
2850
2851
/**
2852
 * Helper function renders static voice bridge settings if the feature is enabled.
2853
 *
2854
 * @param object $renderer
2855
 *
2856
 * @return void
2857
 */
2858
function bigbluebuttonbn_settings_voicebridge(&$renderer) {
2859
    // Configuration for "static voice bridge" feature.
2860
    if ((boolean) \mod_bigbluebuttonbn\settings\validator::section_static_voice_bridge_shown()) {
2861
        $renderer->render_group_header('voicebridge');
2862
        $renderer->render_group_element(
2863
            'voicebridge_editable',
2864
            $renderer->render_group_element_checkbox('voicebridge_editable', 0)
2865
        );
2866
    }
2867
}
2868
2869
/**
2870
 * Helper function renders preuploaded presentation settings if the feature is enabled.
2871
 *
2872
 * @param object $renderer
2873
 *
2874
 * @return void
2875
 */
2876
function bigbluebuttonbn_settings_preupload(&$renderer) {
2877
    // Configuration for "preupload presentation" feature.
2878
    if ((boolean) \mod_bigbluebuttonbn\settings\validator::section_preupload_presentation_shown()) {
2879
        // This feature only works if curl is installed.
2880
        $preuploaddescripion = get_string('config_preuploadpresentation_description', 'bigbluebuttonbn');
2881
        if (!extension_loaded('curl')) {
2882
            $preuploaddescripion .= '<div class="form-defaultinfo">';
2883
            $preuploaddescripion .= get_string('config_warning_curl_not_installed', 'bigbluebuttonbn');
2884
            $preuploaddescripion .= '</div><br>';
2885
        }
2886
        $renderer->render_group_header('preuploadpresentation', null, $preuploaddescripion);
2887
        if (extension_loaded('curl')) {
2888
            $renderer->render_group_element(
2889
                'preuploadpresentation_enabled',
2890
                $renderer->render_group_element_checkbox('preuploadpresentation_enabled', 0)
2891
            );
2892
        }
2893
    }
2894
}
2895
2896
/**
2897
 * Helper function renders preuploaded presentation manage file if the feature is enabled.
2898
 * This allow to select a file for use as default in all BBB instances if preuploaded presetantion is enable.
2899
 *
2900
 * @param object $renderer
2901
 *
2902
 * @return void
2903
 */
2904
function bigbluebuttonbn_settings_preupload_manage_default_file(&$renderer) {
2905
    // Configuration for "preupload presentation" feature.
2906
    if ((boolean) \mod_bigbluebuttonbn\settings\validator::section_preupload_presentation_shown()) {
2907
        if (extension_loaded('curl')) {
2908
            // This feature only works if curl is installed.
2909
            $renderer->render_filemanager_default_file_presentation("presentation_default");
2910
        }
2911
    }
2912
}
2913
2914
/**
2915
 * Helper function renders userlimit settings if the feature is enabled.
2916
 *
2917
 * @param object $renderer
2918
 *
2919
 * @return void
2920
 */
2921
function bigbluebuttonbn_settings_userlimit(&$renderer) {
2922
    // Configuration for "user limit" feature.
2923
    if ((boolean) \mod_bigbluebuttonbn\settings\validator::section_user_limit_shown()) {
2924
        $renderer->render_group_header('userlimit');
2925
        $renderer->render_group_element(
2926
            'userlimit_default',
2927
            $renderer->render_group_element_text('userlimit_default', 0, PARAM_INT)
2928
        );
2929
        $renderer->render_group_element(
2930
            'userlimit_editable',
2931
            $renderer->render_group_element_checkbox('userlimit_editable', 0)
2932
        );
2933
    }
2934
}
2935
2936
/**
2937
 * Helper function renders duration settings if the feature is enabled.
2938
 *
2939
 * @param object $renderer
2940
 *
2941
 * @return void
2942
 */
2943
function bigbluebuttonbn_settings_duration(&$renderer) {
2944
    // Configuration for "scheduled duration" feature.
2945
    if ((boolean) \mod_bigbluebuttonbn\settings\validator::section_scheduled_duration_shown()) {
2946
        $renderer->render_group_header('scheduled');
2947
        $renderer->render_group_element(
2948
            'scheduled_duration_enabled',
2949
            $renderer->render_group_element_checkbox('scheduled_duration_enabled', 1)
2950
        );
2951
        $renderer->render_group_element(
2952
            'scheduled_duration_compensation',
2953
            $renderer->render_group_element_text('scheduled_duration_compensation', 10, PARAM_INT)
2954
        );
2955
        $renderer->render_group_element(
2956
            'scheduled_pre_opening',
2957
            $renderer->render_group_element_text('scheduled_pre_opening', 10, PARAM_INT)
2958
        );
2959
    }
2960
}
2961
2962
/**
2963
 * Helper function renders participant settings if the feature is enabled.
2964
 *
2965
 * @param object $renderer
2966
 *
2967
 * @return void
2968
 */
2969
function bigbluebuttonbn_settings_participants(&$renderer) {
2970
    // Configuration for defining the default role/user that will be moderator on new activities.
2971
    if ((boolean) \mod_bigbluebuttonbn\settings\validator::section_moderator_default_shown()) {
2972
        $renderer->render_group_header('participant');
2973
        $renderer->render_group_element(
2974
            'participant_guestlink',
2975
            $renderer->render_group_element_checkbox('participant_guestlink', 0)
2976
        );
2977
        $renderer->render_group_element(
2978
            'participant_guestlink_logo',
2979
            $renderer->render_group_element_text('custom_logo', '')
2980
            );
2981
        // UI for 'participants' feature.
2982
        $roles = bigbluebuttonbn_get_roles(null, false);
2983
        $owner = array('0' => get_string('mod_form_field_participant_list_type_owner', 'bigbluebuttonbn'));
2984
        $renderer->render_group_element(
2985
            'participant_moderator_default',
2986
            $renderer->render_group_element_configmultiselect(
2987
                'participant_moderator_default',
2988
                array_keys($owner),
2989
                $owner + $roles // CONTRIB-7966: don't use array_merge here so it does not reindex the array.
2990
            )
2991
        );
2992
    }
2993
}
2994
2995
/**
2996
 * Helper function renders notification settings if the feature is enabled.
2997
 *
2998
 * @param object $renderer
2999
 *
3000
 * @return void
3001
 */
3002
function bigbluebuttonbn_settings_notifications(&$renderer) {
3003
    // Configuration for "send notifications" feature.
3004
    if ((boolean) \mod_bigbluebuttonbn\settings\validator::section_send_notifications_shown()) {
3005
        $renderer->render_group_header('sendnotifications');
3006
        $renderer->render_group_element(
3007
            'sendnotifications_enabled',
3008
            $renderer->render_group_element_checkbox('sendnotifications_enabled', 1)
3009
        );
3010
    }
3011
}
3012
3013
/**
3014
 * Helper function renders client type settings if the feature is enabled.
3015
 *
3016
 * @param object $renderer
3017
 *
3018
 * @return void
3019
 */
3020
function bigbluebuttonbn_settings_clienttype(&$renderer) {
3021
    // Configuration for "clienttype" feature.
3022
    if ((boolean) \mod_bigbluebuttonbn\settings\validator::section_clienttype_shown()) {
3023
        $renderer->render_group_header('clienttype');
3024
        $renderer->render_group_element(
3025
            'clienttype_editable',
3026
            $renderer->render_group_element_checkbox('clienttype_editable', 0)
3027
        );
3028
        // Web Client default.
3029
        $default = intval((int) \mod_bigbluebuttonbn\locallib\config::get('clienttype_default'));
3030
        $choices = array(BIGBLUEBUTTON_CLIENTTYPE_FLASH => get_string('mod_form_block_clienttype_flash', 'bigbluebuttonbn'),
3031
            BIGBLUEBUTTON_CLIENTTYPE_HTML5 => get_string('mod_form_block_clienttype_html5', 'bigbluebuttonbn'));
3032
        $renderer->render_group_element(
3033
            'clienttype_default',
3034
            $renderer->render_group_element_configselect(
3035
                'clienttype_default',
3036
                $default,
3037
                $choices
3038
            )
3039
        );
3040
    }
3041
}
3042
3043
/**
3044
 * Helper function renders general settings if the feature is enabled.
3045
 *
3046
 * @param object $renderer
3047
 *
3048
 * @return void
3049
 */
3050 View Code Duplication
function bigbluebuttonbn_settings_muteonstart(&$renderer) {
0 ignored issues
show
Duplication introduced by
This function seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
3051
    // Configuration for BigBlueButton.
3052
    if ((boolean) \mod_bigbluebuttonbn\settings\validator::section_muteonstart_shown()) {
3053
        $renderer->render_group_header('muteonstart');
3054
        $renderer->render_group_element(
3055
            'muteonstart_default',
3056
            $renderer->render_group_element_checkbox('muteonstart_default', 0)
3057
        );
3058
        $renderer->render_group_element(
3059
            'muteonstart_editable',
3060
            $renderer->render_group_element_checkbox('muteonstart_editable', 0)
3061
        );
3062
    }
3063
}
3064
3065
/**
3066
 * Helper function renders general settings if the feature is enabled.
3067
 *
3068
 * @param object $renderer
3069
 *
3070
 * @return void
3071
 */
3072
function bigbluebuttonbn_settings_locksettings(&$renderer) {
3073
    $renderer->render_group_header('locksettings');
3074
    // Configuration for various lock settings for meetings.
3075
    bigbluebuttonbn_settings_disablecam($renderer);
3076
    bigbluebuttonbn_settings_disablemic($renderer);
3077
    bigbluebuttonbn_settings_disableprivatechat($renderer);
3078
    bigbluebuttonbn_settings_disablepublicchat($renderer);
3079
    bigbluebuttonbn_settings_disablenote($renderer);
3080
    bigbluebuttonbn_settings_hideuserlist($renderer);
3081
    bigbluebuttonbn_settings_lockedlayout($renderer);
3082
    bigbluebuttonbn_settings_lockonjoin($renderer);
3083
    bigbluebuttonbn_settings_lockonjoinconfigurable($renderer);
3084
}
3085
3086
/**
3087
 * Helper function renders general settings if the feature is enabled.
3088
 *
3089
 * @param object $renderer
3090
 *
3091
 * @return void
3092
 */
3093
function bigbluebuttonbn_settings_disablecam(&$renderer) {
3094
    // Configuration for BigBlueButton.
3095
    if ((boolean) \mod_bigbluebuttonbn\settings\validator::section_disablecam_shown()) {
3096
        $renderer->render_group_element(
3097
            'disablecam_default',
3098
            $renderer->render_group_element_checkbox('disablecam_default', 0)
3099
        );
3100
        $renderer->render_group_element(
3101
            'disablecam_editable',
3102
            $renderer->render_group_element_checkbox('disablecam_editable', 1)
3103
        );
3104
    }
3105
}
3106
3107
/**
3108
 * Helper function renders general settings if the feature is enabled.
3109
 *
3110
 * @param object $renderer
3111
 *
3112
 * @return void
3113
 */
3114
function bigbluebuttonbn_settings_disablemic(&$renderer) {
3115
    // Configuration for BigBlueButton.
3116
    if ((boolean) \mod_bigbluebuttonbn\settings\validator::section_disablemic_shown()) {
3117
        $renderer->render_group_element(
3118
            'disablemic_default',
3119
            $renderer->render_group_element_checkbox('disablemic_default', 0)
3120
        );
3121
        $renderer->render_group_element(
3122
            'disablecam_editable',
3123
            $renderer->render_group_element_checkbox('disablemic_editable', 1)
3124
        );
3125
    }
3126
}
3127
3128
/**
3129
 * Helper function renders general settings if the feature is enabled.
3130
 *
3131
 * @param object $renderer
3132
 *
3133
 * @return void
3134
 */
3135
function bigbluebuttonbn_settings_disableprivatechat(&$renderer) {
3136
    // Configuration for BigBlueButton.
3137
    if ((boolean) \mod_bigbluebuttonbn\settings\validator::section_disableprivatechat_shown()) {
3138
        $renderer->render_group_element(
3139
            'disableprivatechat_default',
3140
            $renderer->render_group_element_checkbox('disableprivatechat_default', 0)
3141
        );
3142
        $renderer->render_group_element(
3143
            'disableprivatechat_editable',
3144
            $renderer->render_group_element_checkbox('disableprivatechat_editable', 1)
3145
        );
3146
    }
3147
}
3148
3149
/**
3150
 * Helper function renders general settings if the feature is enabled.
3151
 *
3152
 * @param object $renderer
3153
 *
3154
 * @return void
3155
 */
3156
function bigbluebuttonbn_settings_disablepublicchat(&$renderer) {
3157
    // Configuration for BigBlueButton.
3158
    if ((boolean) \mod_bigbluebuttonbn\settings\validator::section_disablepublicchat_shown()) {
3159
        $renderer->render_group_element(
3160
            'disablepublicchat_default',
3161
            $renderer->render_group_element_checkbox('disablepublicchat_default', 0)
3162
        );
3163
        $renderer->render_group_element(
3164
            'disablepublicchat_editable',
3165
            $renderer->render_group_element_checkbox('disablepublicchat_editable', 1)
3166
        );
3167
    }
3168
}
3169
3170
/**
3171
 * Helper function renders general settings if the feature is enabled.
3172
 *
3173
 * @param object $renderer
3174
 *
3175
 * @return void
3176
 */
3177
function bigbluebuttonbn_settings_disablenote(&$renderer) {
3178
    // Configuration for BigBlueButton.
3179
    if ((boolean) \mod_bigbluebuttonbn\settings\validator::section_disablenote_shown()) {
3180
        $renderer->render_group_element(
3181
            'disablenote_default',
3182
            $renderer->render_group_element_checkbox('disablenote_default', 0)
3183
        );
3184
        $renderer->render_group_element(
3185
            'disablenote_editable',
3186
            $renderer->render_group_element_checkbox('disablenote_editable', 1)
3187
        );
3188
    }
3189
}
3190
3191
/**
3192
 * Helper function renders general settings if the feature is enabled.
3193
 *
3194
 * @param object $renderer
3195
 *
3196
 * @return void
3197
 */
3198
function bigbluebuttonbn_settings_hideuserlist(&$renderer) {
3199
    // Configuration for BigBlueButton.
3200
    if ((boolean) \mod_bigbluebuttonbn\settings\validator::section_hideuserlist_shown()) {
3201
        $renderer->render_group_element(
3202
            'hideuserlist_default',
3203
            $renderer->render_group_element_checkbox('hideuserlist_default', 0)
3204
        );
3205
        $renderer->render_group_element(
3206
            'hideuserlist_editable',
3207
            $renderer->render_group_element_checkbox('hideuserlist_editable', 1)
3208
        );
3209
    }
3210
}
3211
3212
/**
3213
 * Helper function renders general settings if the feature is enabled.
3214
 *
3215
 * @param object $renderer
3216
 *
3217
 * @return void
3218
 */
3219
function bigbluebuttonbn_settings_lockedlayout(&$renderer) {
3220
    // Configuration for BigBlueButton.
3221
    if ((boolean) \mod_bigbluebuttonbn\settings\validator::section_lockedlayout_shown()) {
3222
        $renderer->render_group_element(
3223
            'lockedlayout_default',
3224
            $renderer->render_group_element_checkbox('lockedlayout_default', 0)
3225
        );
3226
        $renderer->render_group_element(
3227
            'lockedlayout_editable',
3228
            $renderer->render_group_element_checkbox('lockedlayout_editable', 1)
3229
        );
3230
    }
3231
}
3232
3233
/**
3234
 * Helper function renders general settings if the feature is enabled.
3235
 *
3236
 * @param object $renderer
3237
 *
3238
 * @return void
3239
 */
3240
function bigbluebuttonbn_settings_lockonjoin(&$renderer) {
3241
    // Configuration for BigBlueButton.
3242
    if ((boolean) \mod_bigbluebuttonbn\settings\validator::section_lockonjoin_shown()) {
3243
        $renderer->render_group_element(
3244
            'lockonjoin_default',
3245
            $renderer->render_group_element_checkbox('lockonjoin_default', 0)
3246
        );
3247
        $renderer->render_group_element(
3248
            'lockonjoin_editable',
3249
            $renderer->render_group_element_checkbox('lockonjoin_editable', 1)
3250
        );
3251
    }
3252
}
3253
3254
/**
3255
 * Helper function renders general settings if the feature is enabled.
3256
 *
3257
 * @param object $renderer
3258
 *
3259
 * @return void
3260
 */
3261
function bigbluebuttonbn_settings_lockonjoinconfigurable(&$renderer) {
3262
    // Configuration for BigBlueButton.
3263
    if ((boolean) \mod_bigbluebuttonbn\settings\validator::section_lockonjoinconfigurable_shown()) {
3264
        $renderer->render_group_element(
3265
            'lockonjoinconfigurable_default',
3266
            $renderer->render_group_element_checkbox('lockonjoinconfigurable_default', 0)
3267
        );
3268
        $renderer->render_group_element(
3269
            'lockonjoinconfigurable_editable',
3270
            $renderer->render_group_element_checkbox('lockonjoinconfigurable_editable', 1)
3271
        );
3272
    }
3273
}
3274
3275
/**
3276
 * Helper function renders extended settings if any of the features there is enabled.
3277
 *
3278
 * @param object $renderer
3279
 *
3280
 * @return void
3281
 */
3282
function bigbluebuttonbn_settings_extended(&$renderer) {
3283
    // Configuration for extended capabilities.
3284
    if (!(boolean) \mod_bigbluebuttonbn\settings\validator::section_settings_extended_shown()) {
3285
        return;
3286
    }
3287
    $renderer->render_group_header('extended_capabilities');
3288
    // UI for 'notify users when recording ready' feature.
3289
    $renderer->render_group_element(
3290
        'recordingready_enabled',
3291
        $renderer->render_group_element_checkbox('recordingready_enabled', 0)
3292
    );
3293
    // Configuration for extended BN capabilities should go here.
3294
}
3295
3296
/**
3297
 * Helper function renders experimental settings if any of the features there is enabled.
3298
 *
3299
 * @param object $renderer
3300
 *
3301
 * @return void
3302
 */
3303
function bigbluebuttonbn_settings_experimental(&$renderer) {
3304
    // Configuration for experimental features should go here.
3305
    $renderer->render_group_header('experimental_features');
3306
    // UI for 'register meeting events' feature.
3307
    $renderer->render_group_element(
3308
        'meetingevents_enabled',
3309
        $renderer->render_group_element_checkbox('meetingevents_enabled', 0)
3310
    );
3311
}
3312
3313
/**
3314
 * Helper function returns a sha1 encoded string that is unique and will be used as a seed for meetingid.
3315
 *
3316
 * @return string
3317
 */
3318
function bigbluebuttonbn_unique_meetingid_seed() {
3319
    global $DB;
3320
    do {
3321
        $encodedseed = sha1(bigbluebuttonbn_random_password(12));
3322
        $meetingid = (string) $DB->get_field('bigbluebuttonbn', 'meetingid', array('meetingid' => $encodedseed));
3323
    } while ($meetingid == $encodedseed);
3324
    return $encodedseed;
3325
}
3326
3327
/**
3328
 * Helper function renders the link used for recording type in row for the data used by the recording table.
3329
 *
3330
 * @param array $recording
3331
 * @param array $bbbsession
3332
 * @param array $playback
3333
 *
3334
 * @return boolean
3335
 */
3336
function bigbluebuttonbn_include_recording_data_row_type($recording, $bbbsession, $playback) {
3337
    // All types that are not restricted are included.
3338
    if (array_key_exists('restricted', $playback) && strtolower($playback['restricted']) == 'false') {
3339
        return true;
3340
    }
3341
    // All types that are not statistics are included.
3342
    if ($playback['type'] != 'statistics') {
3343
        return true;
3344
    }
3345
    // Exclude imported recordings.
3346
    if (isset($recording['imported'])) {
3347
        return false;
3348
    }
3349
    // Exclude non moderators.
3350
    if (!$bbbsession['administrator'] && !$bbbsession['moderator']) {
3351
        return false;
3352
    }
3353
    return true;
3354
}
3355
3356
/**
3357
 * Renders the general warning message.
3358
 *
3359
 * @param string $message
3360
 * @param string $type
3361
 * @param string $href
3362
 * @param string $text
3363
 * @param string $class
3364
 *
3365
 * @return string
3366
 */
3367
function bigbluebuttonbn_render_warning($message, $type = 'info', $href = '', $text = '', $class = '') {
3368
    global $OUTPUT;
3369
    $output = "\n";
3370
    // Evaluates if config_warning is enabled.
3371
    if (empty($message)) {
3372
        return $output;
3373
    }
3374
    $output .= $OUTPUT->box_start(
3375
        'box boxalignleft adminerror alert alert-' . $type . ' alert-block fade in',
3376
        'bigbluebuttonbn_view_general_warning'
3377
    ) . "\n";
3378
    $output .= '    ' . $message . "\n";
3379
    $output .= '  <div class="singlebutton pull-right">' . "\n";
3380
    if (!empty($href)) {
3381
        $output .= bigbluebuttonbn_render_warning_button($href, $text, $class);
3382
    }
3383
    $output .= '  </div>' . "\n";
3384
    $output .= $OUTPUT->box_end() . "\n";
3385
    return $output;
3386
}
3387
3388
/**
3389
 * Renders the general warning button.
3390
 *
3391
 * @param string $href
3392
 * @param string $text
3393
 * @param string $class
3394
 * @param string $title
3395
 *
3396
 * @return string
3397
 */
3398
function bigbluebuttonbn_render_warning_button($href, $text = '', $class = '', $title = '') {
3399
    if ($text == '') {
3400
        $text = get_string('ok', 'moodle');
3401
    }
3402
    if ($title == '') {
3403
        $title = $text;
3404
    }
3405
    if ($class == '') {
3406
        $class = 'btn btn-secondary';
3407
    }
3408
    $output = '  <form method="post" action="' . $href . '" class="form-inline">' . "\n";
3409
    $output .= '      <button type="submit" class="' . $class . '"' . "\n";
3410
    $output .= '          title="' . $title . '"' . "\n";
3411
    $output .= '          >' . $text . '</button>' . "\n";
3412
    $output .= '  </form>' . "\n";
3413
    return $output;
3414
}
3415
3416
/**
3417
 * Check if a BigBlueButtonBN is available to be used by the current user.
3418
 *
3419
 * @param  stdClass  $bigbluebuttonbn  BigBlueButtonBN instance
3420
 *
3421
 * @return boolean                     status if room available and current user allowed to join
3422
 */
3423
function bigbluebuttonbn_get_availability_status($bigbluebuttonbn) {
3424
    list($roomavailable) = bigbluebuttonbn_room_is_available($bigbluebuttonbn);
3425
    list($usercanjoin) = bigbluebuttonbn_user_can_join_meeting($bigbluebuttonbn);
3426
    return ($roomavailable && $usercanjoin);
3427
}
3428
3429
/**
3430
 * Helper for evaluating if scheduled activity is avaiable.
3431
 *
3432
 * @param  stdClass  $bigbluebuttonbn  BigBlueButtonBN instance
3433
 *
3434
 * @return array                       status (room available or not and possible warnings)
3435
 */
3436
function bigbluebuttonbn_room_is_available($bigbluebuttonbn) {
3437
    $open = true;
3438
    $closed = false;
3439
    $warnings = array();
3440
3441
    $timenow = time();
3442
    $timeopen = $bigbluebuttonbn->openingtime;
3443
    $timeclose = $bigbluebuttonbn->closingtime;
3444
    if (!empty($timeopen) && $timeopen > $timenow) {
3445
        $open = false;
3446
    }
3447
    if (!empty($timeclose) && $timenow > $timeclose) {
3448
        $closed = true;
3449
    }
3450
3451
    if (!$open || $closed) {
3452
        if (!$open) {
3453
            $warnings['notopenyet'] = userdate($timeopen);
3454
        }
3455
        if ($closed) {
3456
            $warnings['expired'] = userdate($timeclose);
3457
        }
3458
        return array(false, $warnings);
3459
    }
3460
3461
    return array(true, $warnings);
3462
}
3463
3464
/**
3465
 * Helper for evaluating if meeting can be joined.
3466
 *
3467
 * @param  stdClass $bigbluebuttonbn  BigBlueButtonBN instance
3468
 * @param  string   $mid
3469
 * @param  integer  $userid
3470
 *
3471
 * @return array    status (user allowed to join or not and possible message)
3472
 */
3473
function bigbluebuttonbn_user_can_join_meeting($bigbluebuttonbn, $mid = null, $userid = null) {
3474
    // By default, use a meetingid without groups.
3475
    if (empty($mid)) {
3476
        $mid = $bigbluebuttonbn->meetingid . '-' . $bigbluebuttonbn->course . '-' . $bigbluebuttonbn->id;
3477
    }
3478
    // When meeting is running, all authorized users can join right in.
3479
    if (bigbluebuttonbn_is_meeting_running($mid)) {
3480
        return array(true, get_string('view_message_conference_in_progress', 'bigbluebuttonbn'));
3481
    }
3482
    // When meeting is not running, see if the user can join.
3483
    $context = context_course::instance($bigbluebuttonbn->course);
3484
    $participantlist = bigbluebuttonbn_get_participant_list($bigbluebuttonbn, $context);
3485
    $isadmin = is_siteadmin($userid);
3486
    $ismoderator = bigbluebuttonbn_is_moderator($context, $participantlist, $userid);
3487
    // If user is administrator, moderator or if is viewer and no waiting is required, join allowed.
3488
    if ($isadmin || $ismoderator || !$bigbluebuttonbn->wait) {
3489
        return array(true, get_string('view_message_conference_room_ready', 'bigbluebuttonbn'));
3490
    }
3491
    // Otherwise, no join allowed.
3492
    return array(false, get_string('view_message_conference_wait_for_moderator', 'bigbluebuttonbn'));
3493
}
3494
3495
/**
3496
 * Helper for getting a value from a bigbluebuttonbn cache.
3497
 *
3498
 * @param  string   $name       BigBlueButtonBN cache
3499
 * @param  string   $key        Key to be retrieved
3500
 * @param  integer  $default    Default value in case key is not found or it is empty
3501
 *
3502
 * @return variable key value
3503
 */
3504
function bigbluebuttonbn_cache_get($name, $key, $default = null) {
3505
    $cache = cache::make_from_params(cache_store::MODE_APPLICATION, 'mod_bigbluebuttonbn', $name);
3506
    $result = $cache->get($key);
3507
    if (!empty($result)) {
3508
        return $result;
3509
    }
3510
    return $default;
3511
}
3512
3513
/**
3514
 * Helper for setting a value in a bigbluebuttonbn cache.
3515
 *
3516
 * @param  string   $name       BigBlueButtonBN cache
3517
 * @param  string   $key        Key to be created/updated
3518
 * @param  variable $value      Default value to be set
3519
 */
3520
function bigbluebuttonbn_cache_set($name, $key, $value) {
3521
    $cache = cache::make_from_params(cache_store::MODE_APPLICATION, 'mod_bigbluebuttonbn', $name);
3522
    $cache->set($key, $value);
3523
}
3524
3525
/**
3526
 * Helper for getting the owner userid of a bigbluebuttonbn instance.
3527
 *
3528
 * @param  stdClass $bigbluebuttonbn  BigBlueButtonBN instance
3529
 *
3530
 * @return integer ownerid (a valid user id or null if not registered/found)
3531
 */
3532
function bigbluebuttonbn_instance_ownerid($bigbluebuttonbn) {
3533
    global $DB;
3534
    $filters = array('bigbluebuttonbnid' => $bigbluebuttonbn->id, 'log' => 'Add');
3535
    $ownerid = (integer) $DB->get_field('bigbluebuttonbn_logs', 'userid', $filters);
3536
    return $ownerid;
3537
}
3538
3539
/**
3540
 * Helper evaluates if the bigbluebutton server used belongs to blindsidenetworks domain.
3541
 *
3542
 * @return boolean
3543
 */
3544
function bigbluebuttonbn_has_html5_client() {
3545
    $checkurl = \mod_bigbluebuttonbn\locallib\bigbluebutton::root() . "html5client/check";
3546
    $curlinfo = bigbluebuttonbn_wrap_xml_load_file_curl_request($checkurl, 'HEAD');
3547
    return (isset($curlinfo['http_code']) && $curlinfo['http_code'] == 200);
3548
}
3549
3550
/**
3551
 * Return the status of an activity [open|not_started|ended].
3552
 *
3553
 * @param array $bbbsession
3554
 * @return string
3555
 */
3556 View Code Duplication
function bigbluebuttonbn_view_get_activity_status(&$bbbsession) {
0 ignored issues
show
Duplication introduced by
This function seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
3557
    $now = time();
3558
    if (!empty($bbbsession['bigbluebuttonbn']->openingtime) && $now < $bbbsession['bigbluebuttonbn']->openingtime) {
3559
        // The activity has not been opened.
3560
        return 'not_started';
3561
    }
3562
    if (!empty($bbbsession['bigbluebuttonbn']->closingtime) && $now > $bbbsession['bigbluebuttonbn']->closingtime) {
3563
        // The activity has been closed.
3564
        return 'ended';
3565
    }
3566
    // The activity is open.
3567
    return 'open';
3568
}
3569
3570
/**
3571
 * Set session URLs.
3572
 *
3573
 * @param array $bbbsession
3574
 * @param int $id
3575
 * @return string
3576
 */
3577
function bigbluebuttonbn_view_session_config(&$bbbsession, $id) {
3578
    // Operation URLs.
3579
    $bbbsession['bigbluebuttonbnURL'] = plugin::necurl(
3580
        '/mod/bigbluebuttonbn/view.php',
3581
        ['id' => $bbbsession['cm']->id]
3582
    );
3583
    $bbbsession['logoutURL'] = plugin::necurl(
3584
        '/mod/bigbluebuttonbn/bbb_view.php',
3585
        ['action' => 'logout', 'id' => $id, 'bn' => $bbbsession['bigbluebuttonbn']->id]
3586
    );
3587
    $bbbsession['recordingReadyURL'] = plugin::necurl(
3588
        '/mod/bigbluebuttonbn/bbb_broker.php',
3589
        ['action' => 'recording_ready', 'bigbluebuttonbn' => $bbbsession['bigbluebuttonbn']->id]
3590
    );
3591
    $bbbsession['meetingEventsURL'] = plugin::necurl(
3592
        '/mod/bigbluebuttonbn/bbb_broker.php',
3593
        ['action' => 'meeting_events', 'bigbluebuttonbn' => $bbbsession['bigbluebuttonbn']->id]
3594
    );
3595
    $bbbsession['joinURL'] = plugin::necurl(
3596
        '/mod/bigbluebuttonbn/bbb_view.php',
3597
        ['action' => 'join', 'id' => $id, 'bn' => $bbbsession['bigbluebuttonbn']->id]
3598
    );
3599
3600
    // Check status and set extra values.
3601
    $activitystatus = bigbluebuttonbn_view_get_activity_status($bbbsession); // In locallib.
3602 View Code Duplication
    if ($activitystatus == 'ended') {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
3603
        $bbbsession['presentation'] = bigbluebuttonbn_get_presentation_array(
3604
            $bbbsession['context'],
3605
            $bbbsession['bigbluebuttonbn']->presentation
3606
        );
3607
    } else if ($activitystatus == 'open') {
3608
        $bbbsession['presentation'] = bigbluebuttonbn_get_presentation_array(
3609
            $bbbsession['context'],
3610
            $bbbsession['bigbluebuttonbn']->presentation,
3611
            $bbbsession['bigbluebuttonbn']->id
3612
        );
3613
    }
3614
3615
    return $activitystatus;
3616
}
3617
3618
/**
3619
 * Helper for preparing metadata used while creating the meeting.
3620
 *
3621
 * @param  array    $bbbsession
3622
 * @return array
3623
 */
3624
function bigbluebuttonbn_create_meeting_metadata(&$bbbsession) {
3625
    global $USER;
3626
    // Create standard metadata.
3627
    $metadata = [
3628
        'bbb-origin' => $bbbsession['origin'],
3629
        'bbb-origin-version' => $bbbsession['originVersion'],
3630
        'bbb-origin-server-name' => $bbbsession['originServerName'],
3631
        'bbb-origin-server-common-name' => $bbbsession['originServerCommonName'],
3632
        'bbb-origin-tag' => $bbbsession['originTag'],
3633
        'bbb-context' => $bbbsession['course']->fullname,
3634
        'bbb-context-id' => $bbbsession['course']->id,
3635
        'bbb-context-name' => trim(html_to_text($bbbsession['course']->fullname, 0)),
3636
        'bbb-context-label' => trim(html_to_text($bbbsession['course']->shortname, 0)),
3637
        'bbb-recording-name' => bigbluebuttonbn_html2text($bbbsession['meetingname'], 64),
3638
        'bbb-recording-description' => bigbluebuttonbn_html2text($bbbsession['meetingdescription'], 64),
3639
        'bbb-recording-tags' => bigbluebuttonbn_get_tags($bbbsession['cm']->id), // Same as $id.
3640
    ];
3641
    // Special metadata for recording processing.
3642
    if ((boolean) \mod_bigbluebuttonbn\locallib\config::get('recordingstatus_enabled')) {
3643
        $metadata["bn-recording-status"] = json_encode(
3644
            array(
3645
                'email' => array('"' . fullname($USER) . '" <' . $USER->email . '>'),
3646
                'context' => $bbbsession['bigbluebuttonbnURL'],
3647
            )
3648
        );
3649
    }
3650
    if ((boolean) \mod_bigbluebuttonbn\locallib\config::get('recordingready_enabled')) {
3651
        $metadata['bn-recording-ready-url'] = $bbbsession['recordingReadyURL'];
3652
    }
3653
    if ((boolean) \mod_bigbluebuttonbn\locallib\config::get('meetingevents_enabled')) {
3654
        $metadata['analytics-callback-url'] = $bbbsession['meetingEventsURL'];
3655
    }
3656
    return $metadata;
3657
}
3658
3659
/**
3660
 * Helper for preparing data used while joining the meeting.
3661
 *
3662
 * @param array    $bbbsession
3663
 * @param object   $bigbluebuttonbn
3664
 * @param integer  $origin
3665
 */
3666
function bigbluebuttonbn_join_meeting($bbbsession, $bigbluebuttonbn, $origin = 0) {
3667
    // Update the cache.
3668
    $meetinginfo = bigbluebuttonbn_get_meeting_info($bbbsession['meetingid'], BIGBLUEBUTTONBN_UPDATE_CACHE);
3669
    if ($bbbsession['userlimit'] > 0 && intval($meetinginfo['participantCount']) >= $bbbsession['userlimit']) {
3670
        // No more users allowed to join.
3671
        header('Location: '.$bbbsession['logoutURL']);
3672
        return;
3673
    }
3674
    // Build the URL.
3675
    $password = $bbbsession['viewerPW'];
3676
    if ($bbbsession['administrator'] || $bbbsession['moderator']) {
3677
        $password = $bbbsession['modPW'];
3678
    }
3679
    $joinurl = bigbluebuttonbn_get_join_url($bbbsession['meetingid'], $bbbsession['username'],
3680
        $password, $bbbsession['logoutURL'], null, $bbbsession['userID'], $bbbsession['clienttype']);
3681
    // Moodle event logger: Create an event for meeting joined.
3682
    bigbluebuttonbn_event_log(\mod_bigbluebuttonbn\event\events::$events['meeting_join'], $bigbluebuttonbn);
3683
    // Internal logger: Instert a record with the meeting created.
3684
    $overrides = array('meetingid' => $bbbsession['meetingid']);
3685
    $meta = '{"origin":'.$origin.'}';
3686
    bigbluebuttonbn_log($bbbsession['bigbluebuttonbn'], BIGBLUEBUTTONBN_LOG_EVENT_JOIN, $overrides, $meta);
3687
    // Before executing the redirect, increment the number of participants.
3688
    bigbluebuttonbn_participant_joined($bbbsession['meetingid'],
3689
        ($bbbsession['administrator'] || $bbbsession['moderator']));
3690
    // Execute the redirect.
3691
    header('Location: '.$joinurl);
3692
}
3693
3694
/**
3695
 * Helperfunction for getting the bigbluebutton instance with guestlink id
3696
 *
3697
 * @param string $guestlinkid
3698
 * @return mixed|stdClass|false
3699
 */
3700
function bigbluebuttonbn_get_bigbluebuttonbn_by_guestlinkid(string $guestlinkid) {
3701
    global $DB;
3702
    return $DB->get_record('bigbluebuttonbn', ['guestlinkid' => $guestlinkid]);
3703
}
3704