Completed
Pull Request — master (#289)
by
unknown
02:23
created

locallib.php ➔ bigbluebuttonbn_get_bigbluebuttonbn_by_guestlinkid()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 1
dl 0
loc 4
rs 10
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
 * @param string $createtime
103
 *
104
 * @return string
105
 */
106
function bigbluebuttonbn_get_join_url(
107
    $meetingid,
108
    $username,
109
    $pw,
110
    $logouturl,
111
    $configtoken = null,
112
    $userid = null,
113
    $clienttype = BIGBLUEBUTTON_CLIENTTYPE_FLASH,
114
    $createtime = null,
115
    $guest = false
116
) {
117
    $data = ['meetingID' => $meetingid,
118
        'fullName' => $username,
119
        'password' => $pw,
120
        'logoutURL' => $logouturl,
121
    ];
122
    // Choose between Adobe Flash or HTML5 Client.
123
    if ($clienttype == BIGBLUEBUTTON_CLIENTTYPE_HTML5) {
124
        $data['joinViaHtml5'] = 'true';
125
    }
126
    if (!is_null($configtoken)) {
127
        $data['configToken'] = $configtoken;
128
    }
129
    if (!is_null($userid)) {
130
        $data['userID'] = $userid;
131
    }
132
    if (!is_null($createtime)) {
133
        $data['createTime'] = $createtime;
134
    }
135
    $data['guest'] = ($guest ? 'true' : 'false');
136
    return \mod_bigbluebuttonbn\locallib\bigbluebutton::action_url('join', $data);
137
}
138
139
/**
140
 * Creates a bigbluebutton meeting and returns the response in an array.
141
 *
142
 * @param array  $data
143
 * @param array  $metadata
144
 * @param string $pname
145
 * @param string $purl
146
 *
147
 * @return array
148
 */
149
function bigbluebuttonbn_get_create_meeting_array($data, $metadata = array(), $pname = null, $purl = null) {
150
    $createmeetingurl = \mod_bigbluebuttonbn\locallib\bigbluebutton::action_url('create', $data, $metadata);
151
    $method = 'GET';
152
    $payload = null;
153
    if (!is_null($pname) && !is_null($purl)) {
154
        $method = 'POST';
155
        $payload = "<?xml version='1.0' encoding='UTF-8'?><modules><module name='presentation'><document url='".
156
            $purl."' /></module></modules>";
157
    }
158
    $xml = bigbluebuttonbn_wrap_xml_load_file($createmeetingurl, $method, $payload);
159
    if ($xml) {
160
        $response = array('returncode' => $xml->returncode, 'message' => $xml->message, 'messageKey' => $xml->messageKey);
161
        if ($xml->meetingID) {
162
            $response += array('meetingID' => $xml->meetingID, 'attendeePW' => $xml->attendeePW,
163
                'moderatorPW' => $xml->moderatorPW, 'hasBeenForciblyEnded' => $xml->hasBeenForciblyEnded);
164
        }
165
        return $response;
166
    }
167
    return array('returncode' => 'FAILED', 'message' => 'unreachable', 'messageKey' => 'Server is unreachable');
168
}
169
170
/**
171
 * Fetch meeting info and wrap response in array.
172
 *
173
 * @param string $meetingid
174
 *
175
 * @return array
176
 */
177
function bigbluebuttonbn_get_meeting_info_array($meetingid) {
178
    $xml = bigbluebuttonbn_wrap_xml_load_file(
179
        \mod_bigbluebuttonbn\locallib\bigbluebutton::action_url('getMeetingInfo', ['meetingID' => $meetingid])
180
    );
181
    if ($xml && $xml->returncode == 'SUCCESS' && empty($xml->messageKey)) {
182
        // Meeting info was returned.
183
        return array('returncode' => $xml->returncode,
184
            'meetingID' => $xml->meetingID,
185
            'moderatorPW' => $xml->moderatorPW,
186
            'attendeePW' => $xml->attendeePW,
187
            'hasBeenForciblyEnded' => $xml->hasBeenForciblyEnded,
188
            'running' => $xml->running,
189
            'recording' => $xml->recording,
190
            'startTime' => $xml->startTime,
191
            'endTime' => $xml->endTime,
192
            'participantCount' => $xml->participantCount,
193
            'moderatorCount' => $xml->moderatorCount,
194
            'attendees' => $xml->attendees,
195
            'metadata' => $xml->metadata,
196
        );
197
    }
198
    if ($xml) {
199
        // Either failure or success without meeting info.
200
        return (array) $xml;
201
    }
202
    // If the server is unreachable, then prompts the user of the necessary action.
203
    return array('returncode' => 'FAILED', 'message' => 'unreachable', 'messageKey' => 'Server is unreachable');
204
}
205
206
/**
207
 * Helper function to retrieve recordings from a BigBlueButton server.
208
 *
209
 * @param string|array $meetingids   list of meetingIDs "mid1,mid2,mid3" or array("mid1","mid2","mid3")
210
 * @param string|array $recordingids list of $recordingids "rid1,rid2,rid3" or array("rid1","rid2","rid3") for filtering
211
 *
212
 * @return associative array with recordings indexed by recordID, each recording is a non sequential associative array
213
 */
214
function bigbluebuttonbn_get_recordings_array($meetingids, $recordingids = []) {
215
    $meetingidsarray = $meetingids;
216
    if (!is_array($meetingids)) {
217
        $meetingidsarray = explode(',', $meetingids);
218
    }
219
    // If $meetingidsarray is empty there is no need to go further.
220
    if (empty($meetingidsarray)) {
221
        return array();
222
    }
223
    $recordings = bigbluebuttonbn_get_recordings_array_fetch($meetingidsarray);
0 ignored issues
show
Bug introduced by
It seems like $meetingidsarray defined by $meetingids on line 215 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...
224
    // Sort recordings.
225
    uasort($recordings, 'bigbluebuttonbn_recording_build_sorter');
226
    // Filter recordings based on recordingIDs.
227
    $recordingidsarray = $recordingids;
228
    if (!is_array($recordingids)) {
229
        $recordingidsarray = explode(',', $recordingids);
230
    }
231
    if (empty($recordingidsarray)) {
232
        // No recording ids, no need to filter.
233
        return $recordings;
234
    }
235
    return bigbluebuttonbn_get_recordings_array_filter($recordingidsarray, $recordings);
0 ignored issues
show
Bug introduced by
It seems like $recordingidsarray defined by $recordingids on line 227 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...
236
}
237
238
/**
239
 * Helper function to fetch recordings from a BigBlueButton server.
240
 *
241
 * @param array $meetingidsarray array with meeting ids in the form array("mid1","mid2","mid3")
242
 *
243
 * @return array (associative) with recordings indexed by recordID, each recording is a non sequential associative array
244
 */
245
function bigbluebuttonbn_get_recordings_array_fetch($meetingidsarray) {
246
    if ((defined('PHPUNIT_TEST') && PHPUNIT_TEST)
247
            || defined('BEHAT_SITE_RUNNING')
248
            || defined('BEHAT_TEST')
249
            || defined('BEHAT_UTIL')) {
250
        // Just return the fake recording.
251
        global $CFG;
252
        require_once($CFG->libdir . '/testing/generator/lib.php');
253
        require_once(__DIR__ . '/tests/generator/lib.php');
254
        return mod_bigbluebuttonbn_generator::bigbluebuttonbn_get_recordings_array_fetch($meetingidsarray);
255
    }
256
    $recordings = array();
257
    // Execute a paginated getRecordings request.
258
    $pagecount = 25;
259
    $pages = floor(count($meetingidsarray) / $pagecount) + 1;
260
    if (count($meetingidsarray) > 0 && count($meetingidsarray) % $pagecount == 0) {
261
        $pages--;
262
    }
263
    for ($page = 1; $page <= $pages; ++$page) {
264
        $mids = array_slice($meetingidsarray, ($page - 1) * $pagecount, $pagecount);
265
        $recordings += bigbluebuttonbn_get_recordings_array_fetch_page($mids);
266
    }
267
    return $recordings;
268
}
269
270
/**
271
 * Helper function to fetch one page of upto 25 recordings from a BigBlueButton server.
272
 *
273
 * @param array  $mids
274
 *
275
 * @return array
276
 */
277
function bigbluebuttonbn_get_recordings_array_fetch_page($mids) {
278
    $recordings = array();
279
    // Do getRecordings is executed using a method GET (supported by all versions of BBB).
280
    $url = \mod_bigbluebuttonbn\locallib\bigbluebutton::action_url('getRecordings', ['meetingID' => implode(',', $mids)]);
281
    $xml = bigbluebuttonbn_wrap_xml_load_file($url);
282
    if ($xml && $xml->returncode == 'SUCCESS' && isset($xml->recordings)) {
283
        // If there were meetings already created.
284
        foreach ($xml->recordings->recording as $recordingxml) {
285
            $recording = bigbluebuttonbn_get_recording_array_value($recordingxml);
286
            $recordings[$recording['recordID']] = $recording;
287
288
            // Check if there is childs.
289
            if (isset($recordingxml->breakoutRooms->breakoutRoom)) {
290
                foreach ($recordingxml->breakoutRooms->breakoutRoom as $breakoutroom) {
291
                    $url = \mod_bigbluebuttonbn\locallib\bigbluebutton::action_url(
292
                        'getRecordings',
293
                        ['recordID' => implode(',', (array) $breakoutroom)]
294
                    );
295
                    $xml = bigbluebuttonbn_wrap_xml_load_file($url);
296
                    if ($xml && $xml->returncode == 'SUCCESS' && isset($xml->recordings)) {
297
                        // If there were meetings already created.
298
                        foreach ($xml->recordings->recording as $recordingxml) {
299
                            $recording = bigbluebuttonbn_get_recording_array_value($recordingxml);
300
                            $recordings[$recording['recordID']] = $recording;
301
                        }
302
                    }
303
                }
304
            }
305
        }
306
    }
307
    return $recordings;
308
}
309
310
/**
311
 * Helper function to remove a set of recordings from an array.
312
 *
313
 * @param array  $rids
314
 * @param array  $recordings
315
 *
316
 * @return array
317
 */
318
function bigbluebuttonbn_get_recordings_array_filter($rids, &$recordings) {
319
    foreach ($recordings as $key => $recording) {
320
        if (!in_array($recording['recordID'], $rids)) {
321
            unset($recordings[$key]);
322
        }
323
    }
324
    return $recordings;
325
}
326
327
/**
328
 * Helper function to retrieve imported recordings from the Moodle database.
329
 * The references are stored as events in bigbluebuttonbn_logs.
330
 *
331
 * @param string $courseid
332
 * @param string $bigbluebuttonbnid
333
 * @param bool   $subset
334
 *
335
 * @return associative array with imported recordings indexed by recordID, each recording
336
 * is a non sequential associative array that corresponds to the actual recording in BBB
337
 */
338
function bigbluebuttonbn_get_recordings_imported_array($courseid = 0, $bigbluebuttonbnid = null, $subset = true) {
339
    global $DB;
340
    $select = bigbluebuttonbn_get_recordings_imported_sql_select($courseid, $bigbluebuttonbnid, $subset);
341
    $recordsimported = $DB->get_records_select('bigbluebuttonbn_logs', $select);
342
    $recordsimportedarray = array();
343
    foreach ($recordsimported as $recordimported) {
344
        $meta = json_decode($recordimported->meta, true);
345
        $recording = $meta['recording'];
346
        // Override imported flag with actual ID.
347
        $recording['imported'] = $recordimported->id;
348
        if (isset($recordimported->protected)) {
349
            $recording['protected'] = (string) $recordimported->protected;
350
        }
351
        $recordsimportedarray[$recording['recordID']] = $recording;
352
    }
353
    return $recordsimportedarray;
354
}
355
356
/**
357
 * Helper function to retrive the default config.xml file.
358
 *
359
 * @return string
360
 */
361
function bigbluebuttonbn_get_default_config_xml() {
362
    $xml = bigbluebuttonbn_wrap_xml_load_file(
363
        \mod_bigbluebuttonbn\locallib\bigbluebutton::action_url('getDefaultConfigXML')
364
    );
365
    return $xml;
366
}
367
368
/**
369
 * Helper function to convert an xml recording object to an array in the format used by the plugin.
370
 *
371
 * @param object $recording
372
 *
373
 * @return array
374
 */
375
function bigbluebuttonbn_get_recording_array_value($recording) {
376
    // Add formats.
377
    $playbackarray = array();
378
    foreach ($recording->playback->format as $format) {
379
        $playbackarray[(string) $format->type] = array('type' => (string) $format->type,
380
            'url' => trim((string) $format->url), 'length' => (string) $format->length);
381
        // Add preview per format when existing.
382
        if ($format->preview) {
383
            $playbackarray[(string) $format->type]['preview'] = bigbluebuttonbn_get_recording_preview_images($format->preview);
384
        }
385
    }
386
    // Add the metadata to the recordings array.
387
    $metadataarray = bigbluebuttonbn_get_recording_array_meta(get_object_vars($recording->metadata));
388
    $recordingarray = array('recordID' => (string) $recording->recordID,
389
        'meetingID' => (string) $recording->meetingID, 'meetingName' => (string) $recording->name,
390
        'published' => (string) $recording->published, 'startTime' => (string) $recording->startTime,
391
        'endTime' => (string) $recording->endTime, 'playbacks' => $playbackarray);
392
    if (isset($recording->protected)) {
393
        $recordingarray['protected'] = (string) $recording->protected;
394
    }
395
    return $recordingarray + $metadataarray;
396
}
397
398
/**
399
 * Helper function to convert an xml recording preview images to an array in the format used by the plugin.
400
 *
401
 * @param object $preview
402
 *
403
 * @return array
404
 */
405
function bigbluebuttonbn_get_recording_preview_images($preview) {
406
    $imagesarray = array();
407
    foreach ($preview->images->image as $image) {
408
        $imagearray = array('url' => trim((string) $image));
409
        foreach ($image->attributes() as $attkey => $attvalue) {
410
            $imagearray[$attkey] = (string) $attvalue;
411
        }
412
        array_push($imagesarray, $imagearray);
413
    }
414
    return $imagesarray;
415
}
416
417
/**
418
 * Helper function to convert an xml recording metadata object to an array in the format used by the plugin.
419
 *
420
 * @param array $metadata
421
 *
422
 * @return array
423
 */
424
function bigbluebuttonbn_get_recording_array_meta($metadata) {
425
    $metadataarray = array();
426
    foreach ($metadata as $key => $value) {
427
        if (is_object($value)) {
428
            $value = '';
429
        }
430
        $metadataarray['meta_' . $key] = $value;
431
    }
432
    return $metadataarray;
433
}
434
435
/**
436
 * Helper function to sort an array of recordings. It compares the startTime in two recording objecs.
437
 *
438
 * @param object $a
439
 * @param object $b
440
 *
441
 * @return array
442
 */
443
function bigbluebuttonbn_recording_build_sorter($a, $b) {
444
    global $CFG;
445
    $resultless = !empty($CFG->bigbluebuttonbn_recordings_sortorder) ? -1 : 1;
446
    $resultmore = !empty($CFG->bigbluebuttonbn_recordings_sortorder) ? 1 : -1;
447
    if ($a['startTime'] < $b['startTime']) {
448
        return $resultless;
449
    }
450
    if ($a['startTime'] == $b['startTime']) {
451
        return 0;
452
    }
453
    return $resultmore;
454
}
455
456
/**
457
 * Perform deleteRecordings on BBB.
458
 *
459
 * @param string $recordids
460
 *
461
 * @return boolean
462
 */
463 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...
464
    $ids = explode(',', $recordids);
465
    foreach ($ids as $id) {
466
        $xml = bigbluebuttonbn_wrap_xml_load_file(
467
            \mod_bigbluebuttonbn\locallib\bigbluebutton::action_url('deleteRecordings', ['recordID' => $id])
468
        );
469
        if ($xml && $xml->returncode != 'SUCCESS') {
470
            return false;
471
        }
472
    }
473
    return true;
474
}
475
476
/**
477
 * Perform publishRecordings on BBB.
478
 *
479
 * @param string $recordids
480
 * @param string $publish
481
 */
482 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...
483
    $ids = explode(',', $recordids);
484
    foreach ($ids as $id) {
485
        $xml = bigbluebuttonbn_wrap_xml_load_file(
486
            \mod_bigbluebuttonbn\locallib\bigbluebutton::action_url('publishRecordings', ['recordID' => $id, 'publish' => $publish])
487
        );
488
        if ($xml && $xml->returncode != 'SUCCESS') {
489
            return false;
490
        }
491
    }
492
    return true;
493
}
494
495
/**
496
 * Perform updateRecordings on BBB.
497
 *
498
 * @param string $recordids
499
 * @param array $params ['key'=>param_key, 'value']
500
 */
501 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...
502
    $ids = explode(',', $recordids);
503
    foreach ($ids as $id) {
504
        $xml = bigbluebuttonbn_wrap_xml_load_file(
505
            \mod_bigbluebuttonbn\locallib\bigbluebutton::action_url('updateRecordings', ['recordID' => $id] + (array) $params)
506
        );
507
        if ($xml && $xml->returncode != 'SUCCESS') {
508
            return false;
509
        }
510
    }
511
    return true;
512
}
513
514
/**
515
 * Perform end on BBB.
516
 *
517
 * @param string $meetingid
518
 * @param string $modpw
519
 */
520
function bigbluebuttonbn_end_meeting($meetingid, $modpw) {
521
    $xml = bigbluebuttonbn_wrap_xml_load_file(
522
        \mod_bigbluebuttonbn\locallib\bigbluebutton::action_url('end', ['meetingID' => $meetingid, 'password' => $modpw])
523
    );
524
    if ($xml) {
525
        // If the xml packet returned failure it displays the message to the user.
526
        return array('returncode' => $xml->returncode, 'message' => $xml->message, 'messageKey' => $xml->messageKey);
527
    }
528
    // If the server is unreachable, then prompts the user of the necessary action.
529
    return null;
530
}
531
532
/**
533
 * Perform api request on BBB.
534
 *
535
 * @return string
536
 */
537
function bigbluebuttonbn_get_server_version() {
538
    $xml = bigbluebuttonbn_wrap_xml_load_file(
539
        \mod_bigbluebuttonbn\locallib\bigbluebutton::action_url()
540
    );
541
    if ($xml && $xml->returncode == 'SUCCESS') {
542
        return $xml->version;
543
    }
544
    return null;
545
}
546
547
/**
548
 * Perform api request on BBB and wraps the response in an XML object
549
 *
550
 * @param string $url
551
 * @param string $method
552
 * @param string $data
553
 * @param string $contenttype
554
 *
555
 * @return object
556
 */
557
function bigbluebuttonbn_wrap_xml_load_file($url, $method = 'GET', $data = null, $contenttype = 'text/xml') {
558
    if (extension_loaded('curl')) {
559
        $response = bigbluebuttonbn_wrap_xml_load_file_curl_request($url, $method, $data, $contenttype);
560
        if (!$response) {
561
            debugging('No response on wrap_simplexml_load_file', DEBUG_DEVELOPER);
562
            return null;
563
        }
564
        $previous = libxml_use_internal_errors(true);
565
        try {
566
            $xml = simplexml_load_string($response, 'SimpleXMLElement', LIBXML_NOCDATA | LIBXML_NOBLANKS);
567
            return $xml;
568
        } catch (Exception $e) {
569
            libxml_use_internal_errors($previous);
570
            $error = 'Caught exception: ' . $e->getMessage();
571
            debugging($error, DEBUG_DEVELOPER);
572
            return null;
573
        }
574
    }
575
    // Alternative request non CURL based.
576
    $previous = libxml_use_internal_errors(true);
577
    try {
578
        $response = simplexml_load_file($url, 'SimpleXMLElement', LIBXML_NOCDATA | LIBXML_NOBLANKS);
579
        return $response;
580
    } catch (Exception $e) {
581
        $error = 'Caught exception: ' . $e->getMessage();
582
        debugging($error, DEBUG_DEVELOPER);
583
        libxml_use_internal_errors($previous);
584
        return null;
585
    }
586
}
587
588
/**
589
 * Perform api request on BBB using CURL and wraps the response in an XML object
590
 *
591
 * @param string $url
592
 * @param string $method
593
 * @param string $data
594
 * @param string $contenttype
595
 *
596
 * @return object
597
 */
598
function bigbluebuttonbn_wrap_xml_load_file_curl_request($url, $method = 'GET', $data = null, $contenttype = 'text/xml') {
599
    global $CFG;
600
    require_once($CFG->libdir . '/filelib.php');
601
    $c = new curl();
602
    $c->setopt(array('SSL_VERIFYPEER' => true));
603
    if ($method == 'POST') {
604
        if (is_null($data) || is_array($data)) {
605
            return $c->post($url);
606
        }
607
        $options = array();
608
        $options['CURLOPT_HTTPHEADER'] = array(
609
            'Content-Type: ' . $contenttype,
610
            'Content-Length: ' . strlen($data),
611
            'Content-Language: en-US',
612
        );
613
614
        return $c->post($url, $data, $options);
615
    }
616
    if ($method == 'HEAD') {
617
        $c->head($url, array('followlocation' => true, 'timeout' => 1));
618
        return $c->get_info();
619
    }
620
    return $c->get($url);
621
}
622
623
/**
624
 * End the session associated with this instance (if it's running).
625
 *
626
 * @param object $bigbluebuttonbn
627
 *
628
 * @return void
629
 */
630
function bigbluebuttonbn_end_meeting_if_running($bigbluebuttonbn) {
631
    $meetingid = $bigbluebuttonbn->meetingid . '-' . $bigbluebuttonbn->course . '-' . $bigbluebuttonbn->id;
632
    if (bigbluebuttonbn_is_meeting_running($meetingid)) {
633
        bigbluebuttonbn_end_meeting($meetingid, $bigbluebuttonbn->moderatorpass);
634
    }
635
}
636
637
/**
638
 * Returns user roles in a context.
639
 *
640
 * @param object $context
641
 * @param integer $userid
642
 *
643
 * @return array $userroles
644
 */
645
function bigbluebuttonbn_get_user_roles($context, $userid) {
646
    global $DB;
647
    $userroles = get_user_roles($context, $userid);
648
    if ($userroles) {
649
        $where = '';
650
        foreach ($userroles as $userrole) {
651
            $where .= (empty($where) ? ' WHERE' : ' OR') . ' id=' . $userrole->roleid;
652
        }
653
        $userroles = $DB->get_records_sql('SELECT * FROM {role}' . $where);
654
    }
655
    return $userroles;
656
}
657
658
/**
659
 * Returns guest role wrapped in an array.
660
 *
661
 * @return array
662
 */
663
function bigbluebuttonbn_get_guest_role() {
664
    $guestrole = get_guest_role();
665
    return array($guestrole->id => $guestrole);
666
}
667
668
/**
669
 * Returns an array containing all the users in a context.
670
 *
671
 * @param context $context
672
 *
673
 * @return array $users
674
 */
675
function bigbluebuttonbn_get_users(context $context = null) {
676
    $users = (array) get_enrolled_users($context, '', 0, 'u.*', null, 0, 0, true);
677
    foreach ($users as $key => $value) {
678
        $users[$key] = fullname($value);
679
    }
680
    return $users;
681
}
682
683
/**
684
 * Returns an array containing all the users in a context wrapped for html select element.
685
 *
686
 * @param context_course $context
687
 * @param null $bbactivity
688
 * @return array $users
689
 * @throws coding_exception
690
 * @throws moodle_exception
691
 */
692
function bigbluebuttonbn_get_users_select(context_course $context, $bbactivity = null) {
693
    // CONTRIB-7972, check the group of current user and course group mode.
694
    $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...
695
    $users = (array) get_enrolled_users($context, '', 0, 'u.*', null, 0, 0, true);
696
    $course = get_course($context->instanceid);
697
    $groupmode = groups_get_course_groupmode($course);
698
    if ($bbactivity) {
699
        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...
700
        $groupmode = groups_get_activity_groupmode($cm);
701
702
    }
703
    if ($groupmode == SEPARATEGROUPS && !has_capability('moodle/site:accessallgroups', $context)) {
704
        global $USER;
705
        $groups = groups_get_all_groups($course->id, $USER->id);
706
        $users = [];
707
        foreach ($groups as $g) {
708
            $users += (array) get_enrolled_users($context, '', $g->id, 'u.*', null, 0, 0, true);
709
        }
710
    }
711
    return array_map(
712
            function($u) {
713
                return array('id' => $u->id, 'name' => fullname($u));
714
            },
715
            $users);
716
}
717
718
/**
719
 * Returns an array containing all the roles in a context.
720
 *
721
 * @param context $context
722
 * @param bool $onlyviewableroles
723
 *
724
 * @return array $roles
725
 */
726
function bigbluebuttonbn_get_roles(context $context = null, bool $onlyviewableroles = true) {
727
    global $CFG;
728
729
    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...
730
        $roles = (array) get_viewable_roles($context);
731
        foreach ($roles as $key => $value) {
732
            $roles[$key] = $value;
733
        }
734
    } else {
735
        $roles = (array) role_get_names($context);
736
        foreach ($roles as $key => $value) {
737
            $roles[$key] = $value->localname;
738
        }
739
    }
740
741
    return $roles;
742
}
743
744
/**
745
 * Returns an array containing all the roles in a context wrapped for html select element.
746
 *
747
 * @param context $context
748
 * @param bool $onlyviewableroles
749
 *
750
 * @return array $users
751
 */
752
function bigbluebuttonbn_get_roles_select(context $context = null, bool $onlyviewableroles = true) {
753
    global $CFG;
754
755
    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...
756
        $roles = (array) get_viewable_roles($context);
757
        foreach ($roles as $key => $value) {
758
            $roles[$key] = array('id' => $key, 'name' => $value);
759
        }
760
    } else {
761
        $roles = (array) role_get_names($context);
762
        foreach ($roles as $key => $value) {
763
            $roles[$key] = array('id' => $value->id, 'name' => $value->localname);
764
        }
765
    }
766
767
    return $roles;
768
}
769
770
/**
771
 * Returns role that corresponds to an id.
772
 *
773
 * @param string|integer $id
774
 *
775
 * @return object $role
776
 */
777
function bigbluebuttonbn_get_role($id) {
778
    $roles = (array) role_get_names();
779
    if (is_numeric($id) && isset($roles[$id])) {
780
        return (object) $roles[$id];
781
    }
782
    foreach ($roles as $role) {
783
        if ($role->shortname == $id) {
784
            return $role;
785
        }
786
    }
787
}
788
789
/**
790
 * Returns an array to populate a list of participants used in mod_form.js.
791
 *
792
 * @param context $context
793
 * @param null|object $bbactivity
794
 * @return array $data
795
 */
796
function bigbluebuttonbn_get_participant_data($context, $bbactivity = null) {
797
    $data = array(
798
        'all' => array(
799
            'name' => get_string('mod_form_field_participant_list_type_all', 'bigbluebuttonbn'),
800
            'children' => []
801
        ),
802
    );
803
    $data['role'] = array(
804
        'name' => get_string('mod_form_field_participant_list_type_role', 'bigbluebuttonbn'),
805
        'children' => bigbluebuttonbn_get_roles_select($context, true)
806
      );
807
    $data['user'] = array(
808
        'name' => get_string('mod_form_field_participant_list_type_user', 'bigbluebuttonbn'),
809
        'children' => bigbluebuttonbn_get_users_select($context, $bbactivity),
0 ignored issues
show
Bug introduced by
It seems like $bbactivity defined by parameter $bbactivity on line 796 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...
810
    );
811
    return $data;
812
}
813
814
/**
815
 * Returns an array to populate a list of participants used in mod_form.php.
816
 *
817
 * @param object $bigbluebuttonbn
818
 * @param context $context
819
 *
820
 * @return array
821
 */
822
function bigbluebuttonbn_get_participant_list($bigbluebuttonbn, $context) {
823
    global $USER;
824
    if ($bigbluebuttonbn == null) {
825
        return bigbluebuttonbn_get_participant_rules_encoded(
826
            bigbluebuttonbn_get_participant_list_default($context, $USER->id)
827
        );
828
    }
829
    if (empty($bigbluebuttonbn->participants)) {
830
        $bigbluebuttonbn->participants = "[]";
831
    }
832
    $rules = json_decode($bigbluebuttonbn->participants, true);
833
    if (empty($rules)) {
834
        $rules = bigbluebuttonbn_get_participant_list_default($context, bigbluebuttonbn_instance_ownerid($bigbluebuttonbn));
835
    }
836
    return bigbluebuttonbn_get_participant_rules_encoded($rules);
837
}
838
839
/**
840
 * Returns an array to populate a list of participants used in mod_form.php with default values.
841
 *
842
 * @param context $context
843
 * @param integer $ownerid
844
 *
845
 * @return array
846
 */
847
function bigbluebuttonbn_get_participant_list_default($context, $ownerid = null) {
848
    $participantlist = array();
849
    $participantlist[] = array(
850
        'selectiontype' => 'all',
851
        'selectionid' => 'all',
852
        'role' => BIGBLUEBUTTONBN_ROLE_VIEWER,
853
    );
854
    $defaultrules = explode(',', \mod_bigbluebuttonbn\locallib\config::get('participant_moderator_default'));
855
    foreach ($defaultrules as $defaultrule) {
856
        if ($defaultrule == '0') {
857
            if (!empty($ownerid) && is_enrolled($context, $ownerid)) {
858
                $participantlist[] = array(
859
                    'selectiontype' => 'user',
860
                    'selectionid' => (string) $ownerid,
861
                    'role' => BIGBLUEBUTTONBN_ROLE_MODERATOR);
862
            }
863
            continue;
864
        }
865
        $participantlist[] = array(
866
            'selectiontype' => 'role',
867
            'selectionid' => $defaultrule,
868
            'role' => BIGBLUEBUTTONBN_ROLE_MODERATOR);
869
    }
870
    return $participantlist;
871
}
872
873
/**
874
 * Returns an array to populate a list of participants used in mod_form.php with bigbluebuttonbn values.
875
 *
876
 * @param array $rules
877
 *
878
 * @return array
879
 */
880
function bigbluebuttonbn_get_participant_rules_encoded($rules) {
881
    foreach ($rules as $key => $rule) {
882
        if ($rule['selectiontype'] !== 'role' || is_numeric($rule['selectionid'])) {
883
            continue;
884
        }
885
        $role = bigbluebuttonbn_get_role($rule['selectionid']);
886
        if ($role == null) {
887
            unset($rules[$key]);
888
            continue;
889
        }
890
        $rule['selectionid'] = $role->id;
891
        $rules[$key] = $rule;
892
    }
893
    return $rules;
894
}
895
896
/**
897
 * Returns an array to populate a list of participant_selection used in mod_form.php.
898
 *
899
 * @return array
900
 */
901
function bigbluebuttonbn_get_participant_selection_data() {
902
    return [
903
        'type_options' => [
904
            'all' => get_string('mod_form_field_participant_list_type_all', 'bigbluebuttonbn'),
905
            'role' => get_string('mod_form_field_participant_list_type_role', 'bigbluebuttonbn'),
906
            'user' => get_string('mod_form_field_participant_list_type_user', 'bigbluebuttonbn'),
907
        ],
908
        'type_selected' => 'all',
909
        'options' => ['all' => '---------------'],
910
        'selected' => 'all',
911
    ];
912
}
913
914
/**
915
 * Evaluate if a user in a context is moderator based on roles and participation rules.
916
 *
917
 * @param context $context
918
 * @param array $participantlist
919
 * @param integer $userid
920
 *
921
 * @return boolean
922
 */
923
function bigbluebuttonbn_is_moderator($context, $participantlist, $userid = null) {
924
    global $USER;
925
    if (!is_array($participantlist)) {
926
        return false;
927
    }
928
    if (empty($userid)) {
929
        $userid = $USER->id;
930
    }
931
    $userroles = bigbluebuttonbn_get_guest_role();
932
    if (!isguestuser()) {
933
        $userroles = bigbluebuttonbn_get_user_roles($context, $userid);
934
    }
935
    return bigbluebuttonbn_is_moderator_validator($participantlist, $userid, $userroles);
936
}
937
938
/**
939
 * Iterates participant list rules to evaluate if a user is moderator.
940
 *
941
 * @param array $participantlist
942
 * @param integer $userid
943
 * @param array $userroles
944
 *
945
 * @return boolean
946
 */
947
function bigbluebuttonbn_is_moderator_validator($participantlist, $userid, $userroles) {
948
    // Iterate participant rules.
949
    foreach ($participantlist as $participant) {
950
        if (bigbluebuttonbn_is_moderator_validate_rule($participant, $userid, $userroles)) {
951
            return true;
952
        }
953
    }
954
    return false;
955
}
956
957
/**
958
 * Evaluate if a user is moderator based on roles and a particular participation rule.
959
 *
960
 * @param object $participant
961
 * @param integer $userid
962
 * @param array $userroles
963
 *
964
 * @return boolean
965
 */
966
function bigbluebuttonbn_is_moderator_validate_rule($participant, $userid, $userroles) {
967
    if ($participant['role'] == BIGBLUEBUTTONBN_ROLE_VIEWER) {
968
        return false;
969
    }
970
    // Validation for the 'all' rule.
971
    if ($participant['selectiontype'] == 'all') {
972
        return true;
973
    }
974
    // Validation for a 'user' rule.
975
    if ($participant['selectiontype'] == 'user') {
976
        if ($participant['selectionid'] == $userid) {
977
            return true;
978
        }
979
        return false;
980
    }
981
    // Validation for a 'role' rule.
982
    $role = bigbluebuttonbn_get_role($participant['selectionid']);
983
    if ($role != null && array_key_exists($role->id, $userroles)) {
984
        return true;
985
    }
986
    return false;
987
}
988
989
/**
990
 * Helper returns error message key for the language file that corresponds to a bigbluebutton error key.
991
 *
992
 * @param string $messagekey
993
 * @param string $defaultkey
994
 *
995
 * @return string
996
 */
997
function bigbluebuttonbn_get_error_key($messagekey, $defaultkey = null) {
998
    if ($messagekey == 'checksumError') {
999
        return 'index_error_checksum';
1000
    }
1001
    if ($messagekey == 'maxConcurrent') {
1002
        return 'view_error_max_concurrent';
1003
    }
1004
    return $defaultkey;
1005
}
1006
1007
/**
1008
 * Helper evaluates if a voicebridge number is unique.
1009
 *
1010
 * @param integer $instance
1011
 * @param integer $voicebridge
1012
 *
1013
 * @return string
1014
 */
1015
function bigbluebuttonbn_voicebridge_unique($instance, $voicebridge) {
1016
    global $DB;
1017
    if ($voicebridge == 0) {
1018
        return true;
1019
    }
1020
    $select = 'voicebridge = ' . $voicebridge;
1021
    if ($instance != 0) {
1022
        $select .= ' AND id <>' . $instance;
1023
    }
1024
    if (!$DB->get_records_select('bigbluebuttonbn', $select)) {
1025
        return true;
1026
    }
1027
    return false;
1028
}
1029
1030
/**
1031
 * Helper estimate a duration for the meeting based on the closingtime.
1032
 *
1033
 * @param integer $closingtime
1034
 *
1035
 * @return integer
1036
 */
1037
function bigbluebuttonbn_get_duration($closingtime) {
1038
    $duration = 0;
1039
    $now = time();
1040
    if ($closingtime > 0 && $now < $closingtime) {
1041
        $duration = ceil(($closingtime - $now) / 60);
1042
        $compensationtime = intval((int) \mod_bigbluebuttonbn\locallib\config::get('scheduled_duration_compensation'));
1043
        $duration = intval($duration) + $compensationtime;
1044
    }
1045
    return $duration;
1046
}
1047
1048
/**
1049
 * Helper return array containing the file descriptor for a preuploaded presentation.
1050
 *
1051
 * @param context $context
1052
 * @param string $presentation
1053
 * @param integer $id
1054
 *
1055
 * @return array
1056
 */
1057
function bigbluebuttonbn_get_presentation_array($context, $presentation, $id = null) {
1058
    global $CFG;
1059
    if (empty($presentation)) {
1060
        if ($CFG->bigbluebuttonbn_preuploadpresentation_enabled) {
1061
            // Item has not presentation but presentation is enabled..
1062
            // Check if exist some file by default in general mod setting ("presentationdefault").
1063
            $fs = get_file_storage();
1064
            $files = $fs->get_area_files(
1065
                context_system::instance()->id,
1066
                'mod_bigbluebuttonbn',
1067
                'presentationdefault',
1068
                0,
1069
                "filename",
1070
                false
1071
            );
1072
1073 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...
1074
                // Not exist file by default in "presentationbydefault" setting.
1075
                return array('url' => null, 'name' => null, 'icon' => null, 'mimetype_description' => null);
1076
            }
1077
1078
            // Exists file in general setting to use as default for presentation. Cache image for temp public access.
1079
            $file = reset($files);
1080
            unset($files);
1081
            $pnoncevalue = null;
1082 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...
1083
                // Create the nonce component for granting a temporary public access.
1084
                $cache = cache::make_from_params(
1085
                    cache_store::MODE_APPLICATION,
1086
                    'mod_bigbluebuttonbn',
1087
                    'presentationdefault_cache'
1088
                );
1089
                $pnoncekey = sha1(context_system::instance()->id);
1090
                /* The item id was adapted for granting public access to the presentation once in order
1091
                 * to allow BigBlueButton to gather the file. */
1092
                $pnoncevalue = bigbluebuttonbn_generate_nonce();
1093
                $cache->set($pnoncekey, array('value' => $pnoncevalue, 'counter' => 0));
1094
            }
1095
1096
            $url = moodle_url::make_pluginfile_url(
1097
                $file->get_contextid(),
1098
                $file->get_component(),
1099
                $file->get_filearea(),
1100
                $pnoncevalue,
1101
                $file->get_filepath(),
1102
                $file->get_filename()
1103
            );
1104
            return (array('name' => $file->get_filename(), 'icon' => file_file_icon($file, 24),
1105
                'url' => $url->out(false), 'mimetype_description' => get_mimetype_description($file)));
1106
        }
1107
1108
        return array('url' => null, 'name' => null, 'icon' => null, 'mimetype_description' => null);
1109
    }
1110
    $fs = get_file_storage();
1111
    $files = $fs->get_area_files(
1112
        $context->id,
1113
        'mod_bigbluebuttonbn',
1114
        'presentation',
1115
        0,
1116
        'itemid, filepath, filename',
1117
        false
1118
    );
1119 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...
1120
        return array('url' => null, 'name' => null, 'icon' => null, 'mimetype_description' => null);
1121
    }
1122
    $file = reset($files);
1123
    unset($files);
1124
    $pnoncevalue = null;
1125 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...
1126
        // Create the nonce component for granting a temporary public access.
1127
        $cache = cache::make_from_params(
1128
            cache_store::MODE_APPLICATION,
1129
            'mod_bigbluebuttonbn',
1130
            'presentation_cache'
1131
        );
1132
        $pnoncekey = sha1($id);
1133
        /* The item id was adapted for granting public access to the presentation once in order
1134
         * to allow BigBlueButton to gather the file. */
1135
        $pnoncevalue = bigbluebuttonbn_generate_nonce();
1136
        $cache->set($pnoncekey, array('value' => $pnoncevalue, 'counter' => 0));
1137
    }
1138
    $url = moodle_url::make_pluginfile_url(
1139
        $file->get_contextid(),
1140
        $file->get_component(),
1141
        $file->get_filearea(),
1142
        $pnoncevalue,
1143
        $file->get_filepath(),
1144
        $file->get_filename()
1145
    );
1146
    return array('name' => $file->get_filename(), 'icon' => file_file_icon($file, 24),
1147
        'url' => $url->out(false), 'mimetype_description' => get_mimetype_description($file));
1148
}
1149
1150
/**
1151
 * Helper generates a nonce used for the preuploaded presentation callback url.
1152
 *
1153
 * @return string
1154
 */
1155
function bigbluebuttonbn_generate_nonce() {
1156
    $mt = microtime();
1157
    $rand = mt_rand();
1158
    return md5($mt . $rand);
1159
}
1160
1161
/**
1162
 * Helper generates a random password.
1163
 *
1164
 * @param integer $length
1165
 * @param string $unique
1166
 *
1167
 * @return string
1168
 */
1169
function bigbluebuttonbn_random_password($length = 8, $unique = "") {
1170
    $chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
1171
    do {
1172
        $password = substr(str_shuffle($chars), 0, $length);
1173
    } while ($unique == $password);
1174
    return $password;
1175
}
1176
1177
/**
1178
 * Helper register a bigbluebuttonbn event.
1179
 *
1180
 * @param string $type
1181
 * @param object $bigbluebuttonbn
1182
 * @param array $options [timecreated, userid, other]
1183
 *
1184
 * @return void
1185
 */
1186
function bigbluebuttonbn_event_log($type, $bigbluebuttonbn, $options = []) {
1187
    global $DB;
1188
    if (!in_array($type, \mod_bigbluebuttonbn\event\events::$events)) {
1189
        // No log will be created.
1190
        return;
1191
    }
1192
    $course = $DB->get_record('course', array('id' => $bigbluebuttonbn->course), '*', MUST_EXIST);
1193
    $cm = get_coursemodule_from_instance('bigbluebuttonbn', $bigbluebuttonbn->id, $course->id, false, MUST_EXIST);
1194
    $context = context_module::instance($cm->id);
1195
    $params = array('context' => $context, 'objectid' => $bigbluebuttonbn->id);
1196
    if (array_key_exists('timecreated', $options)) {
1197
        $params['timecreated'] = $options['timecreated'];
1198
    }
1199
    if (array_key_exists('userid', $options)) {
1200
        $params['userid'] = $options['userid'];
1201
    }
1202
    if (array_key_exists('other', $options)) {
1203
        $params['other'] = $options['other'];
1204
    }
1205
    $event = call_user_func_array(
1206
        '\mod_bigbluebuttonbn\event\\' . $type . '::create',
1207
        array($params)
1208
    );
1209
    $event->add_record_snapshot('course_modules', $cm);
1210
    $event->add_record_snapshot('course', $course);
1211
    $event->add_record_snapshot('bigbluebuttonbn', $bigbluebuttonbn);
1212
    $event->trigger();
1213
}
1214
1215
/**
1216
 * Updates the meeting info cached object when a participant has joined.
1217
 *
1218
 * @param string $meetingid
1219
 * @param bool $ismoderator
1220
 *
1221
 * @return void
1222
 */
1223
function bigbluebuttonbn_participant_joined($meetingid, $ismoderator) {
1224
    $cache = cache::make_from_params(cache_store::MODE_APPLICATION, 'mod_bigbluebuttonbn', 'meetings_cache');
1225
    $result = $cache->get($meetingid);
1226
    $meetinginfo = json_decode($result['meeting_info']);
1227
    $meetinginfo->participantCount += 1;
1228
    if ($ismoderator) {
1229
        $meetinginfo->moderatorCount += 1;
1230
    }
1231
    $cache->set($meetingid, array('creation_time' => $result['creation_time'],
1232
        'meeting_info' => json_encode($meetinginfo)));
1233
}
1234
1235
/**
1236
 * Gets a meeting info object cached or fetched from the live session.
1237
 *
1238
 * @param string $meetingid
1239
 * @param boolean $updatecache
1240
 *
1241
 * @return array
1242
 */
1243
function bigbluebuttonbn_get_meeting_info($meetingid, $updatecache = false) {
1244
    $cachettl = (int) \mod_bigbluebuttonbn\locallib\config::get('waitformoderator_cache_ttl');
1245
    $cache = cache::make_from_params(cache_store::MODE_APPLICATION, 'mod_bigbluebuttonbn', 'meetings_cache');
1246
    $result = $cache->get($meetingid);
1247
    $now = time();
1248
    if (!$updatecache && !empty($result) && $now < ($result['creation_time'] + $cachettl)) {
1249
        // Use the value in the cache.
1250
        return (array) json_decode($result['meeting_info']);
1251
    }
1252
    // Ping again and refresh the cache.
1253
    $meetinginfo = (array) bigbluebuttonbn_wrap_xml_load_file(
1254
        \mod_bigbluebuttonbn\locallib\bigbluebutton::action_url('getMeetingInfo', ['meetingID' => $meetingid])
1255
    );
1256
    $cache->set($meetingid, array('creation_time' => time(), 'meeting_info' => json_encode($meetinginfo)));
1257
    return $meetinginfo;
1258
}
1259
1260
/**
1261
 * Perform isMeetingRunning on BBB.
1262
 *
1263
 * @param string $meetingid
1264
 * @param boolean $updatecache
1265
 *
1266
 * @return boolean
1267
 */
1268
function bigbluebuttonbn_is_meeting_running($meetingid, $updatecache = false) {
1269
    /* As a workaround to isMeetingRunning that always return SUCCESS but only returns true
1270
     * when at least one user is in the session, we use getMeetingInfo instead.
1271
     */
1272
    $meetinginfo = bigbluebuttonbn_get_meeting_info($meetingid, $updatecache);
1273
    return ($meetinginfo['returncode'] === 'SUCCESS');
1274
}
1275
1276
/**
1277
 * Publish an imported recording.
1278
 *
1279
 * @param string $id
1280
 * @param boolean $publish
1281
 *
1282
 * @return boolean
1283
 */
1284 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...
1285
    global $DB;
1286
    // Locate the record to be updated.
1287
    $record = $DB->get_record('bigbluebuttonbn_logs', array('id' => $id));
1288
    $meta = json_decode($record->meta, true);
1289
    // Prepare data for the update.
1290
    $meta['recording']['published'] = ($publish) ? 'true' : 'false';
1291
    $record->meta = json_encode($meta);
1292
    // Proceed with the update.
1293
    $DB->update_record('bigbluebuttonbn_logs', $record);
1294
    return true;
1295
}
1296
1297
/**
1298
 * Delete an imported recording.
1299
 *
1300
 * @param string $id
1301
 *
1302
 * @return boolean
1303
 */
1304
function bigbluebuttonbn_delete_recording_imported($id) {
1305
    global $DB;
1306
    // Execute delete.
1307
    $DB->delete_records('bigbluebuttonbn_logs', array('id' => $id));
1308
    return true;
1309
}
1310
1311
/**
1312
 * Update an imported recording.
1313
 *
1314
 * @param string $id
1315
 * @param array $params ['key'=>param_key, 'value']
1316
 *
1317
 * @return boolean
1318
 */
1319
function bigbluebuttonbn_update_recording_imported($id, $params) {
1320
    global $DB;
1321
    // Locate the record to be updated.
1322
    $record = $DB->get_record('bigbluebuttonbn_logs', array('id' => $id));
1323
    $meta = json_decode($record->meta, true);
1324
    // Prepare data for the update.
1325
    $meta['recording'] = $params + $meta['recording'];
1326
    $record->meta = json_encode($meta);
1327
    // Proceed with the update.
1328
    if (!$DB->update_record('bigbluebuttonbn_logs', $record)) {
1329
        return false;
1330
    }
1331
    return true;
1332
}
1333
1334
/**
1335
 * Protect/Unprotect an imported recording.
1336
 *
1337
 * @param string $id
1338
 * @param boolean $protect
1339
 *
1340
 * @return boolean
1341
 */
1342 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...
1343
    global $DB;
1344
    // Locate the record to be updated.
1345
    $record = $DB->get_record('bigbluebuttonbn_logs', array('id' => $id));
1346
    $meta = json_decode($record->meta, true);
1347
    // Prepare data for the update.
1348
    $meta['recording']['protected'] = ($protect) ? 'true' : 'false';
1349
    $record->meta = json_encode($meta);
1350
    // Proceed with the update.
1351
    $DB->update_record('bigbluebuttonbn_logs', $record);
1352
    return true;
1353
}
1354
1355
/**
1356
 * Sets a custom config.xml file for being used on create.
1357
 *
1358
 * @param string $meetingid
1359
 * @param string $configxml
1360
 *
1361
 * @return object
1362
 */
1363
function bigbluebuttonbn_set_config_xml($meetingid, $configxml) {
1364
    $urldefaultconfig = \mod_bigbluebuttonbn\locallib\config::get('server_url') . 'api/setConfigXML?';
1365
    $configxmlparams = bigbluebuttonbn_set_config_xml_params($meetingid, $configxml);
1366
    $xml = bigbluebuttonbn_wrap_xml_load_file(
1367
        $urldefaultconfig,
1368
        'POST',
1369
        $configxmlparams,
1370
        'application/x-www-form-urlencoded'
1371
    );
1372
    return $xml;
1373
}
1374
1375
/**
1376
 * Sets qs used with a custom config.xml file request.
1377
 *
1378
 * @param string $meetingid
1379
 * @param string $configxml
1380
 *
1381
 * @return string
1382
 */
1383
function bigbluebuttonbn_set_config_xml_params($meetingid, $configxml) {
1384
    $params = 'configXML=' . urlencode($configxml) . '&meetingID=' . urlencode($meetingid);
1385
    $sharedsecret = \mod_bigbluebuttonbn\locallib\config::get('shared_secret');
1386
    $configxmlparams = $params . '&checksum=' . sha1('setConfigXML' . $params . $sharedsecret);
1387
    return $configxmlparams;
1388
}
1389
1390
/**
1391
 * Sets a custom config.xml file for being used on create.
1392
 *
1393
 * @param string $meetingid
1394
 * @param string $configxml
1395
 *
1396
 * @return array
1397
 */
1398
function bigbluebuttonbn_set_config_xml_array($meetingid, $configxml) {
1399
    $configxml = bigbluebuttonbn_set_config_xml($meetingid, $configxml);
1400
    $configxmlarray = (array) $configxml;
1401
    if ($configxmlarray['returncode'] != 'SUCCESS') {
1402
        debugging('BigBlueButton was not able to set the custom config.xml file', DEBUG_DEVELOPER);
1403
        return '';
1404
    }
1405
    return $configxmlarray['configToken'];
1406
}
1407
1408
/**
1409
 * Helper function builds a row for the data used by the recording table.
1410
 *
1411
 * @param array $bbbsession
1412
 * @param array $recording
1413
 * @param array $tools
1414
 *
1415
 * @return array
1416
 */
1417
function bigbluebuttonbn_get_recording_data_row($bbbsession, $recording, $tools = ['protect', 'publish', 'delete']) {
1418
    if (!bigbluebuttonbn_include_recording_table_row($bbbsession, $recording)) {
1419
        return;
1420
    }
1421
    $rowdata = new stdClass();
1422
    // Set recording_types.
1423
    $rowdata->playback = bigbluebuttonbn_get_recording_data_row_types($recording, $bbbsession);
1424
    // Set activity name.
1425
    $rowdata->recording = bigbluebuttonbn_get_recording_data_row_meta_activity($recording, $bbbsession);
1426
    // Set activity description.
1427
    $rowdata->description = bigbluebuttonbn_get_recording_data_row_meta_description($recording, $bbbsession);
1428
    if (bigbluebuttonbn_get_recording_data_preview_enabled($bbbsession)) {
1429
        // Set recording_preview.
1430
        $rowdata->preview = bigbluebuttonbn_get_recording_data_row_preview($recording);
1431
    }
1432
    // Set date.
1433
    $rowdata->date = bigbluebuttonbn_get_recording_data_row_date($recording);
1434
    // Set formatted date.
1435
    $rowdata->date_formatted = bigbluebuttonbn_get_recording_data_row_date_formatted($rowdata->date);
1436
    // Set formatted duration.
1437
    $rowdata->duration_formatted = $rowdata->duration = bigbluebuttonbn_get_recording_data_row_duration($recording);
1438
    // Set actionbar, if user is allowed to manage recordings.
1439
    if ($bbbsession['managerecordings']) {
1440
        $rowdata->actionbar = bigbluebuttonbn_get_recording_data_row_actionbar($recording, $tools);
1441
    }
1442
    return $rowdata;
1443
}
1444
1445
/**
1446
 * Helper function evaluates if a row for the data used by the recording table is editable.
1447
 *
1448
 * @param array $bbbsession
1449
 *
1450
 * @return boolean
1451
 */
1452
function bigbluebuttonbn_get_recording_data_row_editable($bbbsession) {
1453
    return ($bbbsession['managerecordings'] && ((double) $bbbsession['serverversion'] >= 1.0 || $bbbsession['bnserver']));
1454
}
1455
1456
/**
1457
 * Helper function evaluates if recording preview should be included.
1458
 *
1459
 * @param array $bbbsession
1460
 *
1461
 * @return boolean
1462
 */
1463
function bigbluebuttonbn_get_recording_data_preview_enabled($bbbsession) {
1464
    return ((double) $bbbsession['serverversion'] >= 1.0 && $bbbsession['bigbluebuttonbn']->recordings_preview == '1');
1465
}
1466
1467
/**
1468
 * Helper function converts recording date used in row for the data used by the recording table.
1469
 *
1470
 * @param array $recording
1471
 *
1472
 * @return integer
1473
 */
1474
function bigbluebuttonbn_get_recording_data_row_date($recording) {
1475
    if (!isset($recording['startTime'])) {
1476
        return 0;
1477
    }
1478
    return floatval($recording['startTime']);
1479
}
1480
1481
/**
1482
 * Helper function format recording date used in row for the data used by the recording table.
1483
 *
1484
 * @param integer $starttime
1485
 *
1486
 * @return string
1487
 */
1488
function bigbluebuttonbn_get_recording_data_row_date_formatted($starttime) {
1489
    global $USER;
1490
    $starttime = $starttime - ($starttime % 1000);
1491
    // Set formatted date.
1492
    $dateformat = get_string('strftimerecentfull', 'langconfig') . ' %Z';
1493
    return userdate($starttime / 1000, $dateformat, usertimezone($USER->timezone));
1494
}
1495
1496
/**
1497
 * Helper function converts recording duration used in row for the data used by the recording table.
1498
 *
1499
 * @param array $recording
1500
 *
1501
 * @return integer
1502
 */
1503
function bigbluebuttonbn_get_recording_data_row_duration($recording) {
1504
    foreach (array_values($recording['playbacks']) as $playback) {
1505
        // Ignore restricted playbacks.
1506
        if (array_key_exists('restricted', $playback) && strtolower($playback['restricted']) == 'true') {
1507
            continue;
1508
        }
1509
        // Take the lenght form the fist playback with an actual value.
1510
        if (!empty($playback['length'])) {
1511
            return intval($playback['length']);
1512
        }
1513
    }
1514
    return 0;
1515
}
1516
1517
/**
1518
 * Helper function builds recording actionbar used in row for the data used by the recording table.
1519
 *
1520
 * @param array $recording
1521
 * @param array $tools
1522
 *
1523
 * @return string
1524
 */
1525
function bigbluebuttonbn_get_recording_data_row_actionbar($recording, $tools) {
1526
    $actionbar = '';
1527
    foreach ($tools as $tool) {
1528
        $buttonpayload = bigbluebuttonbn_get_recording_data_row_actionbar_payload($recording, $tool);
1529
        if ($tool == 'protect') {
1530
            if (isset($recording['imported'])) {
1531
                $buttonpayload['disabled'] = 'disabled';
1532
            }
1533
            if (!isset($recording['protected'])) {
1534
                $buttonpayload['disabled'] = 'invisible';
1535
            }
1536
        }
1537
        $actionbar .= bigbluebuttonbn_actionbar_render_button($recording, $buttonpayload);
1538
    }
1539
    $head = html_writer::start_tag('div', array(
1540
        'id' => 'recording-actionbar-' . $recording['recordID'],
1541
        'data-recordingid' => $recording['recordID'],
1542
        'data-meetingid' => $recording['meetingID']));
1543
    $tail = html_writer::end_tag('div');
1544
    return $head . $actionbar . $tail;
1545
}
1546
1547
/**
1548
 * Helper function returns the corresponding payload for an actionbar button used in row
1549
 * for the data used by the recording table.
1550
 *
1551
 * @param array $recording
1552
 * @param array $tool
1553
 *
1554
 * @return array
1555
 */
1556
function bigbluebuttonbn_get_recording_data_row_actionbar_payload($recording, $tool) {
1557
    if ($tool == 'protect') {
1558
        $protected = 'false';
1559
        if (isset($recording['protected'])) {
1560
            $protected = $recording['protected'];
1561
        }
1562
        return bigbluebuttonbn_get_recording_data_row_action_protect($protected);
1563
    }
1564
    if ($tool == 'publish') {
1565
        return bigbluebuttonbn_get_recording_data_row_action_publish($recording['published']);
1566
    }
1567
    return array('action' => $tool, 'tag' => $tool);
1568
}
1569
1570
/**
1571
 * Helper function returns the payload for protect action button used in row
1572
 * for the data used by the recording table.
1573
 *
1574
 * @param string $protected
1575
 *
1576
 * @return array
1577
 */
1578
function bigbluebuttonbn_get_recording_data_row_action_protect($protected) {
1579
    if ($protected == 'true') {
1580
        return array('action' => 'unprotect', 'tag' => 'lock');
1581
    }
1582
    return array('action' => 'protect', 'tag' => 'unlock');
1583
}
1584
1585
/**
1586
 * Helper function returns the payload for publish action button used in row
1587
 * for the data used by the recording table.
1588
 *
1589
 * @param string $published
1590
 *
1591
 * @return array
1592
 */
1593
function bigbluebuttonbn_get_recording_data_row_action_publish($published) {
1594
    if ($published == 'true') {
1595
        return array('action' => 'unpublish', 'tag' => 'hide');
1596
    }
1597
    return array('action' => 'publish', 'tag' => 'show');
1598
}
1599
1600
/**
1601
 * Helper function builds recording preview used in row for the data used by the recording table.
1602
 *
1603
 * @param array $recording
1604
 *
1605
 * @return string
1606
 */
1607
function bigbluebuttonbn_get_recording_data_row_preview($recording) {
1608
    $options = array('id' => 'preview-' . $recording['recordID']);
1609
    if ($recording['published'] === 'false') {
1610
        $options['hidden'] = 'hidden';
1611
    }
1612
    $recordingpreview = html_writer::start_tag('div', $options);
1613
    foreach ($recording['playbacks'] as $playback) {
1614
        if (isset($playback['preview'])) {
1615
            $recordingpreview .= bigbluebuttonbn_get_recording_data_row_preview_images($playback);
1616
            break;
1617
        }
1618
    }
1619
    $recordingpreview .= html_writer::end_tag('div');
1620
    return $recordingpreview;
1621
}
1622
1623
/**
1624
 * Helper function builds element with actual images used in recording preview row based on a selected playback.
1625
 *
1626
 * @param array $playback
1627
 *
1628
 * @return string
1629
 */
1630
function bigbluebuttonbn_get_recording_data_row_preview_images($playback) {
1631
    global $CFG;
1632
    $recordingpreview  = html_writer::start_tag('div', array('class' => 'container-fluid'));
1633
    $recordingpreview .= html_writer::start_tag('div', array('class' => 'row'));
1634
    foreach ($playback['preview'] as $image) {
1635
        if ($CFG->bigbluebuttonbn_recordings_validate_url && !bigbluebuttonbn_is_valid_resource(trim($image['url']))) {
1636
            return '';
1637
        }
1638
        $recordingpreview .= html_writer::start_tag('div', array('class' => ''));
1639
        $recordingpreview .= html_writer::empty_tag(
1640
            'img',
1641
            array('src' => trim($image['url']) . '?' . time(), 'class' => 'recording-thumbnail pull-left')
1642
        );
1643
        $recordingpreview .= html_writer::end_tag('div');
1644
    }
1645
    $recordingpreview .= html_writer::end_tag('div');
1646
    $recordingpreview .= html_writer::start_tag('div', array('class' => 'row'));
1647
    $recordingpreview .= html_writer::tag(
1648
        'div',
1649
        get_string('view_recording_preview_help', 'bigbluebuttonbn'),
1650
        array('class' => 'text-center text-muted small')
1651
    );
1652
    $recordingpreview .= html_writer::end_tag('div');
1653
    $recordingpreview .= html_writer::end_tag('div');
1654
    return $recordingpreview;
1655
}
1656
1657
/**
1658
 * Helper function renders recording types to be used in row for the data used by the recording table.
1659
 *
1660
 * @param array $recording
1661
 * @param array $bbbsession
1662
 *
1663
 * @return string
1664
 */
1665
function bigbluebuttonbn_get_recording_data_row_types($recording, $bbbsession) {
1666
    $dataimported = 'false';
1667
    $title = '';
1668
    if (isset($recording['imported'])) {
1669
        $dataimported = 'true';
1670
        $title = get_string('view_recording_link_warning', 'bigbluebuttonbn');
1671
    }
1672
    $visibility = '';
1673
    if ($recording['published'] === 'false') {
1674
        $visibility = 'hidden ';
1675
    }
1676
    $id = 'playbacks-' . $recording['recordID'];
1677
    $recordingtypes = html_writer::start_tag('div', array('id' => $id, 'data-imported' => $dataimported,
1678
        'data-meetingid' => $recording['meetingID'], 'data-recordingid' => $recording['recordID'],
1679
        'title' => $title, $visibility => $visibility));
1680
    foreach ($recording['playbacks'] as $playback) {
1681
        $recordingtypes .= bigbluebuttonbn_get_recording_data_row_type($recording, $bbbsession, $playback);
1682
    }
1683
    $recordingtypes .= html_writer::end_tag('div');
1684
    return $recordingtypes;
1685
}
1686
1687
/**
1688
 * Helper function renders the link used for recording type in row for the data used by the recording table.
1689
 *
1690
 * @param array $recording
1691
 * @param array $bbbsession
1692
 * @param array $playback
1693
 *
1694
 * @return string
1695
 */
1696
function bigbluebuttonbn_get_recording_data_row_type($recording, $bbbsession, $playback) {
1697
    global $CFG, $OUTPUT;
1698
    if (!bigbluebuttonbn_include_recording_data_row_type($recording, $bbbsession, $playback)) {
1699
        return '';
1700
    }
1701
    $text = bigbluebuttonbn_get_recording_type_text($playback['type']);
1702
    $href = $CFG->wwwroot . '/mod/bigbluebuttonbn/bbb_view.php?action=play&bn=' . $bbbsession['bigbluebuttonbn']->id .
1703
        '&mid=' . $recording['meetingID'] . '&rid=' . $recording['recordID'] . '&rtype=' . $playback['type'];
1704
    if (!isset($recording['imported']) || !isset($recording['protected']) || $recording['protected'] === 'false') {
1705
        $href .= '&href=' . urlencode(trim($playback['url']));
1706
    }
1707
    $linkattributes = array(
1708
        'id' => 'recording-play-' . $playback['type'] . '-' . $recording['recordID'],
1709
        'class' => 'btn btn-sm btn-default',
1710
        'onclick' => 'M.mod_bigbluebuttonbn.recordings.recordingPlay(this);',
1711
        'data-action' => 'play',
1712
        'data-target' => $playback['type'],
1713
        'data-href' => $href,
1714
      );
1715
    if ($CFG->bigbluebuttonbn_recordings_validate_url && !bigbluebuttonbn_is_bn_server()
1716
            && !bigbluebuttonbn_is_valid_resource(trim($playback['url']))) {
1717
        $linkattributes['class'] = 'btn btn-sm btn-warning';
1718
        $linkattributes['title'] = get_string('view_recording_format_errror_unreachable', 'bigbluebuttonbn');
1719
        unset($linkattributes['data-href']);
1720
    }
1721
    return $OUTPUT->action_link('#', $text, null, $linkattributes) . '&#32;';
1722
}
1723
1724
/**
1725
 * Helper function to handle yet unknown recording types
1726
 *
1727
 * @param string $playbacktype : for now presentation, video, statistics, capture, notes, podcast
1728
 *
1729
 * @return string the matching language string or a capitalised version of the provided string
1730
 */
1731
function bigbluebuttonbn_get_recording_type_text($playbacktype) {
1732
    // Check first if string exists, and if it does'nt just default to the capitalised version of the string.
1733
    $text = ucwords($playbacktype);
1734
    $typestringid = 'view_recording_format_' . $playbacktype;
1735
    if (get_string_manager()->string_exists($typestringid, 'bigbluebuttonbn')) {
1736
        $text = get_string($typestringid, 'bigbluebuttonbn');
1737
    }
1738
    return $text;
1739
}
1740
1741
/**
1742
 * Helper function validates a remote resource.
1743
 *
1744
 * @param string $url
1745
 *
1746
 * @return boolean
1747
 */
1748
function bigbluebuttonbn_is_valid_resource($url) {
1749
    $urlhost = parse_url($url, PHP_URL_HOST);
1750
    $serverurlhost = parse_url(\mod_bigbluebuttonbn\locallib\config::get('server_url'), PHP_URL_HOST);
1751
    // Skip validation when the recording URL host is the same as the configured BBB server.
1752
    if ($urlhost == $serverurlhost) {
1753
        return true;
1754
    }
1755
    // Skip validation when the recording URL was already validated.
1756
    $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...
1757
    if (array_key_exists($urlhost, $validatedurls)) {
1758
        return $validatedurls[$urlhost];
1759
    }
1760
    // Validate the recording URL.
1761
    $validatedurls[$urlhost] = true;
1762
    $curlinfo = bigbluebuttonbn_wrap_xml_load_file_curl_request($url, 'HEAD');
1763
    if (!isset($curlinfo['http_code']) || $curlinfo['http_code'] != 200) {
1764
        $error = "Resources hosted by " . $urlhost . " are unreachable. Server responded with code " . $curlinfo['http_code'];
1765
        debugging($error, DEBUG_DEVELOPER);
1766
        $validatedurls[$urlhost] = false;
1767
    }
1768
    bigbluebuttonbn_cache_set('recordings_cache', 'validated_urls', $validatedurls);
1769
    return $validatedurls[$urlhost];
1770
}
1771
1772
/**
1773
 * Helper function renders the name for meeting used in row for the data used by the recording table.
1774
 *
1775
 * @param array $recording
1776
 * @param array $bbbsession
1777
 *
1778
 * @return string
1779
 */
1780
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...
1781
    $payload = array();
1782
    $source = 'meetingName';
1783
    $metaname = trim($recording['meetingName']);
1784
    return bigbluebuttonbn_get_recording_data_row_text($recording, $metaname, $source, $payload);
1785
}
1786
1787
/**
1788
 * Helper function renders the name for recording used in row for the data used by the recording table.
1789
 *
1790
 * @param array $recording
1791
 * @param array $bbbsession
1792
 *
1793
 * @return string
1794
 */
1795
function bigbluebuttonbn_get_recording_data_row_meta_activity($recording, $bbbsession) {
1796
    $payload = array();
1797 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...
1798
        $payload = array('recordingid' => $recording['recordID'], 'meetingid' => $recording['meetingID'],
1799
            'action' => 'edit', 'tag' => 'edit',
1800
            'target' => 'name');
1801
    }
1802
    $oldsource = 'meta_contextactivity';
1803
    if (isset($recording[$oldsource])) {
1804
        $metaname = trim($recording[$oldsource]);
1805
        return bigbluebuttonbn_get_recording_data_row_text($recording, $metaname, $oldsource, $payload);
1806
    }
1807
    $newsource = 'meta_bbb-recording-name';
1808 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...
1809
        $metaname = trim($recording[$newsource]);
1810
        return bigbluebuttonbn_get_recording_data_row_text($recording, $metaname, $newsource, $payload);
1811
    }
1812
    $metaname = trim($recording['meetingName']);
1813
    return bigbluebuttonbn_get_recording_data_row_text($recording, $metaname, $newsource, $payload);
1814
}
1815
1816
/**
1817
 * Helper function renders the description for recording used in row for the data used by the recording table.
1818
 *
1819
 * @param array $recording
1820
 * @param array $bbbsession
1821
 *
1822
 * @return string
1823
 */
1824
function bigbluebuttonbn_get_recording_data_row_meta_description($recording, $bbbsession) {
1825
    $payload = array();
1826 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...
1827
        $payload = array('recordingid' => $recording['recordID'], 'meetingid' => $recording['meetingID'],
1828
            'action' => 'edit', 'tag' => 'edit',
1829
            'target' => 'description');
1830
    }
1831
    $oldsource = 'meta_contextactivitydescription';
1832 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...
1833
        $metadescription = trim($recording[$oldsource]);
1834
        return bigbluebuttonbn_get_recording_data_row_text($recording, $metadescription, $oldsource, $payload);
1835
    }
1836
    $newsource = 'meta_bbb-recording-description';
1837 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...
1838
        $metadescription = trim($recording[$newsource]);
1839
        return bigbluebuttonbn_get_recording_data_row_text($recording, $metadescription, $newsource, $payload);
1840
    }
1841
    return bigbluebuttonbn_get_recording_data_row_text($recording, '', $newsource, $payload);
1842
}
1843
1844
/**
1845
 * Helper function renders text element for recording used in row for the data used by the recording table.
1846
 *
1847
 * @param array $recording
1848
 * @param string $text
1849
 * @param string $source
1850
 * @param array $data
1851
 *
1852
 * @return string
1853
 */
1854
function bigbluebuttonbn_get_recording_data_row_text($recording, $text, $source, $data) {
1855
    $htmltext = '<span>' . htmlentities($text) . '</span>';
1856
    if (empty($data)) {
1857
        return $htmltext;
1858
    }
1859
    $target = $data['action'] . '-' . $data['target'];
1860
    $id = 'recording-' . $target . '-' . $data['recordingid'];
1861
    $attributes = array('id' => $id, 'class' => 'quickeditlink col-md-20',
1862
        'data-recordingid' => $data['recordingid'], 'data-meetingid' => $data['meetingid'],
1863
        'data-target' => $data['target'], 'data-source' => $source);
1864
    $head = html_writer::start_tag('div', $attributes);
1865
    $tail = html_writer::end_tag('div');
1866
    $payload = array('action' => $data['action'], 'tag' => $data['tag'], 'target' => $data['target']);
1867
    $htmllink = bigbluebuttonbn_actionbar_render_button($recording, $payload);
1868
    return $head . $htmltext . $htmllink . $tail;
1869
}
1870
1871
/**
1872
 * Helper function render a button for the recording action bar
1873
 *
1874
 * @param array $recording
1875
 * @param array $data
1876
 *
1877
 * @return string
1878
 */
1879
function bigbluebuttonbn_actionbar_render_button($recording, $data) {
1880
    global $OUTPUT;
1881
    if (empty($data)) {
1882
        return '';
1883
    }
1884
    $target = $data['action'];
1885
    if (isset($data['target'])) {
1886
        $target .= '-' . $data['target'];
1887
    }
1888
    $id = 'recording-' . $target . '-' . $recording['recordID'];
1889
    $onclick = 'M.mod_bigbluebuttonbn.recordings.recording' . ucfirst($data['action']) . '(this); return false;';
1890
    if ((boolean) \mod_bigbluebuttonbn\locallib\config::get('recording_icons_enabled')) {
1891
        // With icon for $manageaction.
1892
        $iconattributes = array('id' => $id, 'class' => 'iconsmall');
1893
        $linkattributes = array(
1894
            'id' => $id,
1895
            'onclick' => $onclick,
1896
            'data-action' => $data['action'],
1897
        );
1898
        if (!isset($recording['imported'])) {
1899
            $linkattributes['data-links'] = bigbluebuttonbn_count_recording_imported_instances(
1900
                $recording['recordID']
1901
            );
1902
        }
1903
        if (isset($data['disabled'])) {
1904
            $iconattributes['class'] .= ' fa-' . $data['disabled'];
1905
            $linkattributes['class'] = 'disabled';
1906
            unset($linkattributes['onclick']);
1907
        }
1908
        $icon = new pix_icon(
1909
            'i/' . $data['tag'],
1910
            get_string('view_recording_list_actionbar_' . $data['action'], 'bigbluebuttonbn'),
1911
            'moodle',
1912
            $iconattributes
1913
        );
1914
        return $OUTPUT->action_icon('#', $icon, null, $linkattributes, false);
1915
    }
1916
    // With text for $manageaction.
1917
    $linkattributes = array('title' => get_string($data['tag']), 'class' => 'btn btn-xs btn-danger',
1918
        'onclick' => $onclick);
1919
    return $OUTPUT->action_link('#', get_string($data['action']), null, $linkattributes);
1920
}
1921
1922
/**
1923
 * Helper function builds the recording table.
1924
 *
1925
 * @param array $bbbsession
1926
 * @param array $recordings
1927
 * @param array $tools
1928
 *
1929
 * @return object
1930
 */
1931
function bigbluebuttonbn_get_recording_table($bbbsession, $recordings, $tools = ['protect', 'publish', 'delete']) {
1932
    global $DB;
1933
    // Declare the table.
1934
    $table = new html_table();
1935
    $table->data = array();
1936
    // Initialize table headers.
1937
    $table->head[] = get_string('view_recording_playback', 'bigbluebuttonbn');
1938
    $table->head[] = get_string('view_recording_name', 'bigbluebuttonbn');
1939
    $table->head[] = get_string('view_recording_description', 'bigbluebuttonbn');
1940
    if (bigbluebuttonbn_get_recording_data_preview_enabled($bbbsession)) {
1941
        $table->head[] = get_string('view_recording_preview', 'bigbluebuttonbn');
1942
    }
1943
    $table->head[] = get_string('view_recording_date', 'bigbluebuttonbn');
1944
    $table->head[] = get_string('view_recording_duration', 'bigbluebuttonbn');
1945
    $table->align = array('left', 'left', 'left', 'left', 'left', 'center');
1946
    $table->size = array('', '', '', '', '', '');
1947
    if ($bbbsession['managerecordings']) {
1948
        $table->head[] = get_string('view_recording_actionbar', 'bigbluebuttonbn');
1949
        $table->align[] = 'left';
1950
        $table->size[] = (count($tools) * 40) . 'px';
1951
    }
1952
    // Get the groups of the user.
1953
    $usergroups = groups_get_all_groups($bbbsession['course']->id, $bbbsession['userID']);
1954
1955
    // Build table content.
1956
    foreach ($recordings as $recording) {
1957
        $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...
1958
        $shortmeetingid = explode('-', $recording['meetingID']);
1959
        if (isset($shortmeetingid[0])) {
1960
            $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...
1961
        }
1962
        // Check if the record belongs to a Visible Group type.
1963
        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...
1964
        $groupmode = groups_get_activity_groupmode($cm);
1965
        $displayrow = true;
1966
        if (($groupmode != VISIBLEGROUPS)
1967
                && !$bbbsession['administrator'] && !$bbbsession['moderator']) {
1968
            $groupid = explode('[', $recording['meetingID']);
1969
            if (isset($groupid[1])) {
1970
                // It is a group recording and the user is not moderator/administrator. Recording should not be included by default.
1971
                $displayrow = false;
1972
                $groupid = explode(']', $groupid[1]);
1973
                if (isset($groupid[0])) {
1974
                    foreach ($usergroups as $usergroup) {
1975
                        if ($usergroup->id == $groupid[0]) {
1976
                            // Include recording if the user is in the same group.
1977
                            $displayrow = true;
1978
                        }
1979
                    }
1980
                }
1981
            }
1982
        }
1983
        if ($displayrow) {
1984
            $rowdata = bigbluebuttonbn_get_recording_data_row($bbbsession, $recording, $tools);
1985
            if (!empty($rowdata)) {
1986
                $row = bigbluebuttonbn_get_recording_table_row($bbbsession, $recording, $rowdata);
1987
                array_push($table->data, $row);
1988
            }
1989
        }
1990
    }
1991
    return $table;
1992
}
1993
1994
/**
1995
 * Helper function builds the recording table row and insert into table.
1996
 *
1997
 * @param array $bbbsession
1998
 * @param array $recording
1999
 * @param object $rowdata
2000
 *
2001
 * @return object
2002
 */
2003
function bigbluebuttonbn_get_recording_table_row($bbbsession, $recording, $rowdata) {
2004
    $row = new html_table_row();
2005
    $row->id = 'recording-tr-' . $recording['recordID'];
2006
    $row->attributes['data-imported'] = 'false';
2007
    $texthead = '';
2008
    $texttail = '';
2009
    if (isset($recording['imported'])) {
2010
        $row->attributes['title'] = get_string('view_recording_link_warning', 'bigbluebuttonbn');
2011
        $row->attributes['data-imported'] = 'true';
2012
        $texthead = '<em>';
2013
        $texttail = '</em>';
2014
    }
2015
    $rowdata->date_formatted = str_replace(' ', '&nbsp;', $rowdata->date_formatted);
2016
    $row->cells = array();
2017
    $row->cells[] = $texthead . $rowdata->playback . $texttail;
2018
    $row->cells[] = $texthead . $rowdata->recording . $texttail;
2019
    $row->cells[] = $texthead . $rowdata->description . $texttail;
2020
    if (bigbluebuttonbn_get_recording_data_preview_enabled($bbbsession)) {
2021
        $row->cells[] = $rowdata->preview;
2022
    }
2023
    $row->cells[] = $texthead . $rowdata->date_formatted . $texttail;
2024
    $row->cells[] = $rowdata->duration_formatted;
2025
    if ($bbbsession['managerecordings']) {
2026
        $row->cells[] = $rowdata->actionbar;
2027
    }
2028
    return $row;
2029
}
2030
2031
/**
2032
 * Get the basic data to display in the table view
2033
 *
2034
 * @param array $bbbsession the current session
2035
 * @param array $enabledfeatures feature enabled for this activity
2036
 * @return associative array containing the recordings indexed by recordID, each recording is also a
2037
 * non sequential associative array itself that corresponds to the actual recording in BBB
2038
 */
2039
function bigbluebutton_get_recordings_for_table_view($bbbsession, $enabledfeatures) {
2040
    $bigbluebuttonbnid = null;
2041
    if ($enabledfeatures['showroom']) {
2042
        $bigbluebuttonbnid = $bbbsession['bigbluebuttonbn']->id;
2043
    }
2044
    // Get recordings.
2045
    $recordings = bigbluebuttonbn_get_recordings(
2046
        $bbbsession['course']->id, $bigbluebuttonbnid, $enabledfeatures['showroom'],
2047
        $bbbsession['bigbluebuttonbn']->recordings_deleted
2048
    );
2049
    if ($enabledfeatures['importrecordings']) {
2050
        // Get recording links.
2051
        $bigbluebuttonbnid = $bbbsession['bigbluebuttonbn']->id;
2052
        $recordingsimported = bigbluebuttonbn_get_recordings_imported_array(
2053
            $bbbsession['course']->id, $bigbluebuttonbnid, true
2054
        );
2055
        /* Perform aritmetic addition instead of merge so the imported recordings corresponding to existent
2056
         * recordings are not included. */
2057
        if ($bbbsession['bigbluebuttonbn']->recordings_imported) {
2058
            $recordings = $recordingsimported;
2059
        } else {
2060
            $recordings += $recordingsimported;
2061
        }
2062
    }
2063
    return $recordings;
2064
}
2065
2066
/**
2067
 * Helper function evaluates if recording row should be included in the table.
2068
 *
2069
 * @param array $bbbsession
2070
 * @param array $recording
2071
 *
2072
 * @return boolean
2073
 */
2074
function bigbluebuttonbn_include_recording_table_row($bbbsession, $recording) {
2075
    // Exclude unpublished recordings, only if user has no rights to manage them.
2076
    if ($recording['published'] != 'true' && !$bbbsession['managerecordings']) {
2077
        return false;
2078
    }
2079
    // Imported recordings are always shown as long as they are published.
2080
    if (isset($recording['imported'])) {
2081
        return true;
2082
    }
2083
    // Administrators and moderators are always allowed.
2084
    if ($bbbsession['administrator'] || $bbbsession['moderator']) {
2085
        return true;
2086
    }
2087
    // When groups are enabled, exclude those to which the user doesn't have access to.
2088
    if (isset($bbbsession['group']) && $recording['meetingID'] != $bbbsession['meetingid']) {
2089
        return false;
2090
    }
2091
    return true;
2092
}
2093
2094
/**
2095
 * Helper function triggers a send notification when the recording is ready.
2096
 *
2097
 * @param object $bigbluebuttonbn
2098
 *
2099
 * @return void
2100
 */
2101
function bigbluebuttonbn_send_notification_recording_ready($bigbluebuttonbn) {
2102
    \mod_bigbluebuttonbn\locallib\notifier::notify_recording_ready($bigbluebuttonbn);
2103
}
2104
2105
/**
2106
 * Helper function enqueues list of meeting events to be stored and processed as for completion.
2107
 *
2108
 * @param object $bigbluebuttonbn
2109
 * @param object $jsonobj
2110
 *
2111
 * @return void
2112
 */
2113
function bigbluebuttonbn_process_meeting_events($bigbluebuttonbn, $jsonobj) {
2114
    $meetingid = $jsonobj->{'meeting_id'};
2115
    $recordid = $jsonobj->{'internal_meeting_id'};
2116
    $attendees = $jsonobj->{'data'}->{'attendees'};
2117
    foreach ($attendees as $attendee) {
2118
        $userid = $attendee->{'ext_user_id'};
2119
        $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...
2120
        $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...
2121
        $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...
2122
        $meta['data'] = $attendee;
2123
        // Stores the log.
2124
        bigbluebuttonbn_log($bigbluebuttonbn, BIGBLUEBUTTON_LOG_EVENT_SUMMARY, $overrides, json_encode($meta));
2125
        // Enqueue a task for processing the completion.
2126
        bigbluebuttonbn_enqueue_completion_update($bigbluebuttonbn, $userid);
2127
    }
2128
}
2129
2130
/**
2131
 * Helper function enqueues one user for being validated as for completion.
2132
 *
2133
 * @param object $bigbluebuttonbn
2134
 * @param string $userid
2135
 *
2136
 * @return void
2137
 */
2138
function bigbluebuttonbn_enqueue_completion_update($bigbluebuttonbn, $userid) {
2139
    try {
2140
        // Create the instance of completion_update_state task.
2141
        $task = new \mod_bigbluebuttonbn\task\completion_update_state();
2142
        // Add custom data.
2143
        $data = array(
2144
            'bigbluebuttonbn' => $bigbluebuttonbn,
2145
            'userid' => $userid,
2146
        );
2147
        $task->set_custom_data($data);
2148
        // CONTRIB-7457: Task should be executed by a user, maybe Teacher as Student won't have rights for overriding.
2149
        // $ task -> set_userid ( $ user -> id );.
2150
        // Enqueue it.
2151
        \core\task\manager::queue_adhoc_task($task);
2152
    } catch (Exception $e) {
2153
        mtrace("Error while enqueuing completion_update_state task. " . (string) $e);
2154
    }
2155
}
2156
2157
/**
2158
 * Helper function enqueues completion trigger.
2159
 *
2160
 * @param object $bigbluebuttonbn
2161
 * @param string $userid
2162
 *
2163
 * @return void
2164
 */
2165
function bigbluebuttonbn_completion_update_state($bigbluebuttonbn, $userid) {
2166
    global $CFG;
2167
    require_once($CFG->libdir.'/completionlib.php');
2168
    list($course, $cm) = get_course_and_cm_from_instance($bigbluebuttonbn, 'bigbluebuttonbn');
2169
    $completion = new completion_info($course);
2170
    if (!$completion->is_enabled($cm)) {
2171
        mtrace("Completion not enabled");
2172
        return;
2173
    }
2174
    if (bigbluebuttonbn_get_completion_state($course, $cm, $userid, COMPLETION_AND)) {
2175
        mtrace("Completion succeeded for user $userid");
2176
        $completion->update_state($cm, COMPLETION_COMPLETE, $userid, true);
2177
    } else {
2178
        mtrace("Completion did not succeed for user $userid");
2179
    }
2180
}
2181
2182
/**
2183
 * Helper evaluates if the bigbluebutton server used belongs to blindsidenetworks domain.
2184
 *
2185
 * @return boolean
2186
 */
2187
function bigbluebuttonbn_is_bn_server() {
2188
    if (\mod_bigbluebuttonbn\locallib\config::get('bn_server')) {
2189
        return true;
2190
    }
2191
    $parsedurl = parse_url(\mod_bigbluebuttonbn\locallib\config::get('server_url'));
2192
    if (!isset($parsedurl['host'])) {
2193
        return false;
2194
    }
2195
    $h = $parsedurl['host'];
2196
    $hends = explode('.', $h);
2197
    $hendslength = count($hends);
2198
    return ($hends[$hendslength - 1] == 'com' && $hends[$hendslength - 2] == 'blindsidenetworks');
2199
}
2200
2201
/**
2202
 * Helper function returns a list of courses a user has access to, wrapped in an array that can be used
2203
 * by a html select.
2204
 *
2205
 * @param array $bbbsession
2206
 *
2207
 * @return array
2208
 */
2209
function bigbluebuttonbn_import_get_courses_for_select(array $bbbsession) {
2210
    if ($bbbsession['administrator']) {
2211
        $courses = get_courses('all', 'c.fullname ASC');
2212
        // It includes the name of the site as a course (category 0), so remove the first one.
2213
        unset($courses['1']);
2214
    } else {
2215
        $courses = enrol_get_users_courses($bbbsession['userID'], false, 'id,shortname,fullname');
2216
    }
2217
    $coursesforselect = [];
2218
    foreach ($courses as $course) {
2219
        $coursesforselect[$course->id] = $course->fullname . " (" . $course->shortname . ")";
2220
    }
2221
    return $coursesforselect;
2222
}
2223
2224
/**
2225
 * Helper function renders recording table.
2226
 *
2227
 * @param array $bbbsession
2228
 * @param array $recordings
2229
 * @param array $tools
2230
 *
2231
 * @return array
2232
 */
2233
function bigbluebuttonbn_output_recording_table($bbbsession, $recordings, $tools = ['protect', 'publish', 'delete']) {
2234
    if (isset($recordings) && !empty($recordings)) {
2235
        // There are recordings for this meeting.
2236
        $table = bigbluebuttonbn_get_recording_table($bbbsession, $recordings, $tools);
2237
    }
2238
    if (!isset($table) || !isset($table->data)) {
2239
        // Render a table with "No recordings".
2240
        return html_writer::div(
2241
            get_string('view_message_norecordings', 'bigbluebuttonbn'),
2242
            '',
2243
            array('id' => 'bigbluebuttonbn_recordings_table')
2244
        );
2245
    }
2246
    // Render the table.
2247
    return html_writer::div(html_writer::table($table), '', array('id' => 'bigbluebuttonbn_recordings_table'));
2248
}
2249
2250
/**
2251
 * Helper function to convert an html string to plain text.
2252
 *
2253
 * @param string $html
2254
 * @param integer $len
2255
 *
2256
 * @return string
2257
 */
2258
function bigbluebuttonbn_html2text($html, $len = 0) {
2259
    $text = strip_tags($html);
2260
    $text = str_replace('&nbsp;', ' ', $text);
2261
    $textlen = strlen($text);
2262
    $text = mb_substr($text, 0, $len);
2263
    if ($textlen > $len) {
2264
        $text .= '...';
2265
    }
2266
    return $text;
2267
}
2268
2269
/**
2270
 * Helper function to obtain the tags linked to a bigbluebuttonbn activity
2271
 *
2272
 * @param string $id
2273
 *
2274
 * @return string containing the tags separated by commas
2275
 */
2276
function bigbluebuttonbn_get_tags($id) {
2277
    if (class_exists('core_tag_tag')) {
2278
        return implode(',', core_tag_tag::get_item_tags_array('core', 'course_modules', $id));
2279
    }
2280
    return implode(',', tag_get_tags('bigbluebuttonbn', $id));
2281
}
2282
2283
/**
2284
 * Helper function to define the sql used for gattering the bigbluebuttonbnids whose meetingids should be included
2285
 * in the getRecordings request
2286
 *
2287
 * @param string $courseid
2288
 * @param string $bigbluebuttonbnid
2289
 * @param bool   $subset
2290
 *
2291
 * @return string containing the sql used for getting the target bigbluebuttonbn instances
2292
 */
2293
function bigbluebuttonbn_get_recordings_sql_select($courseid, $bigbluebuttonbnid = null, $subset = true) {
2294
    if (empty($courseid)) {
2295
        $courseid = 0;
2296
    }
2297
    if (empty($bigbluebuttonbnid)) {
2298
        return "course = '{$courseid}'";
2299
    }
2300
    if ($subset) {
2301
        return "id = '{$bigbluebuttonbnid}'";
2302
    }
2303
    return "id <> '{$bigbluebuttonbnid}' AND course = '{$courseid}'";
2304
}
2305
2306
/**
2307
 * Helper function to define the sql used for gattering the bigbluebuttonbnids whose meetingids should be included
2308
 * in the getRecordings request considering only those that belong to deleted activities.
2309
 *
2310
 * @param string $courseid
2311
 * @param string $bigbluebuttonbnid
2312
 * @param bool   $subset
2313
 *
2314
 * @return string containing the sql used for getting the target bigbluebuttonbn instances
2315
 */
2316 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...
2317
    $sql = "log = '" . BIGBLUEBUTTONBN_LOG_EVENT_DELETE . "' AND meta like '%has_recordings%' AND meta like '%true%'";
2318
    if (empty($courseid)) {
2319
        $courseid = 0;
2320
    }
2321
    if (empty($bigbluebuttonbnid)) {
2322
        return $sql . " AND courseid = {$courseid}";
2323
    }
2324
    if ($subset) {
2325
        return $sql . " AND bigbluebuttonbnid = '{$bigbluebuttonbnid}'";
2326
    }
2327
    return $sql . " AND courseid = {$courseid} AND bigbluebuttonbnid <> '{$bigbluebuttonbnid}'";
2328
}
2329
2330
/**
2331
 * Helper function to define the sql used for gattering the bigbluebuttonbnids whose meetingids should be included
2332
 * in the getRecordings request considering only those that belong to imported recordings.
2333
 *
2334
 * @param string $courseid
2335
 * @param string $bigbluebuttonbnid
2336
 * @param bool   $subset
2337
 *
2338
 * @return string containing the sql used for getting the target bigbluebuttonbn instances
2339
 */
2340 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...
2341
    $sql = "log = '" . BIGBLUEBUTTONBN_LOG_EVENT_IMPORT . "'";
2342
    if (empty($courseid)) {
2343
        $courseid = 0;
2344
    }
2345
    if (empty($bigbluebuttonbnid)) {
2346
        return $sql . " AND courseid = '{$courseid}'";
2347
    }
2348
    if ($subset) {
2349
        return $sql . " AND bigbluebuttonbnid = '{$bigbluebuttonbnid}'";
2350
    }
2351
    return $sql . " AND courseid = '{$courseid}' AND bigbluebuttonbnid <> '{$bigbluebuttonbnid}'";
2352
}
2353
2354
/**
2355
 * Helper function to get recordings and imported recordings together.
2356
 *
2357
 * @param string $courseid
2358
 * @param string $bigbluebuttonbnid
2359
 * @param bool   $subset
2360
 * @param bool   $includedeleted
2361
 *
2362
 * @return associative array containing the recordings indexed by recordID, each recording is also a
2363
 * non sequential associative array itself that corresponds to the actual recording in BBB
2364
 */
2365
function bigbluebuttonbn_get_allrecordings($courseid = 0, $bigbluebuttonbnid = null, $subset = true, $includedeleted = false) {
2366
    $recordings = bigbluebuttonbn_get_recordings($courseid, $bigbluebuttonbnid, $subset, $includedeleted);
2367
    $recordingsimported = bigbluebuttonbn_get_recordings_imported_array($courseid, $bigbluebuttonbnid, $subset);
2368
    return ($recordings + $recordingsimported);
2369
}
2370
2371
/**
2372
 * Helper function to retrieve recordings from the BigBlueButton. The references are stored as events
2373
 * in bigbluebuttonbn_logs.
2374
 *
2375
 * @param string $courseid
2376
 * @param string $bigbluebuttonbnid
2377
 * @param bool   $subset
2378
 * @param bool   $includedeleted
2379
 *
2380
 * @return associative array containing the recordings indexed by recordID, each recording is also a
2381
 * non sequential associative array itself that corresponds to the actual recording in BBB
2382
 */
2383
function bigbluebuttonbn_get_recordings($courseid = 0, $bigbluebuttonbnid = null, $subset = true, $includedeleted = false) {
2384
    global $DB;
2385
    $select = bigbluebuttonbn_get_recordings_sql_select($courseid, $bigbluebuttonbnid, $subset);
2386
    $bigbluebuttonbns = $DB->get_records_select_menu('bigbluebuttonbn', $select, null, 'id', 'id, meetingid');
2387
    /* Consider logs from deleted bigbluebuttonbn instances whose meetingids should be included in
2388
     * the getRecordings request. */
2389
    if ($includedeleted) {
2390
        $selectdeleted = bigbluebuttonbn_get_recordings_deleted_sql_select($courseid, $bigbluebuttonbnid, $subset);
2391
        $bigbluebuttonbnsdel = $DB->get_records_select_menu(
2392
            'bigbluebuttonbn_logs',
2393
            $selectdeleted,
2394
            null,
2395
            'bigbluebuttonbnid',
2396
            'bigbluebuttonbnid, meetingid'
2397
        );
2398
        if (!empty($bigbluebuttonbnsdel)) {
2399
            // Merge bigbluebuttonbnis from deleted instances, only keys are relevant.
2400
            // Artimetic merge is used in order to keep the keys.
2401
            $bigbluebuttonbns += $bigbluebuttonbnsdel;
2402
        }
2403
    }
2404
    // Gather the meetingids from bigbluebuttonbn logs that include a create with record=true.
2405
    if (empty($bigbluebuttonbns)) {
2406
        return array();
2407
    }
2408
    // Prepare select for loading records based on existent bigbluebuttonbns.
2409
    $sql = 'SELECT DISTINCT meetingid, bigbluebuttonbnid FROM {bigbluebuttonbn_logs} WHERE ';
2410
    $sql .= '(bigbluebuttonbnid=' . implode(' OR bigbluebuttonbnid=', array_keys($bigbluebuttonbns)) . ')';
2411
    // Include only Create events and exclude those with record not true.
2412
    $sql .= ' AND log = ? AND meta LIKE ? AND meta LIKE ?';
2413
    // Execute select for loading records based on existent bigbluebuttonbns.
2414
    $records = $DB->get_records_sql_menu($sql, array(BIGBLUEBUTTONBN_LOG_EVENT_CREATE, '%record%', '%true%'));
2415
    // Get actual recordings.
2416
    return bigbluebuttonbn_get_recordings_array(array_keys($records));
2417
}
2418
2419
/**
2420
 * Helper function iterates an array with recordings and unset those already imported.
2421
 *
2422
 * @param array $recordings
2423
 * @param integer $courseid
2424
 * @param integer $bigbluebuttonbnid
2425
 *
2426
 * @return array
2427
 */
2428
function bigbluebuttonbn_unset_existent_recordings_already_imported($recordings, $courseid, $bigbluebuttonbnid) {
2429
    $recordingsimported = bigbluebuttonbn_get_recordings_imported_array($courseid, $bigbluebuttonbnid, true);
2430
    foreach ($recordings as $key => $recording) {
2431
        if (isset($recordingsimported[$recording['recordID']])) {
2432
            unset($recordings[$key]);
2433
        }
2434
    }
2435
    return $recordings;
2436
}
2437
2438
/**
2439
 * Helper function to count the imported recordings for a recordingid.
2440
 *
2441
 * @param string $recordid
2442
 *
2443
 * @return integer
2444
 */
2445
function bigbluebuttonbn_count_recording_imported_instances($recordid) {
2446
    global $DB;
2447
    $sql = 'SELECT COUNT(DISTINCT id) FROM {bigbluebuttonbn_logs} WHERE log = ? AND meta LIKE ? AND meta LIKE ?';
2448
    return $DB->count_records_sql($sql, array(BIGBLUEBUTTONBN_LOG_EVENT_IMPORT, '%recordID%', "%{$recordid}%"));
2449
}
2450
2451
/**
2452
 * Helper function returns an array with all the instances of imported recordings for a recordingid.
2453
 *
2454
 * @param string $recordid
2455
 *
2456
 * @return array
2457
 */
2458
function bigbluebuttonbn_get_recording_imported_instances($recordid) {
2459
    global $DB;
2460
    $sql = 'SELECT * FROM {bigbluebuttonbn_logs} WHERE log = ? AND meta LIKE ? AND meta LIKE ?';
2461
    $recordingsimported = $DB->get_records_sql($sql, array(BIGBLUEBUTTONBN_LOG_EVENT_IMPORT, '%recordID%',
2462
        "%{$recordid}%"));
2463
    return $recordingsimported;
2464
}
2465
2466
/**
2467
 * Helper function to get how much callback events are logged.
2468
 *
2469
 * @param string $recordid
2470
 * @param string $callbacktype
2471
 *
2472
 * @return integer
2473
 */
2474
function bigbluebuttonbn_get_count_callback_event_log($recordid, $callbacktype = 'recording_ready') {
2475
    global $DB;
2476
    $sql = 'SELECT count(DISTINCT id) FROM {bigbluebuttonbn_logs} WHERE log = ? AND meta LIKE ? AND meta LIKE ?';
2477
    // Callback type added on version 2.4, validate recording_ready first or assume it on records with no callback.
2478
    if ($callbacktype == 'recording_ready') {
2479
        $sql .= ' AND (meta LIKE ? OR meta NOT LIKE ? )';
2480
        $count = $DB->count_records_sql($sql, array(BIGBLUEBUTTON_LOG_EVENT_CALLBACK, '%recordid%', "%$recordid%",
2481
            $callbacktype, 'callback'));
2482
        return $count;
2483
    }
2484
    $sql .= ' AND meta LIKE ?;';
2485
    $count = $DB->count_records_sql($sql, array(BIGBLUEBUTTON_LOG_EVENT_CALLBACK, '%recordid%', "%$recordid%", "%$callbacktype%"));
2486
    return $count;
2487
}
2488
2489
/**
2490
 * Helper function returns an array with the profiles (with features per profile) for the different types
2491
 * of bigbluebuttonbn instances.
2492
 *
2493
 * @return array
2494
 */
2495
function bigbluebuttonbn_get_instance_type_profiles() {
2496
    $instanceprofiles = array(
2497
        BIGBLUEBUTTONBN_TYPE_ALL => array('id' => BIGBLUEBUTTONBN_TYPE_ALL,
2498
            'name' => get_string('instance_type_default', 'bigbluebuttonbn'),
2499
            'features' => array('all')),
2500
        BIGBLUEBUTTONBN_TYPE_ROOM_ONLY => array('id' => BIGBLUEBUTTONBN_TYPE_ROOM_ONLY,
2501
            'name' => get_string('instance_type_room_only', 'bigbluebuttonbn'),
2502
            'features' => array('showroom', 'welcomemessage', 'voicebridge', 'waitformoderator', 'userlimit',
2503
                'recording', 'sendnotifications', 'preuploadpresentation', 'permissions', 'schedule', 'groups',
2504
                'modstandardelshdr', 'availabilityconditionsheader', 'tagshdr', 'competenciessection',
2505
                'clienttype', 'completionattendance', 'completionengagement', 'availabilityconditionsheader',
2506
                'viewguestlink', 'changeguestlinkpass')),
2507
        BIGBLUEBUTTONBN_TYPE_RECORDING_ONLY => array('id' => BIGBLUEBUTTONBN_TYPE_RECORDING_ONLY,
2508
            'name' => get_string('instance_type_recording_only', 'bigbluebuttonbn'),
2509
            'features' => array('showrecordings', 'importrecordings', 'availabilityconditionsheader')),
2510
    );
2511
    return $instanceprofiles;
2512
}
2513
2514
/**
2515
 * Helper function returns an array with enabled features for an specific profile type.
2516
 *
2517
 * @param array $typeprofiles
2518
 * @param string $type
2519
 *
2520
 * @return array
2521
 */
2522
function bigbluebuttonbn_get_enabled_features($typeprofiles, $type = null) {
2523
    $enabledfeatures = array();
2524
    $features = $typeprofiles[BIGBLUEBUTTONBN_TYPE_ALL]['features'];
2525
    if (!is_null($type) && key_exists($type, $typeprofiles)) {
2526
        $features = $typeprofiles[$type]['features'];
2527
    }
2528
    $enabledfeatures['showroom'] = (in_array('all', $features) || in_array('showroom', $features));
2529
    if (\mod_bigbluebuttonbn\locallib\config::guestlinks_enabled()) {
2530
        $enabledfeatures['viewguestlink'] = (in_array('all', $features) || in_array('viewguestlink', $features));
2531
        $enabledfeatures['changeguestlinkpass'] = (in_array('all', $features) || in_array('changeguestlinkpass', $features));
2532
    }
2533
    // Evaluates if recordings are enabled for the Moodle site.
2534
    $enabledfeatures['showrecordings'] = false;
2535
    if (\mod_bigbluebuttonbn\locallib\config::recordings_enabled()) {
2536
        $enabledfeatures['showrecordings'] = (in_array('all', $features) || in_array('showrecordings', $features));
2537
    }
2538
    $enabledfeatures['importrecordings'] = false;
2539
    if (\mod_bigbluebuttonbn\locallib\config::importrecordings_enabled()) {
2540
        $enabledfeatures['importrecordings'] = (in_array('all', $features) || in_array('importrecordings', $features));
2541
    }
2542
    // Evaluates if clienttype is enabled for the Moodle site.
2543
    $enabledfeatures['clienttype'] = false;
2544
    if (\mod_bigbluebuttonbn\locallib\config::clienttype_enabled()) {
2545
        $enabledfeatures['clienttype'] = (in_array('all', $features) || in_array('clienttype', $features));
2546
    }
2547
    return $enabledfeatures;
2548
}
2549
2550
/**
2551
 * Helper function returns an array with the profiles (with features per profile) for the different types
2552
 * of bigbluebuttonbn instances that the user is allowed to create.
2553
 *
2554
 * @param boolean $room
2555
 * @param boolean $recording
2556
 *
2557
 * @return array
2558
 */
2559
function bigbluebuttonbn_get_instance_type_profiles_create_allowed($room, $recording) {
2560
    $profiles = bigbluebuttonbn_get_instance_type_profiles();
2561
    if (!$room) {
2562
        unset($profiles[BIGBLUEBUTTONBN_TYPE_ROOM_ONLY]);
2563
        unset($profiles[BIGBLUEBUTTONBN_TYPE_ALL]);
2564
    }
2565
    if (!$recording) {
2566
        unset($profiles[BIGBLUEBUTTONBN_TYPE_RECORDING_ONLY]);
2567
        unset($profiles[BIGBLUEBUTTONBN_TYPE_ALL]);
2568
    }
2569
    return $profiles;
2570
}
2571
2572
/**
2573
 * Helper function returns an array with the profiles (with features per profile) for the different types
2574
 * of bigbluebuttonbn instances.
2575
 *
2576
 * @param array $profiles
2577
 *
2578
 * @return array
2579
 */
2580
function bigbluebuttonbn_get_instance_profiles_array($profiles = []) {
2581
    $profilesarray = array();
2582
    foreach ($profiles as $key => $profile) {
2583
        $profilesarray[$profile['id']] = $profile['name'];
2584
    }
2585
    return $profilesarray;
2586
}
2587
2588
/**
2589
 * Helper function returns time in a formatted string.
2590
 *
2591
 * @param integer $time
2592
 *
2593
 * @return string
2594
 */
2595
function bigbluebuttonbn_format_activity_time($time) {
2596
    global $CFG;
2597
    require_once($CFG->dirroot.'/calendar/lib.php');
2598
    $activitytime = '';
2599
    if ($time) {
2600
        $activitytime = calendar_day_representation($time) . ' ' .
2601
        get_string('mod_form_field_notification_msg_at', 'bigbluebuttonbn') . ' ' .
2602
        calendar_time_representation($time);
2603
    }
2604
    return $activitytime;
2605
}
2606
2607
/**
2608
 * Helper function returns array with all the strings to be used in javascript.
2609
 *
2610
 * @return array
2611
 */
2612
function bigbluebuttonbn_get_strings_for_js() {
2613
    $locale = bigbluebuttonbn_get_locale();
2614
    $stringman = get_string_manager();
2615
    $strings = $stringman->load_component_strings('bigbluebuttonbn', $locale);
2616
    return $strings;
2617
}
2618
2619
/**
2620
 * Helper function returns the locale set by moodle.
2621
 *
2622
 * @return string
2623
 */
2624
function bigbluebuttonbn_get_locale() {
2625
    $lang = get_string('locale', 'core_langconfig');
2626
    return substr($lang, 0, strpos($lang, '.'));
2627
}
2628
2629
/**
2630
 * Helper function returns the locale code based on the locale set by moodle.
2631
 *
2632
 * @return string
2633
 */
2634
function bigbluebuttonbn_get_localcode() {
2635
    $locale = bigbluebuttonbn_get_locale();
2636
    return substr($locale, 0, strpos($locale, '_'));
2637
}
2638
2639
/**
2640
 * Helper function returns array with the instance settings used in views.
2641
 *
2642
 * @param string $id
2643
 * @param object $bigbluebuttonbnid
2644
 *
2645
 * @return array
2646
 */
2647
function bigbluebuttonbn_view_validator($id, $bigbluebuttonbnid) {
2648
    if ($id) {
2649
        return bigbluebuttonbn_view_instance_id($id);
2650
    }
2651
    if ($bigbluebuttonbnid) {
2652
        return bigbluebuttonbn_view_instance_bigbluebuttonbn($bigbluebuttonbnid);
2653
    }
2654
}
2655
2656
/**
2657
 * Helper function returns array with the instance settings used in views based on id.
2658
 *
2659
 * @param string $id
2660
 *
2661
 * @return array
2662
 */
2663 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...
2664
    global $DB;
2665
    $cm = get_coursemodule_from_id('bigbluebuttonbn', $id, 0, false, MUST_EXIST);
2666
    $course = $DB->get_record('course', array('id' => $cm->course), '*', MUST_EXIST);
2667
    $bigbluebuttonbn = $DB->get_record('bigbluebuttonbn', array('id' => $cm->instance), '*', MUST_EXIST);
2668
    return array('cm' => $cm, 'course' => $course, 'bigbluebuttonbn' => $bigbluebuttonbn);
2669
}
2670
2671
/**
2672
 * Helper function returns array with the instance settings used in views based on bigbluebuttonbnid.
2673
 *
2674
 * @param object $bigbluebuttonbnid
2675
 *
2676
 * @return array
2677
 */
2678 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...
2679
    global $DB;
2680
    $bigbluebuttonbn = $DB->get_record('bigbluebuttonbn', array('id' => $bigbluebuttonbnid), '*', MUST_EXIST);
2681
    $course = $DB->get_record('course', array('id' => $bigbluebuttonbn->course), '*', MUST_EXIST);
2682
    $cm = get_coursemodule_from_instance('bigbluebuttonbn', $bigbluebuttonbn->id, $course->id, false, MUST_EXIST);
2683
    return array('cm' => $cm, 'course' => $course, 'bigbluebuttonbn' => $bigbluebuttonbn);
2684
}
2685
2686
/**
2687
 * Helper function renders general settings if the feature is enabled.
2688
 *
2689
 * @param object $renderer
2690
 *
2691
 * @return void
2692
 */
2693
function bigbluebuttonbn_settings_general(&$renderer) {
2694
    // Configuration for BigBlueButton.
2695
    if ((boolean) \mod_bigbluebuttonbn\settings\validator::section_general_shown()) {
2696
        $renderer->render_group_header('general');
2697
        $renderer->render_group_element(
2698
            'server_url',
2699
            $renderer->render_group_element_text('server_url', BIGBLUEBUTTONBN_DEFAULT_SERVER_URL)
2700
        );
2701
        $renderer->render_group_element(
2702
            'shared_secret',
2703
            $renderer->render_group_element_text('shared_secret', BIGBLUEBUTTONBN_DEFAULT_SHARED_SECRET)
2704
        );
2705
    }
2706
}
2707
2708
/**
2709
 * Helper function renders record settings if the feature is enabled.
2710
 *
2711
 * @param object $renderer
2712
 *
2713
 * @return void
2714
 */
2715
function bigbluebuttonbn_settings_record(&$renderer) {
2716
    // Configuration for 'recording' feature.
2717
    if ((boolean) \mod_bigbluebuttonbn\settings\validator::section_record_meeting_shown()) {
2718
        $renderer->render_group_header('recording');
2719
        $renderer->render_group_element(
2720
            'recording_default',
2721
            $renderer->render_group_element_checkbox('recording_default', 1)
2722
        );
2723
        $renderer->render_group_element(
2724
            'recording_editable',
2725
            $renderer->render_group_element_checkbox('recording_editable', 1)
2726
        );
2727
        $renderer->render_group_element(
2728
            'recording_icons_enabled',
2729
            $renderer->render_group_element_checkbox('recording_icons_enabled', 1)
2730
        );
2731
2732
        // Add recording start to load and allow/hide stop/pause.
2733
        $renderer->render_group_element(
2734
            'recording_all_from_start_default',
2735
            $renderer->render_group_element_checkbox('recording_all_from_start_default', 0)
2736
        );
2737
        $renderer->render_group_element(
2738
            'recording_all_from_start_editable',
2739
            $renderer->render_group_element_checkbox('recording_all_from_start_editable', 0)
2740
        );
2741
        $renderer->render_group_element(
2742
            'recording_hide_button_default',
2743
            $renderer->render_group_element_checkbox('recording_hide_button_default', 0)
2744
        );
2745
        $renderer->render_group_element(
2746
            'recording_hide_button_editable',
2747
            $renderer->render_group_element_checkbox('recording_hide_button_editable', 0)
2748
        );
2749
    }
2750
}
2751
2752
/**
2753
 * Helper function renders import recording settings if the feature is enabled.
2754
 *
2755
 * @param object $renderer
2756
 *
2757
 * @return void
2758
 */
2759 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...
2760
    // Configuration for 'import recordings' feature.
2761
    if ((boolean) \mod_bigbluebuttonbn\settings\validator::section_import_recordings_shown()) {
2762
        $renderer->render_group_header('importrecordings');
2763
        $renderer->render_group_element(
2764
            'importrecordings_enabled',
2765
            $renderer->render_group_element_checkbox('importrecordings_enabled', 0)
2766
        );
2767
        $renderer->render_group_element(
2768
            'importrecordings_from_deleted_enabled',
2769
            $renderer->render_group_element_checkbox('importrecordings_from_deleted_enabled', 0)
2770
        );
2771
    }
2772
}
2773
2774
/**
2775
 * Helper function renders show recording settings if the feature is enabled.
2776
 *
2777
 * @param object $renderer
2778
 *
2779
 * @return void
2780
 */
2781
function bigbluebuttonbn_settings_showrecordings(&$renderer) {
2782
    // Configuration for 'show recordings' feature.
2783
    if ((boolean) \mod_bigbluebuttonbn\settings\validator::section_show_recordings_shown()) {
2784
        $renderer->render_group_header('recordings');
2785
        $renderer->render_group_element(
2786
            'recordings_html_default',
2787
            $renderer->render_group_element_checkbox('recordings_html_default', 1)
2788
        );
2789
        $renderer->render_group_element(
2790
            'recordings_html_editable',
2791
            $renderer->render_group_element_checkbox('recordings_html_editable', 0)
2792
        );
2793
        $renderer->render_group_element(
2794
            'recordings_deleted_default',
2795
            $renderer->render_group_element_checkbox('recordings_deleted_default', 1)
2796
        );
2797
        $renderer->render_group_element(
2798
            'recordings_deleted_editable',
2799
            $renderer->render_group_element_checkbox('recordings_deleted_editable', 0)
2800
        );
2801
        $renderer->render_group_element(
2802
            'recordings_imported_default',
2803
            $renderer->render_group_element_checkbox('recordings_imported_default', 0)
2804
        );
2805
        $renderer->render_group_element(
2806
            'recordings_imported_editable',
2807
            $renderer->render_group_element_checkbox('recordings_imported_editable', 1)
2808
        );
2809
        $renderer->render_group_element(
2810
            'recordings_preview_default',
2811
            $renderer->render_group_element_checkbox('recordings_preview_default', 1)
2812
        );
2813
        $renderer->render_group_element(
2814
            'recordings_preview_editable',
2815
            $renderer->render_group_element_checkbox('recordings_preview_editable', 0)
2816
        );
2817
        $renderer->render_group_element(
2818
            'recordings_sortorder',
2819
            $renderer->render_group_element_checkbox('recordings_sortorder', 0)
2820
        );
2821
        $renderer->render_group_element(
2822
            'recordings_validate_url',
2823
            $renderer->render_group_element_checkbox('recordings_validate_url', 1)
2824
        );
2825
    }
2826
}
2827
2828
/**
2829
 * Helper function renders wait for moderator settings if the feature is enabled.
2830
 *
2831
 * @param object $renderer
2832
 *
2833
 * @return void
2834
 */
2835
function bigbluebuttonbn_settings_waitmoderator(&$renderer) {
2836
    // Configuration for wait for moderator feature.
2837
    if ((boolean) \mod_bigbluebuttonbn\settings\validator::section_wait_moderator_shown()) {
2838
        $renderer->render_group_header('waitformoderator');
2839
        $renderer->render_group_element(
2840
            'waitformoderator_default',
2841
            $renderer->render_group_element_checkbox('waitformoderator_default', 0)
2842
        );
2843
        $renderer->render_group_element(
2844
            'waitformoderator_editable',
2845
            $renderer->render_group_element_checkbox('waitformoderator_editable', 1)
2846
        );
2847
        $renderer->render_group_element(
2848
            'waitformoderator_ping_interval',
2849
            $renderer->render_group_element_text('waitformoderator_ping_interval', 10, PARAM_INT)
2850
        );
2851
        $renderer->render_group_element(
2852
            'waitformoderator_cache_ttl',
2853
            $renderer->render_group_element_text('waitformoderator_cache_ttl', 60, PARAM_INT)
2854
        );
2855
    }
2856
}
2857
2858
/**
2859
 * Helper function renders static voice bridge settings if the feature is enabled.
2860
 *
2861
 * @param object $renderer
2862
 *
2863
 * @return void
2864
 */
2865
function bigbluebuttonbn_settings_voicebridge(&$renderer) {
2866
    // Configuration for "static voice bridge" feature.
2867
    if ((boolean) \mod_bigbluebuttonbn\settings\validator::section_static_voice_bridge_shown()) {
2868
        $renderer->render_group_header('voicebridge');
2869
        $renderer->render_group_element(
2870
            'voicebridge_editable',
2871
            $renderer->render_group_element_checkbox('voicebridge_editable', 0)
2872
        );
2873
    }
2874
}
2875
2876
/**
2877
 * Helper function renders preuploaded presentation settings if the feature is enabled.
2878
 *
2879
 * @param object $renderer
2880
 *
2881
 * @return void
2882
 */
2883
function bigbluebuttonbn_settings_preupload(&$renderer) {
2884
    // Configuration for "preupload presentation" feature.
2885
    if ((boolean) \mod_bigbluebuttonbn\settings\validator::section_preupload_presentation_shown()) {
2886
        // This feature only works if curl is installed.
2887
        $preuploaddescripion = get_string('config_preuploadpresentation_description', 'bigbluebuttonbn');
2888
        if (!extension_loaded('curl')) {
2889
            $preuploaddescripion .= '<div class="form-defaultinfo">';
2890
            $preuploaddescripion .= get_string('config_warning_curl_not_installed', 'bigbluebuttonbn');
2891
            $preuploaddescripion .= '</div><br>';
2892
        }
2893
        $renderer->render_group_header('preuploadpresentation', null, $preuploaddescripion);
2894
        if (extension_loaded('curl')) {
2895
            $renderer->render_group_element(
2896
                'preuploadpresentation_enabled',
2897
                $renderer->render_group_element_checkbox('preuploadpresentation_enabled', 0)
2898
            );
2899
        }
2900
    }
2901
}
2902
2903
/**
2904
 * Helper function renders preuploaded presentation manage file if the feature is enabled.
2905
 * This allow to select a file for use as default in all BBB instances if preuploaded presetantion is enable.
2906
 *
2907
 * @param object $renderer
2908
 *
2909
 * @return void
2910
 */
2911
function bigbluebuttonbn_settings_preupload_manage_default_file(&$renderer) {
2912
    // Configuration for "preupload presentation" feature.
2913
    if ((boolean) \mod_bigbluebuttonbn\settings\validator::section_preupload_presentation_shown()) {
2914
        if (extension_loaded('curl')) {
2915
            // This feature only works if curl is installed.
2916
            $renderer->render_filemanager_default_file_presentation("presentation_default");
2917
        }
2918
    }
2919
}
2920
2921
/**
2922
 * Helper function renders userlimit settings if the feature is enabled.
2923
 *
2924
 * @param object $renderer
2925
 *
2926
 * @return void
2927
 */
2928
function bigbluebuttonbn_settings_userlimit(&$renderer) {
2929
    // Configuration for "user limit" feature.
2930
    if ((boolean) \mod_bigbluebuttonbn\settings\validator::section_user_limit_shown()) {
2931
        $renderer->render_group_header('userlimit');
2932
        $renderer->render_group_element(
2933
            'userlimit_default',
2934
            $renderer->render_group_element_text('userlimit_default', 0, PARAM_INT)
2935
        );
2936
        $renderer->render_group_element(
2937
            'userlimit_editable',
2938
            $renderer->render_group_element_checkbox('userlimit_editable', 0)
2939
        );
2940
    }
2941
}
2942
2943
/**
2944
 * Helper function renders duration settings if the feature is enabled.
2945
 *
2946
 * @param object $renderer
2947
 *
2948
 * @return void
2949
 */
2950
function bigbluebuttonbn_settings_duration(&$renderer) {
2951
    // Configuration for "scheduled duration" feature.
2952
    if ((boolean) \mod_bigbluebuttonbn\settings\validator::section_scheduled_duration_shown()) {
2953
        $renderer->render_group_header('scheduled');
2954
        $renderer->render_group_element(
2955
            'scheduled_duration_enabled',
2956
            $renderer->render_group_element_checkbox('scheduled_duration_enabled', 1)
2957
        );
2958
        $renderer->render_group_element(
2959
            'scheduled_duration_compensation',
2960
            $renderer->render_group_element_text('scheduled_duration_compensation', 10, PARAM_INT)
2961
        );
2962
        $renderer->render_group_element(
2963
            'scheduled_pre_opening',
2964
            $renderer->render_group_element_text('scheduled_pre_opening', 10, PARAM_INT)
2965
        );
2966
    }
2967
}
2968
2969
/**
2970
 * Helper function renders participant settings if the feature is enabled.
2971
 *
2972
 * @param object $renderer
2973
 *
2974
 * @return void
2975
 */
2976
function bigbluebuttonbn_settings_participants(&$renderer) {
2977
    // Configuration for defining the default role/user that will be moderator on new activities.
2978
    if ((boolean) \mod_bigbluebuttonbn\settings\validator::section_moderator_default_shown()) {
2979
        $renderer->render_group_header('participant');
2980
        $renderer->render_group_element(
2981
            'participant_guestlink',
2982
            $renderer->render_group_element_checkbox('participant_guestlink', 0)
2983
        );
2984
        // UI for 'participants' feature.
2985
        $roles = bigbluebuttonbn_get_roles(null, false);
2986
        $owner = array('0' => get_string('mod_form_field_participant_list_type_owner', 'bigbluebuttonbn'));
2987
        $renderer->render_group_element(
2988
            'participant_moderator_default',
2989
            $renderer->render_group_element_configmultiselect(
2990
                'participant_moderator_default',
2991
                array_keys($owner),
2992
                $owner + $roles // CONTRIB-7966: don't use array_merge here so it does not reindex the array.
2993
            )
2994
        );
2995
    }
2996
}
2997
2998
/**
2999
 * Helper function renders notification settings if the feature is enabled.
3000
 *
3001
 * @param object $renderer
3002
 *
3003
 * @return void
3004
 */
3005
function bigbluebuttonbn_settings_notifications(&$renderer) {
3006
    // Configuration for "send notifications" feature.
3007
    if ((boolean) \mod_bigbluebuttonbn\settings\validator::section_send_notifications_shown()) {
3008
        $renderer->render_group_header('sendnotifications');
3009
        $renderer->render_group_element(
3010
            'sendnotifications_enabled',
3011
            $renderer->render_group_element_checkbox('sendnotifications_enabled', 1)
3012
        );
3013
    }
3014
}
3015
3016
/**
3017
 * Helper function renders client type settings if the feature is enabled.
3018
 *
3019
 * @param object $renderer
3020
 *
3021
 * @return void
3022
 */
3023
function bigbluebuttonbn_settings_clienttype(&$renderer) {
3024
    // Configuration for "clienttype" feature.
3025
    if ((boolean) \mod_bigbluebuttonbn\settings\validator::section_clienttype_shown()) {
3026
        $renderer->render_group_header('clienttype');
3027
        $renderer->render_group_element(
3028
            'clienttype_editable',
3029
            $renderer->render_group_element_checkbox('clienttype_editable', 0)
3030
        );
3031
        // Web Client default.
3032
        $default = intval((int) \mod_bigbluebuttonbn\locallib\config::get('clienttype_default'));
3033
        $choices = array(BIGBLUEBUTTON_CLIENTTYPE_FLASH => get_string('mod_form_block_clienttype_flash', 'bigbluebuttonbn'),
3034
            BIGBLUEBUTTON_CLIENTTYPE_HTML5 => get_string('mod_form_block_clienttype_html5', 'bigbluebuttonbn'));
3035
        $renderer->render_group_element(
3036
            'clienttype_default',
3037
            $renderer->render_group_element_configselect(
3038
                'clienttype_default',
3039
                $default,
3040
                $choices
3041
            )
3042
        );
3043
    }
3044
}
3045
3046
/**
3047
 * Helper function renders general settings if the feature is enabled.
3048
 *
3049
 * @param object $renderer
3050
 *
3051
 * @return void
3052
 */
3053 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...
3054
    // Configuration for BigBlueButton.
3055
    if ((boolean) \mod_bigbluebuttonbn\settings\validator::section_muteonstart_shown()) {
3056
        $renderer->render_group_header('muteonstart');
3057
        $renderer->render_group_element(
3058
            'muteonstart_default',
3059
            $renderer->render_group_element_checkbox('muteonstart_default', 0)
3060
        );
3061
        $renderer->render_group_element(
3062
            'muteonstart_editable',
3063
            $renderer->render_group_element_checkbox('muteonstart_editable', 0)
3064
        );
3065
    }
3066
}
3067
3068
/**
3069
 * Helper function renders general settings if the feature is enabled.
3070
 *
3071
 * @param object $renderer
3072
 *
3073
 * @return void
3074
 */
3075
function bigbluebuttonbn_settings_locksettings(&$renderer) {
3076
    $renderer->render_group_header('locksettings');
3077
    // Configuration for various lock settings for meetings.
3078
    bigbluebuttonbn_settings_disablecam($renderer);
3079
    bigbluebuttonbn_settings_disablemic($renderer);
3080
    bigbluebuttonbn_settings_disableprivatechat($renderer);
3081
    bigbluebuttonbn_settings_disablepublicchat($renderer);
3082
    bigbluebuttonbn_settings_disablenote($renderer);
3083
    bigbluebuttonbn_settings_hideuserlist($renderer);
3084
    bigbluebuttonbn_settings_lockedlayout($renderer);
3085
    bigbluebuttonbn_settings_lockonjoin($renderer);
3086
    bigbluebuttonbn_settings_lockonjoinconfigurable($renderer);
3087
}
3088
3089
/**
3090
 * Helper function renders general settings if the feature is enabled.
3091
 *
3092
 * @param object $renderer
3093
 *
3094
 * @return void
3095
 */
3096
function bigbluebuttonbn_settings_disablecam(&$renderer) {
3097
    // Configuration for BigBlueButton.
3098
    if ((boolean) \mod_bigbluebuttonbn\settings\validator::section_disablecam_shown()) {
3099
        $renderer->render_group_element(
3100
            'disablecam_default',
3101
            $renderer->render_group_element_checkbox('disablecam_default', 0)
3102
        );
3103
        $renderer->render_group_element(
3104
            'disablecam_editable',
3105
            $renderer->render_group_element_checkbox('disablecam_editable', 1)
3106
        );
3107
    }
3108
}
3109
3110
/**
3111
 * Helper function renders general settings if the feature is enabled.
3112
 *
3113
 * @param object $renderer
3114
 *
3115
 * @return void
3116
 */
3117
function bigbluebuttonbn_settings_disablemic(&$renderer) {
3118
    // Configuration for BigBlueButton.
3119
    if ((boolean) \mod_bigbluebuttonbn\settings\validator::section_disablemic_shown()) {
3120
        $renderer->render_group_element(
3121
            'disablemic_default',
3122
            $renderer->render_group_element_checkbox('disablemic_default', 0)
3123
        );
3124
        $renderer->render_group_element(
3125
            'disablecam_editable',
3126
            $renderer->render_group_element_checkbox('disablemic_editable', 1)
3127
        );
3128
    }
3129
}
3130
3131
/**
3132
 * Helper function renders general settings if the feature is enabled.
3133
 *
3134
 * @param object $renderer
3135
 *
3136
 * @return void
3137
 */
3138
function bigbluebuttonbn_settings_disableprivatechat(&$renderer) {
3139
    // Configuration for BigBlueButton.
3140
    if ((boolean) \mod_bigbluebuttonbn\settings\validator::section_disableprivatechat_shown()) {
3141
        $renderer->render_group_element(
3142
            'disableprivatechat_default',
3143
            $renderer->render_group_element_checkbox('disableprivatechat_default', 0)
3144
        );
3145
        $renderer->render_group_element(
3146
            'disableprivatechat_editable',
3147
            $renderer->render_group_element_checkbox('disableprivatechat_editable', 1)
3148
        );
3149
    }
3150
}
3151
3152
/**
3153
 * Helper function renders general settings if the feature is enabled.
3154
 *
3155
 * @param object $renderer
3156
 *
3157
 * @return void
3158
 */
3159
function bigbluebuttonbn_settings_disablepublicchat(&$renderer) {
3160
    // Configuration for BigBlueButton.
3161
    if ((boolean) \mod_bigbluebuttonbn\settings\validator::section_disablepublicchat_shown()) {
3162
        $renderer->render_group_element(
3163
            'disablepublicchat_default',
3164
            $renderer->render_group_element_checkbox('disablepublicchat_default', 0)
3165
        );
3166
        $renderer->render_group_element(
3167
            'disablepublicchat_editable',
3168
            $renderer->render_group_element_checkbox('disablepublicchat_editable', 1)
3169
        );
3170
    }
3171
}
3172
3173
/**
3174
 * Helper function renders general settings if the feature is enabled.
3175
 *
3176
 * @param object $renderer
3177
 *
3178
 * @return void
3179
 */
3180
function bigbluebuttonbn_settings_disablenote(&$renderer) {
3181
    // Configuration for BigBlueButton.
3182
    if ((boolean) \mod_bigbluebuttonbn\settings\validator::section_disablenote_shown()) {
3183
        $renderer->render_group_element(
3184
            'disablenote_default',
3185
            $renderer->render_group_element_checkbox('disablenote_default', 0)
3186
        );
3187
        $renderer->render_group_element(
3188
            'disablenote_editable',
3189
            $renderer->render_group_element_checkbox('disablenote_editable', 1)
3190
        );
3191
    }
3192
}
3193
3194
/**
3195
 * Helper function renders general settings if the feature is enabled.
3196
 *
3197
 * @param object $renderer
3198
 *
3199
 * @return void
3200
 */
3201
function bigbluebuttonbn_settings_hideuserlist(&$renderer) {
3202
    // Configuration for BigBlueButton.
3203
    if ((boolean) \mod_bigbluebuttonbn\settings\validator::section_hideuserlist_shown()) {
3204
        $renderer->render_group_element(
3205
            'hideuserlist_default',
3206
            $renderer->render_group_element_checkbox('hideuserlist_default', 0)
3207
        );
3208
        $renderer->render_group_element(
3209
            'hideuserlist_editable',
3210
            $renderer->render_group_element_checkbox('hideuserlist_editable', 1)
3211
        );
3212
    }
3213
}
3214
3215
/**
3216
 * Helper function renders general settings if the feature is enabled.
3217
 *
3218
 * @param object $renderer
3219
 *
3220
 * @return void
3221
 */
3222
function bigbluebuttonbn_settings_lockedlayout(&$renderer) {
3223
    // Configuration for BigBlueButton.
3224
    if ((boolean) \mod_bigbluebuttonbn\settings\validator::section_lockedlayout_shown()) {
3225
        $renderer->render_group_element(
3226
            'lockedlayout_default',
3227
            $renderer->render_group_element_checkbox('lockedlayout_default', 0)
3228
        );
3229
        $renderer->render_group_element(
3230
            'lockedlayout_editable',
3231
            $renderer->render_group_element_checkbox('lockedlayout_editable', 1)
3232
        );
3233
    }
3234
}
3235
3236
/**
3237
 * Helper function renders general settings if the feature is enabled.
3238
 *
3239
 * @param object $renderer
3240
 *
3241
 * @return void
3242
 */
3243
function bigbluebuttonbn_settings_lockonjoin(&$renderer) {
3244
    // Configuration for BigBlueButton.
3245
    if ((boolean) \mod_bigbluebuttonbn\settings\validator::section_lockonjoin_shown()) {
3246
        $renderer->render_group_element(
3247
            'lockonjoin_default',
3248
            $renderer->render_group_element_checkbox('lockonjoin_default', 0)
3249
        );
3250
        $renderer->render_group_element(
3251
            'lockonjoin_editable',
3252
            $renderer->render_group_element_checkbox('lockonjoin_editable', 1)
3253
        );
3254
    }
3255
}
3256
3257
/**
3258
 * Helper function renders general settings if the feature is enabled.
3259
 *
3260
 * @param object $renderer
3261
 *
3262
 * @return void
3263
 */
3264
function bigbluebuttonbn_settings_lockonjoinconfigurable(&$renderer) {
3265
    // Configuration for BigBlueButton.
3266
    if ((boolean) \mod_bigbluebuttonbn\settings\validator::section_lockonjoinconfigurable_shown()) {
3267
        $renderer->render_group_element(
3268
            'lockonjoinconfigurable_default',
3269
            $renderer->render_group_element_checkbox('lockonjoinconfigurable_default', 0)
3270
        );
3271
        $renderer->render_group_element(
3272
            'lockonjoinconfigurable_editable',
3273
            $renderer->render_group_element_checkbox('lockonjoinconfigurable_editable', 1)
3274
        );
3275
    }
3276
}
3277
3278
/**
3279
 * Helper function renders default messages settings.
3280
 *
3281
 * @param object $renderer
3282
 *
3283
 * @return void
3284
 */
3285
function bigbluebuttonbn_settings_default_messages(&$renderer) {
3286
    $renderer->render_group_header('default_messages');
3287
    $renderer->render_group_element(
3288
        'welcome_default',
3289
        $renderer->render_group_element_textarea('welcome_default', '', PARAM_TEXT)
3290
    );
3291
}
3292
3293
/**
3294
 * Helper function renders extended settings if any of the features there is enabled.
3295
 *
3296
 * @param object $renderer
3297
 *
3298
 * @return void
3299
 */
3300
function bigbluebuttonbn_settings_extended(&$renderer) {
3301
    // Configuration for extended capabilities.
3302
    if (!(boolean) \mod_bigbluebuttonbn\settings\validator::section_settings_extended_shown()) {
3303
        return;
3304
    }
3305
    $renderer->render_group_header('extended_capabilities');
3306
    // UI for 'notify users when recording ready' feature.
3307
    $renderer->render_group_element(
3308
        'recordingready_enabled',
3309
        $renderer->render_group_element_checkbox('recordingready_enabled', 0)
3310
    );
3311
    // Configuration for extended BN capabilities should go here.
3312
}
3313
3314
/**
3315
 * Helper function renders experimental settings if any of the features there is enabled.
3316
 *
3317
 * @param object $renderer
3318
 *
3319
 * @return void
3320
 */
3321
function bigbluebuttonbn_settings_experimental(&$renderer) {
3322
    // Configuration for experimental features should go here.
3323
    $renderer->render_group_header('experimental_features');
3324
    // UI for 'register meeting events' feature.
3325
    $renderer->render_group_element(
3326
        'meetingevents_enabled',
3327
        $renderer->render_group_element_checkbox('meetingevents_enabled', 0)
3328
    );
3329
}
3330
3331
/**
3332
 * Helper function returns a sha1 encoded string that is unique and will be used as a seed for meetingid.
3333
 *
3334
 * @return string
3335
 */
3336
function bigbluebuttonbn_unique_meetingid_seed() {
3337
    global $DB;
3338
    do {
3339
        $encodedseed = sha1(bigbluebuttonbn_random_password(12));
3340
        $meetingid = (string) $DB->get_field('bigbluebuttonbn', 'meetingid', array('meetingid' => $encodedseed));
3341
    } while ($meetingid == $encodedseed);
3342
    return $encodedseed;
3343
}
3344
3345
/**
3346
 * Helper function renders the link used for recording type in row for the data used by the recording table.
3347
 *
3348
 * @param array $recording
3349
 * @param array $bbbsession
3350
 * @param array $playback
3351
 *
3352
 * @return boolean
3353
 */
3354
function bigbluebuttonbn_include_recording_data_row_type($recording, $bbbsession, $playback) {
3355
    // All types that are not restricted are included.
3356
    if (array_key_exists('restricted', $playback) && strtolower($playback['restricted']) == 'false') {
3357
        return true;
3358
    }
3359
    // All types that are not statistics are included.
3360
    if ($playback['type'] != 'statistics') {
3361
        return true;
3362
    }
3363
    // Exclude imported recordings.
3364
    if (isset($recording['imported'])) {
3365
        return false;
3366
    }
3367
    // Exclude non moderators.
3368
    if (!$bbbsession['administrator'] && !$bbbsession['moderator']) {
3369
        return false;
3370
    }
3371
    return true;
3372
}
3373
3374
/**
3375
 * Renders the general warning message.
3376
 *
3377
 * @param string $message
3378
 * @param string $type
3379
 * @param string $href
3380
 * @param string $text
3381
 * @param string $class
3382
 *
3383
 * @return string
3384
 */
3385
function bigbluebuttonbn_render_warning($message, $type = 'info', $href = '', $text = '', $class = '') {
3386
    global $OUTPUT;
3387
    $output = "\n";
3388
    // Evaluates if config_warning is enabled.
3389
    if (empty($message)) {
3390
        return $output;
3391
    }
3392
    $output .= $OUTPUT->box_start(
3393
        'box boxalignleft adminerror alert alert-' . $type . ' alert-block fade in',
3394
        'bigbluebuttonbn_view_general_warning'
3395
    ) . "\n";
3396
    $output .= '    ' . $message . "\n";
3397
    $output .= '  <div class="singlebutton pull-right">' . "\n";
3398
    if (!empty($href)) {
3399
        $output .= bigbluebuttonbn_render_warning_button($href, $text, $class);
3400
    }
3401
    $output .= '  </div>' . "\n";
3402
    $output .= $OUTPUT->box_end() . "\n";
3403
    return $output;
3404
}
3405
3406
/**
3407
 * Renders the general warning button.
3408
 *
3409
 * @param string $href
3410
 * @param string $text
3411
 * @param string $class
3412
 * @param string $title
3413
 *
3414
 * @return string
3415
 */
3416
function bigbluebuttonbn_render_warning_button($href, $text = '', $class = '', $title = '') {
3417
    if ($text == '') {
3418
        $text = get_string('ok', 'moodle');
3419
    }
3420
    if ($title == '') {
3421
        $title = $text;
3422
    }
3423
    if ($class == '') {
3424
        $class = 'btn btn-secondary';
3425
    }
3426
    $output = '  <form method="post" action="' . $href . '" class="form-inline">' . "\n";
3427
    $output .= '      <button type="submit" class="' . $class . '"' . "\n";
3428
    $output .= '          title="' . $title . '"' . "\n";
3429
    $output .= '          >' . $text . '</button>' . "\n";
3430
    $output .= '  </form>' . "\n";
3431
    return $output;
3432
}
3433
3434
/**
3435
 * Check if a BigBlueButtonBN is available to be used by the current user.
3436
 *
3437
 * @param  stdClass  $bigbluebuttonbn  BigBlueButtonBN instance
3438
 *
3439
 * @return boolean                     status if room available and current user allowed to join
3440
 */
3441
function bigbluebuttonbn_get_availability_status($bigbluebuttonbn) {
3442
    list($roomavailable) = bigbluebuttonbn_room_is_available($bigbluebuttonbn);
3443
    list($usercanjoin) = bigbluebuttonbn_user_can_join_meeting($bigbluebuttonbn);
3444
    return ($roomavailable && $usercanjoin);
3445
}
3446
3447
/**
3448
 * Helper for evaluating if scheduled activity is avaiable.
3449
 *
3450
 * @param  stdClass  $bigbluebuttonbn  BigBlueButtonBN instance
3451
 *
3452
 * @return array                       status (room available or not and possible warnings)
3453
 */
3454
function bigbluebuttonbn_room_is_available($bigbluebuttonbn) {
3455
    $open = true;
3456
    $closed = false;
3457
    $warnings = array();
3458
3459
    $timenow = time();
3460
    $timeopen = $bigbluebuttonbn->openingtime;
3461
    $timeclose = $bigbluebuttonbn->closingtime;
3462
    if (!empty($timeopen) && $timeopen > $timenow) {
3463
        $open = false;
3464
    }
3465
    if (!empty($timeclose) && $timenow > $timeclose) {
3466
        $closed = true;
3467
    }
3468
3469
    if (!$open || $closed) {
3470
        if (!$open) {
3471
            $warnings['notopenyet'] = userdate($timeopen);
3472
        }
3473
        if ($closed) {
3474
            $warnings['expired'] = userdate($timeclose);
3475
        }
3476
        return array(false, $warnings);
3477
    }
3478
3479
    return array(true, $warnings);
3480
}
3481
3482
/**
3483
 * Helper for evaluating if meeting can be joined.
3484
 *
3485
 * @param  stdClass $bigbluebuttonbn  BigBlueButtonBN instance
3486
 * @param  string   $mid
3487
 * @param  integer  $userid
3488
 *
3489
 * @return array    status (user allowed to join or not and possible message)
3490
 */
3491
function bigbluebuttonbn_user_can_join_meeting($bigbluebuttonbn, $mid = null, $userid = null) {
3492
    // By default, use a meetingid without groups.
3493
    if (empty($mid)) {
3494
        $mid = $bigbluebuttonbn->meetingid . '-' . $bigbluebuttonbn->course . '-' . $bigbluebuttonbn->id;
3495
    }
3496
    // When meeting is running, all authorized users can join right in.
3497
    if (bigbluebuttonbn_is_meeting_running($mid)) {
3498
        return array(true, get_string('view_message_conference_in_progress', 'bigbluebuttonbn'));
3499
    }
3500
    // When meeting is not running, see if the user can join.
3501
    $context = context_course::instance($bigbluebuttonbn->course);
3502
    $participantlist = bigbluebuttonbn_get_participant_list($bigbluebuttonbn, $context);
3503
    $isadmin = is_siteadmin($userid);
3504
    $ismoderator = bigbluebuttonbn_is_moderator($context, $participantlist, $userid);
3505
    // If user is administrator, moderator or if is viewer and no waiting is required, join allowed.
3506
    if ($isadmin || $ismoderator || !$bigbluebuttonbn->wait) {
3507
        return array(true, get_string('view_message_conference_room_ready', 'bigbluebuttonbn'));
3508
    }
3509
    // Otherwise, no join allowed.
3510
    return array(false, get_string('view_message_conference_wait_for_moderator', 'bigbluebuttonbn'));
3511
}
3512
3513
/**
3514
 * Helper for getting a value from a bigbluebuttonbn cache.
3515
 *
3516
 * @param  string   $name       BigBlueButtonBN cache
3517
 * @param  string   $key        Key to be retrieved
3518
 * @param  integer  $default    Default value in case key is not found or it is empty
3519
 *
3520
 * @return variable key value
3521
 */
3522
function bigbluebuttonbn_cache_get($name, $key, $default = null) {
3523
    $cache = cache::make_from_params(cache_store::MODE_APPLICATION, 'mod_bigbluebuttonbn', $name);
3524
    $result = $cache->get($key);
3525
    if (!empty($result)) {
3526
        return $result;
3527
    }
3528
    return $default;
3529
}
3530
3531
/**
3532
 * Helper for setting a value in a bigbluebuttonbn cache.
3533
 *
3534
 * @param  string   $name       BigBlueButtonBN cache
3535
 * @param  string   $key        Key to be created/updated
3536
 * @param  variable $value      Default value to be set
3537
 */
3538
function bigbluebuttonbn_cache_set($name, $key, $value) {
3539
    $cache = cache::make_from_params(cache_store::MODE_APPLICATION, 'mod_bigbluebuttonbn', $name);
3540
    $cache->set($key, $value);
3541
}
3542
3543
/**
3544
 * Helper for getting the owner userid of a bigbluebuttonbn instance.
3545
 *
3546
 * @param  stdClass $bigbluebuttonbn  BigBlueButtonBN instance
3547
 *
3548
 * @return integer ownerid (a valid user id or null if not registered/found)
3549
 */
3550
function bigbluebuttonbn_instance_ownerid($bigbluebuttonbn) {
3551
    global $DB;
3552
    $filters = array('bigbluebuttonbnid' => $bigbluebuttonbn->id, 'log' => 'Add');
3553
    $ownerid = (integer) $DB->get_field('bigbluebuttonbn_logs', 'userid', $filters);
3554
    return $ownerid;
3555
}
3556
3557
/**
3558
 * Helper evaluates if the bigbluebutton server used belongs to blindsidenetworks domain.
3559
 *
3560
 * @return boolean
3561
 */
3562
function bigbluebuttonbn_has_html5_client() {
3563
    $checkurl = \mod_bigbluebuttonbn\locallib\bigbluebutton::root() . "html5client/check";
3564
    $curlinfo = bigbluebuttonbn_wrap_xml_load_file_curl_request($checkurl, 'HEAD');
3565
    return (isset($curlinfo['http_code']) && $curlinfo['http_code'] == 200);
3566
}
3567
3568
/**
3569
 * Return the status of an activity [open|not_started|ended].
3570
 *
3571
 * @param array $bbbsession
3572
 * @return string
3573
 */
3574 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...
3575
    $now = time();
3576
    if (!empty($bbbsession['bigbluebuttonbn']->openingtime) && $now < $bbbsession['bigbluebuttonbn']->openingtime) {
3577
        // The activity has not been opened.
3578
        return 'not_started';
3579
    }
3580
    if (!empty($bbbsession['bigbluebuttonbn']->closingtime) && $now > $bbbsession['bigbluebuttonbn']->closingtime) {
3581
        // The activity has been closed.
3582
        return 'ended';
3583
    }
3584
    // The activity is open.
3585
    return 'open';
3586
}
3587
3588
/**
3589
 * Set session URLs.
3590
 *
3591
 * @param array $bbbsession
3592
 * @param int $id
3593
 * @return string
3594
 */
3595
function bigbluebuttonbn_view_session_config(&$bbbsession, $id) {
3596
    // Operation URLs.
3597
    $bbbsession['bigbluebuttonbnURL'] = plugin::necurl(
3598
        '/mod/bigbluebuttonbn/view.php',
3599
        ['id' => $bbbsession['cm']->id]
3600
    );
3601
    $bbbsession['logoutURL'] = plugin::necurl(
3602
        '/mod/bigbluebuttonbn/bbb_view.php',
3603
        ['action' => 'logout', 'id' => $id, 'bn' => $bbbsession['bigbluebuttonbn']->id]
3604
    );
3605
    $bbbsession['recordingReadyURL'] = plugin::necurl(
3606
        '/mod/bigbluebuttonbn/bbb_broker.php',
3607
        ['action' => 'recording_ready', 'bigbluebuttonbn' => $bbbsession['bigbluebuttonbn']->id]
3608
    );
3609
    $bbbsession['meetingEventsURL'] = plugin::necurl(
3610
        '/mod/bigbluebuttonbn/bbb_broker.php',
3611
        ['action' => 'meeting_events', 'bigbluebuttonbn' => $bbbsession['bigbluebuttonbn']->id]
3612
    );
3613
    $bbbsession['joinURL'] = plugin::necurl(
3614
        '/mod/bigbluebuttonbn/bbb_view.php',
3615
        ['action' => 'join', 'id' => $id, 'bn' => $bbbsession['bigbluebuttonbn']->id]
3616
    );
3617
3618
    // Check status and set extra values.
3619
    $activitystatus = bigbluebuttonbn_view_get_activity_status($bbbsession); // In locallib.
3620 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...
3621
        $bbbsession['presentation'] = bigbluebuttonbn_get_presentation_array(
3622
            $bbbsession['context'],
3623
            $bbbsession['bigbluebuttonbn']->presentation
3624
        );
3625
    } else if ($activitystatus == 'open') {
3626
        $bbbsession['presentation'] = bigbluebuttonbn_get_presentation_array(
3627
            $bbbsession['context'],
3628
            $bbbsession['bigbluebuttonbn']->presentation,
3629
            $bbbsession['bigbluebuttonbn']->id
3630
        );
3631
    }
3632
3633
    return $activitystatus;
3634
}
3635
3636
/**
3637
 * Helper for preparing metadata used while creating the meeting.
3638
 *
3639
 * @param  array    $bbbsession
3640
 * @return array
3641
 */
3642
function bigbluebuttonbn_create_meeting_metadata(&$bbbsession) {
3643
    global $USER;
3644
    // Create standard metadata.
3645
    $metadata = [
3646
        'bbb-origin' => $bbbsession['origin'],
3647
        'bbb-origin-version' => $bbbsession['originVersion'],
3648
        'bbb-origin-server-name' => $bbbsession['originServerName'],
3649
        'bbb-origin-server-common-name' => $bbbsession['originServerCommonName'],
3650
        'bbb-origin-tag' => $bbbsession['originTag'],
3651
        'bbb-context' => $bbbsession['course']->fullname,
3652
        'bbb-context-id' => $bbbsession['course']->id,
3653
        'bbb-context-name' => trim(html_to_text($bbbsession['course']->fullname, 0)),
3654
        'bbb-context-label' => trim(html_to_text($bbbsession['course']->shortname, 0)),
3655
        'bbb-recording-name' => bigbluebuttonbn_html2text($bbbsession['meetingname'], 64),
3656
        'bbb-recording-description' => bigbluebuttonbn_html2text($bbbsession['meetingdescription'], 64),
3657
        'bbb-recording-tags' => bigbluebuttonbn_get_tags($bbbsession['cm']->id), // Same as $id.
3658
    ];
3659
    // Special metadata for recording processing.
3660
    if ((boolean) \mod_bigbluebuttonbn\locallib\config::get('recordingstatus_enabled')) {
3661
        $metadata["bn-recording-status"] = json_encode(
3662
            array(
3663
                'email' => array('"' . fullname($USER) . '" <' . $USER->email . '>'),
3664
                'context' => $bbbsession['bigbluebuttonbnURL'],
3665
            )
3666
        );
3667
    }
3668
    if ((boolean) \mod_bigbluebuttonbn\locallib\config::get('recordingready_enabled')) {
3669
        $metadata['bn-recording-ready-url'] = $bbbsession['recordingReadyURL'];
3670
    }
3671
    if ((boolean) \mod_bigbluebuttonbn\locallib\config::get('meetingevents_enabled')) {
3672
        $metadata['analytics-callback-url'] = $bbbsession['meetingEventsURL'];
3673
    }
3674
    return $metadata;
3675
}
3676
3677
/**
3678
 * Helper for preparing data used while joining the meeting.
3679
 *
3680
 * @param array    $bbbsession
3681
 * @param object   $bigbluebuttonbn
3682
 * @param integer  $origin
3683
 */
3684
function bigbluebuttonbn_join_meeting($bbbsession, $bigbluebuttonbn, $origin = 0) {
3685
    // Update the cache.
3686
    $meetinginfo = bigbluebuttonbn_get_meeting_info($bbbsession['meetingid'], BIGBLUEBUTTONBN_UPDATE_CACHE);
3687 View Code Duplication
    if ($bbbsession['userlimit'] > 0 && intval($meetinginfo['participantCount']) >= $bbbsession['userlimit']) {
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...
3688
        // No more users allowed to join.
3689
        header('Location: '.$bbbsession['logoutURL']);
3690
        return;
3691
    }
3692
    // Mark guests (from external guestlink)
3693
    $guest = false;
3694
    if (isset($bbbsession['guest']) && $bbbsession['guest'] == true) {
3695
        $guest = true;
3696
    }
3697
    // Build the URL.
3698
    $password = $bbbsession['viewerPW'];
3699
    if ($bbbsession['administrator'] || $bbbsession['moderator']) {
3700
        $password = $bbbsession['modPW'];
3701
    }
3702
    $joinurl = bigbluebuttonbn_get_join_url($bbbsession['meetingid'], $bbbsession['username'],
3703
        $password, $bbbsession['logoutURL'], null, $bbbsession['userID'], $bbbsession['clienttype'], null, $guest);
3704
    // Moodle event logger: Create an event for meeting joined.
3705
    bigbluebuttonbn_event_log(\mod_bigbluebuttonbn\event\events::$events['meeting_join'], $bigbluebuttonbn);
3706
    // Internal logger: Instert a record with the meeting created.
3707
    $overrides = array('meetingid' => $bbbsession['meetingid']);
3708
    $meta = '{"origin":'.$origin.'}';
3709
    bigbluebuttonbn_log($bbbsession['bigbluebuttonbn'], BIGBLUEBUTTONBN_LOG_EVENT_JOIN, $overrides, $meta);
3710
    // Before executing the redirect, increment the number of participants.
3711
    bigbluebuttonbn_participant_joined($bbbsession['meetingid'],
3712
        ($bbbsession['administrator'] || $bbbsession['moderator']));
3713
    // Execute the redirect.
3714
    header('Location: '.$joinurl);
3715
}
3716
3717
/**
3718
 * Helperfunction for getting the bigbluebutton instance with guestlink id
3719
 *
3720
 * @param string $guestlinkid
3721
 * @return mixed|stdClass|false
3722
 */
3723
function bigbluebuttonbn_get_bigbluebuttonbn_by_guestlinkid(string $guestlinkid) {
3724
    global $DB;
3725
    return $DB->get_record('bigbluebuttonbn', ['guestlinkid' => $guestlinkid]);
3726
}
3727