Completed
Pull Request — master (#33)
by Jesus
02:27
created

locallib.php ➔ bigbluebuttonbn_wrap_xml_load_file()   B

Complexity

Conditions 5
Paths 6

Size

Total Lines 41
Code Lines 28

Duplication

Lines 0
Ratio 0 %

Importance

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