Completed
Push — master ( 32c9ae...514091 )
by Jesus
04:47
created

locallib.php ➔ bigbluebuttonbn_event_log_standard()   B

Complexity

Conditions 5
Paths 9

Size

Total Lines 24
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 5
eloc 15
nc 9
nop 4
dl 0
loc 24
rs 8.5125
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_ACTIVITY_MANAGEMENT_VIEWED = 'activity_management_viewed';
45
const BIGBLUEBUTTON_EVENT_LIVE_SESSION = 'live_session';
46
const BIGBLUEBUTTON_EVENT_MEETING_CREATED = 'meeting_created';
47
const BIGBLUEBUTTON_EVENT_MEETING_ENDED = 'meeting_ended';
48
const BIGBLUEBUTTON_EVENT_MEETING_JOINED = 'meeting_joined';
49
const BIGBLUEBUTTON_EVENT_MEETING_LEFT = 'meeting_left';
50
const BIGBLUEBUTTON_EVENT_RECORDING_DELETED = 'recording_deleted';
51
const BIGBLUEBUTTON_EVENT_RECORDING_IMPORTED = 'recording_imported';
52
const BIGBLUEBUTTON_EVENT_RECORDING_PROTECTED = 'recording_protected';
53
const BIGBLUEBUTTON_EVENT_RECORDING_PUBLISHED = 'recording_published';
54
const BIGBLUEBUTTON_EVENT_RECORDING_UNPROTECTED = 'recording_unprotected';
55
const BIGBLUEBUTTON_EVENT_RECORDING_UNPUBLISHED = 'recording_unpublished';
56
const BIGBLUEBUTTON_EVENT_RECORDING_EDITED = 'recording_edited';
57
const BIGBLUEBUTTON_EVENT_RECORDING_VIEWED = 'recording_viewed';
58
59
function bigbluebuttonbn_logs(array $bbbsession, $event, array $overrides = [], $meta = null) {
60
    global $DB;
61
62
    $log = new stdClass();
63
64
    // Default values.
65
    $log->courseid = $bbbsession['course']->id;
66
    $log->bigbluebuttonbnid = $bbbsession['bigbluebuttonbn']->id;
67
    $log->userid = $bbbsession['userID'];
68
    $log->meetingid = $bbbsession['meetingid'];
69
    $log->timecreated = time();
70
    // Overrides.
71
    foreach ($overrides as $key => $value) {
72
        $log->$key = $value;
73
    }
74
75
    $log->log = $event;
76
    if (isset($meta)) {
77
        $log->meta = $meta;
78
    } else if ($event == BIGBLUEBUTTONBN_LOG_EVENT_CREATE) {
79
        $log->meta = '{"record":'.($bbbsession['record'] ? 'true' : 'false').'}';
80
    }
81
82
    $DB->insert_record('bigbluebuttonbn_logs', $log);
83
}
84
85
// BigBlueButton API Calls.
86
function bigbluebuttonbn_get_join_url($meetingid, $username, $pw, $logouturl, $configtoken = null, $userid = null) {
87
    $data = ['meetingID' => $meetingid,
88
              'fullName' => $username,
89
              'password' => $pw,
90
              'logoutURL' => $logouturl,
91
            ];
92
93
    if (!is_null($configtoken)) {
94
        $data['configToken'] = $configtoken;
95
    }
96
    if (!is_null($userid)) {
97
        $data['userID'] = $userid;
98
    }
99
100
    return bigbluebuttonbn_bigbluebutton_action_url('join', $data);
101
}
102
103
/**
104
 * @param string $recordid
105
 * @param array  $metadata
106
 */
107
function bigbluebuttonbn_get_update_recordings_url($recordid, $metadata = array()) {
108
    return bigbluebuttonbn_bigbluebutton_action_url('updateRecordings', ['recordID' => $recordid], $metadata);
109
}
110
111
/**
112
 * @param string $action
113
 * @param array  $data
114
 * @param array  $metadata
115
 */
116
function bigbluebuttonbn_bigbluebutton_action_url($action = '', $data = array(), $metadata = array()) {
117
    $baseurl = bigbluebuttonbn_get_cfg_server_url().'api/'.$action.'?';
118
    $params = '';
119
120
    foreach ($data as $key => $value) {
121
        $params .= '&'.$key.'='.urlencode($value);
122
    }
123
124
    foreach ($metadata as $key => $value) {
125
        $params .= '&'.'meta_'.$key.'='.urlencode($value);
126
    }
127
128
    return $baseurl.$params.'&checksum='.sha1($action.$params.bigbluebuttonbn_get_cfg_shared_secret());
129
}
130
131
function bigbluebuttonbn_get_create_meeting_array($data, $metadata = array(), $pname = null, $purl = null) {
132
    $createmeetingurl = bigbluebuttonbn_bigbluebutton_action_url('create', $data, $metadata);
133
    $method = BIGBLUEBUTTONBN_METHOD_GET;
134
    $data = null;
135
136
    if (!is_null($pname) && !is_null($purl)) {
137
        $method = BIGBLUEBUTTONBN_METHOD_POST;
138
        $data = "<?xml version='1.0' encoding='UTF-8'?><modules><module name='presentation'><document url='".
139
            $purl."' /></module></modules>";
140
    }
141
142
    $xml = bigbluebuttonbn_wrap_xml_load_file($createmeetingurl, $method, $data);
143
144
    if ($xml) {
145
        $response = array('returncode' => $xml->returncode, 'message' => $xml->message, 'messageKey' => $xml->messageKey);
146
        if ($xml->meetingID) {
147
            $response += array('meetingID' => $xml->meetingID, 'attendeePW' => $xml->attendeePW,
148
                'moderatorPW' => $xml->moderatorPW, 'hasBeenForciblyEnded' => $xml->hasBeenForciblyEnded);
149
        }
150
151
        return $response;
152
    }
153
154
    return null;
155
}
156
157
/**
158
 * @param string $meetingid
159
 */
160
function bigbluebuttonbn_get_meeting_array($meetingid) {
161
    $meetings = bigbluebuttonbn_get_meetings_array();
162
    if ($meetings) {
163
        foreach ($meetings as $meeting) {
164
            if ($meeting['meetingID'] == $meetingid) {
165
                return $meeting;
166
            }
167
        }
168
    }
169
170
    return null;
171
}
172
173
function bigbluebuttonbn_get_meetings_array() {
174
    $xml = bigbluebuttonbn_wrap_xml_load_file(bigbluebuttonbn_bigbluebutton_action_url('getMeetings'));
175
176
    if ($xml && $xml->returncode == 'SUCCESS' && empty($xml->messageKey)) {
177
        // Meetings were returned.
178
        $meetings = array();
179
        foreach ($xml->meetings->meeting as $meeting) {
180
            $meetings[] = array('meetingID' => $meeting->meetingID,
181
                                'moderatorPW' => $meeting->moderatorPW,
182
                                'attendeePW' => $meeting->attendeePW,
183
                                'hasBeenForciblyEnded' => $meeting->hasBeenForciblyEnded,
184
                                'running' => $meeting->running, );
185
        }
186
187
        return $meetings;
188
    }
189
190 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...
191
        // Either failure or success without meetings.
192
        return array('returncode' => $xml->returncode, 'message' => $xml->message, 'messageKey' => $xml->messageKey);
193
    }
194
195
    // If the server is unreachable, then prompts the user of the necessary action.
196
    return null;
197
}
198
199
/**
200
 * @param string $meetingid
201
 */
202
function bigbluebuttonbn_get_meeting_info_array($meetingid) {
203
    $xml = bigbluebuttonbn_wrap_xml_load_file(
204
        bigbluebuttonbn_bigbluebutton_action_url('getMeetingInfo', ['meetingID' => $meetingid])
205
      );
206
207
    if ($xml && $xml->returncode == 'SUCCESS' && empty($xml->messageKey)) {
208
        // Meeting info was returned.
209
        return array('returncode' => $xml->returncode,
210
                     'meetingID' => $xml->meetingID,
211
                     'moderatorPW' => $xml->moderatorPW,
212
                     'attendeePW' => $xml->attendeePW,
213
                     'hasBeenForciblyEnded' => $xml->hasBeenForciblyEnded,
214
                     'running' => $xml->running,
215
                     'recording' => $xml->recording,
216
                     'startTime' => $xml->startTime,
217
                     'endTime' => $xml->endTime,
218
                     'participantCount' => $xml->participantCount,
219
                     'moderatorCount' => $xml->moderatorCount,
220
                     'attendees' => $xml->attendees,
221
                     'metadata' => $xml->metadata,
222
                   );
223
    }
224
225 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...
226
        // Either failure or success without meeting info.
227
        return array('returncode' => $xml->returncode, 'message' => $xml->message, 'messageKey' => $xml->messageKey);
228
    }
229
230
    // If the server is unreachable, then prompts the user of the necessary action.
231
    return null;
232
}
233
234
/**
235
 * helper function to retrieve recordings from a BigBlueButton server.
236
 *
237
 * @param string or array $meetingids   list of meetingIDs "mid1,mid2,mid3" or array("mid1","mid2","mid3")
238
 * @param string or array $recordingids list of $recordingids "rid1,rid2,rid3" or array("rid1","rid2","rid3") for filtering
239
 *
240
 * @return associative array with recordings indexed by recordID, each recording is a non sequential associative array
241
 */
242
function bigbluebuttonbn_get_recordings_array($meetingids, $recordingids = []) {
243
244
    $meetingidsarray = $meetingids;
245
    if (!is_array($meetingids)) {
246
        $meetingidsarray = explode(',', $meetingids);
247
    }
248
249
    // If $meetingidsarray is empty there is no need to go further.
250
    if (empty($meetingidsarray)) {
251
        return array();
252
    }
253
254
    $recordings = bigbluebuttonbn_get_recordings_array_fetch($meetingidsarray);
255
256
    // Filter recordings based on recordingIDs.
257
    $recordingidsarray = $recordingids;
258
    if (!is_array($recordingids)) {
259
        $recordingidsarray = explode(',', $recordingids);
260
    }
261
262
    if (empty($recordingidsarray)) {
263
        // No recording ids, no need to filter.
264
        return $recordings;
265
    }
266
267
    return bigbluebuttonbn_get_recordings_array_filter($recordingidsarray, $recordings);
268
}
269
270
/**
271
 * helper function to fetch recordings from a BigBlueButton server.
272
 *
273
 * @param array $meetingidsarray   array with meeting ids in the form array("mid1","mid2","mid3")
274
 *
275
 * @return associative array with recordings indexed by recordID, each recording is a non sequential associative array
276
 */
277
function bigbluebuttonbn_get_recordings_array_fetch($meetingidsarray) {
278
279
    $recordings = array();
280
281
    // Execute a paginated getRecordings request.
282
    $pages = floor(count($meetingidsarray) / 25) + 1;
283
    for ($page = 1; $page <= $pages; ++$page) {
284
        $mids = array_slice($meetingidsarray, ($page - 1) * 25, 25);
285
        // Do getRecordings is executed using a method GET (supported by all versions of BBB).
286
        $xml = bigbluebuttonbn_wrap_xml_load_file(
287
            bigbluebuttonbn_bigbluebutton_action_url('getRecordings', ['meetingID' => implode(',', $mids)])
288
          );
289
        if ($xml && $xml->returncode == 'SUCCESS' && isset($xml->recordings)) {
290
            // If there were meetings already created.
291
            foreach ($xml->recordings->recording as $recording) {
292
                $recordingarrayvalue = bigbluebuttonbn_get_recording_array_value($recording);
293
                $recordings[$recordingarrayvalue['recordID']] = $recordingarrayvalue;
294
            }
295
            uasort($recordings, 'bigbluebuttonbn_recording_build_sorter');
296
        }
297
    }
298
299
    return $recordings;
300
}
301
302
function bigbluebuttonbn_get_recordings_array_filter($recordingidsarray, &$recordings) {
303
304
    foreach ($recordings as $key => $recording) {
305
        if (!in_array($recording['recordID'], $recordingidsarray)) {
306
            unset($recordings[$key]);
307
        }
308
    }
309
310
    return $recordings;
311
}
312
313
/**
314
 * Helper function to retrieve imported recordings from the Moodle database.
315
 * The references are stored as events in bigbluebuttonbn_logs.
316
 *
317
 * @param string $courseid
318
 * @param string $bigbluebuttonbnid
319
 * @param bool   $subset
320
 *
321
 * @return associative array with imported recordings indexed by recordID, each recording is a non sequential associative
322
 * array that corresponds to the actual recording in BBB
323
 */
324
function bigbluebuttonbn_get_recordings_imported_array($courseid, $bigbluebuttonbnid = null, $subset = true) {
325
    global $DB;
326
327
    $select = "courseid = '{$courseid}' AND bigbluebuttonbnid <> '{$bigbluebuttonbnid}' AND log = '".
328
        BIGBLUEBUTTONBN_LOG_EVENT_IMPORT."'";
329
    if ($bigbluebuttonbnid === null) {
330
        $select = "courseid = '{$courseid}' AND log = '".BIGBLUEBUTTONBN_LOG_EVENT_IMPORT."'";
331
    } else if ($subset) {
332
        $select = "bigbluebuttonbnid = '{$bigbluebuttonbnid}' AND log = '".BIGBLUEBUTTONBN_LOG_EVENT_IMPORT."'";
333
    }
334
    $recordsimported = $DB->get_records_select('bigbluebuttonbn_logs', $select);
335
336
    $recordsimportedarray = array();
337
    foreach ($recordsimported as $recordimported) {
338
        $meta = json_decode($recordimported->meta, true);
339
        $recording = $meta['recording'];
340
        $recordsimportedarray[$recording['recordID']] = $recording;
341
    }
342
343
    return $recordsimportedarray;
344
}
345
346
function bigbluebuttonbn_get_default_config_xml() {
347
    $xml = bigbluebuttonbn_wrap_xml_load_file(
348
        bigbluebuttonbn_bigbluebutton_action_url('getDefaultConfigXML')
349
      );
350
351
    return $xml;
352
}
353
354
function bigbluebuttonbn_get_default_config_xml_array() {
355
    $defaultconfigxml = bigbluebuttonbn_getDefaultConfigXML();
356
357
    return (array) $defaultconfigxml;
358
}
359
360
function bigbluebuttonbn_get_recording_array_value($recording) {
361
    // Add formats.
362
    $playbackarray = array();
363
    foreach ($recording->playback->format as $format) {
364
        $playbackarray[(string) $format->type] = array('type' => (string) $format->type,
365
            'url' => (string) $format->url, 'length' => (string) $format->length);
366
        // Add preview per format when existing.
367
        if ($format->preview) {
368
            $imagesarray = array();
369
            foreach ($format->preview->images->image as $image) {
370
                $imagearray = array('url' => (string) $image);
371
                foreach ($image->attributes() as $attkey => $attvalue) {
372
                    $imagearray[$attkey] = (string) $attvalue;
373
                }
374
                array_push($imagesarray, $imagearray);
375
            }
376
            $playbackarray[(string) $format->type]['preview'] = $imagesarray;
377
        }
378
    }
379
380
    // Add the metadata to the recordings array.
381
    $metadataarray = bigbluebuttonbn_get_recording_array_meta(get_object_vars($recording->metadata));
382
    return array('recordID' => (string) $recording->recordID,
383
        'meetingID' => (string) $recording->meetingID, 'meetingName' => (string) $recording->name,
384
        'published' => (string) $recording->published, 'startTime' => (string) $recording->startTime,
385
        'endTime' => (string) $recording->endTime, 'playbacks' => $playbackarray) + $metadataarray;
386
}
387
388
function bigbluebuttonbn_get_recording_array_meta($metadata) {
389
    $metadataarray = array();
390
    foreach ($metadata as $key => $value) {
391
        if (is_object($value)) {
392
            $value = '';
393
        }
394
        $metadataarray['meta_'.$key] = $value;
395
    }
396
    return $metadataarray;
397
}
398
399
function bigbluebuttonbn_recording_build_sorter($a, $b) {
400
    if ($a['startTime'] < $b['startTime']) {
401
        return -1;
402
    }
403
    if ($a['startTime'] == $b['startTime']) {
404
        return 0;
405
    }
406
    return 1;
407
}
408
409
/**
410
 * @param string $recordids
411
 */
412 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...
413
    $ids = explode(',', $recordids);
414
    foreach ($ids as $id) {
415
        $xml = bigbluebuttonbn_wrap_xml_load_file(
416
            bigbluebuttonbn_bigbluebutton_action_url('deleteRecordings', ['recordID' => $id])
417
          );
418
        if ($xml && $xml->returncode != 'SUCCESS') {
419
            return false;
420
        }
421
    }
422
423
    return true;
424
}
425
426
/**
427
 * @param string $recordids
428
 * @param string $publish
429
 */
430 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...
431
    $ids = explode(',', $recordids);
432
    foreach ($ids as $id) {
433
        $xml = bigbluebuttonbn_wrap_xml_load_file(
434
            bigbluebuttonbn_bigbluebutton_action_url('publishRecordings', ['recordID' => $id, 'publish' => $publish])
435
          );
436
        if ($xml && $xml->returncode != 'SUCCESS') {
437
            return false;
438
        }
439
    }
440
441
    return true;
442
}
443
444
/**
445
 * @param string $recordids
446
 * @param array $params ['key'=>param_key, 'value']
447
 */
448 View Code Duplication
function bigbluebuttonbn_update_recordings($recordids, $params) {
0 ignored issues
show
Duplication introduced by
This function seems to be duplicated in your project.

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

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

Loading history...
449
    $ids = explode(',', $recordids);
450
    foreach ($ids as $id) {
451
        $xml = bigbluebuttonbn_wrap_xml_load_file(
452
            bigbluebuttonbn_bigbluebutton_action_url('updateRecordings', ['recordID' => $id] + (array) $params)
453
          );
454
        if ($xml && $xml->returncode != 'SUCCESS') {
455
            return false;
456
        }
457
    }
458
459
    return true;
460
}
461
462
/**
463
 * @param string $recordids
464
 * @param string $bigbluebuttonbnid
465
 * @param array $params ['key'=>param_key, 'value']
466
 */
467
function bigbluebuttonbn_update_recording_imported($recordids, $bigbluebuttonbnid, $params) {
468
    $ids = explode(',', $recordids);
469
    foreach ($ids as $id) {
470
        if (!bigbluebuttonbn_update_recording_imported_perform($id, $bigbluebuttonbnid, $params)) {
471
            return false;
472
        }
473
    }
474
    return true;
475
}
476
477
/**
478
 * @param string $recordid
479
 * @param string $bigbluebuttonbnid
480
 * @param array $params ['key'=>param_key, 'value']
481
 */
482
function bigbluebuttonbn_update_recording_imported_perform($recordid, $bigbluebuttonbnid, $params) {
483
    global $DB;
484
485
    // Locate the record to be updated.
486
    $records = $DB->get_records('bigbluebuttonbn_logs', array('bigbluebuttonbnid' => $bigbluebuttonbnid,
487
        'log' => BIGBLUEBUTTONBN_LOG_EVENT_IMPORT));
488
489
    foreach ($records as $key => $record) {
490
        $meta = json_decode($record->meta, true);
491
        if ($recordid == $meta['recording']['recordID']) {
492
            // Found, prepare data for the update.
493
            $meta['recording'] = $params + $meta['recording'];
494
            $records[$key]->meta = json_encode($meta);
495
496
            // Proceed with the update.
497
            if (!$DB->update_record('bigbluebuttonbn_logs', $records[$key])) {
498
                return false;
499
            }
500
        }
501
    }
502
    return true;
503
}
504
505
/**
506
 * @param string $meetingid
507
 * @param string $modpw
508
 */
509
function bigbluebuttonbn_end_meeting($meetingid, $modpw) {
510
    $xml = bigbluebuttonbn_wrap_xml_load_file(
511
        bigbluebuttonbn_bigbluebutton_action_url('end', ['meetingID' => $meetingid, 'password' => $modpw])
512
      );
513
514 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...
515
        // If the xml packet returned failure it displays the message to the user.
516
        return array('returncode' => $xml->returncode, 'message' => $xml->message, 'messageKey' => $xml->messageKey);
517
    }
518
519
    // If the server is unreachable, then prompts the user of the necessary action.
520
    return null;
521
}
522
523
/**
524
 * @param string $meetingid
525
 */
526
function bigbluebuttonbn_is_meeting_running($meetingid) {
527
    $xml = bigbluebuttonbn_wrap_xml_load_file(
528
        bigbluebuttonbn_bigbluebutton_action_url('isMeetingRunning', ['meetingID' => $meetingid])
529
      );
530
531
    if ($xml && $xml->returncode == 'SUCCESS') {
532
        return ($xml->running == 'true');
533
    }
534
535
    return false;
536
}
537
538
function bigbluebuttonbn_get_server_version() {
539
    $xml = bigbluebuttonbn_wrap_xml_load_file(
540
        bigbluebuttonbn_bigbluebutton_action_url()
541
      );
542
543
    if ($xml && $xml->returncode == 'SUCCESS') {
544
        return $xml->version;
545
    }
546
547
    return null;
548
}
549
550
/**
551
 * @param string $url
552
 * @param string $data
553
 */
554
function bigbluebuttonbn_wrap_xml_load_file($url, $method = BIGBLUEBUTTONBN_METHOD_GET,
555
    $data = null, $contenttype = 'text/xml') {
556
557
    //debugging('Request to: '.$url, DEBUG_DEVELOPER);
0 ignored issues
show
Unused Code Comprehensibility introduced by
60% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
558
559
    if (extension_loaded('curl')) {
560
        $response = bigbluebuttonbn_wrap_xml_load_file_curl_request($url, $method, $data, $contenttype);
561
562
        if (!$response) {
563
            //debugging('No response on wrap_simplexml_load_file', DEBUG_DEVELOPER);
0 ignored issues
show
Unused Code Comprehensibility introduced by
63% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
564
            return null;
565
        }
566
567
        //debugging('Response: '.$response, DEBUG_DEVELOPER);
0 ignored issues
show
Unused Code Comprehensibility introduced by
60% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
568
569
        $previous = libxml_use_internal_errors(true);
570
        try {
571
            $xml = simplexml_load_string($response, 'SimpleXMLElement', LIBXML_NOCDATA | LIBXML_NOBLANKS);
572
573
            return $xml;
574
        } catch (Exception $e) {
575
            libxml_use_internal_errors($previous);
576
            //$error = 'Caught exception: '.$e->getMessage();
0 ignored issues
show
Unused Code Comprehensibility introduced by
59% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
577
            //debugging($error, DEBUG_DEVELOPER);
0 ignored issues
show
Unused Code Comprehensibility introduced by
63% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
578
            return null;
579
        }
580
    }
581
582
    // Alternative request non CURL based.
583
    $previous = libxml_use_internal_errors(true);
584
    try {
585
        $response = simplexml_load_file($url, 'SimpleXMLElement', LIBXML_NOCDATA | LIBXML_NOBLANKS);
586
        //debugging('Response processed: '.$response->asXML(), DEBUG_DEVELOPER);
0 ignored issues
show
Unused Code Comprehensibility introduced by
65% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
587
        return $response;
588
    } catch (Exception $e) {
589
        //$error = 'Caught exception: '.$e->getMessage();
0 ignored issues
show
Unused Code Comprehensibility introduced by
59% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
590
        //debugging($error, DEBUG_DEVELOPER);
0 ignored issues
show
Unused Code Comprehensibility introduced by
63% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
591
        libxml_use_internal_errors($previous);
592
        return null;
593
    }
594
}
595
596
function bigbluebuttonbn_wrap_xml_load_file_curl_request($url, $method = BIGBLUEBUTTONBN_METHOD_GET,
597
    $data = null, $contenttype = 'text/xml') {
598
    $c = new curl();
599
    $c->setopt(array('SSL_VERIFYPEER' => true));
600
    if ($method == BIGBLUEBUTTONBN_METHOD_POST) {
601
        if (is_null($data) || is_array($data)) {
602
            return $c->post($url);
603
        }
604
605
        $options = array();
606
        $options['CURLOPT_HTTPHEADER'] = array(
607
                 'Content-Type: '.$contenttype,
608
                 'Content-Length: '.strlen($data),
609
                 'Content-Language: en-US',
610
               );
611
612
        return $c->post($url, $data, $options);
613
    }
614
615
    return $c->get($url);
616
}
617
618
function bigbluebuttonbn_get_user_roles($context, $userid) {
619
    global $DB;
620
621
    $userroles = get_user_roles($context, $userid);
622
    if ($userroles) {
623
        $where = '';
624
        foreach ($userroles as $value) {
625
            $where .= (empty($where) ? ' WHERE' : ' AND').' id='.$value->roleid;
626
        }
627
        $userroles = $DB->get_records_sql('SELECT * FROM {role}'.$where);
628
    }
629
630
    return $userroles;
631
}
632
633
function bigbluebuttonbn_get_guest_role() {
634
    $guestrole = get_guest_role();
635
636
    return array($guestrole->id => $guestrole);
637
}
638
639
function bigbluebuttonbn_get_users(context $context = null) {
640
    $users = (array) get_enrolled_users($context);
641
    foreach ($users as $key => $value) {
642
        $users[$key] = fullname($value);
643
    }
644
    return $users;
645
}
646
647
function bigbluebuttonbn_get_users_select(context $context = null) {
648
    $users = (array) get_enrolled_users($context);
649
    foreach ($users as $key => $value) {
650
        $users[$key] = array('id' => $value->id, 'name' => fullname($value));
651
    }
652
    return $users;
653
}
654
655
function bigbluebuttonbn_get_roles(context $context = null) {
656
    $roles = (array) role_get_names($context);
657
    foreach ($roles as $key => $value) {
658
        $roles[$key] = $value->localname;
659
    }
660
    return $roles;
661
}
662
663
function bigbluebuttonbn_get_roles_select(context $context = null) {
664
    $roles = (array) role_get_names($context);
665
    foreach ($roles as $key => $value) {
666
        $roles[$key] = array('id' => $value->id, 'name' => $value->localname);
667
    }
668
    return $roles;
669
 }
670
671
function bigbluebuttonbn_get_role($id) {
672
    $roles = (array) role_get_names();
673
    if (is_numeric($id)) {
674
        return $roles[$id];
675
    }
676
677
    foreach ($roles as $role) {
678
        if ($role->shortname == $id) {
679
            return $role;
680
        }
681
    }
682
}
683
684
function bigbluebuttonbn_get_participant_data($context) {
685
    $data = array(
686
        'all' => array(
687
            'name' => get_string('mod_form_field_participant_list_type_all', 'bigbluebuttonbn'),
688
            'children' => []
689
          )
690
      );
691
692
    $data['role'] = array(
693
        'name' => get_string('mod_form_field_participant_list_type_role', 'bigbluebuttonbn'),
694
        'children' => bigbluebuttonbn_get_roles_select($context)
695
      );
696
697
    $data['user'] = array(
698
        'name' => get_string('mod_form_field_participant_list_type_user', 'bigbluebuttonbn'),
699
        'children' => bigbluebuttonbn_get_users_select($context)
700
      );
701
702
    return $data;
703
}
704
705
function bigbluebuttonbn_get_participant_list($bigbluebuttonbn, $context) {
706
    if ($bigbluebuttonbn == null) {
707
        return bigbluebuttonbn_get_participant_list_default($context);
708
    }
709
710
    return bigbluebuttonbn_get_participant_rules_encoded($bigbluebuttonbn);
711
}
712
713
function bigbluebuttonbn_get_participant_rules_encoded($bigbluebuttonbn) {
714
    $rules = json_decode($bigbluebuttonbn->participants, true);
715
    foreach ($rules as $key => $rule) {
716
        if ($rule['selectiontype'] === 'role' && !is_numeric($rule['selectionid'])) {
717
            $role = bigbluebuttonbn_get_role($rule['selectionid']);
718
            $rule['selectionid'] = $role->id;
719
        }
720
        $rules[$key] = $rule;
721
    }
722
    return $rules;
723
}
724
725
function bigbluebuttonbn_get_participant_list_default($context) {
726
    global $USER;
727
728
    $participantlistarray = array();
729
    $participantlistarray[] = array(
730
        'selectiontype' => 'all',
731
        'selectionid' => 'all',
732
        'role' => BIGBLUEBUTTONBN_ROLE_VIEWER);
733
734
    $moderatordefaults = explode(',', bigbluebuttonbn_get_cfg_moderator_default());
735
    foreach ($moderatordefaults as $moderatordefault) {
736
        if ($moderatordefault == 'owner') {
737
            if (is_enrolled($context, $USER->id)) {
738
                $participantlistarray[] = array(
739
                    'selectiontype' => 'user',
740
                    'selectionid' => $USER->id,
741
                    'role' => BIGBLUEBUTTONBN_ROLE_MODERATOR);
742
            }
743
            continue;
744
        }
745
746
        $participantlistarray[] = array(
747
              'selectiontype' => 'role',
748
              'selectionid' => $moderatordefault,
749
              'role' => BIGBLUEBUTTONBN_ROLE_MODERATOR);
750
    }
751
752
    return $participantlistarray;
753
}
754
755
function bigbluebuttonbn_get_participant_selection_data() {
756
    return [
757
        'type_options' => [
758
            'all' => get_string('mod_form_field_participant_list_type_all', 'bigbluebuttonbn'),
759
            'role' => get_string('mod_form_field_participant_list_type_role', 'bigbluebuttonbn'),
760
            'user' => get_string('mod_form_field_participant_list_type_user', 'bigbluebuttonbn'),
761
          ],
762
        'type_selected' => 'all',
763
        'options' => ['all' => '---------------'],
764
        'selected' => 'all',
765
      ];
766
}
767
768
function bigbluebuttonbn_is_moderator($context, $participants, $userid = null, $userroles = null) {
769
    global $USER;
770
771
    if (empty($userid)) {
772
        $userid = $USER->id;
773
    }
774
775
    if (empty($userroles)) {
776
        $userroles = get_user_roles($context, $userid, true);
777
    }
778
779
    if (empty($participants)) {
780
        // The room that is being used comes from a previous version.
781
        return has_capability('mod/bigbluebuttonbn:moderate', $context);
782
    }
783
784
    $participantlist = json_decode($participants);
785
    // Iterate participant rules.
786
    foreach ($participantlist as $participant) {
787
        if (bigbluebuttonbn_is_moderator_rule_validation($participant, $userid, $userroles)) {
788
            return true;
789
        }
790
    }
791
792
    return false;
793
}
794
795
function bigbluebuttonbn_is_moderator_rule_validation($participant, $userid, $userroles) {
796
797
    if ($participant->role == BIGBLUEBUTTONBN_ROLE_VIEWER) {
798
        return false;
799
    }
800
801
    // Looks for all configuration.
802
    if ($participant->selectiontype == 'all') {
803
        return true;
804
    }
805
806
    // Looks for users.
807
    if ($participant->selectiontype == 'user' && $participant->selectionid == $userid) {
808
        return true;
809
    }
810
811
    // Looks for roles.
812
    $role = bigbluebuttonbn_get_role($participant->selectionid);
813
    if (array_key_exists($role->id, $userroles)) {
814
        return true;
815
    }
816
817
    return false;
818
}
819
820
function bigbluebuttonbn_get_error_key($messagekey, $defaultkey = null) {
821
    if ($messagekey == 'checksumError') {
822
        return 'index_error_checksum';
823
    }
824
    if ($messagekey == 'maxConcurrent') {
825
        return 'view_error_max_concurrent';
826
    }
827
    return $defaultkey;
828
}
829
830
function bigbluebuttonbn_voicebridge_unique($voicebridge, $id = null) {
831
    global $DB;
832
833
    $isunique = true;
834
    if ($voicebridge != 0) {
835
        $table = 'bigbluebuttonbn';
836
        $select = 'voicebridge = '.$voicebridge;
837
        if ($id) {
838
            $select .= ' AND id <> '.$id;
839
        }
840
        if ($DB->get_records_select($table, $select)) {
841
            $isunique = false;
842
        }
843
    }
844
845
    return $isunique;
846
}
847
848
function bigbluebuttonbn_get_duration($closingtime) {
849
    $duration = 0;
850
    $now = time();
851
    if ($closingtime > 0 && $now < $closingtime) {
852
        $duration = ceil(($closingtime - $now) / 60);
853
        $compensationtime = intval(bigbluebuttonbn_get_cfg_scheduled_duration_compensation());
854
        $duration = intval($duration) + $compensationtime;
855
    }
856
857
    return $duration;
858
}
859
860
function bigbluebuttonbn_get_presentation_array($context, $presentation, $id = null) {
861
    $pname = null;
862
    $purl = null;
863
    $picon = null;
864
    $pmimetypedescrip = null;
865
866
    if (!empty($presentation)) {
867
        $fs = get_file_storage();
868
        $files = $fs->get_area_files($context->id, 'mod_bigbluebuttonbn', 'presentation', 0,
869
            'itemid, filepath, filename', false);
870
        if (count($files) >= 1) {
871
            $file = reset($files);
872
            unset($files);
873
            $pname = $file->get_filename();
874
            $picon = file_file_icon($file, 24);
875
            $pmimetypedescrip = get_mimetype_description($file);
876
            $pnoncevalue = null;
877
878
            if (!is_null($id)) {
879
                // Create the nonce component for granting a temporary public access.
880
                $cache = cache::make_from_params(cache_store::MODE_APPLICATION, 'mod_bigbluebuttonbn',
881
                    'presentation_cache');
882
                $pnoncekey = sha1($id);
883
                /* The item id was adapted for granting public access to the presentation once in order
884
                 * to allow BigBlueButton to gather the file. */
885
                $pnoncevalue = bigbluebuttonbn_generate_nonce();
886
                $cache->set($pnoncekey, array('value' => $pnoncevalue, 'counter' => 0));
887
            }
888
            $url = moodle_url::make_pluginfile_url($file->get_contextid(), $file->get_component(),
889
                $file->get_filearea(), $pnoncevalue, $file->get_filepath(), $file->get_filename());
890
891
            $purl = $url->out(false);
892
        }
893
    }
894
895
    $parray = array('url' => $purl, 'name' => $pname,
896
                               'icon' => $picon,
897
                               'mimetype_description' => $pmimetypedescrip);
898
899
    return $parray;
900
}
901
902
function bigbluebuttonbn_generate_nonce() {
903
    $mt = microtime();
904
    $rand = mt_rand();
905
906
    return md5($mt.$rand);
907
}
908
909
function bigbluebuttonbn_random_password($length = 8) {
910
    $chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*()_-=+;:,.?';
911
    $password = substr(str_shuffle($chars), 0, $length);
912
913
    return $password;
914
}
915
916
function bigbluebuttonbn_get_moodle_version_major() {
917
    global $CFG;
918
919
    $versionarray = explode('.', $CFG->version);
920
921
    return $versionarray[0];
922
}
923
924
function bigbluebuttonbn_events() {
925
    return array(
926
        (string) BIGBLUEBUTTON_EVENT_ACTIVITY_VIEWED,
927
        (string) BIGBLUEBUTTON_EVENT_ACTIVITY_MANAGEMENT_VIEWED,
928
        (string) BIGBLUEBUTTON_EVENT_LIVE_SESSION,
929
        (string) BIGBLUEBUTTON_EVENT_MEETING_CREATED,
930
        (string) BIGBLUEBUTTON_EVENT_MEETING_ENDED,
931
        (string) BIGBLUEBUTTON_EVENT_MEETING_JOINED,
932
        (string) BIGBLUEBUTTON_EVENT_MEETING_LEFT,
933
        (string) BIGBLUEBUTTON_EVENT_RECORDING_DELETED,
934
        (string) BIGBLUEBUTTON_EVENT_RECORDING_IMPORTED,
935
        (string) BIGBLUEBUTTON_EVENT_RECORDING_PROTECTED,
936
        (string) BIGBLUEBUTTON_EVENT_RECORDING_PUBLISHED,
937
        (string) BIGBLUEBUTTON_EVENT_RECORDING_UNPROTECTED,
938
        (string) BIGBLUEBUTTON_EVENT_RECORDING_UNPUBLISHED,
939
        (string) BIGBLUEBUTTON_EVENT_RECORDING_EDITED,
940
        (string) BIGBLUEBUTTON_EVENT_RECORDING_VIEWED
941
    );
942
}
943
944
function bigbluebuttonbn_events_action() {
945
    return array(
946
        'view' => (string) BIGBLUEBUTTON_EVENT_ACTIVITY_VIEWED,
947
        'view_management' => (string) BIGBLUEBUTTON_EVENT_ACTIVITY_MANAGEMENT_VIEWED,
948
        'live_action' => (string) BIGBLUEBUTTON_EVENT_LIVE_SESSION,
949
        'meeting_create' => (string) BIGBLUEBUTTON_EVENT_MEETING_CREATED,
950
        'meeting_end' => (string) BIGBLUEBUTTON_EVENT_MEETING_ENDED,
951
        'meeting_join' => (string) BIGBLUEBUTTON_EVENT_MEETING_JOINED,
952
        'meeting_left' => (string) BIGBLUEBUTTON_EVENT_MEETING_LEFT,
953
        'recording_delete' => (string) BIGBLUEBUTTON_EVENT_RECORDING_DELETED,
954
        'recording_import' => (string) BIGBLUEBUTTON_EVENT_RECORDING_IMPORTED,
955
        'recording_protect' => (string) BIGBLUEBUTTON_EVENT_RECORDING_PROTECTED,
956
        'recording_publish' => (string) BIGBLUEBUTTON_EVENT_RECORDING_PUBLISHED,
957
        'recording_unprotect' => (string) BIGBLUEBUTTON_EVENT_RECORDING_UNPROTECTED,
958
        'recording_unpublish' => (string) BIGBLUEBUTTON_EVENT_RECORDING_UNPUBLISHED,
959
        'recording_edit' => (string) BIGBLUEBUTTON_EVENT_RECORDING_EDITED,
960
        'recording_play' => (string) BIGBLUEBUTTON_EVENT_RECORDING_VIEWED
961
    );
962
}
963
964
function bigbluebuttonbn_event_log_standard($eventtype, $bigbluebuttonbn, $cm, $options = []) {
965
966
    $events = bigbluebuttonbn_events();
967
    if (!in_array($eventtype, $events)) {
968
        // No log will be created.
969
        return;
970
    }
971
972
    $context = context_module::instance($cm->id);
973
    $eventproperties = array('context' => $context, 'objectid' => $bigbluebuttonbn->id);
974
    if (array_key_exists('timecreated', $options)) {
975
        $eventproperties['timecreated'] = $options['timecreated'];
976
    }
977
    if (array_key_exists('userid', $options)) {
978
        $eventproperties['userid'] = $options['userid'];
979
    }
980
    if (array_key_exists('other', $options)) {
981
        $eventproperties['other'] = $options['other'];
982
    }
983
984
    $event = call_user_func_array('\mod_bigbluebuttonbn\event\bigbluebuttonbn_'.$eventtype.'::create',
985
      array($eventproperties));
986
    $event->trigger();
987
}
988
989
function bigbluebuttonbn_event_log($eventtype, $bigbluebuttonbn, $cm, $options = []) {
990
    bigbluebuttonbn_event_log_standard($eventtype, $bigbluebuttonbn, $cm, $options);
991
}
992
993
function bigbluebuttonbn_live_session_event_log($event, $bigbluebuttonbn, $cm) {
994
    bigbluebuttonbn_event_log_standard(BIGBLUEBUTTON_EVENT_LIVE_SESSION, $bigbluebuttonbn, $cm,
995
        ['timecreated' => $event->timestamp, 'userid' => $event->user, 'other' => $event->event]);
996
997
}
998
999
/**
1000
 * @param string $meetingid
1001
 * @param bool $ismoderator
1002
 */
1003
function bigbluebuttonbn_participant_joined($meetingid, $ismoderator) {
1004
    $cache = cache::make_from_params(cache_store::MODE_APPLICATION, 'mod_bigbluebuttonbn', 'meetings_cache');
1005
    $result = $cache->get($meetingid);
1006
    $meetinginfo = json_decode($result['meeting_info']);
1007
    $meetinginfo->participantCount += 1;
1008
    if ($ismoderator) {
1009
        $meetinginfo->moderatorCount += 1;
1010
    }
1011
    $cache->set($meetingid, array('creation_time' => $result['creation_time'],
1012
        'meeting_info' => json_encode($meetinginfo)));
1013
}
1014
1015
/**
1016
 * @param string $meetingid
1017
 * @param boolean $forced
1018
 */
1019
function bigbluebuttonbn_get_meeting_info($meetingid, $forced = false) {
1020
    $cachettl = bigbluebuttonbn_get_cfg_waitformoderator_cache_ttl();
1021
1022
    $cache = cache::make_from_params(cache_store::MODE_APPLICATION, 'mod_bigbluebuttonbn', 'meetings_cache');
1023
    $result = $cache->get($meetingid);
1024
    $now = time();
1025
    if (!$forced && isset($result) && $now < ($result['creation_time'] + $cachettl)) {
1026
        // Use the value in the cache.
1027
        return (array) json_decode($result['meeting_info']);
1028
    }
1029
1030
    // Ping again and refresh the cache.
1031
    $meetinginfo = (array) bigbluebuttonbn_wrap_xml_load_file(
1032
        bigbluebuttonbn_bigbluebutton_action_url('getMeetingInfo', ['meetingID' => $meetingid])
1033
      );
1034
    $cache->set($meetingid, array('creation_time' => time(), 'meeting_info' => json_encode($meetinginfo)));
1035
1036
    return $meetinginfo;
1037
}
1038
1039
/**
1040
 * @param string $recordingid
1041
 * @param string $bigbluebuttonbnid
1042
 * @param boolean $publish
1043
 */
1044
function bigbluebuttonbn_publish_recording_imported($recordingid, $bigbluebuttonbnid, $publish = true) {
1045
    global $DB;
1046
1047
    // Locate the record to be updated.
1048
    $records = $DB->get_records('bigbluebuttonbn_logs', array('bigbluebuttonbnid' => $bigbluebuttonbnid,
1049
        'log' => BIGBLUEBUTTONBN_LOG_EVENT_IMPORT));
1050
1051
    foreach ($records as $key => $record) {
1052
        $meta = json_decode($record->meta, true);
1053
        if ($recordingid == $meta['recording']['recordID']) {
1054
            // Found, prepare data for the update.
1055
            $meta['recording']['published'] = ($publish) ? 'true' : 'false';
1056
            $records[$key]->meta = json_encode($meta);
1057
1058
            // Proceed with the update.
1059
            $DB->update_record('bigbluebuttonbn_logs', $records[$key]);
1060
        }
1061
    }
1062
}
1063
1064
function bigbluebuttonbn_delete_recording_imported($recordingid, $bigbluebuttonbnid) {
1065
    global $DB;
1066
1067
    // Locate the record to be updated.
1068
    $records = $DB->get_records('bigbluebuttonbn_logs', array('bigbluebuttonbnid' => $bigbluebuttonbnid,
1069
        'log' => BIGBLUEBUTTONBN_LOG_EVENT_IMPORT));
1070
1071
    foreach ($records as $key => $record) {
1072
        $meta = json_decode($record->meta, true);
1073
        if ($recordingid == $meta['recording']['recordID']) {
1074
            // Execute delete.
1075
            $DB->delete_records('bigbluebuttonbn_logs', array('id' => $key));
1076
        }
1077
    }
1078
}
1079
1080
/**
1081
 * @param string $meetingid
1082
 * @param string $configxml
1083
 */
1084
function bigbluebuttonbn_set_config_xml_params($meetingid, $configxml) {
1085
    $params = 'configXML='.urlencode($configxml).'&meetingID='.urlencode($meetingid);
1086
    $configxmlparams = $params.'&checksum='.sha1('setConfigXML'.$params.bigbluebuttonbn_get_cfg_shared_secret());
1087
1088
    return $configxmlparams;
1089
}
1090
1091
/**
1092
 * @param string $meetingid
1093
 * @param string $configxml
1094
 */
1095
function bigbluebuttonbn_set_config_xml($meetingid, $configxml) {
1096
    $urldefaultconfig = bigbluebuttonbn_get_cfg_server_url().'api/setConfigXML?';
1097
    $configxmlparams = bigbluebuttonbn_set_config_xml_params($meetingid, $configxml);
1098
    $xml = bigbluebuttonbn_wrap_xml_load_file($urldefaultconfig, BIGBLUEBUTTONBN_METHOD_POST,
1099
        $configxmlparams, 'application/x-www-form-urlencoded');
1100
1101
    return $xml;
1102
}
1103
1104
/**
1105
 * @param string $meetingid
1106
 * @param string $configxml
1107
 */
1108
function bigbluebuttonbn_set_config_xml_array($meetingid, $configxml) {
1109
    $configxml = bigbluebuttonbn_setConfigXML($meetingid, $configxml);
1110
    $configxmlarray = (array) $configxml;
1111
    if ($configxmlarray['returncode'] != 'SUCCESS') {
1112
        //debugging('BigBlueButton was not able to set the custom config.xml file', DEBUG_DEVELOPER);
0 ignored issues
show
Unused Code Comprehensibility introduced by
63% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
1113
        return '';
1114
    }
1115
1116
    return $configxmlarray['configToken'];
1117
}
1118
1119
function bigbluebuttonbn_get_recording_data_row($bbbsession, $recording, $tools = ['publishing', 'deleting']) {
1120
    global $USER;
1121
1122
    $row = null;
1123
1124
    $managerecordings = $bbbsession['managerecordings'];
1125
    if ($managerecordings || $recording['published'] == 'true') {
1126
        $row = new stdClass();
1127
1128
        // Set recording_types.
1129
        $row->recording = bigbluebuttonbn_get_recording_data_row_types($recording, $bbbsession['bigbluebuttonbn']->id);
1130
1131
        // Set activity name and description.
1132
        $row->activity = bigbluebuttonbn_get_recording_data_row_meta_activity($recording, $managerecordings);
1133
        $row->description = bigbluebuttonbn_get_recording_data_row_meta_description($recording, $managerecordings);
1134
1135
        // Set recording_preview.
1136
        $row->preview = bigbluebuttonbn_get_recording_data_row_preview($recording);
1137
1138
        // Set date.
1139
        $starttime = 0;
1140
        if (isset($recording['startTime'])) {
1141
            $starttime = floatval($recording['startTime']);
1142
        }
1143
        $row->date = $starttime;
1144
        $starttime = $starttime - ($starttime % 1000);
1145
1146
        // Set formatted date.
1147
        $dateformat = get_string('strftimerecentfull', 'langconfig').' %Z';
1148
        $row->date_formatted = userdate($starttime / 1000, $dateformat, usertimezone($USER->timezone));
1149
1150
        // Set formatted duration.
1151
        $firstplayback = array_values($recording['playbacks'])[0];
1152
        $length = isset($firstplayback['length']) ? $firstplayback['length'] : 0;
1153
        $row->duration_formatted = $row->duration = intval($length);
1154
1155
        // Set actionbar, if user is allowed to manage recordings.
1156
        if ($managerecordings) {
1157
            $row->actionbar = bigbluebuttonbn_get_recording_data_row_actionbar($recording, $tools);
1158
        }
1159
    }
1160
1161
    return $row;
1162
}
1163
1164
function bigbluebuttonbn_get_recording_data_row_actionbar($recording, $tools) {
1165
1166
    $actionbar = '';
1167
    foreach ($tools as $tool) {
1168
        $actionbar .= bigbluebuttonbn_actionbar_render_button(
1169
            $recording,
1170
            bigbluebuttonbn_get_recording_data_row_actionbar_payload($recording, $tool)
1171
          );
1172
    }
1173
1174
    $head = html_writer::start_tag('div', array(
1175
        'id' => 'recording-actionbar-' . $recording['recordID'],
1176
        'data-recordingid' => $recording['recordID'],
1177
        'data-meetingid' => $recording['meetingID']));
1178
    $tail = html_writer::end_tag('div');
1179
    return $head . $actionbar . $tail;
1180
}
1181
1182
function bigbluebuttonbn_get_recording_data_row_action_protect($protected) {
1183
    if ($protected == 'true') {
1184
        return array('action' => 'unprotect', 'tag' => 'unprotect');
1185
    }
1186
1187
    return array('action' => 'protect', 'tag' => 'protect');
1188
}
1189
1190
function bigbluebuttonbn_get_recording_data_row_action_publish($published) {
1191
    if ($published == 'true') {
1192
        return array('action' => 'unpublish', 'tag' => 'hide');
1193
    }
1194
1195
    return array('action' => 'publish', 'tag' => 'show');
1196
}
1197
1198
function bigbluebuttonbn_get_recording_data_row_actionbar_payload($recording, $tool) {
1199
    if ($tool == 'protecting' && isset($recording['protected'])) {
1200
        return bigbluebuttonbn_get_recording_data_row_action_protect($recording['protected']);
1201
    }
1202
1203
    if ($tool == 'publishing') {
1204
        return bigbluebuttonbn_get_recording_data_row_action_publish($recording['published']);
1205
    }
1206
1207
    if ($tool == 'deleting') {
1208
        return array('action' => 'delete', 'tag' => 'delete');
1209
    }
1210
1211
    return array('action' => 'import', 'tag' => 'import');
1212
}
1213
1214
function bigbluebuttonbn_get_recording_data_row_preview($recording) {
1215
1216
    $visibility = '';
1217
    if ($recording['published'] === 'false') {
1218
        $visibility = 'hidden ';
1219
    }
1220
1221
    $recordingpreview = html_writer::start_tag('div',
1222
        array('id' => 'preview-'.$recording['recordID'], $visibility => $visibility));
1223
    foreach ($recording['playbacks'] as $playback) {
1224
        if (isset($playback['preview'])) {
1225
            foreach ($playback['preview'] as $image) {
1226
                $recordingpreview .= html_writer::empty_tag('img',
1227
                    array('src' => $image['url'] . '?' . time(), 'class' => 'thumbnail'));
1228
            }
1229
            $recordingpreview .= html_writer::empty_tag('br');
1230
            $recordingpreview .= html_writer::tag('div',
1231
                get_string('view_recording_preview_help', 'bigbluebuttonbn'), array('class' => 'text-muted small'));
1232
            break;
1233
        }
1234
    }
1235
    $recordingpreview .= html_writer::end_tag('div');
1236
1237
    return $recordingpreview;
1238
}
1239
1240
function bigbluebuttonbn_get_recording_data_row_types($recording, $bigbluebuttonbnid) {
1241
    global $CFG, $OUTPUT;
1242
1243
    $dataimported = 'false';
1244
    $title = '';
1245
    if (isset($recording['imported'])) {
1246
        $dataimported = 'true';
1247
        $title = get_string('view_recording_link_warning', 'bigbluebuttonbn');
1248
    }
1249
1250
    $visibility = '';
1251
    if ($recording['published'] === 'false') {
1252
        $visibility = 'hidden ';
1253
    }
1254
1255
    $id = 'playbacks-'.$recording['recordID'];
1256
    $recordingtypes = html_writer::start_tag('div', array('id' => $id, 'data-imported' => $dataimported,
1257
          'data-recordingid' => $recording['recordID'], 'data-meetingid' => $recording['meetingID'],
1258
          'title' => $title, $visibility => $visibility));
1259
    foreach ($recording['playbacks'] as $playback) {
1260
        $onclick = 'M.mod_bigbluebuttonbn.recordings.recording_play(this);';
1261
        $href = $CFG->wwwroot.'/mod/bigbluebuttonbn/bbb_view.php?action=playback&bn='.$bigbluebuttonbnid.
1262
            '&href='.urlencode($playback['url']).'&rid='.$recording['recordID'];
1263
        //$href = $playback['url'];
0 ignored issues
show
Unused Code Comprehensibility introduced by
67% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
1264
        $linkattributes = array('title' => get_string('view_recording_format_'.$playback['type'], 'bigbluebuttonbn'),
1265
            'class' => 'btn btn-sm btn-default', 'onclick' => $onclick,
1266
            'data-action' => 'play', 'data-href' => $href);
1267
        $recordingtypes .= $OUTPUT->action_link('#', get_string('view_recording_format_'.$playback['type'],
1268
            'bigbluebuttonbn'), null, $linkattributes).'&#32;';
1269
    }
1270
    $recordingtypes .= html_writer::end_tag('div');
1271
1272
    return $recordingtypes;
1273
}
1274
1275
function bigbluebuttonbn_get_recording_data_row_meta_activity($recording, $editable) {
1276
    $payload = array();
1277 View Code Duplication
    if ($editable) {
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...
1278
        $payload = array('recordingid' => $recording['recordID'], 'meetingid' => $recording['meetingID'],
1279
            'action' => 'edit', 'tag' => 'edit',
1280
            'target' => 'name', 'source' => 'meta_bbb-recording-name');
1281
    }
1282
    if (isset($recording['meta_contextactivity'])) {
1283
        $payload['source'] = 'meta_contextactivity';
1284
        return bigbluebuttonbn_get_recording_data_row_text($recording, $recording[$payload['source']], $payload);
1285
    }
1286
1287
    if (isset($recording['meta_bbb-recording-name'])) {
1288
        return bigbluebuttonbn_get_recording_data_row_text($recording, $recording[$payload['source']], $payload);
1289
    }
1290
1291
    return bigbluebuttonbn_get_recording_data_row_text($recording, $recording['meetingName'], $payload);
1292
}
1293
1294
function bigbluebuttonbn_get_recording_data_row_meta_description($recording, $editable) {
1295
    $payload = array();
1296 View Code Duplication
    if ($editable) {
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...
1297
        $payload = array('recordingid' => $recording['recordID'], 'meetingid' => $recording['meetingID'],
1298
            'action' => 'edit', 'tag' => 'edit',
1299
            'target' => 'description', 'source' => 'meta_bbb-recording-description');
1300
    }
1301
1302 View Code Duplication
    if (isset($recording['meta_contextactivitydescription'])) {
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...
1303
        $payload['source'] = 'meta_contextactivitydescription';
1304
        $metadescription = trim($recording[$payload['source']]);
1305
        if (!empty($metadescription)) {
1306
          return bigbluebuttonbn_get_recording_data_row_text($recording, $metadescription, $payload);
1307
        }
1308
    }
1309
1310 View Code Duplication
    if (isset($recording['meta_bbb-recording-description'])) {
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...
1311
        $metadescription = trim($recording[$payload['source']]);
1312
        if (!empty($metadescription)) {
1313
            return bigbluebuttonbn_get_recording_data_row_text($recording, $metadescription, $payload);
1314
        }
1315
    }
1316
1317
    return bigbluebuttonbn_get_recording_data_row_text($recording, '', $payload);
1318
}
1319
1320
function bigbluebuttonbn_get_recording_data_row_text($recording, $text, $data) {
1321
    $htmltext = '<span>' . htmlentities($text) . '</span>';
1322
1323
    if (empty($data)) {
1324
        return $htmltext;
1325
    }
1326
1327
    $target = $data['action'] . '-' . $data['target'];
1328
    $id = 'recording-' . $target . '-' . $data['recordingid'];
1329
    $attributes = array('id' => $id, 'class' => 'quickeditlink col-md-20',
1330
        'data-recordingid' => $data['recordingid'], 'data-meetingid' => $data['meetingid'],
1331
        'data-target' => $data['target'], 'data-source' => $data['source']);
1332
    $head = html_writer::start_tag('div', $attributes);
1333
    $tail = html_writer::end_tag('div');
1334
1335
    $payload = array('action' => $data['action'], 'tag' => $data['tag'], 'target' => $data['target']);
1336
    $htmllink = bigbluebuttonbn_actionbar_render_button($recording, $payload);
1337
1338
    return $head . $htmltext . $htmllink . $tail;
1339
}
1340
1341
function bigbluebuttonbn_actionbar_render_button($recording, $data) {
1342
    global $OUTPUT;
1343
1344
    $target = $data['action'];
1345
    if (isset($data['target'])) {
1346
        $target .= '-' . $data['target'];
1347
    }
1348
    $id = 'recording-' . $target . '-' . $recording['recordID'];
1349
    $onclick = 'M.mod_bigbluebuttonbn.recordings.recording_'.$data['action'].'(this);';
1350
    if (bigbluebuttonbn_get_cfg_recording_icons_enabled()) {
1351
        // With icon for $manageaction.
1352
        $iconattributes = array('id' => $id, 'class' => 'iconsmall');
1353
        $icon = new pix_icon('i/'.$data['tag'],
1354
            get_string('view_recording_list_actionbar_' . $data['action'], 'bigbluebuttonbn'),
1355
            'moodle', $iconattributes);
1356
        $linkattributes = array(
1357
            'id' => $id,
1358
            'onclick' => $onclick,
1359
            'data-action' => $data['action'],
1360
            'data-links' => bigbluebuttonbn_get_count_recording_imported_instances($recording['recordID'])
1361
          );
1362
        return $OUTPUT->action_icon('#', $icon, null, $linkattributes, false);
1363
    }
1364
1365
    // With text for $manageaction.
1366
    $linkattributes = array('title' => get_string($data['tag']), 'class' => 'btn btn-xs btn-danger',
1367
        'onclick' => $onclick);
1368
    return $OUTPUT->action_link('#', get_string($data['action']), null, $linkattributes);
1369
}
1370
1371
function bigbluebuttonbn_get_recording_columns($bbbsession) {
1372
    // Set strings to show.
1373
    $recording = get_string('view_recording_recording', 'bigbluebuttonbn');
1374
    $activity = get_string('view_recording_activity', 'bigbluebuttonbn');
1375
    $description = get_string('view_recording_description', 'bigbluebuttonbn');
1376
    $preview = get_string('view_recording_preview', 'bigbluebuttonbn');
1377
    $date = get_string('view_recording_date', 'bigbluebuttonbn');
1378
    $duration = get_string('view_recording_duration', 'bigbluebuttonbn');
1379
    $actionbar = get_string('view_recording_actionbar', 'bigbluebuttonbn');
1380
1381
    // Initialize table headers.
1382
    $recordingsbncolumns = array(
1383
        array('key' => 'recording', 'label' => $recording, 'width' => '125px', 'allowHTML' => true),
1384
        array('key' => 'activity', 'label' => $activity, 'sortable' => true, 'width' => '175px', 'allowHTML' => true),
1385
        array('key' => 'description', 'label' => $description, 'width' => '250px', 'sortable' => true,
1386
            'width' => '250px', 'allowHTML' => true),
1387
        array('key' => 'preview', 'label' => $preview, 'width' => '250px', 'allowHTML' => true),
1388
        array('key' => 'date', 'label' => $date, 'sortable' => true, 'width' => '225px', 'allowHTML' => true),
1389
        array('key' => 'duration', 'label' => $duration, 'width' => '50px'),
1390
        );
1391
1392
    if ($bbbsession['managerecordings']) {
1393
        array_push($recordingsbncolumns, array('key' => 'actionbar', 'label' => $actionbar, 'width' => '100px',
1394
            'allowHTML' => true));
1395
    }
1396
1397
    return $recordingsbncolumns;
1398
}
1399
1400
function bigbluebuttonbn_get_recording_data($bbbsession, $recordings, $tools = ['publishing', 'deleting']) {
1401
    $tabledata = array();
1402
1403
    // Build table content.
1404
    if (isset($recordings) && !array_key_exists('messageKey', $recordings)) {
1405
        // There are recordings for this meeting.
1406
        foreach ($recordings as $recording) {
1407
            $row = bigbluebuttonbn_get_recording_data_row($bbbsession, $recording, $tools);
1408
            if ($row != null) {
1409
                array_push($tabledata, $row);
1410
            }
1411
        }
1412
    }
1413
1414
    return $tabledata;
1415
}
1416
1417
function bigbluebuttonbn_get_recording_table($bbbsession, $recordings, $tools = ['publishing', 'deleting']) {
1418
    // Set strings to show.
1419
    $recording = get_string('view_recording_recording', 'bigbluebuttonbn');
1420
    $description = get_string('view_recording_description', 'bigbluebuttonbn');
1421
    $date = get_string('view_recording_date', 'bigbluebuttonbn');
1422
    $duration = get_string('view_recording_duration', 'bigbluebuttonbn');
1423
    $actionbar = get_string('view_recording_actionbar', 'bigbluebuttonbn');
1424
    $playback = get_string('view_recording_playback', 'bigbluebuttonbn');
1425
    $preview = get_string('view_recording_preview', 'bigbluebuttonbn');
1426
1427
    // Declare the table.
1428
    $table = new html_table();
1429
    $table->data = array();
1430
1431
    // Initialize table headers.
1432
    $table->head = array($playback, $recording, $description, $preview, $date, $duration);
1433
    $table->align = array('left', 'left', 'left', 'left', 'left', 'center');
1434
    if ($bbbsession['managerecordings']) {
1435
        $table->head[] = $actionbar;
1436
        $table->align[] = 'left';
1437
    }
1438
1439
    // Build table content.
1440
    if (isset($recordings) && !array_key_exists('messageKey', $recordings)) {
1441
        // There are recordings for this meeting.
1442
        foreach ($recordings as $recording) {
1443
            $row = new html_table_row();
1444
            $row->id = 'recording-td-'.$recording['recordID'];
1445
            $row->attributes['data-imported'] = 'false';
1446
            $texthead = '';
1447
            $texttail = '';
1448
            if (isset($recording['imported'])) {
1449
                $row->attributes['data-imported'] = 'true';
1450
                $row->attributes['title'] = get_string('view_recording_link_warning', 'bigbluebuttonbn');
1451
                $texthead = '<em>';
1452
                $texttail = '</em>';
1453
            }
1454
1455
            $rowdata = bigbluebuttonbn_get_recording_data_row($bbbsession, $recording, $tools);
1456
            if ($rowdata != null) {
1457
                $rowdata->date_formatted = str_replace(' ', '&nbsp;', $rowdata->date_formatted);
1458
                $row->cells = array($texthead.$rowdata->recording.$texttail,
1459
                    $texthead.$rowdata->activity.$texttail, $texthead.$rowdata->description.$texttail,
1460
                    $rowdata->preview, $texthead.$rowdata->date_formatted.$texttail,
1461
                    $rowdata->duration_formatted);
1462
                if ($bbbsession['managerecordings']) {
1463
                    $row->cells[] = $rowdata->actionbar;
1464
                }
1465
                array_push($table->data, $row);
1466
            }
1467
        }
1468
    }
1469
1470
    return $table;
1471
}
1472
1473
function bigbluebuttonbn_send_notification_recording_ready($bigbluebuttonbn) {
1474
    $sender = get_admin();
1475
1476
    // Prepare message.
1477
    $msg = new stdClass();
1478
1479
    // Build the message_body.
1480
    $msg->activity_type = '';
1481
    $msg->activity_title = $bigbluebuttonbn->name;
1482
    $messagetext = '<p>'.get_string('email_body_recording_ready_for', 'bigbluebuttonbn').' '.
1483
        $msg->activity_type.' &quot;'.$msg->activity_title.'&quot; '.
1484
        get_string('email_body_recording_ready_is_ready', 'bigbluebuttonbn').'.</p>';
1485
1486
    bigbluebuttonbn_send_notification($sender, $bigbluebuttonbn, $messagetext);
1487
}
1488
1489
function bigbluebuttonbn_is_bn_server() {
1490
    // Validates if the server may have extended capabilities.
1491
    $parsedurl = parse_url(bigbluebuttonbn_get_cfg_server_url());
1492
    if (!isset($parsedurl['host'])) {
1493
        return false;
1494
    }
1495
1496
    $h = $parsedurl['host'];
1497
    $hends = explode('.', $h);
1498
    $hendslength = count($hends);
1499
1500
    return ($hends[$hendslength - 1] == 'com' && $hends[$hendslength - 2] == 'blindsidenetworks');
1501
}
1502
1503
/**
1504
 * @return string
1505
 */
1506
function bigbluebuttonbn_get_cfg_server_url() {
1507
    global $CFG;
1508
1509
    if (isset($CFG->bigbluebuttonbn['server_url'])) {
1510
        return trim(trim($CFG->bigbluebuttonbn['server_url']), '/').'/';
1511
    }
1512
1513
    if (isset($CFG->bigbluebuttonbn_server_url)) {
1514
        return trim(trim($CFG->bigbluebuttonbn_server_url), '/').'/';
1515
    }
1516
1517
    if (isset($CFG->BigBlueButtonBNServerURL)) {
1518
        return trim(trim($CFG->BigBlueButtonBNServerURL), '/').'/';
1519
    }
1520
1521
    return  BIGBLUEBUTTONBN_DEFAULT_SERVER_URL;
1522
}
1523
1524
/**
1525
 * @return string
1526
 */
1527
function bigbluebuttonbn_get_cfg_shared_secret() {
1528
    global $CFG;
1529
1530
    if (isset($CFG->bigbluebuttonbn['shared_secret'])) {
1531
        return trim($CFG->bigbluebuttonbn['shared_secret']);
1532
    }
1533
1534
    if (isset($CFG->bigbluebuttonbn_shared_secret)) {
1535
        return trim($CFG->bigbluebuttonbn_shared_secret);
1536
    }
1537
1538
    if (isset($CFG->BigBlueButtonBNSecuritySalt)) {
1539
        return trim($CFG->BigBlueButtonBNSecuritySalt);
1540
    }
1541
1542
    return  BIGBLUEBUTTONBN_DEFAULT_SHARED_SECRET;
1543
}
1544
1545
/**
1546
 * @return boolean
1547
 */
1548
function bigbluebuttonbn_get_cfg_voicebridge_editable() {
1549
    global $CFG;
1550
1551
    if (isset($CFG->bigbluebuttonbn['voicebridge_editable'])) {
1552
        return $CFG->bigbluebuttonbn['voicebridge_editable'];
1553
    }
1554
1555
    if (isset($CFG->bigbluebuttonbn_voicebridge_editable)) {
1556
        return $CFG->bigbluebuttonbn_voicebridge_editable;
1557
    }
1558
1559
    return  false;
1560
}
1561
1562
/**
1563
 * @return boolean
1564
 */
1565
function bigbluebuttonbn_get_cfg_recording_default() {
1566
    global $CFG;
1567
1568
    if (isset($CFG->bigbluebuttonbn['recording_default'])) {
1569
        return $CFG->bigbluebuttonbn['recording_default'];
1570
    }
1571
1572
    if (isset($CFG->bigbluebuttonbn_recording_default)) {
1573
        return $CFG->bigbluebuttonbn_recording_default;
1574
    }
1575
1576
    return  true;
1577
}
1578
1579
/**
1580
 * @return string
1581
 */
1582
function bigbluebuttonbn_get_cfg_recording_editable() {
1583
    global $CFG;
1584
1585
    if (isset($CFG->bigbluebuttonbn['recording_editable'])) {
1586
        return $CFG->bigbluebuttonbn['recording_editable'];
1587
    }
1588
1589
    if (isset($CFG->bigbluebuttonbn_recording_editable)) {
1590
        return $CFG->bigbluebuttonbn_recording_editable;
1591
    }
1592
1593
    return  true;
1594
}
1595
1596
/**
1597
 * @return boolean
1598
 */
1599
function bigbluebuttonbn_get_cfg_recording_icons_enabled() {
1600
    global $CFG;
1601
1602
    if (isset($CFG->bigbluebuttonbn['recording_icons_enabled'])) {
1603
        return $CFG->bigbluebuttonbn['recording_icons_enabled'];
1604
    }
1605
1606
    if (isset($CFG->bigbluebuttonbn_recording_icons_enabled)) {
1607
        return $CFG->bigbluebuttonbn_recording_icons_enabled;
1608
    }
1609
1610
    return  true;
1611
}
1612
1613
/**
1614
 * @return boolean
1615
 */
1616
function bigbluebuttonbn_get_cfg_importrecordings_enabled() {
1617
    global $CFG;
1618
1619
    if (isset($CFG->bigbluebuttonbn['importrecordings_enabled'])) {
1620
        return $CFG->bigbluebuttonbn['importrecordings_enabled'];
1621
    }
1622
1623
    if (isset($CFG->bigbluebuttonbn_importrecordings_enabled)) {
1624
        return $CFG->bigbluebuttonbn_importrecordings_enabled;
1625
    }
1626
1627
    return  false;
1628
}
1629
1630
/**
1631
 * @return boolean
1632
 */
1633
function bigbluebuttonbn_get_cfg_importrecordings_from_deleted_activities_enabled() {
1634
    global $CFG;
1635
1636
    if (isset($CFG->bigbluebuttonbn['importrecordings_from_deleted_activities_enabled'])) {
1637
        return $CFG->bigbluebuttonbn['importrecordings_from_deleted_activities_enabled'];
1638
    }
1639
1640
    if (isset($CFG->bigbluebuttonbn_importrecordings_from_deleted_activities_enabled)) {
1641
        return $CFG->bigbluebuttonbn_importrecordings_from_deleted_activities_enabled;
1642
    }
1643
1644
    return  false;
1645
}
1646
1647
/**
1648
 * @return boolean
1649
 */
1650
function bigbluebuttonbn_get_cfg_waitformoderator_default() {
1651
    global $CFG;
1652
1653
    if (isset($CFG->bigbluebuttonbn['waitformoderator_default'])) {
1654
        return $CFG->bigbluebuttonbn['waitformoderator_default'];
1655
    }
1656
1657
    if (isset($CFG->bigbluebuttonbn_waitformoderator_default)) {
1658
        return $CFG->bigbluebuttonbn_waitformoderator_default;
1659
    }
1660
1661
    return  false;
1662
}
1663
1664
/**
1665
 * @return boolean
1666
 */
1667
function bigbluebuttonbn_get_cfg_waitformoderator_editable() {
1668
    global $CFG;
1669
1670
    if (isset($CFG->bigbluebuttonbn['waitformoderator_editable'])) {
1671
        return $CFG->bigbluebuttonbn['waitformoderator_editable'];
1672
    }
1673
1674
    if (isset($CFG->bigbluebuttonbn_waitformoderator_editable)) {
1675
        return $CFG->bigbluebuttonbn_waitformoderator_editable;
1676
    }
1677
1678
    return  true;
1679
}
1680
1681
/**
1682
 * @return number
1683
 */
1684
function bigbluebuttonbn_get_cfg_waitformoderator_ping_interval() {
1685
    global $CFG;
1686
1687
    if (isset($CFG->bigbluebuttonbn['waitformoderator_ping_interval'])) {
1688
        return $CFG->bigbluebuttonbn['waitformoderator_ping_interval'];
1689
    }
1690
1691
    if (isset($CFG->bigbluebuttonbn_waitformoderator_ping_interval)) {
1692
        return $CFG->bigbluebuttonbn_waitformoderator_ping_interval;
1693
    }
1694
1695
    return  10;
1696
}
1697
1698
/**
1699
 * @return number
1700
 */
1701
function bigbluebuttonbn_get_cfg_waitformoderator_cache_ttl() {
1702
    global $CFG;
1703
1704
    if (isset($CFG->bigbluebuttonbn['waitformoderator_cache_ttl'])) {
1705
        return $CFG->bigbluebuttonbn['waitformoderator_cache_ttl'];
1706
    }
1707
1708
    if (isset($CFG->bigbluebuttonbn_waitformoderator_cache_ttl)) {
1709
        return $CFG->bigbluebuttonbn_waitformoderator_cache_ttl;
1710
    }
1711
1712
    return  60;
1713
}
1714
1715
/**
1716
 * @return number
1717
 */
1718
function bigbluebuttonbn_get_cfg_userlimit_default() {
1719
    global $CFG;
1720
1721
    if (isset($CFG->bigbluebuttonbn['userlimit_default'])) {
1722
        return $CFG->bigbluebuttonbn['userlimit_default'];
1723
    }
1724
1725
    if (isset($CFG->bigbluebuttonbn_userlimit_default)) {
1726
        return $CFG->bigbluebuttonbn_userlimit_default;
1727
    }
1728
1729
    return  0;
1730
}
1731
1732
/**
1733
 * @return boolean
1734
 */
1735
function bigbluebuttonbn_get_cfg_userlimit_editable() {
1736
    global $CFG;
1737
1738
    if (isset($CFG->bigbluebuttonbn['userlimit_editable'])) {
1739
        return $CFG->bigbluebuttonbn['userlimit_editable'];
1740
    }
1741
1742
    if (isset($CFG->bigbluebuttonbn_userlimit_editable)) {
1743
        return $CFG->bigbluebuttonbn_userlimit_editable;
1744
    }
1745
1746
    return  false;
1747
}
1748
1749
/**
1750
 * @return boolean
1751
 */
1752
function bigbluebuttonbn_get_cfg_preuploadpresentation_enabled() {
1753
    global $CFG;
1754
1755
    if (!extension_loaded('curl')) {
1756
        return false;
1757
    }
1758
1759
    if (isset($CFG->bigbluebuttonbn['preuploadpresentation_enabled'])) {
1760
        return $CFG->bigbluebuttonbn['preuploadpresentation_enabled'];
1761
    }
1762
1763
    if (isset($CFG->bigbluebuttonbn_preuploadpresentation_enabled)) {
1764
        return $CFG->bigbluebuttonbn_preuploadpresentation_enabled;
1765
    }
1766
1767
    return  false;
1768
}
1769
1770
/**
1771
 * @return boolean
1772
 */
1773
function bigbluebuttonbn_get_cfg_sendnotifications_enabled() {
1774
    global $CFG;
1775
1776
    if (isset($CFG->bigbluebuttonbn['sendnotifications_enabled'])) {
1777
        return $CFG->bigbluebuttonbn['sendnotifications_enabled'];
1778
    }
1779
1780
    if (isset($CFG->bigbluebuttonbn_sendnotifications_enabled)) {
1781
        return $CFG->bigbluebuttonbn_sendnotifications_enabled;
1782
    }
1783
1784
    return  false;
1785
}
1786
1787
/**
1788
 * @return boolean
1789
 */
1790
function bigbluebuttonbn_get_cfg_recordingready_enabled() {
1791
    global $CFG;
1792
1793
    if (isset($CFG->bigbluebuttonbn['recordingready_enabled'])) {
1794
        return $CFG->bigbluebuttonbn['recordingready_enabled'];
1795
    }
1796
1797
    if (isset($CFG->bigbluebuttonbn_recordingready_enabled)) {
1798
        return $CFG->bigbluebuttonbn_recordingready_enabled;
1799
    }
1800
1801
    return  false;
1802
}
1803
1804
/**
1805
 * @return boolean
1806
 */
1807
function bigbluebuttonbn_get_cfg_meetingevents_enabled() {
1808
    global $CFG;
1809
1810
    if (isset($CFG->bigbluebuttonbn['meetingevents_enabled'])) {
1811
        return $CFG->bigbluebuttonbn['meetingevents_enabled'];
1812
    }
1813
1814
    if (isset($CFG->bigbluebuttonbn_meetingevents_enabled)) {
1815
        return $CFG->bigbluebuttonbn_meetingevents_enabled;
1816
    }
1817
1818
    return  false;
1819
}
1820
1821
/**
1822
 * @return string
1823
 */
1824
function bigbluebuttonbn_get_cfg_moderator_default() {
1825
    global $CFG;
1826
1827
    if (isset($CFG->bigbluebuttonbn['moderator_default'])) {
1828
        return $CFG->bigbluebuttonbn['moderator_default'];
1829
    }
1830
1831
    if (isset($CFG->bigbluebuttonbn_moderator_default)) {
1832
        return $CFG->bigbluebuttonbn_moderator_default;
1833
    }
1834
1835
    return  'owner';
1836
}
1837
1838
/**
1839
 * @return boolean
1840
 */
1841
function bigbluebuttonbn_get_cfg_scheduled_duration_enabled() {
1842
    global $CFG;
1843
1844
    if (isset($CFG->bigbluebuttonbn['scheduled_duration_enabled'])) {
1845
        return $CFG->bigbluebuttonbn['scheduled_duration_enabled'];
1846
    }
1847
1848
    if (isset($CFG->bigbluebuttonbn_scheduled_duration_enabled)) {
1849
        return $CFG->bigbluebuttonbn_scheduled_duration_enabled;
1850
    }
1851
1852
    return  false;
1853
}
1854
1855
/**
1856
 * @return number
1857
 */
1858
function bigbluebuttonbn_get_cfg_scheduled_duration_compensation() {
1859
    global $CFG;
1860
1861
    if (isset($CFG->bigbluebuttonbn['scheduled_duration_compensation'])) {
1862
        return $CFG->bigbluebuttonbn['scheduled_duration_compensation'];
1863
    }
1864
1865
    if (isset($CFG->bigbluebuttonbn_scheduled_duration_compensation)) {
1866
        return $CFG->bigbluebuttonbn_scheduled_duration_compensation;
1867
    }
1868
1869
    return  10;
1870
}
1871
1872
/**
1873
 * @return number
1874
 */
1875
function bigbluebuttonbn_get_cfg_scheduled_pre_opening() {
1876
    global $CFG;
1877
1878
    if (isset($CFG->bigbluebuttonbn['scheduled_pre_opening'])) {
1879
        return $CFG->bigbluebuttonbn['scheduled_pre_opening'];
1880
    }
1881
1882
    if (isset($CFG->bigbluebuttonbn_scheduled_pre_opening)) {
1883
        return $CFG->bigbluebuttonbn_scheduled_pre_opening;
1884
    }
1885
1886
    return  10;
1887
}
1888
1889
/**
1890
 * @return boolean
1891
 */
1892
function bigbluebuttonbn_get_cfg_recordings_html_default() {
1893
    global $CFG;
1894
1895
    if (isset($CFG->bigbluebuttonbn['recordings_html_default'])) {
1896
        return $CFG->bigbluebuttonbn['recordings_html_default'];
1897
    }
1898
1899
    if (isset($CFG->bigbluebuttonbn_recordings_html_default)) {
1900
        return $CFG->bigbluebuttonbn_recordings_html_default;
1901
    }
1902
1903
    return  false;
1904
}
1905
1906
/**
1907
 * @return boolean
1908
 */
1909
function bigbluebuttonbn_get_cfg_recordings_html_editable() {
1910
    global $CFG;
1911
1912
    if (isset($CFG->bigbluebuttonbn['recordings_html_editable'])) {
1913
        return $CFG->bigbluebuttonbn['recordings_html_editable'];
1914
    }
1915
1916
    if (isset($CFG->bigbluebuttonbn_recordings_html_editable)) {
1917
        return $CFG->bigbluebuttonbn_recordings_html_editable;
1918
    }
1919
1920
    return  false;
1921
}
1922
1923
/**
1924
 * @return boolean
1925
 */
1926
function bigbluebuttonbn_get_cfg_recordings_deleted_activities_default() {
1927
    global $CFG;
1928
1929
    if (isset($CFG->bigbluebuttonbn['recordings_deleted_activities_default'])) {
1930
        return $CFG->bigbluebuttonbn['recordings_deleted_activities_default'];
1931
    }
1932
1933
    if (isset($CFG->bigbluebuttonbn_recordings_deleted_activities_default)) {
1934
        return $CFG->bigbluebuttonbn_recordings_deleted_activities_default;
1935
    }
1936
1937
    return  false;
1938
}
1939
1940
/**
1941
 * @return boolean
1942
 */
1943
function bigbluebuttonbn_get_cfg_recordings_deleted_activities_editable() {
1944
    global $CFG;
1945
1946
    if (isset($CFG->bigbluebuttonbn['recordings_deleted_activities_editable'])) {
1947
        return $CFG->bigbluebuttonbn['recordings_deleted_activities_editable'];
1948
    }
1949
1950
    if (isset($CFG->bigbluebuttonbn_recordings_deleted_activities_editable)) {
1951
        return $CFG->bigbluebuttonbn_recordings_deleted_activities_editable;
1952
    }
1953
1954
    return  false;
1955
}
1956
1957
/**
1958
 * @return array
1959
 */
1960
function bigbluebuttonbn_get_cfg_options() {
1961
    return [
1962
          'version_major' => bigbluebuttonbn_get_moodle_version_major(),
1963
          'voicebridge_editable' => bigbluebuttonbn_get_cfg_voicebridge_editable(),
1964
          'recording_default' => bigbluebuttonbn_get_cfg_recording_default(),
1965
          'recording_editable' => bigbluebuttonbn_get_cfg_recording_editable(),
1966
          'waitformoderator_default' => bigbluebuttonbn_get_cfg_waitformoderator_default(),
1967
          'waitformoderator_editable' => bigbluebuttonbn_get_cfg_waitformoderator_editable(),
1968
          'userlimit_default' => bigbluebuttonbn_get_cfg_userlimit_default(),
1969
          'userlimit_editable' => bigbluebuttonbn_get_cfg_userlimit_editable(),
1970
          'preuploadpresentation_enabled' => bigbluebuttonbn_get_cfg_preuploadpresentation_enabled(),
1971
          'sendnotifications_enabled' => bigbluebuttonbn_get_cfg_sendnotifications_enabled(),
1972
          'recordings_html_default' => bigbluebuttonbn_get_cfg_recordings_html_default(),
1973
          'recordings_html_editable' => bigbluebuttonbn_get_cfg_recordings_html_editable(),
1974
          'recordings_deleted_activities_default' => bigbluebuttonbn_get_cfg_recordings_deleted_activities_default(),
1975
          'recordings_deleted_activities_editable' => bigbluebuttonbn_get_cfg_recordings_deleted_activities_editable(),
1976
          'recording_icons_enabled' => bigbluebuttonbn_get_cfg_recording_icons_enabled(),
1977
          'instance_type_enabled' => bigbluebuttonbn_recordings_enabled(),
1978
          'instance_type_default' => BIGBLUEBUTTONBN_TYPE_ALL,
1979
        ];
1980
}
1981
1982
function bigbluebuttonbn_import_get_courses_for_select(array $bbbsession) {
1983
    if ($bbbsession['administrator']) {
1984
        $courses = get_courses('all', 'c.id ASC', 'c.id,c.shortname,c.fullname');
1985
        // It includes the name of the site as a course (category 0), so remove the first one.
1986
        unset($courses['1']);
1987
    } else {
1988
        $courses = enrol_get_users_courses($bbbsession['userID'], false, 'id,shortname,fullname');
1989
    }
1990
1991
    $coursesforselect = [];
1992
    foreach ($courses as $course) {
1993
        $coursesforselect[$course->id] = $course->fullname;
1994
    }
1995
1996
    return $coursesforselect;
1997
}
1998
1999
function bigbluebutton_output_recording_table($bbbsession, $recordings, $tools = ['publishing', 'deleting']) {
2000
    if (isset($recordings) && !empty($recordings)) {
2001
        // There are recordings for this meeting.
2002
        $table = bigbluebuttonbn_get_recording_table($bbbsession, $recordings, $tools);
2003
    }
2004
2005
    if (!isset($table) || !isset($table->data)) {
2006
        // Render a table qith "No recordings".
2007
        return html_writer::div(get_string('view_message_norecordings', 'bigbluebuttonbn'), '',
2008
            array('id' => 'bigbluebuttonbn_html_table'));
2009
    }
2010
2011
    // Render the table.
2012
    return html_writer::div(html_writer::table($table), '', array('id' => 'bigbluebuttonbn_html_table'));
2013
}
2014
2015
function bigbluebuttonbn_html2text($html, $len) {
2016
    $text = strip_tags($html);
2017
    $text = str_replace('&nbsp;', ' ', $text);
2018
    $text = substr($text, 0, $len);
2019
    if (strlen($text) > $len) {
2020
        $text .= '...';
2021
    }
2022
2023
    return $text;
2024
}
2025
2026
/**
2027
 * helper function to obtain the tags linked to a bigbluebuttonbn activity
2028
 *
2029
 * @param string $id
2030
 *
2031
 * @return string containing the tags separated by commas
2032
 */
2033
function bigbluebuttonbn_get_tags($id) {
2034
    $tagsarray = core_tag_tag::get_item_tags_array('core', 'course_modules', $id);
2035
    return implode(',', $tagsarray);
2036
}
2037
2038
/**
2039
 * helper function to retrieve recordings from the BigBlueButton. The references are stored as events
2040
 * in bigbluebuttonbn_logs.
2041
 *
2042
 * @param string $courseid
2043
 * @param string $bigbluebuttonbnid
2044
 * @param bool   $subset
2045
 * @param bool   $includedeleted
2046
 *
2047
 * @return associative array containing the recordings indexed by recordID, each recording is also a
2048
 * non sequential associative array itself that corresponds to the actual recording in BBB
2049
 */
2050
function bigbluebuttonbn_get_recordings($courseid, $bigbluebuttonbnid = null,
2051
        $subset = true, $includedeleted = false) {
2052
    global $DB;
2053
2054
    // Gather the bigbluebuttonbnids whose meetingids should be included in the getRecordings request'.
2055
    $select = "id <> '{$bigbluebuttonbnid}' AND course = '{$courseid}'";
2056
    $selectdeleted = "courseid = '{$courseid}' AND bigbluebuttonbnid <> '{$bigbluebuttonbnid}' AND log = '".
2057
        BIGBLUEBUTTONBN_LOG_EVENT_DELETE."' AND meta like '%has_recordings%' AND meta like '%true%'";
2058
    if ($bigbluebuttonbnid === null) {
2059
        $select = "course = '{$courseid}'";
2060
        $selectdeleted = "courseid = '{$courseid}' AND log = '".BIGBLUEBUTTONBN_LOG_EVENT_DELETE.
2061
            "' AND meta like '%has_recordings%' AND meta like '%true%'";
2062
    } else if ($subset) {
2063
        $select = "id = '{$bigbluebuttonbnid}'";
2064
        $selectdeleted = "bigbluebuttonbnid = '{$bigbluebuttonbnid}' AND log = '".BIGBLUEBUTTONBN_LOG_EVENT_DELETE.
2065
            "' AND meta like '%has_recordings%' AND meta like '%true%'";
2066
    }
2067
    $bigbluebuttonbns = $DB->get_records_select_menu('bigbluebuttonbn', $select, null, 'id', 'id, meetingid');
2068
2069
    /* Consider logs from deleted bigbluebuttonbn instances whose meetingids should be included in
2070
     * the getRecordings request. */
2071
    if ($includedeleted) {
2072
        $bigbluebuttonbnsdel = $DB->get_records_select_menu('bigbluebuttonbn_logs', $selectdeleted, null,
2073
            'bigbluebuttonbnid', 'bigbluebuttonbnid, meetingid');
2074
        if (!empty($bigbluebuttonbnsdel)) {
2075
            // Merge bigbluebuttonbnis from deleted instances, only keys are relevant.
2076
            // Artimetic merge is used in order to keep the keys.
2077
            $bigbluebuttonbns += $bigbluebuttonbnsdel;
2078
        }
2079
    }
2080
2081
    // Gather the meetingids from bigbluebuttonbn logs that include a create with record=true.
2082
    $recordings = array();
2083
    if (!empty($bigbluebuttonbns)) {
2084
        // Prepare select for loading records based on existent bigbluebuttonbns.
2085
        $sql = 'SELECT DISTINCT meetingid, bigbluebuttonbnid FROM {bigbluebuttonbn_logs} WHERE ';
2086
        $sql .= '(bigbluebuttonbnid='.implode(' OR bigbluebuttonbnid=', array_keys($bigbluebuttonbns)).')';
2087
        // Include only Create events and exclude those with record not true.
2088
        $sql .= ' AND log = ? AND meta LIKE ? AND meta LIKE ?';
2089
        // Execute select for loading records based on existent bigbluebuttonbns.
2090
        $records = $DB->get_records_sql_menu($sql, array(BIGBLUEBUTTONBN_LOG_EVENT_CREATE, '%record%', '%true%'));
2091
        // Get actual recordings.
2092
        $recordings = bigbluebuttonbn_get_recordings_array(array_keys($records));
2093
    }
2094
2095
    // Get recording links.
2096
    $recordingsimported = bigbluebuttonbn_get_recordings_imported_array($courseid, $bigbluebuttonbnid, $subset);
2097
2098
    /* Perform aritmetic add instead of merge so the imported recordings corresponding to existent recordings
2099
     * are not included. */
2100
    return $recordings + $recordingsimported;
2101
}
2102
2103
function bigbluebuttonbn_unset_existent_recordings_already_imported($recordings, $courseid, $bigbluebuttonbnid) {
2104
    $recordingsimported = bigbluebuttonbn_get_recordings_imported_array($courseid, $bigbluebuttonbnid, true);
2105
2106
    foreach ($recordings as $key => $recording) {
2107
        if (isset($recordingsimported[$recording['recordID']])) {
2108
            unset($recordings[$key]);
2109
        }
2110
    }
2111
2112
    return $recordings;
2113
}
2114
2115
function bigbluebuttonbn_get_count_recording_imported_instances($recordid) {
2116
    global $DB;
2117
2118
    $sql = 'SELECT COUNT(DISTINCT id) FROM {bigbluebuttonbn_logs} WHERE log = ? AND meta LIKE ? AND meta LIKE ?';
2119
2120
    return $DB->count_records_sql($sql, array(BIGBLUEBUTTONBN_LOG_EVENT_IMPORT, '%recordID%', "%{$recordid}%"));
2121
}
2122
2123
function bigbluebuttonbn_get_recording_imported_instances($recordid) {
2124
    global $DB;
2125
2126
    $sql = 'SELECT * FROM {bigbluebuttonbn_logs} WHERE log = ? AND meta LIKE ? AND meta LIKE ?';
2127
    $recordingsimported = $DB->get_records_sql($sql, array(BIGBLUEBUTTONBN_LOG_EVENT_IMPORT, '%recordID%',
2128
        "%{$recordid}%"));
2129
2130
    return $recordingsimported;
2131
}
2132
2133
function bigbluebuttonbn_get_instance_type_profiles() {
2134
    $instanceprofiles = array(
2135
            array('id' => BIGBLUEBUTTONBN_TYPE_ALL, 'name' => get_string('instance_type_default', 'bigbluebuttonbn'),
2136
                'features' => array('all')),
2137
            array('id' => BIGBLUEBUTTONBN_TYPE_ROOM_ONLY, 'name' => get_string('instance_type_room_only', 'bigbluebuttonbn'),
2138
                'features' => array('showroom', 'welcomemessage', 'voicebridge', 'waitformoderator', 'userlimit', 'recording',
2139
                    'sendnotifications', 'preuploadpresentation', 'permissions', 'schedule', 'groups')),
2140
            array('id' => BIGBLUEBUTTONBN_TYPE_RECORDING_ONLY, 'name' => get_string('instance_type_recording_only',
2141
                'bigbluebuttonbn'), 'features' => array('showrecordings', 'importrecordings')),
2142
    );
2143
2144
    return $instanceprofiles;
2145
}
2146
2147
function bigbluebuttonbn_get_enabled_features($typeprofiles, $type = null) {
2148
    $enabledfeatures = array();
2149
2150
    $features = $typeprofiles[0]['features'];
2151
    if (!is_null($type)) {
2152
        $features = $typeprofiles[$type]['features'];
2153
    }
2154
    $enabledfeatures['showroom'] = (in_array('all', $features) || in_array('showroom', $features));
2155
    $enabledfeatures['showrecordings'] = (in_array('all', $features) || in_array('showrecordings', $features));
2156
    $enabledfeatures['importrecordings'] = (in_array('all', $features) || in_array('importrecordings', $features));
2157
2158
    return $enabledfeatures;
2159
}
2160
2161
function bigbluebuttonbn_get_instance_profiles_array($profiles = null) {
2162
    if (is_null($profiles) || empty($profiles)) {
2163
        $profiles = bigbluebuttonbn_get_instance_type_profiles();
2164
    }
2165
2166
    $profilesarray = array();
2167
2168
    foreach ($profiles as $profile) {
2169
        $profilesarray += array("{$profile['id']}" => $profile['name']);
2170
    }
2171
2172
    return $profilesarray;
2173
}
2174
2175
function bigbluebuttonbn_format_activity_time($time) {
2176
    $activitytime = '';
2177
    if ($time) {
2178
        $activitytime = calendar_day_representation($time).' '.
2179
          get_string('mod_form_field_notification_msg_at', 'bigbluebuttonbn').' '.
2180
          calendar_time_representation($time);
2181
    }
2182
2183
    return $activitytime;
2184
}
2185
2186
function bigbluebuttonbn_recordings_enabled() {
2187
    global $CFG;
2188
2189
    return !(isset($CFG->bigbluebuttonbn['recording_default)']) &&
2190
             isset($CFG->bigbluebuttonbn['recording_editable']));
2191
}
2192
2193
function bigbluebuttonbn_get_strings_for_js() {
2194
    $locale = bigbluebuttonbn_get_locale();
2195
    $stringman = get_string_manager();
2196
    $strings = $stringman->load_component_strings('bigbluebuttonbn', $locale);
2197
    return $strings;
2198
}
2199
2200
function bigbluebuttonbn_get_locale() {
2201
    $lang = get_string('locale', 'core_langconfig');
2202
    return substr($lang, 0, strpos($lang, '.'));
2203
}
2204
2205
function bigbluebuttonbn_get_localcode() {
2206
    $locale = bigbluebuttonbn_get_locale();
2207
    return substr($locale, 0, strpos($locale, '_'));
2208
}
2209