Completed
Push — master ( 411be6...041992 )
by Jesus
03:50
created

locallib.php ➔ bigbluebuttonbn_getCreateMeetingURL()   B

Complexity

Conditions 6
Paths 16

Size

Total Lines 31
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 6
eloc 19
nc 16
nop 11
dl 0
loc 31
rs 8.439
c 0
b 0
f 0

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

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
 * @author    Fred Dixon  (ffdixon [at] blindsidenetworks [dt] com)
21
 * @author    Jesus Federico  (jesus [at] blindsidenetworks [dt] com)
22
 * @copyright 2010-2015 Blindside Networks Inc
23
 * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v2 or later
24
 */
25
defined('MOODLE_INTERNAL') || die;
26
27
global $BIGBLUEBUTTONBN_CFG, $CFG;
28
29
require_once dirname(__FILE__).'/lib.php';
30
31
const BIGBLUEBUTTONBN_FORCED = true;
32
33
const BIGBLUEBUTTONBN_TYPE_ALL = 0;
34
const BIGBLUEBUTTONBN_TYPE_ROOM_ONLY = 1;
35
const BIGBLUEBUTTONBN_TYPE_RECORDING_ONLY = 2;
36
37
const BIGBLUEBUTTONBN_ROLE_VIEWER = 'viewer';
38
const BIGBLUEBUTTONBN_ROLE_MODERATOR = 'moderator';
39
const BIGBLUEBUTTONBN_METHOD_GET = 'GET';
40
const BIGBLUEBUTTONBN_METHOD_POST = 'POST';
41
42
const BIGBLUEBUTTON_EVENT_ACTIVITY_VIEWED = 'activity_viewed';
43
const BIGBLUEBUTTON_EVENT_MEETING_CREATED = 'meeting_created';
44
const BIGBLUEBUTTON_EVENT_MEETING_ENDED = 'meeting_ended';
45
const BIGBLUEBUTTON_EVENT_MEETING_JOINED = 'meeting_joined';
46
const BIGBLUEBUTTON_EVENT_MEETING_LEFT = 'meeting_left';
47
const BIGBLUEBUTTON_EVENT_MEETING_EVENT = 'meeting_event';
48
const BIGBLUEBUTTON_EVENT_RECORDING_DELETED = 'recording_deleted';
49
const BIGBLUEBUTTON_EVENT_RECORDING_IMPORTED = 'recording_imported';
50
const BIGBLUEBUTTON_EVENT_RECORDING_PUBLISHED = 'recording_published';
51
const BIGBLUEBUTTON_EVENT_RECORDING_UNPUBLISHED = 'recording_unpublished';
52
53
function bigbluebuttonbn_logs(array $bbbsession, $event, array $overrides = [], $meta = null)
54
{
55
    global $DB;
56
57
    $log = new stdClass();
58
59
    $log->courseid = isset($overrides['courseid']) ? $overrides['courseid'] : $bbbsession['course']->id;
60
    $log->bigbluebuttonbnid = isset($overrides['bigbluebuttonbnid']) ? $overrides['bigbluebuttonbnid'] : $bbbsession['bigbluebuttonbn']->id;
61
    $log->userid = isset($overrides['userid']) ? $overrides['userid'] : $bbbsession['userID'];
62
    $log->meetingid = isset($overrides['meetingid']) ? $overrides['meetingid'] : $bbbsession['meetingid'];
63
    $log->timecreated = isset($overrides['timecreated']) ? $overrides['timecreated'] : time();
64
    $log->log = $event;
65
    if (isset($meta)) {
66
        $log->meta = $meta;
67
    } elseif ($event == BIGBLUEBUTTONBN_LOG_EVENT_CREATE) {
68
        $log->meta = '{"record":'.($bbbsession['record'] ? 'true' : 'false').'}';
69
    }
70
71
    $DB->insert_record('bigbluebuttonbn_logs', $log);
72
}
73
74
//  BigBlueButton API Calls  //
75
function bigbluebuttonbn_getJoinURL($meetingID, $userName, $PW, $logoutURL, $configToken = null, $userId = null)
76
{
77
    $data = ['meetingID' => $meetingID,
78
              'fullName' => $userName,
79
              'password' => $PW,
80
              'logoutURL' => $logoutURL,
81
            ];
82
83
    if (!is_null($configToken)) {
84
        $data['configToken'] = $configToken;
85
    }
86
    if (!is_null($userId)) {
87
        $data['userID'] = $userId;
88
    }
89
90
    return bigbluebuttonbn_bigbluebutton_action_url('join', $data);
91
}
92
93
function bigbluebuttonbn_getCreateMeetingURL($name, $meetingID, $attendeePW, $moderatorPW, $welcome, $logoutURL, $record = 'false', $duration = 0, $voiceBridge = 0, $maxParticipants = 0, $metadata = array())
94
{
95
    $data = ['meetingID' => $meetingID,
96
              'name' => $name,
97
              'attendeePW' => $attendeePW,
98
              'moderatorPW' => $moderatorPW,
99
              'logoutURL' => $logoutURL,
100
              'record' => $record,
101
            ];
102
103
    $voiceBridge = intval($voiceBridge);
104
    if ($voiceBridge > 0 && $voiceBridge < 79999) {
105
        $data['voiceBridge'] = $voiceBridge;
106
    }
107
108
    $duration = intval($duration);
109
    if ($duration > 0) {
110
        $data['duration'] = $duration;
111
    }
112
113
    $maxParticipants = intval($maxParticipants);
114
    if ($maxParticipants > 0) {
115
        $data['maxParticipants'] = $maxParticipants;
116
    }
117
118
    if (trim($welcome)) {
119
        $data['welcome'] = $welcome;
120
    }
121
122
    return bigbluebuttonbn_bigbluebutton_action_url('create', $data, $metadata);
123
}
124
125
function bigbluebuttonbn_getIsMeetingRunningURL($meetingID)
126
{
127
    return bigbluebuttonbn_bigbluebutton_action_url('isMeetingRunning', ['meetingID' => $meetingID]);
128
}
129
130
function bigbluebuttonbn_getMeetingInfoURL($meetingID)
131
{
132
    return bigbluebuttonbn_bigbluebutton_action_url('getMeetingInfo', ['meetingID' => $meetingID]);
133
}
134
135
function bigbluebuttonbn_getMeetingsURL()
136
{
137
    return bigbluebuttonbn_bigbluebutton_action_url('getMeetings');
138
}
139
140
/**
141
 * @param string $meetingID
142
 * @param string $modPW
143
 */
144
function bigbluebuttonbn_getEndMeetingURL($meetingID, $modPW)
145
{
146
    return bigbluebuttonbn_bigbluebutton_action_url('end', ['meetingID' => $meetingID, 'password' => $modPW]);
147
}
148
149
/**
150
 * @param string $meetingID
151
 */
152
function bigbluebuttonbn_getRecordingsURL($meetingID)
153
{
154
    return bigbluebuttonbn_bigbluebutton_action_url('getRecordings', ['meetingID' => $meetingID]);
155
}
156
157
/**
158
 * @param string $recordID
159
 */
160
function bigbluebuttonbn_getDeleteRecordingsURL($recordID)
161
{
162
    return bigbluebuttonbn_bigbluebutton_action_url('deleteRecordings', ['recordID' => $recordID]);
163
}
164
165
/**
166
 * @param string $recordID
167
 * @param string $publish
168
 */
169
function bigbluebuttonbn_getPublishRecordingsURL($recordID, $publish)
170
{
171
    return bigbluebuttonbn_bigbluebutton_action_url('publishRecordings', ['recordID' => $recordID, 'publish' => $publish]);
172
}
173
174
/**
175
 * @param string $recordID
176
 * @param array  $metadata
177
 */
178
function bigbluebuttonbn_getUpdateRecordingsURL($recordID, $metadata = array())
179
{
180
    return bigbluebuttonbn_bigbluebutton_action_url('updateRecordings', ['recordID' => $recordID], $metadata);
181
}
182
183
function bigbluebuttonbn_getDefaultConfigXMLURL()
184
{
185
    return bigbluebuttonbn_bigbluebutton_action_url('getDefaultConfigXML');
186
}
187
188
function bigbluebuttonbn_bigbluebutton_action_url($action, $data = array(), $metadata = array())
189
{
190
    $base_url = bigbluebuttonbn_get_cfg_server_url().'api/'.$action.'?';
191
192
    $params = '';
193
194
    foreach ($data as $key => $value) {
195
        $params .= '&'.$key.'='.urlencode($value);
196
    }
197
198
    foreach ($metadata as $key => $value) {
199
        $params .= '&'.'meta_'.$key.'='.urlencode($value);
200
    }
201
202
    return $base_url.$params.'&checksum='.sha1($action.$params.bigbluebuttonbn_get_cfg_shared_secret());
203
}
204
205
function bigbluebuttonbn_getCreateMeetingArray($meetingName, $meetingID, $welcomeString, $mPW, $aPW, $logoutURL, $record = 'false', $duration = 0, $voiceBridge = 0, $maxParticipants = 0, $metadata = array(), $presentation_name = null, $presentation_url = null)
206
{
207
    $create_meeting_url = bigbluebuttonbn_getCreateMeetingURL($meetingName, $meetingID, $aPW, $mPW, $welcomeString, $logoutURL, $record, $duration, $voiceBridge, $maxParticipants, $metadata);
208
    $method = BIGBLUEBUTTONBN_METHOD_GET;
209
    $data = null;
210
211
    if (!is_null($presentation_name) && !is_null($presentation_url)) {
212
        $method = BIGBLUEBUTTONBN_METHOD_POST;
213
        $data = "<?xml version='1.0' encoding='UTF-8'?><modules><module name='presentation'><document url='".$presentation_url."' /></module></modules>";
214
    }
215
216
    $xml = bigbluebuttonbn_wrap_xml_load_file($create_meeting_url, $method, $data);
217
218
    if ($xml) {
219
        $response = array('returncode' => $xml->returncode, 'message' => $xml->message, 'messageKey' => $xml->messageKey);
220
        if ($xml->meetingID) {
221
            $response += array('meetingID' => $xml->meetingID, 'attendeePW' => $xml->attendeePW, 'moderatorPW' => $xml->moderatorPW, 'hasBeenForciblyEnded' => $xml->hasBeenForciblyEnded);
222
        }
223
224
        return $response;
225
    }
226
227
    return null;
228
}
229
230
/**
231
 * @param string $meetingID
232
 */
233
function bigbluebuttonbn_getMeetingArray($meetingID)
234
{
235
    $meetings = bigbluebuttonbn_getMeetingsArray();
236
    if ($meetings) {
237
        foreach ($meetings as $meeting) {
238
            if ($meeting['meetingID'] == $meetingID) {
239
                return $meeting;
240
            }
241
        }
242
    }
243
244
    return null;
245
}
246
247
function bigbluebuttonbn_getMeetingsArray()
248
{
249
    $xml = bigbluebuttonbn_wrap_xml_load_file(bigbluebuttonbn_getMeetingsURL());
250
251
    if ($xml && $xml->returncode == 'SUCCESS' && empty($xml->messageKey)) {
252
        // Meetings were returned
253
        $meetings = array();
254
        foreach ($xml->meetings->meeting as $meeting) {
255
            $meetings[] = array('meetingID' => $meeting->meetingID,
256
                                'moderatorPW' => $meeting->moderatorPW,
257
                                'attendeePW' => $meeting->attendeePW,
258
                                'hasBeenForciblyEnded' => $meeting->hasBeenForciblyEnded,
259
                                'running' => $meeting->running, );
260
        }
261
262
        return $meetings;
263
    }
264
265 View Code Duplication
    if ($xml) {
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...
266
        // Either failutre or success without meetings
267
        return array('returncode' => $xml->returncode, 'message' => $xml->message, 'messageKey' => $xml->messageKey);
268
    }
269
270
    //If the server is unreachable, then prompts the user of the necessary action
271
    return null;
272
}
273
274
/**
275
 * @param string $meetingID
276
 */
277
function bigbluebuttonbn_getMeetingInfo($meetingID)
278
{
279
    $xml = bigbluebuttonbn_wrap_xml_load_file(bigbluebuttonbn_getMeetingInfoURL($meetingID));
280
281
    return $xml;
282
}
283
284
/**
285
 * @param string $meetingID
286
 */
287
function bigbluebuttonbn_getMeetingInfoArray($meetingID)
288
{
289
    $xml = bigbluebuttonbn_wrap_xml_load_file(bigbluebuttonbn_getMeetingInfoURL($meetingID));
290
291
    if ($xml && $xml->returncode == 'SUCCESS' && empty($xml->messageKey)) {
292
        // Meeting info was returned
293
        return array('returncode' => $xml->returncode,
294
                     'meetingID' => $xml->meetingID,
295
                     'moderatorPW' => $xml->moderatorPW,
296
                     'attendeePW' => $xml->attendeePW,
297
                     'hasBeenForciblyEnded' => $xml->hasBeenForciblyEnded,
298
                     'running' => $xml->running,
299
                     'recording' => $xml->recording,
300
                     'startTime' => $xml->startTime,
301
                     'endTime' => $xml->endTime,
302
                     'participantCount' => $xml->participantCount,
303
                     'moderatorCount' => $xml->moderatorCount,
304
                     'attendees' => $xml->attendees,
305
                     'metadata' => $xml->metadata,
306
                   );
307
    }
308
309 View Code Duplication
    if ($xml) {
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...
310
        // Either failutre or success without meeting info
311
        return array('returncode' => $xml->returncode, 'message' => $xml->message, 'messageKey' => $xml->messageKey);
312
    }
313
314
    //If the server is unreachable, then prompts the user of the necessary action
315
    return null;
316
}
317
318
/**
319
 * helper function to retrieve recordings from a BigBlueButton server.
320
 *
321
 * @param string or array $meetingIDs   an array or string containing a list of meetingIDs "mid1,mid2,mid3" or array("mid1","mid2","mid3")
322
 * @param string or array $recordingIDs an array or string containing a list of $recordingIDs "rid1,rid2,rid3" or array("rid1","rid2","rid3") to be used as a filter
323
 *
324
 * @return associative array containing the actual recordings indexed by recordID, each recording is also a non sequential associative array itself
325
 */
326
function bigbluebuttonbn_getRecordingsArray($meetingIDs, $recordingIDs = null)
327
{
328
    $recordings = array();
329
330
    $meetingIDsArray = $meetingIDs;
331
    if (!is_array($meetingIDs)) {
332
        $meetingIDsArray = explode(',', $meetingIDs);
333
    }
334
335
    // If $meetingIDsArray is not empty a paginated getRecordings request is executed
336
    if (!empty($meetingIDsArray)) {
337
        $pages = floor(sizeof($meetingIDsArray) / 25) + 1;
338
        for ($page = 1; $page <= $pages; ++$page) {
339
            $mIDs = array_slice($meetingIDsArray, ($page - 1) * 25, 25);
340
            // getRecordings is executed using a method GET (supported by all versions of BBB)
341
            $xml = bigbluebuttonbn_wrap_xml_load_file(bigbluebuttonbn_getRecordingsURL(implode(',', $mIDs)));
342
            if ($xml && $xml->returncode == 'SUCCESS' && isset($xml->recordings)) { //If there were meetings already created
343
                foreach ($xml->recordings->recording as $recording) {
344
                    $recording_array_value = bigbluebuttonbn_getRecordingArrayValue($recording);
345
                    $recordings[$recording_array_value['recordID']] = $recording_array_value;
346
                }
347
                uasort($recordings, 'bigbluebuttonbn_recordingBuildSorter');
348
            }
349
        }
350
    }
351
352
    // Filter recordings based on recordingIDs
353
    if (!empty($recordings) && !is_null($recordingIDs)) {
354
        $recordingIDsArray = $recordingIDs;
355
        if (!is_array($recordingIDs)) {
356
            $recordingIDsArray = explode(',', $recordingIDs);
357
        }
358
359
        foreach ($recordings as $key => $recording) {
360
            if (!in_array($recording['recordID'], $recordingIDsArray)) {
361
                unset($recordings[$key]);
362
            }
363
        }
364
    }
365
366
    return $recordings;
367
}
368
369
/**
370
 * helper function to retrieve imported recordings from the Moodle database. The references are stored as events in bigbluebuttonbn_logs.
371
 *
372
 * @param string $courseID
373
 * @param string $bigbluebuttonbnID
374
 * @param bool   $subset
375
 *
376
 * @return associative array containing the imported recordings indexed by recordID, each recording is also a non sequential associative array itself that corresponds to the actual recording in BBB
377
 */
378
function bigbluebuttonbn_getRecordingsImportedArray($courseID, $bigbluebuttonbnID = null, $subset = true)
379
{
380
    global $DB;
381
382
    $select = "courseid = '{$courseID}' AND bigbluebuttonbnid <> '{$bigbluebuttonbnID}' AND log = '".BIGBLUEBUTTONBN_LOG_EVENT_IMPORT."'";
383
    if ($bigbluebuttonbnID === null) {
384
        $select = "courseid = '{$courseID}' AND log = '".BIGBLUEBUTTONBN_LOG_EVENT_IMPORT."'";
385
    } elseif ($subset) {
386
        $select = "bigbluebuttonbnid = '{$bigbluebuttonbnID}' AND log = '".BIGBLUEBUTTONBN_LOG_EVENT_IMPORT."'";
387
    }
388
    $records_imported = $DB->get_records_select('bigbluebuttonbn_logs', $select);
389
390
    $recordings_imported = $records_imported;
391
    // Check if array is not sequential
392
    if (!empty($records_imported) && array_keys($records_imported) !== range(0, count($records_imported) - 1)) {
393
        // The response contains a single record and needs to be converted to a sequential array format
394
        $recordings_imported = array($records_imported);
395
    }
396
397
    $recordings_imported_array = array();
398
    foreach ($recordings_imported as $key => $recording_imported) {
399
        $meta = json_decode($recording_imported->meta, true);
400
        $recordings_imported_array[$meta['recording']['recordID']] = $meta['recording'];
401
    }
402
403
    return $recordings_imported_array;
404
}
405
406
function bigbluebuttonbn_getDefaultConfigXML()
407
{
408
    $xml = bigbluebuttonbn_wrap_xml_load_file(bigbluebuttonbn_getDefaultConfigXMLURL());
409
410
    return $xml;
411
}
412
413
function bigbluebuttonbn_getDefaultConfigXMLArray()
414
{
415
    $default_config_xml = bigbluebuttonbn_getDefaultConfigXML();
416
    $default_config_xml_array = (array) $default_config_xml;
417
418
    return $default_config_xml_array;
419
}
420
421
function bigbluebuttonbn_getRecordingArrayValue($recording)
422
{
423
    //Add formats
424
    $playbackArray = array();
425
    foreach ($recording->playback->format as $format) {
426
        $playbackArray[(string) $format->type] = array('type' => (string) $format->type, 'url' => (string) $format->url, 'length' => (string) $format->length);
427
        //Add preview per format when existing
428
        if ($format->preview) {
429
            $imagesArray = array();
430
            foreach ($format->preview->images->image as $image) {
431
                $imageArray = array('url' => (string) $image);
432
                foreach ($image->attributes() as $attKey => $attValue) {
433
                    $imageArray[$attKey] = (string) $attValue;
434
                }
435
                array_push($imagesArray, $imageArray);
436
            }
437
            $playbackArray[(string) $format->type]['preview'] = $imagesArray;
438
        }
439
    }
440
441
    //Add the metadata to the recordings array
442
    $metadataArray = array();
443
    $metadata = get_object_vars($recording->metadata);
444
    foreach ($metadata as $key => $value) {
445
        if (is_object($value)) {
446
            $value = '';
447
        }
448
        $metadataArray['meta_'.$key] = $value;
449
    }
450
451
    $recordingArrayValue = array('recordID' => (string) $recording->recordID, 'meetingID' => (string) $recording->meetingID, 'meetingName' => (string) $recording->name, 'published' => (string) $recording->published, 'startTime' => (string) $recording->startTime, 'endTime' => (string) $recording->endTime, 'playbacks' => $playbackArray) + $metadataArray;
452
453
    return $recordingArrayValue;
454
}
455
456
function bigbluebuttonbn_recordingBuildSorter($a, $b)
457
{
458
    if ($a['startTime'] < $b['startTime']) {
459
        return -1;
460
    } elseif ($a['startTime'] == $b['startTime']) {
461
        return 0;
462
    }
463
464
    return 1;
465
}
466
467
/**
468
 * @param string $recordIDs
469
 */
470 View Code Duplication
function bigbluebuttonbn_doDeleteRecordings($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...
471
{
472
    $ids = explode(',', $recordIDs);
473
    foreach ($ids as $id) {
474
        $xml = bigbluebuttonbn_wrap_xml_load_file(bigbluebuttonbn_getDeleteRecordingsURL($id));
475
        if ($xml && $xml->returncode != 'SUCCESS') {
476
            return false;
477
        }
478
    }
479
480
    return true;
481
}
482
483
/**
484
 * @param string $recordIDs
485
 * @param string $publish
486
 */
487 View Code Duplication
function bigbluebuttonbn_doPublishRecordings($recordIDs, $publish)
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...
488
{
489
    $ids = explode(',', $recordIDs);
490
    foreach ($ids as $id) {
491
        $xml = bigbluebuttonbn_wrap_xml_load_file(bigbluebuttonbn_getPublishRecordingsURL($id, $publish));
492
        if ($xml && $xml->returncode != 'SUCCESS') {
493
            return false;
494
        }
495
    }
496
497
    return true;
498
}
499
500
/**
501
 * @param string $meetingID
502
 * @param string $modPW
503
 */
504
function bigbluebuttonbn_doEndMeeting($meetingID, $modPW)
505
{
506
    $xml = bigbluebuttonbn_wrap_xml_load_file(bigbluebuttonbn_getEndMeetingURL($meetingID, $modPW));
507
508 View Code Duplication
    if ($xml) { //If the xml packet returned failure it displays the message to the user
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...
509
        return array('returncode' => $xml->returncode, 'message' => $xml->message, 'messageKey' => $xml->messageKey);
510
    }
511
512
    //If the server is unreachable, then prompts the user of the necessary action
513
    return null;
514
}
515
516
/**
517
 * @param string $meetingID
518
 */
519
function bigbluebuttonbn_isMeetingRunning($meetingID)
520
{
521
    $xml = bigbluebuttonbn_wrap_xml_load_file(bigbluebuttonbn_getIsMeetingRunningURL($meetingID));
522
    if ($xml && $xml->returncode == 'SUCCESS') {
523
        return ($xml->running == 'true') ? true : false;
524
    }
525
526
    return false;
527
}
528
529
function bigbluebuttonbn_getServerVersion()
530
{
531
    $xml = bigbluebuttonbn_wrap_xml_load_file(bigbluebuttonbn_get_cfg_server_url().'api');
532
    if ($xml && $xml->returncode == 'SUCCESS') {
533
        return $xml->version;
534
    }
535
536
    return null;
537
}
538
539
function bigbluebuttonbn_getMeetingXML($meetingID)
540
{
541
    $xml = bigbluebuttonbn_wrap_xml_load_file(bigbluebuttonbn_getIsMeetingRunningURL($meetingID));
542
    if ($xml && $xml->returncode == 'SUCCESS') {
543
        return str_replace('</response>', '', str_replace("<?xml version=\"1.0\"?>\n<response>", '', $xml->asXML()));
544
    }
545
546
    return 'false';
547
}
548
549
/**
550
 * @param string $url
551
 * @param string $data
552
 */
553
function bigbluebuttonbn_wrap_xml_load_file($url, $method = BIGBLUEBUTTONBN_METHOD_GET, $data = null, $content_type = 'text/xml')
554
{
555
    if (bigbluebuttonbn_debugdisplay()) {
556
        error_log('Request to: '.$url);
557
    }
558
559
    if (extension_loaded('curl')) {
560
        $response = bigbluebuttonbn_wrap_xml_load_file_curl_request($url, $method, $data, $content_type);
561
562
        if (!$response) {
563
            error_log('No response on wrap_simplexml_load_file');
564
565
            return null;
566
        }
567
568
        if (bigbluebuttonbn_debugdisplay()) {
569
            error_log('Response: '.$response);
570
        }
571
572
        $previous = libxml_use_internal_errors(true);
573
        try {
574
            $xml = simplexml_load_string($response, 'SimpleXMLElement', LIBXML_NOCDATA | LIBXML_NOBLANKS);
575
576
            return $xml;
577
        } catch (Exception $e) {
578
            libxml_use_internal_errors($previous);
579
            $error = 'Caught exception: '.$e->getMessage();
580
            error_log($error);
581
582
            return null;
583
        }
584
    }
585
586
    // Alternative request non CURL based
587
    $previous = libxml_use_internal_errors(true);
588
    try {
589
        $response = simplexml_load_file($url, 'SimpleXMLElement', LIBXML_NOCDATA | LIBXML_NOBLANKS);
590
        if (bigbluebuttonbn_debugdisplay()) {
591
            error_log('Response processed: '.$response->asXML());
592
        }
593
594
        return $response;
595
    } catch (Exception $e) {
596
        $error = 'Caught exception: '.$e->getMessage();
597
        error_log($error);
598
        libxml_use_internal_errors($previous);
599
600
        return null;
601
    }
602
}
603
604
function bigbluebuttonbn_wrap_xml_load_file_curl_request($url, $method = BIGBLUEBUTTONBN_METHOD_GET, $data = null, $content_type = 'text/xml')
605
{
606
    $c = new curl();
607
    $c->setopt(array('SSL_VERIFYPEER' => true));
608
    if ($method == BIGBLUEBUTTONBN_METHOD_POST) {
609
        if (is_null($data) || is_array($data)) {
610
            return $c->post($url);
611
        }
612
613
        $options = array();
614
        $options['CURLOPT_HTTPHEADER'] = array(
615
                 'Content-Type: '.$content_type,
616
                 'Content-Length: '.strlen($data),
617
                 'Content-Language: en-US',
618
               );
619
620
        return $c->post($url, $data, $options);
621
    }
622
623
    return $c->get($url);
624
}
625
626
function bigbluebuttonbn_get_user_roles($context, $userid)
627
{
628
    global $DB;
629
630
    $user_roles = get_user_roles($context, $userid);
631
    if ($user_roles) {
632
        $where = '';
633
        foreach ($user_roles as $key => $value) {
634
            $where .= (empty($where) ? ' WHERE' : ' AND').' id='.$value->roleid;
635
        }
636
        $user_roles = $DB->get_records_sql('SELECT * FROM {role}'.$where);
637
    }
638
639
    return $user_roles;
640
}
641
642
function bigbluebuttonbn_get_guest_role()
643
{
644
    $guest_role = get_guest_role();
645
646
    return array($guest_role->id => $guest_role);
647
}
648
649
function bigbluebuttonbn_get_roles(context $context = null)
650
{
651
    $roles = role_get_names($context);
652
    $roles_array = array();
653
    foreach ($roles as $role) {
654
        $roles_array[$role->shortname] = $role->localname;
655
    }
656
657
    return $roles_array;
658
}
659
660
function bigbluebuttonbn_get_roles_select($roles = array())
661
{
662
    $roles_array = array();
663
    foreach ($roles as $key => $value) {
664
        $roles_array[] = array('id' => $key, 'name' => $value);
665
    }
666
667
    return $roles_array;
668
}
669
670
function bigbluebuttonbn_get_users_select($users)
671
{
672
    $users_array = array();
673
    foreach ($users as $user) {
674
        $users_array[] = array('id' => $user->id, 'name' => fullname($user));
675
    }
676
677
    return $users_array;
678
}
679
680
function bigbluebuttonbn_get_participant_list($bigbluebuttonbn, $context = null)
681
{
682
    if ($bigbluebuttonbn == null) {
683
        return bigbluebuttonbn_get_participant_list_default($context);
684
    }
685
686
    $participant_list_array = array();
687
    $participant_list = json_decode($bigbluebuttonbn->participants);
688
    foreach ($participant_list as $participant) {
689
        $participant_list_array[] = array('selectiontype' => $participant->selectiontype,
690
                                          'selectionid' => $participant->selectionid,
691
                                          'role' => $participant->role, );
692
    }
693
694
    return $participant_list_array;
695
}
696
697
function bigbluebuttonbn_get_participant_list_default($context)
698
{
699
    global $USER;
700
701
    $participant_list_array = array();
702
    $participant_list_array[] = array('selectiontype' => 'all',
703
                                       'selectionid' => 'all',
704
                                       'role' => BIGBLUEBUTTONBN_ROLE_VIEWER, );
705
706
    $moderator_defaults = explode(',', bigbluebuttonbn_get_cfg_moderator_default());
707
    foreach ($moderator_defaults as $moderator_default) {
708
        if ($moderator_default == 'owner') {
709
            $users = get_enrolled_users($context);
710
            foreach ($users as $user) {
711
                if ($user->id == $USER->id) {
712
                    $participant_list_array[] = array('selectiontype' => 'user',
713
                                                       'selectionid' => $USER->id,
714
                                                       'role' => BIGBLUEBUTTONBN_ROLE_MODERATOR, );
715
                    break;
716
                }
717
            }
718
            continue;
719
        }
720
721
        $participant_list_array[] = array('selectiontype' => 'role',
722
                                          'selectionid' => $moderator_default,
723
                                          'role' => BIGBLUEBUTTONBN_ROLE_MODERATOR, );
724
    }
725
726
    return $participant_list_array;
727
}
728
function bigbluebuttonbn_get_participant_list_json($bigbluebuttonbnid = null)
729
{
730
    return json_encode(bigbluebuttonbn_get_participant_list($bigbluebuttonbnid));
731
}
732
733
function bigbluebuttonbn_is_moderator($user, $roles, $participants)
734
{
735
    $participant_list = json_decode($participants);
736
737
    // Iterate participant rules
738
    foreach ($participant_list as $participant) {
739
        if ($participant->role == BIGBLUEBUTTONBN_ROLE_MODERATOR) {
740
            // looks for all configuration
741
            if ($participant->selectiontype == 'all') {
742
                return true;
743
            }
744
            // looks for users
745
            if ($participant->selectiontype == 'user' && $participant->selectionid == $user) {
746
                return true;
747
            }
748
            // looks for roles
749
            if ($participant->selectiontype == 'role') {
750
                foreach ($roles as $role) {
751
                    if ($participant->selectionid == $role->shortname) {
752
                        return true;
753
                    }
754
                }
755
            }
756
        }
757
    }
758
759
    return false;
760
}
761
762
function bigbluebuttonbn_get_error_key($messageKey, $defaultKey = null)
763
{
764
    $key = $defaultKey;
765
    if ($messageKey == 'checksumError') {
766
        $key = 'index_error_checksum';
767
    } elseif ($messageKey == 'maxConcurrent') {
768
        $key = 'view_error_max_concurrent';
769
    }
770
771
    return $key;
772
}
773
774
function bigbluebuttonbn_voicebridge_unique($voicebridge, $id = null)
775
{
776
    global $DB;
777
778
    $is_unique = true;
779
    if ($voicebridge != 0) {
780
        $table = 'bigbluebuttonbn';
781
        $select = 'voicebridge = '.$voicebridge;
782
        if ($id) {
783
            $select .= ' AND id <> '.$id;
784
        }
785
        if ($DB->get_records_select($table, $select)) {
786
            $is_unique = false;
787
        }
788
    }
789
790
    return $is_unique;
791
}
792
793
function bigbluebuttonbn_get_duration($closingtime)
794
{
795
    $duration = 0;
796
    $now = time();
797
    if ($closingtime > 0 && $now < $closingtime) {
798
        $duration = ceil(($closingtime - $now) / 60);
799
        $compensation_time = intval(bigbluebuttonbn_get_cfg_scheduled_duration_compensation());
800
        $duration = intval($duration) + $compensation_time;
801
    }
802
803
    return $duration;
804
}
805
806
function bigbluebuttonbn_get_presentation_array($context, $presentation, $id = null)
807
{
808
    $presentation_name = null;
809
    $presentation_url = null;
810
    $presentation_icon = null;
811
    $presentation_mimetype_description = null;
812
813
    if (!empty($presentation)) {
814
        $fs = get_file_storage();
815
        $files = $fs->get_area_files($context->id, 'mod_bigbluebuttonbn', 'presentation', 0, 'itemid, filepath, filename', false);
816
        if (count($files) >= 1) {
817
            $file = reset($files);
818
            unset($files);
819
            $presentation_name = $file->get_filename();
820
            $presentation_icon = file_file_icon($file, 24);
821
            $presentation_mimetype_description = get_mimetype_description($file);
822
            $presentation_nonce_value = null;
823
824
            if (!is_null($id)) {
825
                //Create the nonce component for granting a temporary public access
826
                $cache = cache::make_from_params(cache_store::MODE_APPLICATION, 'mod_bigbluebuttonbn', 'presentation_cache');
827
                $presentation_nonce_key = sha1($id);
828
                //The item id was adapted for granting public access to the presentation once in order to allow BigBlueButton to gather the file
829
                $presentation_nonce_value = bigbluebuttonbn_generate_nonce();
830
                $cache->set($presentation_nonce_key, array('value' => $presentation_nonce_value, 'counter' => 0));
831
            }
832
            $url = moodle_url::make_pluginfile_url($file->get_contextid(), $file->get_component(), $file->get_filearea(), $presentation_nonce_value, $file->get_filepath(), $file->get_filename());
833
834
            $presentation_url = $url->out(false);
835
        }
836
    }
837
838
    $presentation_array = array('url' => $presentation_url, 'name' => $presentation_name, 'icon' => $presentation_icon, 'mimetype_description' => $presentation_mimetype_description);
839
840
    return $presentation_array;
841
}
842
843
function bigbluebuttonbn_generate_nonce()
844
{
845
    $mt = microtime();
846
    $rand = mt_rand();
847
848
    return md5($mt.$rand);
849
}
850
851
function bigbluebuttonbn_random_password($length = 8)
852
{
853
    $chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*()_-=+;:,.?';
854
    $password = substr(str_shuffle($chars), 0, $length);
855
856
    return $password;
857
}
858
859
function bigbluebuttonbn_get_moodle_version_major()
860
{
861
    global $CFG;
862
863
    $version_array = explode('.', $CFG->version);
864
865
    return $version_array[0];
866
}
867
868
function bigbluebuttonbn_event_log_standard($event_type, $bigbluebuttonbn, $cm, $timecreated = null, $userid = null, $event_subtype = null)
869
{
870
    $context = context_module::instance($cm->id);
871
    $event_properties = array('context' => $context, 'objectid' => $bigbluebuttonbn->id);
872
873
    switch ($event_type) {
874
        case BIGBLUEBUTTON_EVENT_MEETING_JOINED:
875
            $event = \mod_bigbluebuttonbn\event\bigbluebuttonbn_meeting_joined::create($event_properties);
876
            break;
877
        case BIGBLUEBUTTON_EVENT_MEETING_CREATED:
878
            $event = \mod_bigbluebuttonbn\event\bigbluebuttonbn_meeting_created::create($event_properties);
879
            break;
880
        case BIGBLUEBUTTON_EVENT_MEETING_ENDED:
881
            $event = \mod_bigbluebuttonbn\event\bigbluebuttonbn_meeting_ended::create($event_properties);
882
            break;
883
        case BIGBLUEBUTTON_EVENT_MEETING_LEFT:
884
            $event = \mod_bigbluebuttonbn\event\bigbluebuttonbn_meeting_left::create($event_properties);
885
            break;
886
        case BIGBLUEBUTTON_EVENT_RECORDING_PUBLISHED:
887
            $event = \mod_bigbluebuttonbn\event\bigbluebuttonbn_recording_published::create($event_properties);
888
            break;
889
        case BIGBLUEBUTTON_EVENT_RECORDING_UNPUBLISHED:
890
            $event = \mod_bigbluebuttonbn\event\bigbluebuttonbn_recording_unpublished::create($event_properties);
891
            break;
892
        case BIGBLUEBUTTON_EVENT_RECORDING_DELETED:
893
            $event = \mod_bigbluebuttonbn\event\bigbluebuttonbn_recording_deleted::create($event_properties);
894
            break;
895
        case BIGBLUEBUTTON_EVENT_ACTIVITY_VIEWED:
896
            $event = \mod_bigbluebuttonbn\event\bigbluebuttonbn_activity_viewed::create($event_properties);
897
            break;
898
        case BIGBLUEBUTTON_EVENT_ACTIVITY_MANAGEMENT_VIEWED:
899
            $event = \mod_bigbluebuttonbn\event\bigbluebuttonbn_activity_management_viewed::create($event_properties);
900
            break;
901
        case BIGBLUEBUTTON_EVENT_MEETING_EVENT:
902
            $event_properties['userid'] = $userid;
903
            $event_properties['timecreated'] = $timecreated;
904
            $event_properties['other'] = $event_subtype;
905
            $event = \mod_bigbluebuttonbn\event\bigbluebuttonbn_meeting_event::create($event_properties);
906
            break;
907
    }
908
    if (isset($event)) {
909
        $event->trigger();
910
    }
911
}
912
913
function bigbluebuttonbn_event_log($event_type, $bigbluebuttonbn, $cm)
914
{
915
    bigbluebuttonbn_event_log_standard($event_type, $bigbluebuttonbn, $cm);
916
}
917
918
function bigbluebuttonbn_meeting_event_log($event, $bigbluebuttonbn, $cm)
919
{
920
    bigbluebuttonbn_event_log_standard(BIGBLUEBUTTON_EVENT_MEETING_EVENT, $bigbluebuttonbn, $cm, $event->timestamp, $event->user, $event->event);
921
}
922
923
/**
924
 * @param bool $is_moderator
925
 */
926
function bigbluebuttonbn_participant_joined($meetingid, $is_moderator)
927
{
928
    $cache = cache::make_from_params(cache_store::MODE_APPLICATION, 'mod_bigbluebuttonbn', 'meetings_cache');
929
    $result = $cache->get($meetingid);
930
    $meeting_info = json_decode($result['meeting_info']);
931
    $meeting_info->participantCount += 1;
932
    if ($is_moderator) {
933
        $meeting_info->moderatorCount += 1;
934
    }
935
    $cache->set($meetingid, array('creation_time' => $result['creation_time'], 'meeting_info' => json_encode($meeting_info)));
936
}
937
938
function bigbluebuttonbn_is_meeting_running($meeting_info)
939
{
940
    $meeting_running = (isset($meeting_info) && isset($meeting_info->returncode) && $meeting_info->returncode == 'SUCCESS');
941
942
    return $meeting_running;
943
}
944
945
function bigbluebuttonbn_get_meeting_info($meetingid, $forced = false)
946
{
947
    $cache_ttl = bigbluebuttonbn_get_cfg_waitformoderator_cache_ttl();
948
949
    $cache = cache::make_from_params(cache_store::MODE_APPLICATION, 'mod_bigbluebuttonbn', 'meetings_cache');
950
    $result = $cache->get($meetingid);
951
    $now = time();
952
    if (!$forced && isset($result) && $now < ($result['creation_time'] + $cache_ttl)) {
953
        //Use the value in the cache
954
        return json_decode($result['meeting_info']);
955
    }
956
957
    //Ping again and refresh the cache
958
    $meeting_info = (array) bigbluebuttonbn_getMeetingInfo($meetingid);
959
    $cache->set($meetingid, array('creation_time' => time(), 'meeting_info' => json_encode($meeting_info)));
960
961
    return $meeting_info;
962
}
963
964
function bigbluebuttonbn_end_meeting($meetingid, $password)
965
{
966
    bigbluebuttonbn_doEndMeeting($meetingid, $password);
967
}
968
969
function bigbluebuttonbn_publish_recording($recordingid, $publish = true)
970
{
971
    bigbluebuttonbn_doPublishRecordings($recordingid, ($publish) ? 'true' : 'false');
972
}
973
974
function bigbluebuttonbn_publish_recording_imported($recordingid, $bigbluebuttonbnID, $publish = true)
975
{
976
    global $DB;
977
978
    //Locate the record to be updated
979
    $records = $DB->get_records('bigbluebuttonbn_logs', array('bigbluebuttonbnid' => $bigbluebuttonbnID, 'log' => BIGBLUEBUTTONBN_LOG_EVENT_IMPORT));
980
981
    foreach ($records as $key => $record) {
982
        $meta = json_decode($record->meta, true);
983
        if ($recordingid == $meta['recording']['recordID']) {
984
            // Found, prepare data for the update
985
            $meta['recording']['published'] = ($publish) ? 'true' : 'false';
986
            $records[$key]->meta = json_encode($meta);
987
988
            // Proceed with the update
989
            $DB->update_record('bigbluebuttonbn_logs', $records[$key]);
990
        }
991
    }
992
}
993
994
function bigbluebuttonbn_delete_recording($recordingid)
995
{
996
    bigbluebuttonbn_doDeleteRecordings($recordingid);
997
}
998
999
function bigbluebuttonbn_delete_recording_imported($recordingid, $bigbluebuttonbnID)
1000
{
1001
    global $DB;
1002
1003
    //Locate the record to be updated
1004
    $records = $DB->get_records('bigbluebuttonbn_logs', array('bigbluebuttonbnid' => $bigbluebuttonbnID, 'log' => BIGBLUEBUTTONBN_LOG_EVENT_IMPORT));
1005
1006
    foreach ($records as $key => $record) {
1007
        $meta = json_decode($record->meta, true);
1008
        if ($recordingid == $meta['recording']['recordID']) {
1009
            // Execute delete
1010
            $DB->delete_records('bigbluebuttonbn_logs', array('id' => $key));
1011
        }
1012
    }
1013
}
1014
1015
function bigbluebuttonbn_validate_parameters($params)
1016
{
1017
    $error = '';
1018
1019
    if (!isset($params['callback'])) {
1020
        return bigbluebuttonbn_add_error($error, 'This call must include a javascript callback.');
1021
    }
1022
1023
    if (!isset($params['action'])) {
1024
        return bigbluebuttonbn_add_error($error, 'Action parameter must be included.');
1025
    }
1026
1027
    switch (strtolower($params['action'])) {
1028
        case 'server_ping':
1029
        case 'meeting_info':
1030
        case 'meeting_end':
1031
            if (!isset($params['id'])) {
1032
                return bigbluebuttonbn_add_error($error, 'The meetingID must be specified.');
1033
            }
1034
            break;
1035
        case 'recording_info':
1036
        case 'recording_links':
1037
        case 'recording_publish':
1038
        case 'recording_unpublish':
1039
        case 'recording_delete':
1040
        case 'recording_import':
1041
            if (!isset($params['id'])) {
1042
                return bigbluebuttonbn_add_error($error, 'The recordingID must be specified.');
1043
            }
1044
            break;
1045
        case 'recording_ready':
1046
        case 'meeting_events':
1047
            if (empty($params['signed_parameters'])) {
1048
                return bigbluebuttonbn_add_error($error, 'A JWT encoded string must be included as [signed_parameters].');
1049
            }
1050
            break;
1051
        case 'moodle_event':
1052
            break;
1053
        default:
1054
            return bigbluebuttonbn_add_error($error, 'Action '.$params['action'].' can not be performed.');
1055
    }
1056
1057
    return '';
1058
}
1059
1060
function bigbluebuttonbn_add_error($org_msg, $new_msg = '')
1061
{
1062
    $error = $org_msg;
1063
1064
    if (!empty($new_msg)) {
1065
        if (!empty($error)) {
1066
            $error .= ' ';
1067
        }
1068
        $error .= $new_msg;
1069
    }
1070
1071
    return $error;
1072
}
1073
1074
/**
1075
 * @param string $meetingID
1076
 * @param string $configXML
1077
 */
1078
function bigbluebuttonbn_setConfigXMLParams($meetingID, $configXML)
1079
{
1080
    $params = 'configXML='.urlencode($configXML).'&meetingID='.urlencode($meetingID);
1081
    $config_xml_params = $params.'&checksum='.sha1('setConfigXML'.$params.bigbluebuttonbn_get_cfg_shared_secret());
1082
1083
    return $config_xml_params;
1084
}
1085
1086
/**
1087
 * @param string $meetingID
1088
 * @param string $configXML
1089
 */
1090
function bigbluebuttonbn_setConfigXML($meetingID, $configXML)
1091
{
1092
    $url_default_config = bigbluebuttonbn_get_cfg_server_url().'api/setConfigXML?';
1093
    $config_xml_params = bigbluebuttonbn_setConfigXMLParams($meetingID, $configXML);
1094
    $xml = bigbluebuttonbn_wrap_xml_load_file($url_default_config, BIGBLUEBUTTONBN_METHOD_POST, $config_xml_params, 'application/x-www-form-urlencoded');
1095
1096
    return $xml;
1097
}
1098
1099
/**
1100
 * @param string $meetingID
1101
 * @param string $configXML
1102
 */
1103
function bigbluebuttonbn_setConfigXMLArray($meetingID, $configXML)
1104
{
1105
    $config_xml = bigbluebuttonbn_setConfigXML($meetingID, $configXML);
1106
    $config_xml_array = (array) $config_xml;
1107
1108
    return $config_xml_array;
1109
}
1110
1111
function bigbluebuttonbn_set_config_xml($meetingID, $configXML)
1112
{
1113
    $config_xml_array = bigbluebuttonbn_setConfigXMLArray($meetingID, $configXML);
1114
    if ($config_xml_array['returncode'] != 'SUCCESS') {
1115
        error_log('BigBlueButton was not able to set the custom config.xml file');
1116
1117
        return '';
1118
    }
1119
1120
    return $config_xml_array['configToken'];
1121
}
1122
1123
function bigbluebuttonbn_get_recording_data_row($bbbsession, $recording, $tools = ['publishing', 'deleting'])
1124
{
1125
    global $USER;
1126
1127
    $row = null;
1128
1129
    if ($bbbsession['managerecordings'] || $recording['published'] == 'true') {
1130
        $row = new stdClass();
1131
1132
        // Set recording_types
1133
        $row->recording = bigbluebuttonbn_get_recording_data_row_types($recording);
1134
1135
        // Set activity name and description
1136
        $row->activity = bigbluebuttonbn_get_recording_data_row_meta_activity(recording);
1137
        $row->description = bigbluebuttonbn_get_recording_data_row_meta_description(recording);
1138
1139
        // Set recording_preview
1140
        $row->preview = bigbluebuttonbn_get_recording_data_row_preview($recording);
1141
1142
        // Set date
1143
        $startTime = isset($recording['startTime']) ? floatval($recording['startTime']) : 0;
1144
        $startTime = $startTime - ($startTime % 1000);
1145
        $row->date = floatval($recording['startTime']);
1146
1147
        // Set formatted date
1148
        $dateformat = get_string('strftimerecentfull', 'langconfig').' %Z';
1149
        $row->date_formatted = userdate($startTime / 1000, $dateformat, usertimezone($USER->timezone));
1150
1151
        // Set formatted duration
1152
        $first_playback = array_values($recording['playbacks'])[0];
1153
        $length = isset($first_playback['length']) ? $first_playback['length'] : 0;
1154
        $row->duration_formatted = $row->duration = intval($length);
1155
1156
        // Set actionbar, if user is allowed to manage recordings
1157
        if ($bbbsession['managerecordings']) {
1158
            $row->actionbar = bigbluebuttonbn_get_recording_data_row_actionbar($recording, $tools);
1159
        }
1160
    }
1161
1162
    return $row;
1163
}
1164
1165
function bigbluebuttonbn_get_recording_data_row_actionbar($recording, $tools)
1166
{
1167
    $actionbar = '';
1168
1169
    if (in_array('publishing', $tools)) {
1170
        /// Set action [show|hide]
1171
        $manage_action = 'publish';
1172
        $manage_tag = 'show';
1173
        if ($recording['published'] == 'true') {
1174
            $manage_action = 'unpublish';
1175
            $manage_tag = 'hide';
1176
        }
1177
        $actionbar .= bigbluebuttonbn_actionbar_render($manage_action, $manage_tag, $recording);
1178
    }
1179
1180 View Code Duplication
    if (in_array('deleting', $tools)) {
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...
1181
        $manage_action = $manage_tag = 'delete';
1182
        $actionbar .= bigbluebuttonbn_actionbar_render($manage_action, $manage_tag, $recording);
1183
    }
1184
1185 View Code Duplication
    if (in_array('importing', $tools)) {
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...
1186
        $manage_action = $manage_tag = 'import';
1187
        $actionbar .= bigbluebuttonbn_actionbar_render($manage_action, $manage_tag, $recording);
1188
    }
1189
1190
    return $actionbar;
1191
}
1192
1193
function bigbluebuttonbn_get_recording_data_row_preview($recording)
1194
{
1195
    $recording_preview = '';
1196
    foreach ($recording['playbacks'] as $playback) {
1197
        if (isset($playback['preview'])) {
1198
            foreach ($playback['preview'] as $image) {
1199
                $recording_preview .= html_writer::empty_tag('img', array('src' => $image['url'], 'class' => 'thumbnail'));
1200
            }
1201
            $recording_preview .= html_writer::empty_tag('br');
1202
            $recording_preview .= html_writer::tag('div', get_string('view_recording_preview_help', 'bigbluebuttonbn'), array('class' => 'text-muted small'));
1203
            break;
1204
        }
1205
    }
1206
1207
    return $recording_preview;
1208
}
1209
1210
function bigbluebuttonbn_get_recording_data_row_types($recording)
1211
{
1212
    global $OUTPUT;
1213
1214
    $attributes = 'data-imported="false"';
1215
    if (isset($recording['imported'])) {
1216
        $attributes = 'data-imported="true" title="'.get_string('view_recording_link_warning', 'bigbluebuttonbn').'"';
1217
    }
1218
1219
    $visibility = '';
1220
    if ($recording['published'] === 'false') {
1221
        $visibility = 'hidden ';
1222
    }
1223
1224
    $recording_types = '<div id="playbacks-'.$recording['recordID'].'" '.$attributes.' '.$visibility.'>';
1225
    foreach ($recording['playbacks'] as $playback) {
1226
        $recording_types .= $OUTPUT->action_link($playback['url'], get_string('view_recording_format_'.$playback['type'], 'bigbluebuttonbn'), null, array('title' => get_string('view_recording_format_'.$playback['type'], 'bigbluebuttonbn'), 'target' => '_new')).'&#32;';
1227
    }
1228
    $recording_types .= '</div>';
1229
1230
    return $recording_types;
1231
}
1232
1233
function bigbluebuttonbn_get_recording_data_row_meta_activity($recording)
1234
{
1235
    if (isset($recording['meta_contextactivity'])) {
1236
        return htmlentities($recording['meta_contextactivity']);
1237
    } elseif (isset($recording['meta_bbb-recording-name'])) {
1238
        return htmlentities($recording['meta_bbb-recording-name']);
1239
    }
1240
1241
    return htmlentities($recording['meetingName']);
1242
}
1243
1244
function bigbluebuttonbn_get_recording_data_row_meta_description($recording)
1245
{
1246
    $meta_description = html_writer::start_tag('div', array('class' => 'col-md-20'));
1247
    if (isset($recording['meta_contextactivitydescription']) && trim($recording['meta_contextactivitydescription']) != '') {
1248
        $meta_description .= htmlentities($recording['meta_contextactivitydescription']);
1249
    } elseif (isset($recording['meta_bbb-recording-description']) && trim($recording['meta_bbb-recording-description']) != '') {
1250
        $meta_description .= htmlentities($recording['meta_bbb-recording-description']);
1251
    }
1252
    $meta_description .= html_writer::end_tag('div');
1253
1254
    return $meta_description;
1255
}
1256
1257
function bigbluebuttonbn_actionbar_render($manage_action, $manage_tag, $recording)
1258
{
1259
    global $OUTPUT;
1260
1261
    $onclick = 'M.mod_bigbluebuttonbn.broker_manageRecording("'.$manage_action.'", "'.$recording['recordID'].'", "'.$recording['meetingID'].'");';
1262
    if (bigbluebuttonbn_get_cfg_recording_icons_enabled()) {
1263
        //With icon for $manage_action
1264
        $icon_attributes = array('id' => 'recording-btn-'.$manage_action.'-'.$recording['recordID']);
1265
        $icon = new pix_icon('i/'.$manage_tag, get_string($manage_tag), 'moodle', $icon_attributes);
1266
        $link_attributes = array('id' => 'recording-link-'.$manage_action.'-'.$recording['recordID'], 'onclick' => $onclick);
1267
1268
        return $OUTPUT->action_icon('#', $icon, null, $link_attributes, false);
1269
    }
1270
1271
    //With text for $manage_action
1272
    $link_attributes = array('title' => get_string($manage_tag), 'class' => 'btn btn-xs btn-danger', 'onclick' => $onclick);
1273
1274
    return $OUTPUT->action_link('#', get_string($manage_action), null, $link_attributes);
1275
}
1276
1277
function bigbluebuttonbn_get_recording_columns($bbbsession)
1278
{
1279
    ///Set strings to show
1280
    $recording = get_string('view_recording_recording', 'bigbluebuttonbn');
1281
    $activity = get_string('view_recording_activity', 'bigbluebuttonbn');
1282
    $description = get_string('view_recording_description', 'bigbluebuttonbn');
1283
    $preview = get_string('view_recording_preview', 'bigbluebuttonbn');
1284
    $date = get_string('view_recording_date', 'bigbluebuttonbn');
1285
    $duration = get_string('view_recording_duration', 'bigbluebuttonbn');
1286
    $actionbar = get_string('view_recording_actionbar', 'bigbluebuttonbn');
1287
1288
    ///Initialize table headers
1289
    $recordingsbn_columns = array(
1290
        array('key' => 'recording', 'label' => $recording, 'width' => '125px', 'allowHTML' => true),
1291
        array('key' => 'activity', 'label' => $activity, 'sortable' => true, 'width' => '175px', 'allowHTML' => true),
1292
        array('key' => 'description', 'label' => $description, 'width' => '250px', 'sortable' => true, 'width' => '250px', 'allowHTML' => true),
1293
        array('key' => 'preview', 'label' => $preview, 'width' => '250px', 'allowHTML' => true),
1294
        array('key' => 'date', 'label' => $date, 'sortable' => true, 'width' => '225px', 'allowHTML' => true),
1295
        array('key' => 'duration', 'label' => $duration, 'width' => '50px'),
1296
        );
1297
1298
    if ($bbbsession['managerecordings']) {
1299
        array_push($recordingsbn_columns, array('key' => 'actionbar', 'label' => $actionbar, 'width' => '100px', 'allowHTML' => true));
1300
    }
1301
1302
    return $recordingsbn_columns;
1303
}
1304
1305
function bigbluebuttonbn_get_recording_data($bbbsession, $recordings, $tools = ['publishing', 'deleting'])
1306
{
1307
    $table_data = array();
1308
1309
    ///Build table content
1310
    if (isset($recordings) && !array_key_exists('messageKey', $recordings)) {  // There are recordings for this meeting
1311
        foreach ($recordings as $recording) {
1312
            $row = bigbluebuttonbn_get_recording_data_row($bbbsession, $recording, $tools);
1313
            if ($row != null) {
1314
                array_push($table_data, $row);
1315
            }
1316
        }
1317
    }
1318
1319
    return $table_data;
1320
}
1321
1322
function bigbluebuttonbn_get_recording_table($bbbsession, $recordings, $tools = ['publishing', 'deleting'])
1323
{
1324
    ///Set strings to show
1325
    $recording = get_string('view_recording_recording', 'bigbluebuttonbn');
1326
    $description = get_string('view_recording_description', 'bigbluebuttonbn');
1327
    $date = get_string('view_recording_date', 'bigbluebuttonbn');
1328
    $duration = get_string('view_recording_duration', 'bigbluebuttonbn');
1329
    $actionbar = get_string('view_recording_actionbar', 'bigbluebuttonbn');
1330
    $playback = get_string('view_recording_playback', 'bigbluebuttonbn');
1331
    $preview = get_string('view_recording_preview', 'bigbluebuttonbn');
1332
1333
    ///Declare the table
1334
    $table = new html_table();
1335
    $table->data = array();
1336
1337
    ///Initialize table headers
1338
    $table->head = array($playback.$recording, $description, $preview, $date, $duration);
1339
    $table->align = array('left', 'left', 'left', 'left', 'left', 'center');
1340
    if ($bbbsession['managerecordings']) {
1341
        $table->head[] = $actionbar;
1342
        $table->align[] = 'left';
1343
    }
1344
1345
    ///Build table content
1346
    if (isset($recordings) && !array_key_exists('messageKey', $recordings)) {  // There are recordings for this meeting
1347
        foreach ($recordings as $recording) {
1348
            $row = new html_table_row();
1349
            $row->id = 'recording-td-'.$recording['recordID'];
1350
            $row->attributes['data-imported'] = 'false';
1351
            if (isset($recording['imported'])) {
1352
                $row->attributes['data-imported'] = 'true';
1353
                $row->attributes['title'] = get_string('view_recording_link_warning', 'bigbluebuttonbn');
1354
            }
1355
1356
            $row_data = bigbluebuttonbn_get_recording_data_row($bbbsession, $recording, $tools);
1357
            if ($row_data != null) {
1358
                $row_data->date_formatted = str_replace(' ', '&nbsp;', $row_data->date_formatted);
1359
                $row->cells = array($row_data->recording, $row_data->activity, $row_data->description, $row_data->preview, $row_data->date_formatted, $row_data->duration_formatted);
1360
                if ($bbbsession['managerecordings']) {
1361
                    $row->cells[] = $row_data->actionbar;
1362
                }
1363
                array_push($table->data, $row);
1364
            }
1365
        }
1366
    }
1367
1368
    return $table;
1369
}
1370
1371
function bigbluebuttonbn_send_notification_recording_ready($bigbluebuttonbn)
1372
{
1373
    $sender = get_admin();
1374
1375
    // Prepare message
1376
    $msg = new stdClass();
1377
1378
    /// Build the message_body
1379
    $msg->activity_type = '';
1380
    $msg->activity_title = $bigbluebuttonbn->name;
1381
    $message_text = '<p>'.get_string('email_body_recording_ready_for', 'bigbluebuttonbn').' '.$msg->activity_type.' &quot;'.$msg->activity_title.'&quot; '.get_string('email_body_recording_ready_is_ready', 'bigbluebuttonbn').'.</p>';
1382
1383
    bigbluebuttonbn_send_notification($sender, $bigbluebuttonbn, $message_text);
1384
}
1385
1386
function bigbluebuttonbn_server_offers_bn_capabilities()
1387
{
1388
    //Validates if the server may have extended capabilities
1389
    $parsed_url = parse_url(bigbluebuttonbn_get_cfg_server_url());
1390
    $host = isset($parsed_url['host']) ? $parsed_url['host'] : '';
1391
    $host_ends = explode('.', $host);
1392
    $host_ends_length = count($host_ends);
1393
1394
    return $host_ends_length > 0 && $host_ends[$host_ends_length - 1] == 'com' && $host_ends[$host_ends_length - 2] == 'blindsidenetworks';
1395
}
1396
1397
function bigbluebuttonbn_get_locales_for_view()
1398
{
1399
    $locales = array(
1400
            'not_started' => get_string('view_message_conference_not_started', 'bigbluebuttonbn'),
1401
            'wait_for_moderator' => get_string('view_message_conference_wait_for_moderator', 'bigbluebuttonbn'),
1402
            'in_progress' => get_string('view_message_conference_in_progress', 'bigbluebuttonbn'),
1403
            'started_at' => get_string('view_message_session_started_at', 'bigbluebuttonbn'),
1404
            'session_no_users' => get_string('view_message_session_no_users', 'bigbluebuttonbn'),
1405
            'session_has_user' => get_string('view_message_session_has_user', 'bigbluebuttonbn'),
1406
            'session_has_users' => get_string('view_message_session_has_users', 'bigbluebuttonbn'),
1407
            'has_joined' => get_string('view_message_has_joined', 'bigbluebuttonbn'),
1408
            'have_joined' => get_string('view_message_have_joined', 'bigbluebuttonbn'),
1409
            'user' => get_string('view_message_user', 'bigbluebuttonbn'),
1410
            'users' => get_string('view_message_users', 'bigbluebuttonbn'),
1411
            'viewer' => get_string('view_message_viewer', 'bigbluebuttonbn'),
1412
            'viewers' => get_string('view_message_viewers', 'bigbluebuttonbn'),
1413
            'moderator' => get_string('view_message_moderator', 'bigbluebuttonbn'),
1414
            'moderators' => get_string('view_message_moderators', 'bigbluebuttonbn'),
1415
            'publish' => get_string('view_recording_list_actionbar_publish', 'bigbluebuttonbn'),
1416
            'publishing' => get_string('view_recording_list_actionbar_publishing', 'bigbluebuttonbn'),
1417
            'unpublish' => get_string('view_recording_list_actionbar_unpublish', 'bigbluebuttonbn'),
1418
            'unpublishing' => get_string('view_recording_list_actionbar_unpublishing', 'bigbluebuttonbn'),
1419
            'modal_title' => get_string('view_recording_modal_title', 'bigbluebuttonbn'),
1420
            'modal_button' => get_string('view_recording_modal_button', 'bigbluebuttonbn'),
1421
            'userlimit_reached' => get_string('view_error_userlimit_reached', 'bigbluebuttonbn'),
1422
            'recording' => get_string('view_recording', 'bigbluebuttonbn'),
1423
            'recording_link' => get_string('view_recording_link', 'bigbluebuttonbn'),
1424
            'recording_link_warning' => get_string('view_recording_link_warning', 'bigbluebuttonbn'),
1425
            'unpublish_confirmation' => get_string('view_recording_unpublish_confirmation', 'bigbluebuttonbn'),
1426
            'unpublish_confirmation_warning_s' => get_string('view_recording_unpublish_confirmation_warning_s', 'bigbluebuttonbn'),
1427
            'unpublish_confirmation_warning_p' => get_string('view_recording_unpublish_confirmation_warning_p', 'bigbluebuttonbn'),
1428
            'delete_confirmation' => get_string('view_recording_delete_confirmation', 'bigbluebuttonbn'),
1429
            'delete_confirmation_warning_s' => get_string('view_recording_delete_confirmation_warning_s', 'bigbluebuttonbn'),
1430
            'delete_confirmation_warning_p' => get_string('view_recording_delete_confirmation_warning_p', 'bigbluebuttonbn'),
1431
            'import_confirmation' => get_string('view_recording_import_confirmation', 'bigbluebuttonbn'),
1432
            'conference_ended' => get_string('view_message_conference_has_ended', 'bigbluebuttonbn'),
1433
            'conference_not_started' => get_string('view_message_conference_not_started', 'bigbluebuttonbn'),
1434
    );
1435
1436
    return $locales;
1437
}
1438
1439
function bigbluebuttonbn_get_cfg_server_url_default()
1440
{
1441
    global $BIGBLUEBUTTONBN_CFG, $CFG;
1442
1443
    return isset($BIGBLUEBUTTONBN_CFG->bigbluebuttonbn_server_url) ? $BIGBLUEBUTTONBN_CFG->bigbluebuttonbn_server_url : (isset($CFG->bigbluebuttonbn_server_url) ? $CFG->bigbluebuttonbn_server_url : (isset($CFG->BigBlueButtonBNServerURL) ? $CFG->BigBlueButtonBNServerURL : BIGBLUEBUTTONBN_DEFAULT_SERVER_URL));
1444
}
1445
1446
function bigbluebuttonbn_get_cfg_shared_secret_default()
1447
{
1448
    global $BIGBLUEBUTTONBN_CFG, $CFG;
1449
1450
    return isset($BIGBLUEBUTTONBN_CFG->bigbluebuttonbn_shared_secret) ? $BIGBLUEBUTTONBN_CFG->bigbluebuttonbn_shared_secret : (isset($CFG->bigbluebuttonbn_shared_secret) ? $CFG->bigbluebuttonbn_shared_secret : (isset($CFG->BigBlueButtonBNSecuritySalt) ? $CFG->BigBlueButtonBNSecuritySalt : BIGBLUEBUTTONBN_DEFAULT_SHARED_SECRET));
1451
}
1452
1453
function bigbluebuttonbn_get_cfg_voicebridge_editable()
1454
{
1455
    global $BIGBLUEBUTTONBN_CFG, $CFG;
1456
1457
    return isset($BIGBLUEBUTTONBN_CFG->bigbluebuttonbn_voicebridge_editable) ? $BIGBLUEBUTTONBN_CFG->bigbluebuttonbn_voicebridge_editable : (isset($CFG->bigbluebuttonbn_voicebridge_editable) ? $CFG->bigbluebuttonbn_voicebridge_editable : false);
1458
}
1459
1460
function bigbluebuttonbn_get_cfg_recording_default()
1461
{
1462
    global $BIGBLUEBUTTONBN_CFG, $CFG;
1463
1464
    return isset($BIGBLUEBUTTONBN_CFG->bigbluebuttonbn_recording_default) ? $BIGBLUEBUTTONBN_CFG->bigbluebuttonbn_recording_default : (isset($CFG->bigbluebuttonbn_recording_default) ? $CFG->bigbluebuttonbn_recording_default : true);
1465
}
1466
1467
function bigbluebuttonbn_get_cfg_recording_editable()
1468
{
1469
    global $BIGBLUEBUTTONBN_CFG, $CFG;
1470
1471
    return isset($BIGBLUEBUTTONBN_CFG->bigbluebuttonbn_recording_editable) ? $BIGBLUEBUTTONBN_CFG->bigbluebuttonbn_recording_editable : (isset($CFG->bigbluebuttonbn_recording_editable) ? $CFG->bigbluebuttonbn_recording_editable : true);
1472
}
1473
1474
function bigbluebuttonbn_get_cfg_recording_tagging_default()
1475
{
1476
    global $BIGBLUEBUTTONBN_CFG, $CFG;
1477
1478
    return isset($BIGBLUEBUTTONBN_CFG->bigbluebuttonbn_recordingtagging_default) ? $BIGBLUEBUTTONBN_CFG->bigbluebuttonbn_recordingtagging_default : (isset($CFG->bigbluebuttonbn_recordingtagging_default) ? $CFG->bigbluebuttonbn_recordingtagging_default : false);
1479
}
1480
1481
function bigbluebuttonbn_get_cfg_recording_tagging_editable()
1482
{
1483
    global $BIGBLUEBUTTONBN_CFG, $CFG;
1484
1485
    return isset($BIGBLUEBUTTONBN_CFG->bigbluebuttonbn_recordingtagging_editable) ? $BIGBLUEBUTTONBN_CFG->bigbluebuttonbn_recordingtagging_editable : (isset($CFG->bigbluebuttonbn_recordingtagging_editable) ? $CFG->bigbluebuttonbn_recordingtagging_editable : false);
1486
}
1487
1488
function bigbluebuttonbn_get_cfg_recording_icons_enabled()
1489
{
1490
    global $BIGBLUEBUTTONBN_CFG, $CFG;
1491
1492
    return isset($BIGBLUEBUTTONBN_CFG->bigbluebuttonbn_recording_icons_enabled) ? $BIGBLUEBUTTONBN_CFG->bigbluebuttonbn_recording_icons_enabled : (isset($CFG->bigbluebuttonbn_recording_icons_enabled) ? $CFG->bigbluebuttonbn_recording_icons_enabled : true);
1493
}
1494
1495
function bigbluebuttonbn_get_cfg_importrecordings_enabled()
1496
{
1497
    global $BIGBLUEBUTTONBN_CFG, $CFG;
1498
1499
    return isset($BIGBLUEBUTTONBN_CFG->bigbluebuttonbn_importrecordings_enabled) ? $BIGBLUEBUTTONBN_CFG->bigbluebuttonbn_importrecordings_enabled : (isset($CFG->bigbluebuttonbn_importrecordings_enabled) ? $CFG->bigbluebuttonbn_importrecordings_enabled : false);
1500
}
1501
1502
function bigbluebuttonbn_get_cfg_importrecordings_from_deleted_activities_enabled()
1503
{
1504
    global $BIGBLUEBUTTONBN_CFG, $CFG;
1505
1506
    return isset($BIGBLUEBUTTONBN_CFG->bigbluebuttonbn_importrecordings_from_deleted_activities_enabled) ? $BIGBLUEBUTTONBN_CFG->bigbluebuttonbn_importrecordings_from_deleted_activities_enabled : (isset($CFG->bigbluebuttonbn_importrecordings_from_deleted_activities_enabled) ? $CFG->bigbluebuttonbn_importrecordings_from_deleted_activities_enabled : false);
1507
}
1508
1509
function bigbluebuttonbn_get_cfg_waitformoderator_default()
1510
{
1511
    global $BIGBLUEBUTTONBN_CFG, $CFG;
1512
1513
    return isset($BIGBLUEBUTTONBN_CFG->bigbluebuttonbn_waitformoderator_default) ? $BIGBLUEBUTTONBN_CFG->bigbluebuttonbn_waitformoderator_default : (isset($CFG->bigbluebuttonbn_waitformoderator_default) ? $CFG->bigbluebuttonbn_waitformoderator_default : false);
1514
}
1515
1516
function bigbluebuttonbn_get_cfg_waitformoderator_editable()
1517
{
1518
    global $BIGBLUEBUTTONBN_CFG, $CFG;
1519
1520
    return isset($BIGBLUEBUTTONBN_CFG->bigbluebuttonbn_waitformoderator_editable) ? $BIGBLUEBUTTONBN_CFG->bigbluebuttonbn_waitformoderator_editable : (isset($CFG->bigbluebuttonbn_waitformoderator_editable) ? $CFG->bigbluebuttonbn_waitformoderator_editable : true);
1521
}
1522
1523
function bigbluebuttonbn_get_cfg_waitformoderator_ping_interval()
1524
{
1525
    global $BIGBLUEBUTTONBN_CFG, $CFG;
1526
1527
    return isset($BIGBLUEBUTTONBN_CFG->bigbluebuttonbn_waitformoderator_ping_interval) ? $BIGBLUEBUTTONBN_CFG->bigbluebuttonbn_waitformoderator_ping_interval : (isset($CFG->bigbluebuttonbn_waitformoderator_ping_interval) ? $CFG->bigbluebuttonbn_waitformoderator_ping_interval : 15);
1528
}
1529
1530
function bigbluebuttonbn_get_cfg_waitformoderator_cache_ttl()
1531
{
1532
    global $BIGBLUEBUTTONBN_CFG, $CFG;
1533
1534
    return isset($BIGBLUEBUTTONBN_CFG->bigbluebuttonbn_waitformoderator_cache_ttl) ? $BIGBLUEBUTTONBN_CFG->bigbluebuttonbn_waitformoderator_cache_ttl : (isset($CFG->bigbluebuttonbn_waitformoderator_cache_ttl) ? $CFG->bigbluebuttonbn_waitformoderator_cache_ttl : 60);
1535
}
1536
1537
function bigbluebuttonbn_get_cfg_userlimit_default()
1538
{
1539
    global $BIGBLUEBUTTONBN_CFG, $CFG;
1540
1541
    return isset($BIGBLUEBUTTONBN_CFG->bigbluebuttonbn_userlimit_default) ? $BIGBLUEBUTTONBN_CFG->bigbluebuttonbn_userlimit_default : (isset($CFG->bigbluebuttonbn_userlimit_default) ? $CFG->bigbluebuttonbn_userlimit_default : 0);
1542
}
1543
1544
function bigbluebuttonbn_get_cfg_userlimit_editable()
1545
{
1546
    global $BIGBLUEBUTTONBN_CFG, $CFG;
1547
1548
    return isset($BIGBLUEBUTTONBN_CFG->bigbluebuttonbn_userlimit_editable) ? $BIGBLUEBUTTONBN_CFG->bigbluebuttonbn_userlimit_editable : (isset($CFG->bigbluebuttonbn_userlimit_editable) ? $CFG->bigbluebuttonbn_userlimit_editable : false);
1549
}
1550
1551
function bigbluebuttonbn_get_cfg_preuploadpresentation_enabled()
1552
{
1553
    global $BIGBLUEBUTTONBN_CFG, $CFG;
1554
    if (extension_loaded('curl')) {
1555
        // This feature only works if curl is installed
1556
        return isset($BIGBLUEBUTTONBN_CFG->bigbluebuttonbn_preuploadpresentation_enabled) ? $BIGBLUEBUTTONBN_CFG->bigbluebuttonbn_preuploadpresentation_enabled : (isset($CFG->bigbluebuttonbn_preuploadpresentation_enabled) ? $CFG->bigbluebuttonbn_preuploadpresentation_enabled : false);
1557
    }
1558
1559
    return false;
1560
}
1561
1562
function bigbluebuttonbn_get_cfg_sendnotifications_enabled()
1563
{
1564
    global $BIGBLUEBUTTONBN_CFG, $CFG;
1565
1566
    return isset($BIGBLUEBUTTONBN_CFG->bigbluebuttonbn_sendnotifications_enabled) ? $BIGBLUEBUTTONBN_CFG->bigbluebuttonbn_sendnotifications_enabled : (isset($CFG->bigbluebuttonbn_sendnotifications_enabled) ? $CFG->bigbluebuttonbn_sendnotifications_enabled : false);
1567
}
1568
1569
function bigbluebuttonbn_get_cfg_recordingready_enabled()
1570
{
1571
    global $BIGBLUEBUTTONBN_CFG, $CFG;
1572
1573
    return isset($BIGBLUEBUTTONBN_CFG->bigbluebuttonbn_recordingready_enabled) ? $BIGBLUEBUTTONBN_CFG->bigbluebuttonbn_recordingready_enabled : (isset($CFG->bigbluebuttonbn_recordingready_enabled) ? $CFG->bigbluebuttonbn_recordingready_enabled : false);
1574
}
1575
1576
function bigbluebuttonbn_get_cfg_meetingevents_enabled()
1577
{
1578
    global $BIGBLUEBUTTONBN_CFG, $CFG;
1579
1580
    return isset($BIGBLUEBUTTONBN_CFG->bigbluebuttonbn_meetingevents_enabled) ? $BIGBLUEBUTTONBN_CFG->bigbluebuttonbn_meetingevents_enabled : (isset($CFG->bigbluebuttonbn_meetingevents_enabled) ? $CFG->bigbluebuttonbn_meetingevents_enabled : false);
1581
}
1582
1583
/**
1584
 * @return string
1585
 */
1586
function bigbluebuttonbn_get_cfg_moderator_default()
1587
{
1588
    global $BIGBLUEBUTTONBN_CFG, $CFG;
1589
1590
    return isset($BIGBLUEBUTTONBN_CFG->bigbluebuttonbn_moderator_default) ? $BIGBLUEBUTTONBN_CFG->bigbluebuttonbn_moderator_default : (isset($CFG->bigbluebuttonbn_moderator_default) ? $CFG->bigbluebuttonbn_moderator_default : 'owner');
1591
}
1592
1593
function bigbluebuttonbn_get_cfg_scheduled_duration_enabled()
1594
{
1595
    global $BIGBLUEBUTTONBN_CFG, $CFG;
1596
1597
    return isset($BIGBLUEBUTTONBN_CFG->bigbluebuttonbn_scheduled_duration_enabled) ? $BIGBLUEBUTTONBN_CFG->bigbluebuttonbn_scheduled_duration_enabled : (isset($CFG->bigbluebuttonbn_scheduled_duration_enabled) ? $CFG->bigbluebuttonbn_scheduled_duration_enabled : false);
1598
}
1599
1600
function bigbluebuttonbn_get_cfg_scheduled_duration_compensation()
1601
{
1602
    global $BIGBLUEBUTTONBN_CFG, $CFG;
1603
1604
    return isset($BIGBLUEBUTTONBN_CFG->bigbluebuttonbn_scheduled_duration_compensation) ? $BIGBLUEBUTTONBN_CFG->bigbluebuttonbn_scheduled_duration_compensation : (isset($CFG->bigbluebuttonbn_scheduled_duration_compensation) ? $CFG->bigbluebuttonbn_scheduled_duration_compensation : 10);
1605
}
1606
1607
function bigbluebuttonbn_get_cfg_scheduled_pre_opening()
1608
{
1609
    global $BIGBLUEBUTTONBN_CFG, $CFG;
1610
1611
    return isset($BIGBLUEBUTTONBN_CFG->bigbluebuttonbn_scheduled_pre_opening) ? $BIGBLUEBUTTONBN_CFG->bigbluebuttonbn_scheduled_pre_opening : (isset($CFG->bigbluebuttonbn_scheduled_pre_opening) ? $CFG->bigbluebuttonbn_scheduled_pre_opening : 10);
1612
}
1613
1614
function bigbluebuttonbn_get_cfg_recordings_html_default()
1615
{
1616
    global $BIGBLUEBUTTONBN_CFG, $CFG;
1617
1618
    return isset($BIGBLUEBUTTONBN_CFG->bigbluebuttonbn_recordings_html_default) ? $BIGBLUEBUTTONBN_CFG->bigbluebuttonbn_recordings_html_default : (isset($CFG->bigbluebuttonbn_recordings_html_default) ? $CFG->bigbluebuttonbn_recordings_html_default : false);
1619
}
1620
1621
function bigbluebuttonbn_get_cfg_recordings_html_editable()
1622
{
1623
    global $BIGBLUEBUTTONBN_CFG, $CFG;
1624
1625
    return isset($BIGBLUEBUTTONBN_CFG->bigbluebuttonbn_recordings_html_editable) ? $BIGBLUEBUTTONBN_CFG->bigbluebuttonbn_recordings_html_editable : (isset($CFG->bigbluebuttonbn_recordings_html_editable) ? $CFG->bigbluebuttonbn_recordings_html_editable : false);
1626
}
1627
1628
function bigbluebuttonbn_get_cfg_recordings_deleted_activities_default()
1629
{
1630
    global $BIGBLUEBUTTONBN_CFG, $CFG;
1631
1632
    return isset($BIGBLUEBUTTONBN_CFG->bigbluebuttonbn_recordings_deleted_activities_default) ? $BIGBLUEBUTTONBN_CFG->bigbluebuttonbn_recordings_deleted_activities_default : (isset($CFG->bigbluebuttonbn_recordings_deleted_activities_default) ? $CFG->bigbluebuttonbn_recordings_deleted_activities_default : false);
1633
}
1634
1635
function bigbluebuttonbn_get_cfg_recordings_deleted_activities_editable()
1636
{
1637
    global $BIGBLUEBUTTONBN_CFG, $CFG;
1638
1639
    return isset($BIGBLUEBUTTONBN_CFG->bigbluebuttonbn_recordings_deleted_activities_editable) ? $BIGBLUEBUTTONBN_CFG->bigbluebuttonbn_recordings_deleted_activities_editable : (isset($CFG->bigbluebuttonbn_recordings_deleted_activities_editable) ? $CFG->bigbluebuttonbn_recordings_deleted_activities_editable : false);
1640
}
1641
1642
function bigbluebuttonbn_get_cfg_options()
1643
{
1644
    return [
1645
          'voicebridge_editable' => bigbluebuttonbn_get_cfg_voicebridge_editable(),
1646
          'recording_default' => bigbluebuttonbn_get_cfg_recording_default(),
1647
          'recording_editable' => bigbluebuttonbn_get_cfg_recording_editable(),
1648
          'recording_tagging_default' => bigbluebuttonbn_get_cfg_recording_tagging_default(),
1649
          'recording_tagging_editable' => bigbluebuttonbn_get_cfg_recording_tagging_editable(),
1650
          'waitformoderator_default' => bigbluebuttonbn_get_cfg_waitformoderator_default(),
1651
          'waitformoderator_editable' => bigbluebuttonbn_get_cfg_waitformoderator_editable(),
1652
          'userlimit_default' => bigbluebuttonbn_get_cfg_userlimit_default(),
1653
          'userlimit_editable' => bigbluebuttonbn_get_cfg_userlimit_editable(),
1654
          'preuploadpresentation_enabled' => bigbluebuttonbn_get_cfg_preuploadpresentation_enabled(),
1655
          'sendnotifications_enabled' => bigbluebuttonbn_get_cfg_sendnotifications_enabled(),
1656
          'recordings_html_default' => bigbluebuttonbn_get_cfg_recordings_html_default(),
1657
          'recordings_html_editable' => bigbluebuttonbn_get_cfg_recordings_html_editable(),
1658
          'recordings_deleted_activities_default' => bigbluebuttonbn_get_cfg_recordings_deleted_activities_default(),
1659
          'recordings_deleted_activities_editable' => bigbluebuttonbn_get_cfg_recordings_deleted_activities_editable(),
1660
          'recording_icons_enabled' => bigbluebuttonbn_get_cfg_recording_icons_enabled(),
1661
          'instance_type_enabled' => bigbluebuttonbn_recordings_enabled(),
1662
          'instance_type_default' => BIGBLUEBUTTONBN_TYPE_ALL,
1663
        ];
1664
}
1665
1666
function bigbluebuttonbn_import_get_courses_for_select(array $bbbsession)
1667
{
1668
    if ($bbbsession['administrator']) {
1669
        $courses = get_courses('all', 'c.id ASC', 'c.id,c.shortname,c.fullname');
1670
        //It includes the name of the site as a course (category 0), so remove the first one
1671
        unset($courses['1']);
1672
    } else {
1673
        $courses = enrol_get_users_courses($bbbsession['userID'], false, 'id,shortname,fullname');
1674
    }
1675
1676
    $courses_for_select = [];
1677
    foreach ($courses as $course) {
1678
        $courses_for_select[$course->id] = $course->fullname;
1679
    }
1680
1681
    return $courses_for_select;
1682
}
1683
1684
function bigbluebuttonbn_getRecordedMeetingsDeleted($courseID, $bigbluebuttonbnID = null)
1685
{
1686
    global $DB;
1687
1688
    $records_deleted = array();
1689
1690
    $filter = array('courseid' => $courseID, 'log' => BIGBLUEBUTTONBN_LOG_EVENT_DELETE);
1691
    if ($bigbluebuttonbnID != null) {
1692
        $filter['id'] = $bigbluebuttonbnID;
1693
    }
1694
1695
    $bigbluebuttonbns_deleted = $DB->get_records('bigbluebuttonbn_logs', $filter);
1696
1697
    foreach ($bigbluebuttonbns_deleted as $key => $bigbluebuttonbn_deleted) {
1698
        $records = $DB->get_records('bigbluebuttonbn_logs', array('courseid' => $courseID, 'log' => BIGBLUEBUTTONBN_LOG_EVENT_CREATE));
1699
1700
        if (!empty($records)) {
1701
            //Remove duplicates
1702
            $unique_records = array();
1703
            foreach ($records as $key => $record) {
1704
                if (array_key_exists($record->meetingid, $unique_records)) {
1705
                    unset($records[$key]);
1706
                } else {
1707
                    $meta = json_decode($record->meta);
1708
                    if (!$meta->record) {
1709
                        unset($records[$key]);
1710
                    } elseif ($bigbluebuttonbn_deleted->meetingid != substr($record->meetingid, 0, strlen($bigbluebuttonbn_deleted->meetingid))) {
1711
                        unset($records[$key]);
1712
                    } else {
1713
                        array_push($unique_records, $record->meetingid);
1714
                    }
1715
                }
1716
            }
1717
1718
            $records_deleted = array_merge($records_deleted, $records);
1719
        }
1720
    }
1721
1722
    return $records_deleted;
1723
}
1724
1725
function bigbluebuttonbn_getRecordedMeetings($courseID, $bigbluebuttonbnID = null)
1726
{
1727
    global $DB;
1728
1729
    $records = array();
1730
1731
    $filter = array('course' => $courseID);
1732
    if ($bigbluebuttonbnID != null) {
1733
        $filter['id'] = $bigbluebuttonbnID;
1734
    }
1735
    $bigbluebuttonbns = $DB->get_records('bigbluebuttonbn', $filter);
1736
1737
    if (!empty($bigbluebuttonbns)) {
1738
        $table = 'bigbluebuttonbn_logs';
1739
1740
        //Prepare select for loading records based on existent bigbluebuttonbns
1741
        $select = '';
1742
        foreach ($bigbluebuttonbns as $key => $bigbluebuttonbn) {
1743
            $select .= strlen($select) == 0 ? '(' : ' OR ';
1744
            $select .= 'bigbluebuttonbnid='.$bigbluebuttonbn->id;
1745
        }
1746
        $select .= ") AND log='".BIGBLUEBUTTONBN_LOG_EVENT_CREATE."'";
1747
1748
        //Execute select for loading records based on existent bigbluebuttonbns
1749
        $records = $DB->get_records_select($table, $select);
1750
1751
        //Remove duplicates
1752
        $unique_records = array();
1753
        foreach ($records as $key => $record) {
1754
            $record_key = $record->meetingid.','.$record->bigbluebuttonbnid.','.$record->meta;
1755
            if (array_search($record_key, $unique_records) === true) {
1756
                unset($records[$key]);
1757
                continue;
1758
            }
1759
            array_push($unique_records, $record_key);
1760
        }
1761
1762
        //Remove the ones with record=false
1763
        foreach ($records as $key => $record) {
1764
            $meta = json_decode($record->meta);
1765
            if (!$meta || !$meta->record) {
1766
                unset($records[$key]);
1767
            }
1768
        }
1769
    }
1770
1771
    return $records;
1772
}
1773
1774
function bigbluebutton_output_recording_table($bbbsession, $recordings, $tools = ['publishing', 'deleting'])
1775
{
1776
    if (isset($recordings) && !empty($recordings)) {  // There are recordings for this meeting
1777
        $table = bigbluebuttonbn_get_recording_table($bbbsession, $recordings, $tools);
1778
    }
1779
1780
    if (!isset($table) || !isset($table->data)) {
1781
        // Render a table qith "No recordings"
1782
        return html_writer::div(get_string('view_message_norecordings', 'bigbluebuttonbn'), '', array('id' => 'bigbluebuttonbn_html_table'));
1783
    }
1784
1785
    // Render the table
1786
    return html_writer::div(html_writer::table($table), '', array('id' => 'bigbluebuttonbn_html_table'));
1787
}
1788
1789
function bigbluebuttonbn_debugdisplay()
1790
{
1791
    global $CFG;
1792
1793
    return (bool) $CFG->debugdisplay;
1794
}
1795
1796
function bigbluebuttonbn_html2text($html, $len)
1797
{
1798
    $text = strip_tags($html);
1799
    $text = str_replace('&nbsp;', ' ', $text);
1800
    $text = substr($text, 0, $len);
1801
    if (strlen($text) > $len) {
1802
        $text .= '...';
1803
    }
1804
1805
    return $text;
1806
}
1807
1808
function bigbluebuttonbn_get_tags($id)
1809
{
1810
    $tags = '';
1811
    $tags_array = core_tag_tag::get_item_tags_array('core', 'course_modules', $id);
1812
    foreach ($tags_array as $tag) {
1813
        $tags .= ($tags == '') ? $tag : ','.$tag;
1814
    }
1815
1816
    return $tags;
1817
}
1818
1819
/**
1820
 * helper function to retrieve recordings from the BigBlueButton. The references are stored as events in bigbluebuttonbn_logs.
1821
 *
1822
 * @param string $courseID
1823
 * @param string $bigbluebuttonbnID
1824
 * @param bool   $subset
1825
 * @param bool   $include_deleted
1826
 *
1827
 * @return associative array containing the recordings indexed by recordID, each recording is also a non sequential associative array itself that corresponds to the actual recording in BBB
1828
 */
1829
function bigbluebuttonbn_get_recordings($courseID, $bigbluebuttonbnID = null, $subset = true, $include_deleted = false)
1830
{
1831
    global $DB;
1832
1833
    // Gather the bigbluebuttonbnids whose meetingids should be included in the getRecordings request
1834
    $select = "id <> '{$bigbluebuttonbnID}' AND course = '{$courseID}'";
1835
    $select_deleted = "courseid = '{$courseID}' AND bigbluebuttonbnid <> '{$bigbluebuttonbnID}' AND log = '".BIGBLUEBUTTONBN_LOG_EVENT_DELETE."' AND meta like '%has_recordings%' AND meta like '%true%'";
1836
    if ($bigbluebuttonbnID === null) {
1837
        $select = "course = '{$courseID}'";
1838
        $select_deleted = "courseid = '{$courseID}' AND log = '".BIGBLUEBUTTONBN_LOG_EVENT_DELETE."' AND meta like '%has_recordings%' AND meta like '%true%'";
1839
    } elseif ($subset) {
1840
        $select = "id = '{$bigbluebuttonbnID}'";
1841
        $select_deleted = "bigbluebuttonbnid = '{$bigbluebuttonbnID}' AND log = '".BIGBLUEBUTTONBN_LOG_EVENT_DELETE."' AND meta like '%has_recordings%' AND meta like '%true%'";
1842
    }
1843
    $bigbluebuttonbns = $DB->get_records_select_menu('bigbluebuttonbn', $select, null, 'id', 'id, meetingid');
1844
1845
    // Consider logs from deleted bigbluebuttonbn instances whose meetingids should be included in the getRecordings request
1846
    if ($include_deleted) {
1847
        $bigbluebuttonbns_del = $DB->get_records_select_menu('bigbluebuttonbn_logs', $select_deleted, null, 'bigbluebuttonbnid', 'bigbluebuttonbnid, meetingid');
1848
        if (!empty($bigbluebuttonbns_del)) {
1849
            // Merge bigbluebuttonbnis from deleted instances, only keys are relevant. Artimetic merge is used in order to keep the keys
1850
            $bigbluebuttonbns += $bigbluebuttonbns_del;
1851
        }
1852
    }
1853
1854
    // Gather the meetingids from bigbluebuttonbn logs that include a create with record=true
1855
    $recordings = array();
1856
    if (!empty($bigbluebuttonbns)) {
1857
        //Prepare select for loading records based on existent bigbluebuttonbns
1858
        $sql = 'SELECT DISTINCT meetingid, bigbluebuttonbnid FROM {bigbluebuttonbn_logs} WHERE ';
1859
        $sql .= '(bigbluebuttonbnid='.implode(' OR bigbluebuttonbnid=', array_keys($bigbluebuttonbns)).')';
1860
        //Include only Create events and exclude those with record not true
1861
        $sql .= ' AND log = ? AND meta LIKE ? AND meta LIKE ?';
1862
        //Execute select for loading records based on existent bigbluebuttonbns
1863
        $records = $DB->get_records_sql_menu($sql, array(BIGBLUEBUTTONBN_LOG_EVENT_CREATE, '%record%', '%true%'));
1864
        // Get actual recordings
1865
        $recordings = bigbluebuttonbn_getRecordingsArray(array_keys($records));
1866
    }
1867
1868
    // Get recording links
1869
    $recordings_imported = bigbluebuttonbn_getRecordingsImportedArray($courseID, $bigbluebuttonbnID, $subset);
1870
1871
    // Perform aritmetic add instead of merge so the imported recordings corresponding to existent recordings are not included
1872
    return $recordings + $recordings_imported;
1873
}
1874
1875
function bigbluebuttonbn_unset_existent_recordings_already_imported($recordings, $courseID, $bigbluebuttonbnID)
1876
{
1877
    $recordings_imported = bigbluebuttonbn_getRecordingsImportedArray($courseID, $bigbluebuttonbnID, true);
1878
1879
    foreach ($recordings as $key => $recording) {
1880
        if (isset($recordings_imported[$recording['recordID']])) {
1881
            unset($recordings[$key]);
1882
        }
1883
    }
1884
1885
    return $recordings;
1886
}
1887
1888
function bigbluebuttonbn_get_count_recording_imported_instances($recordID)
1889
{
1890
    global $DB;
1891
1892
    $sql = 'SELECT * FROM {bigbluebuttonbn_logs} WHERE log = ? AND meta LIKE ? AND meta LIKE ?';
1893
1894
    return $DB->count_records_sql($sql, array(BIGBLUEBUTTONBN_LOG_EVENT_IMPORT, '%recordID%', "%{$recordID}%"));
1895
}
1896
1897
function bigbluebuttonbn_get_recording_imported_instances($recordID)
1898
{
1899
    global $DB;
1900
1901
    $sql = 'SELECT * FROM {bigbluebuttonbn_logs} WHERE log = ? AND meta LIKE ? AND meta LIKE ?';
1902
    $recordings_imported = $DB->get_records_sql($sql, array(BIGBLUEBUTTONBN_LOG_EVENT_IMPORT, '%recordID%', "%{$recordID}%"));
1903
1904
    return $recordings_imported;
1905
}
1906
1907
function bigbluebuttonbn_get_instance_type_profiles()
1908
{
1909
    $instanceprofiles = array(
1910
            array('id' => BIGBLUEBUTTONBN_TYPE_ALL, 'name' => get_string('instance_type_default', 'bigbluebuttonbn'), 'features' => array('all')),
1911
            array('id' => BIGBLUEBUTTONBN_TYPE_ROOM_ONLY, 'name' => get_string('instance_type_room_only', 'bigbluebuttonbn'), 'features' => array('showroom', 'welcomemessage', 'voicebridge', 'waitformoderator', 'userlimit', 'recording', 'recordingtagging', 'sendnotifications', 'preuploadpresentation', 'permissions', 'schedule', 'groups')),
1912
            array('id' => BIGBLUEBUTTONBN_TYPE_RECORDING_ONLY, 'name' => get_string('instance_type_recording_only', 'bigbluebuttonbn'), 'features' => array('showrecordings', 'importrecordings')),
1913
    );
1914
1915
    return $instanceprofiles;
1916
}
1917
1918
function bigbluebuttonbn_get_instance_profiles_array($profiles = null)
1919
{
1920
    if (is_null($profiles) || empty($profiles)) {
1921
        $profiles = bigbluebuttonbn_get_instanceprofiles();
1922
    }
1923
1924
    $profiles_array = array();
1925
1926
    foreach ($profiles as $profile) {
1927
        $profiles_array += array("{$profile['id']}" => $profile['name']);
1928
    }
1929
1930
    return $profiles_array;
1931
}
1932
1933
function bigbluebuttonbn_format_activity_time($time)
1934
{
1935
    $activity_time = '';
1936
    if ($time) {
1937
        $activity_time = calendar_day_representation($time).' '.
1938
          get_string('mod_form_field_notification_msg_at', 'bigbluebuttonbn').' '.
1939
          calendar_time_representation($time);
1940
    }
1941
1942
    return $activity_time;
1943
}
1944
1945
function bigbluebuttonbn_recordings_enabled()
1946
{
1947
    global $BIGBLUEBUTTONBN_CFG;
1948
1949
    return !(isset($BIGBLUEBUTTONBN_CFG->bigbluebuttonbn_recording_default) &&
1950
             isset($BIGBLUEBUTTONBN_CFG->bigbluebuttonbn_recording_editable));
1951
}
1952