Completed
Push — master ( 349104...1d1df5 )
by Jesus
02:37
created

locallib.php ➔ bigbluebuttonbn_get_moderator_email()   A

Complexity

Conditions 4
Paths 3

Size

Total Lines 15
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
eloc 11
nc 3
nop 1
dl 0
loc 15
rs 9.2
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
    $meetingidsarray = $meetingids;
244
    if (!is_array($meetingids)) {
245
        $meetingidsarray = explode(',', $meetingids);
246
    }
247
248
    // If $meetingidsarray is empty there is no need to go further.
249
    if (empty($meetingidsarray)) {
250
        return array();
251
    }
252
    $recordings = bigbluebuttonbn_get_recordings_array_fetch($meetingidsarray);
253
254
    // Filter recordings based on recordingIDs.
255
    $recordingidsarray = $recordingids;
256
    if (!is_array($recordingids)) {
257
        $recordingidsarray = explode(',', $recordingids);
258
    }
259
260
    if (empty($recordingidsarray)) {
261
        // No recording ids, no need to filter.
262
        return $recordings;
263
    }
264
265
    return bigbluebuttonbn_get_recordings_array_filter($recordingidsarray, $recordings);
266
}
267
268
/**
269
 * helper function to fetch recordings from a BigBlueButton server.
270
 *
271
 * @param array $meetingidsarray   array with meeting ids in the form array("mid1","mid2","mid3")
272
 *
273
 * @return associative array with recordings indexed by recordID, each recording is a non sequential associative array
274
 */
275
function bigbluebuttonbn_get_recordings_array_fetch($meetingidsarray) {
276
277
    $recordings = array();
278
279
    // Execute a paginated getRecordings request.
280
    $pages = floor(count($meetingidsarray) / 25) + 1;
281
    for ($page = 1; $page <= $pages; ++$page) {
282
        $mids = array_slice($meetingidsarray, ($page - 1) * 25, 25);
283
        // Do getRecordings is executed using a method GET (supported by all versions of BBB).
284
        $xml = bigbluebuttonbn_wrap_xml_load_file(
285
            bigbluebuttonbn_bigbluebutton_action_url('getRecordings', ['meetingID' => implode(',', $mids)])
286
          );
287
        if ($xml && $xml->returncode == 'SUCCESS' && isset($xml->recordings)) {
288
            // If there were meetings already created.
289
            foreach ($xml->recordings->recording as $recording) {
290
                $recordingarrayvalue = bigbluebuttonbn_get_recording_array_value($recording);
291
                $recordings[$recordingarrayvalue['recordID']] = $recordingarrayvalue;
292
            }
293
            uasort($recordings, 'bigbluebuttonbn_recording_build_sorter');
294
        }
295
    }
296
297
    return $recordings;
298
}
299
300
function bigbluebuttonbn_get_recordings_array_filter($recordingidsarray, &$recordings) {
301
302
    foreach ($recordings as $key => $recording) {
303
        if (!in_array($recording['recordID'], $recordingidsarray)) {
304
            unset($recordings[$key]);
305
        }
306
    }
307
308
    return $recordings;
309
}
310
311
/**
312
 * Helper function to retrieve imported recordings from the Moodle database.
313
 * The references are stored as events in bigbluebuttonbn_logs.
314
 *
315
 * @param string $courseid
316
 * @param string $bigbluebuttonbnid
317
 * @param bool   $subset
318
 *
319
 * @return associative array with imported recordings indexed by recordID, each recording is a non sequential associative
320
 * array that corresponds to the actual recording in BBB
321
 */
322
function bigbluebuttonbn_get_recordings_imported_array($courseid, $bigbluebuttonbnid = null, $subset = true) {
323
    global $DB;
324
325
    $select = "courseid = '{$courseid}' AND bigbluebuttonbnid <> '{$bigbluebuttonbnid}' AND log = '".
326
        BIGBLUEBUTTONBN_LOG_EVENT_IMPORT."'";
327
    if ($bigbluebuttonbnid === null) {
328
        $select = "courseid = '{$courseid}' AND log = '".BIGBLUEBUTTONBN_LOG_EVENT_IMPORT."'";
329
    } else if ($subset) {
330
        $select = "bigbluebuttonbnid = '{$bigbluebuttonbnid}' AND log = '".BIGBLUEBUTTONBN_LOG_EVENT_IMPORT."'";
331
    }
332
    $recordsimported = $DB->get_records_select('bigbluebuttonbn_logs', $select);
333
334
    $recordsimportedarray = array();
335
    foreach ($recordsimported as $recordimported) {
336
        $meta = json_decode($recordimported->meta, true);
337
        $recording = $meta['recording'];
338
        //FORCE protected
339
        $recording['protected'] = 'true';
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
    $recordingarray = 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);
386
    if (isset($recording->protected)) {
387
        $recordingarray['protected'] = (string) $recording->protected;
388
    }
389
    //FORCE protected
390
    $recordingarray['protected'] = 'false';
391
    return $recordingarray + $metadataarray;
392
}
393
394
function bigbluebuttonbn_get_recording_array_meta($metadata) {
395
    $metadataarray = array();
396
    foreach ($metadata as $key => $value) {
397
        if (is_object($value)) {
398
            $value = '';
399
        }
400
        $metadataarray['meta_'.$key] = $value;
401
    }
402
    return $metadataarray;
403
}
404
405
function bigbluebuttonbn_recording_build_sorter($a, $b) {
406
    if ($a['startTime'] < $b['startTime']) {
407
        return -1;
408
    }
409
    if ($a['startTime'] == $b['startTime']) {
410
        return 0;
411
    }
412
    return 1;
413
}
414
415
/**
416
 * @param string $recordids
417
 */
418 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...
419
    $ids = explode(',', $recordids);
420
    foreach ($ids as $id) {
421
        $xml = bigbluebuttonbn_wrap_xml_load_file(
422
            bigbluebuttonbn_bigbluebutton_action_url('deleteRecordings', ['recordID' => $id])
423
          );
424
        if ($xml && $xml->returncode != 'SUCCESS') {
425
            return false;
426
        }
427
    }
428
429
    return true;
430
}
431
432
/**
433
 * @param string $recordids
434
 * @param string $publish
435
 */
436 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...
437
    $ids = explode(',', $recordids);
438
    foreach ($ids as $id) {
439
        $xml = bigbluebuttonbn_wrap_xml_load_file(
440
            bigbluebuttonbn_bigbluebutton_action_url('publishRecordings', ['recordID' => $id, 'publish' => $publish])
441
          );
442
        if ($xml && $xml->returncode != 'SUCCESS') {
443
            return false;
444
        }
445
    }
446
447
    return true;
448
}
449
450
/**
451
 * @param string $recordids
452
 * @param array $params ['key'=>param_key, 'value']
453
 */
454 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...
455
    $ids = explode(',', $recordids);
456
    foreach ($ids as $id) {
457
        $xml = bigbluebuttonbn_wrap_xml_load_file(
458
            bigbluebuttonbn_bigbluebutton_action_url('updateRecordings', ['recordID' => $id] + (array) $params)
459
          );
460
        if ($xml && $xml->returncode != 'SUCCESS') {
461
            return false;
462
        }
463
    }
464
465
    return true;
466
}
467
468
/**
469
 * @param string $recordids
470
 * @param string $bigbluebuttonbnid
471
 * @param array $params ['key'=>param_key, 'value']
472
 */
473
function bigbluebuttonbn_update_recording_imported($recordids, $bigbluebuttonbnid, $params) {
474
    $ids = explode(',', $recordids);
475
    foreach ($ids as $id) {
476
        if (!bigbluebuttonbn_update_recording_imported_perform($id, $bigbluebuttonbnid, $params)) {
477
            return false;
478
        }
479
    }
480
    return true;
481
}
482
483
/**
484
 * @param string $recordid
485
 * @param string $bigbluebuttonbnid
486
 * @param array $params ['key'=>param_key, 'value']
487
 */
488
function bigbluebuttonbn_update_recording_imported_perform($recordid, $bigbluebuttonbnid, $params) {
489
    global $DB;
490
491
    // Locate the record to be updated.
492
    $records = $DB->get_records('bigbluebuttonbn_logs', array('bigbluebuttonbnid' => $bigbluebuttonbnid,
493
        'log' => BIGBLUEBUTTONBN_LOG_EVENT_IMPORT));
494
495
    foreach ($records as $key => $record) {
496
        $meta = json_decode($record->meta, true);
497
        if ($recordid == $meta['recording']['recordID']) {
498
            // Found, prepare data for the update.
499
            $meta['recording'] = $params + $meta['recording'];
500
            $records[$key]->meta = json_encode($meta);
501
502
            // Proceed with the update.
503
            if (!$DB->update_record('bigbluebuttonbn_logs', $records[$key])) {
504
                return false;
505
            }
506
        }
507
    }
508
    return true;
509
}
510
511
/**
512
 * @param string $meetingid
513
 * @param string $modpw
514
 */
515
function bigbluebuttonbn_end_meeting($meetingid, $modpw) {
516
    $xml = bigbluebuttonbn_wrap_xml_load_file(
517
        bigbluebuttonbn_bigbluebutton_action_url('end', ['meetingID' => $meetingid, 'password' => $modpw])
518
      );
519
520 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...
521
        // If the xml packet returned failure it displays the message to the user.
522
        return array('returncode' => $xml->returncode, 'message' => $xml->message, 'messageKey' => $xml->messageKey);
523
    }
524
525
    // If the server is unreachable, then prompts the user of the necessary action.
526
    return null;
527
}
528
529
/**
530
 * @param string $meetingid
531
 */
532
function bigbluebuttonbn_is_meeting_running($meetingid) {
533
    $xml = bigbluebuttonbn_wrap_xml_load_file(
534
        bigbluebuttonbn_bigbluebutton_action_url('isMeetingRunning', ['meetingID' => $meetingid])
535
      );
536
537
    if ($xml && $xml->returncode == 'SUCCESS') {
538
        return ($xml->running == 'true');
539
    }
540
541
    return false;
542
}
543
544
function bigbluebuttonbn_get_server_version() {
545
    $xml = bigbluebuttonbn_wrap_xml_load_file(
546
        bigbluebuttonbn_bigbluebutton_action_url()
547
      );
548
549
    if ($xml && $xml->returncode == 'SUCCESS') {
550
        return $xml->version;
551
    }
552
553
    return null;
554
}
555
556
/**
557
 * @param string $url
558
 * @param string $data
559
 */
560
function bigbluebuttonbn_wrap_xml_load_file($url, $method = BIGBLUEBUTTONBN_METHOD_GET,
561
    $data = null, $contenttype = 'text/xml') {
562
563
    //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...
564
565
    if (extension_loaded('curl')) {
566
        $response = bigbluebuttonbn_wrap_xml_load_file_curl_request($url, $method, $data, $contenttype);
567
568
        if (!$response) {
569
            //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...
570
            return null;
571
        }
572
573
        //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...
574
575
        $previous = libxml_use_internal_errors(true);
576
        try {
577
            $xml = simplexml_load_string($response, 'SimpleXMLElement', LIBXML_NOCDATA | LIBXML_NOBLANKS);
578
579
            return $xml;
580
        } catch (Exception $e) {
581
            libxml_use_internal_errors($previous);
582
            //$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...
583
            //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...
584
            return null;
585
        }
586
    }
587
588
    // Alternative request non CURL based.
589
    $previous = libxml_use_internal_errors(true);
590
    try {
591
        $response = simplexml_load_file($url, 'SimpleXMLElement', LIBXML_NOCDATA | LIBXML_NOBLANKS);
592
        //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...
593
        return $response;
594
    } catch (Exception $e) {
595
        //$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...
596
        //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...
597
        libxml_use_internal_errors($previous);
598
        return null;
599
    }
600
}
601
602
function bigbluebuttonbn_wrap_xml_load_file_curl_request($url, $method = BIGBLUEBUTTONBN_METHOD_GET,
603
    $data = null, $contenttype = 'text/xml') {
604
    $c = new curl();
605
    $c->setopt(array('SSL_VERIFYPEER' => true));
606
    if ($method == BIGBLUEBUTTONBN_METHOD_POST) {
607
        if (is_null($data) || is_array($data)) {
608
            return $c->post($url);
609
        }
610
611
        $options = array();
612
        $options['CURLOPT_HTTPHEADER'] = array(
613
                 'Content-Type: '.$contenttype,
614
                 'Content-Length: '.strlen($data),
615
                 'Content-Language: en-US',
616
               );
617
618
        return $c->post($url, $data, $options);
619
    }
620
621
    return $c->get($url);
622
}
623
624
function bigbluebuttonbn_get_user_roles($context, $userid) {
625
    global $DB;
626
627
    $userroles = get_user_roles($context, $userid);
628
    if ($userroles) {
629
        $where = '';
630
        foreach ($userroles as $value) {
631
            $where .= (empty($where) ? ' WHERE' : ' AND').' id='.$value->roleid;
632
        }
633
        $userroles = $DB->get_records_sql('SELECT * FROM {role}'.$where);
634
    }
635
636
    return $userroles;
637
}
638
639
function bigbluebuttonbn_get_guest_role() {
640
    $guestrole = get_guest_role();
641
642
    return array($guestrole->id => $guestrole);
643
}
644
645
function bigbluebuttonbn_get_users(context $context = null) {
646
    $users = (array) get_enrolled_users($context);
647
    foreach ($users as $key => $value) {
648
        $users[$key] = fullname($value);
649
    }
650
    return $users;
651
}
652
653
function bigbluebuttonbn_get_users_select(context $context = null) {
654
    $users = (array) get_enrolled_users($context);
655
    foreach ($users as $key => $value) {
656
        $users[$key] = array('id' => $value->id, 'name' => fullname($value));
657
    }
658
    return $users;
659
}
660
661
function bigbluebuttonbn_get_roles(context $context = null) {
662
    $roles = (array) role_get_names($context);
663
    foreach ($roles as $key => $value) {
664
        $roles[$key] = $value->localname;
665
    }
666
    return $roles;
667
}
668
669
function bigbluebuttonbn_get_roles_select(context $context = null) {
670
    $roles = (array) role_get_names($context);
671
    foreach ($roles as $key => $value) {
672
        $roles[$key] = array('id' => $value->id, 'name' => $value->localname);
673
    }
674
    return $roles;
675
 }
676
677
function bigbluebuttonbn_get_role($id) {
678
    $roles = (array) role_get_names();
679
    if (is_numeric($id)) {
680
        return $roles[$id];
681
    }
682
683
    foreach ($roles as $role) {
684
        if ($role->shortname == $id) {
685
            return $role;
686
        }
687
    }
688
}
689
690
function bigbluebuttonbn_get_participant_data($context) {
691
    $data = array(
692
        'all' => array(
693
            'name' => get_string('mod_form_field_participant_list_type_all', 'bigbluebuttonbn'),
694
            'children' => []
695
          )
696
      );
697
698
    $data['role'] = array(
699
        'name' => get_string('mod_form_field_participant_list_type_role', 'bigbluebuttonbn'),
700
        'children' => bigbluebuttonbn_get_roles_select($context)
701
      );
702
703
    $data['user'] = array(
704
        'name' => get_string('mod_form_field_participant_list_type_user', 'bigbluebuttonbn'),
705
        'children' => bigbluebuttonbn_get_users_select($context)
706
      );
707
708
    return $data;
709
}
710
711
function bigbluebuttonbn_get_participant_list($bigbluebuttonbn, $context) {
712
    if ($bigbluebuttonbn == null) {
713
        return bigbluebuttonbn_get_participant_list_default($context);
714
    }
715
716
    return bigbluebuttonbn_get_participant_rules_encoded($bigbluebuttonbn);
717
}
718
719
function bigbluebuttonbn_get_participant_rules_encoded($bigbluebuttonbn) {
720
    $rules = json_decode($bigbluebuttonbn->participants, true);
721
    foreach ($rules as $key => $rule) {
722
        if ($rule['selectiontype'] === 'role' && !is_numeric($rule['selectionid'])) {
723
            $role = bigbluebuttonbn_get_role($rule['selectionid']);
724
            $rule['selectionid'] = $role->id;
725
        }
726
        $rules[$key] = $rule;
727
    }
728
    return $rules;
729
}
730
731
function bigbluebuttonbn_get_participant_list_default($context) {
732
    global $USER;
733
734
    $participantlistarray = array();
735
    $participantlistarray[] = array(
736
        'selectiontype' => 'all',
737
        'selectionid' => 'all',
738
        'role' => BIGBLUEBUTTONBN_ROLE_VIEWER);
739
740
    $moderatordefaults = explode(',', bigbluebuttonbn_get_cfg_moderator_default());
741
    foreach ($moderatordefaults as $moderatordefault) {
742
        if ($moderatordefault == 'owner') {
743
            if (is_enrolled($context, $USER->id)) {
744
                $participantlistarray[] = array(
745
                    'selectiontype' => 'user',
746
                    'selectionid' => $USER->id,
747
                    'role' => BIGBLUEBUTTONBN_ROLE_MODERATOR);
748
            }
749
            continue;
750
        }
751
752
        $participantlistarray[] = array(
753
              'selectiontype' => 'role',
754
              'selectionid' => $moderatordefault,
755
              'role' => BIGBLUEBUTTONBN_ROLE_MODERATOR);
756
    }
757
758
    return $participantlistarray;
759
}
760
761
function bigbluebuttonbn_get_participant_selection_data() {
762
    return [
763
        'type_options' => [
764
            'all' => get_string('mod_form_field_participant_list_type_all', 'bigbluebuttonbn'),
765
            'role' => get_string('mod_form_field_participant_list_type_role', 'bigbluebuttonbn'),
766
            'user' => get_string('mod_form_field_participant_list_type_user', 'bigbluebuttonbn'),
767
          ],
768
        'type_selected' => 'all',
769
        'options' => ['all' => '---------------'],
770
        'selected' => 'all',
771
      ];
772
}
773
774
function bigbluebuttonbn_is_moderator($context, $participants, $userid = null, $userroles = null) {
775
    global $USER;
776
777
    if (empty($userid)) {
778
        $userid = $USER->id;
779
    }
780
781
    if (empty($userroles)) {
782
        $userroles = get_user_roles($context, $userid, true);
783
    }
784
785
    if (empty($participants)) {
786
        // The room that is being used comes from a previous version.
787
        return has_capability('mod/bigbluebuttonbn:moderate', $context);
788
    }
789
790
    $participantlist = json_decode($participants);
791
    // Iterate participant rules.
792
    foreach ($participantlist as $participant) {
793
        if (bigbluebuttonbn_is_moderator_rule_validation($participant, $userid, $userroles)) {
794
            return true;
795
        }
796
    }
797
798
    return false;
799
}
800
801
function bigbluebuttonbn_is_moderator_rule_validation($participant, $userid, $userroles) {
802
803
    if ($participant->role == BIGBLUEBUTTONBN_ROLE_VIEWER) {
804
        return false;
805
    }
806
807
    // Looks for all configuration.
808
    if ($participant->selectiontype == 'all') {
809
        return true;
810
    }
811
812
    // Looks for users.
813
    if ($participant->selectiontype == 'user' && $participant->selectionid == $userid) {
814
        return true;
815
    }
816
817
    // Looks for roles.
818
    $role = bigbluebuttonbn_get_role($participant->selectionid);
819
    if (array_key_exists($role->id, $userroles)) {
820
        return true;
821
    }
822
823
    return false;
824
}
825
826
function bigbluebuttonbn_get_error_key($messagekey, $defaultkey = null) {
827
    if ($messagekey == 'checksumError') {
828
        return 'index_error_checksum';
829
    }
830
    if ($messagekey == 'maxConcurrent') {
831
        return 'view_error_max_concurrent';
832
    }
833
    return $defaultkey;
834
}
835
836
function bigbluebuttonbn_voicebridge_unique($voicebridge, $id = null) {
837
    global $DB;
838
839
    $isunique = true;
840
    if ($voicebridge != 0) {
841
        $table = 'bigbluebuttonbn';
842
        $select = 'voicebridge = '.$voicebridge;
843
        if ($id) {
844
            $select .= ' AND id <> '.$id;
845
        }
846
        if ($DB->get_records_select($table, $select)) {
847
            $isunique = false;
848
        }
849
    }
850
851
    return $isunique;
852
}
853
854
function bigbluebuttonbn_get_duration($closingtime) {
855
    $duration = 0;
856
    $now = time();
857
    if ($closingtime > 0 && $now < $closingtime) {
858
        $duration = ceil(($closingtime - $now) / 60);
859
        $compensationtime = intval(bigbluebuttonbn_get_cfg_scheduled_duration_compensation());
860
        $duration = intval($duration) + $compensationtime;
861
    }
862
863
    return $duration;
864
}
865
866
function bigbluebuttonbn_get_presentation_array($context, $presentation, $id = null) {
867
    $pname = null;
868
    $purl = null;
869
    $picon = null;
870
    $pmimetypedescrip = null;
871
872
    if (!empty($presentation)) {
873
        $fs = get_file_storage();
874
        $files = $fs->get_area_files($context->id, 'mod_bigbluebuttonbn', 'presentation', 0,
875
            'itemid, filepath, filename', false);
876
        if (count($files) >= 1) {
877
            $file = reset($files);
878
            unset($files);
879
            $pname = $file->get_filename();
880
            $picon = file_file_icon($file, 24);
881
            $pmimetypedescrip = get_mimetype_description($file);
882
            $pnoncevalue = null;
883
884
            if (!is_null($id)) {
885
                // Create the nonce component for granting a temporary public access.
886
                $cache = cache::make_from_params(cache_store::MODE_APPLICATION, 'mod_bigbluebuttonbn',
887
                    'presentation_cache');
888
                $pnoncekey = sha1($id);
889
                /* The item id was adapted for granting public access to the presentation once in order
890
                 * to allow BigBlueButton to gather the file. */
891
                $pnoncevalue = bigbluebuttonbn_generate_nonce();
892
                $cache->set($pnoncekey, array('value' => $pnoncevalue, 'counter' => 0));
893
            }
894
            $url = moodle_url::make_pluginfile_url($file->get_contextid(), $file->get_component(),
895
                $file->get_filearea(), $pnoncevalue, $file->get_filepath(), $file->get_filename());
896
897
            $purl = $url->out(false);
898
        }
899
    }
900
901
    $parray = array('url' => $purl, 'name' => $pname,
902
                               'icon' => $picon,
903
                               'mimetype_description' => $pmimetypedescrip);
904
905
    return $parray;
906
}
907
908
function bigbluebuttonbn_generate_nonce() {
909
    $mt = microtime();
910
    $rand = mt_rand();
911
912
    return md5($mt.$rand);
913
}
914
915
function bigbluebuttonbn_random_password($length = 8) {
916
    $chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*()_-=+;:,.?';
917
    $password = substr(str_shuffle($chars), 0, $length);
918
919
    return $password;
920
}
921
922
function bigbluebuttonbn_get_moodle_version_major() {
923
    global $CFG;
924
925
    $versionarray = explode('.', $CFG->version);
926
927
    return $versionarray[0];
928
}
929
930
function bigbluebuttonbn_events() {
931
    return array(
932
        (string) BIGBLUEBUTTON_EVENT_ACTIVITY_VIEWED,
933
        (string) BIGBLUEBUTTON_EVENT_ACTIVITY_MANAGEMENT_VIEWED,
934
        (string) BIGBLUEBUTTON_EVENT_LIVE_SESSION,
935
        (string) BIGBLUEBUTTON_EVENT_MEETING_CREATED,
936
        (string) BIGBLUEBUTTON_EVENT_MEETING_ENDED,
937
        (string) BIGBLUEBUTTON_EVENT_MEETING_JOINED,
938
        (string) BIGBLUEBUTTON_EVENT_MEETING_LEFT,
939
        (string) BIGBLUEBUTTON_EVENT_RECORDING_DELETED,
940
        (string) BIGBLUEBUTTON_EVENT_RECORDING_IMPORTED,
941
        (string) BIGBLUEBUTTON_EVENT_RECORDING_PROTECTED,
942
        (string) BIGBLUEBUTTON_EVENT_RECORDING_PUBLISHED,
943
        (string) BIGBLUEBUTTON_EVENT_RECORDING_UNPROTECTED,
944
        (string) BIGBLUEBUTTON_EVENT_RECORDING_UNPUBLISHED,
945
        (string) BIGBLUEBUTTON_EVENT_RECORDING_EDITED,
946
        (string) BIGBLUEBUTTON_EVENT_RECORDING_VIEWED
947
    );
948
}
949
950
function bigbluebuttonbn_events_action() {
951
    return array(
952
        'view' => (string) BIGBLUEBUTTON_EVENT_ACTIVITY_VIEWED,
953
        'view_management' => (string) BIGBLUEBUTTON_EVENT_ACTIVITY_MANAGEMENT_VIEWED,
954
        'live_action' => (string) BIGBLUEBUTTON_EVENT_LIVE_SESSION,
955
        'meeting_create' => (string) BIGBLUEBUTTON_EVENT_MEETING_CREATED,
956
        'meeting_end' => (string) BIGBLUEBUTTON_EVENT_MEETING_ENDED,
957
        'meeting_join' => (string) BIGBLUEBUTTON_EVENT_MEETING_JOINED,
958
        'meeting_left' => (string) BIGBLUEBUTTON_EVENT_MEETING_LEFT,
959
        'recording_delete' => (string) BIGBLUEBUTTON_EVENT_RECORDING_DELETED,
960
        'recording_import' => (string) BIGBLUEBUTTON_EVENT_RECORDING_IMPORTED,
961
        'recording_protect' => (string) BIGBLUEBUTTON_EVENT_RECORDING_PROTECTED,
962
        'recording_publish' => (string) BIGBLUEBUTTON_EVENT_RECORDING_PUBLISHED,
963
        'recording_unprotect' => (string) BIGBLUEBUTTON_EVENT_RECORDING_UNPROTECTED,
964
        'recording_unpublish' => (string) BIGBLUEBUTTON_EVENT_RECORDING_UNPUBLISHED,
965
        'recording_edit' => (string) BIGBLUEBUTTON_EVENT_RECORDING_EDITED,
966
        'recording_play' => (string) BIGBLUEBUTTON_EVENT_RECORDING_VIEWED
967
    );
968
}
969
970
function bigbluebuttonbn_event_log_standard($eventtype, $bigbluebuttonbn, $cm, $options = []) {
971
972
    $events = bigbluebuttonbn_events();
973
    if (!in_array($eventtype, $events)) {
974
        // No log will be created.
975
        return;
976
    }
977
978
    $context = context_module::instance($cm->id);
979
    $eventproperties = array('context' => $context, 'objectid' => $bigbluebuttonbn->id);
980
    if (array_key_exists('timecreated', $options)) {
981
        $eventproperties['timecreated'] = $options['timecreated'];
982
    }
983
    if (array_key_exists('userid', $options)) {
984
        $eventproperties['userid'] = $options['userid'];
985
    }
986
    if (array_key_exists('other', $options)) {
987
        $eventproperties['other'] = $options['other'];
988
    }
989
990
    $event = call_user_func_array('\mod_bigbluebuttonbn\event\bigbluebuttonbn_'.$eventtype.'::create',
991
      array($eventproperties));
992
    $event->trigger();
993
}
994
995
function bigbluebuttonbn_event_log($eventtype, $bigbluebuttonbn, $cm, $options = []) {
996
    bigbluebuttonbn_event_log_standard($eventtype, $bigbluebuttonbn, $cm, $options);
997
}
998
999
function bigbluebuttonbn_live_session_event_log($event, $bigbluebuttonbn, $cm) {
1000
    bigbluebuttonbn_event_log_standard(BIGBLUEBUTTON_EVENT_LIVE_SESSION, $bigbluebuttonbn, $cm,
1001
        ['timecreated' => $event->timestamp, 'userid' => $event->user, 'other' => $event->event]);
1002
1003
}
1004
1005
/**
1006
 * @param string $meetingid
1007
 * @param bool $ismoderator
1008
 */
1009
function bigbluebuttonbn_participant_joined($meetingid, $ismoderator) {
1010
    $cache = cache::make_from_params(cache_store::MODE_APPLICATION, 'mod_bigbluebuttonbn', 'meetings_cache');
1011
    $result = $cache->get($meetingid);
1012
    $meetinginfo = json_decode($result['meeting_info']);
1013
    $meetinginfo->participantCount += 1;
1014
    if ($ismoderator) {
1015
        $meetinginfo->moderatorCount += 1;
1016
    }
1017
    $cache->set($meetingid, array('creation_time' => $result['creation_time'],
1018
        'meeting_info' => json_encode($meetinginfo)));
1019
}
1020
1021
/**
1022
 * @param string $meetingid
1023
 * @param boolean $forced
1024
 */
1025
function bigbluebuttonbn_get_meeting_info($meetingid, $forced = false) {
1026
    $cachettl = bigbluebuttonbn_get_cfg_waitformoderator_cache_ttl();
1027
1028
    $cache = cache::make_from_params(cache_store::MODE_APPLICATION, 'mod_bigbluebuttonbn', 'meetings_cache');
1029
    $result = $cache->get($meetingid);
1030
    $now = time();
1031
    if (!$forced && isset($result) && $now < ($result['creation_time'] + $cachettl)) {
1032
        // Use the value in the cache.
1033
        return (array) json_decode($result['meeting_info']);
1034
    }
1035
1036
    // Ping again and refresh the cache.
1037
    $meetinginfo = (array) bigbluebuttonbn_wrap_xml_load_file(
1038
        bigbluebuttonbn_bigbluebutton_action_url('getMeetingInfo', ['meetingID' => $meetingid])
1039
      );
1040
    $cache->set($meetingid, array('creation_time' => time(), 'meeting_info' => json_encode($meetinginfo)));
1041
1042
    return $meetinginfo;
1043
}
1044
1045
/**
1046
 * @param string $recordingid
1047
 * @param string $bigbluebuttonbnid
1048
 * @param boolean $publish
1049
 */
1050
function bigbluebuttonbn_publish_recording_imported($recordingid, $bigbluebuttonbnid, $publish = true) {
1051
    global $DB;
1052
1053
    // Locate the record to be updated.
1054
    $records = $DB->get_records('bigbluebuttonbn_logs', array('bigbluebuttonbnid' => $bigbluebuttonbnid,
1055
        'log' => BIGBLUEBUTTONBN_LOG_EVENT_IMPORT));
1056
1057
    foreach ($records as $key => $record) {
1058
        $meta = json_decode($record->meta, true);
1059
        if ($recordingid == $meta['recording']['recordID']) {
1060
            // Found, prepare data for the update.
1061
            $meta['recording']['published'] = ($publish) ? 'true' : 'false';
1062
            $records[$key]->meta = json_encode($meta);
1063
1064
            // Proceed with the update.
1065
            $DB->update_record('bigbluebuttonbn_logs', $records[$key]);
1066
        }
1067
    }
1068
}
1069
1070
function bigbluebuttonbn_delete_recording_imported($recordingid, $bigbluebuttonbnid) {
1071
    global $DB;
1072
1073
    // Locate the record to be updated.
1074
    $records = $DB->get_records('bigbluebuttonbn_logs', array('bigbluebuttonbnid' => $bigbluebuttonbnid,
1075
        'log' => BIGBLUEBUTTONBN_LOG_EVENT_IMPORT));
1076
1077
    foreach ($records as $key => $record) {
1078
        $meta = json_decode($record->meta, true);
1079
        if ($recordingid == $meta['recording']['recordID']) {
1080
            // Execute delete.
1081
            $DB->delete_records('bigbluebuttonbn_logs', array('id' => $key));
1082
        }
1083
    }
1084
}
1085
1086
/**
1087
 * @param string $meetingid
1088
 * @param string $configxml
1089
 */
1090
function bigbluebuttonbn_set_config_xml_params($meetingid, $configxml) {
1091
    $params = 'configXML='.urlencode($configxml).'&meetingID='.urlencode($meetingid);
1092
    $configxmlparams = $params.'&checksum='.sha1('setConfigXML'.$params.bigbluebuttonbn_get_cfg_shared_secret());
1093
1094
    return $configxmlparams;
1095
}
1096
1097
/**
1098
 * @param string $meetingid
1099
 * @param string $configxml
1100
 */
1101
function bigbluebuttonbn_set_config_xml($meetingid, $configxml) {
1102
    $urldefaultconfig = bigbluebuttonbn_get_cfg_server_url().'api/setConfigXML?';
1103
    $configxmlparams = bigbluebuttonbn_set_config_xml_params($meetingid, $configxml);
1104
    $xml = bigbluebuttonbn_wrap_xml_load_file($urldefaultconfig, BIGBLUEBUTTONBN_METHOD_POST,
1105
        $configxmlparams, 'application/x-www-form-urlencoded');
1106
1107
    return $xml;
1108
}
1109
1110
/**
1111
 * @param string $meetingid
1112
 * @param string $configxml
1113
 */
1114
function bigbluebuttonbn_set_config_xml_array($meetingid, $configxml) {
1115
    $configxml = bigbluebuttonbn_setConfigXML($meetingid, $configxml);
1116
    $configxmlarray = (array) $configxml;
1117
    if ($configxmlarray['returncode'] != 'SUCCESS') {
1118
        //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...
1119
        return '';
1120
    }
1121
1122
    return $configxmlarray['configToken'];
1123
}
1124
1125
function bigbluebuttonbn_get_recording_data_row($bbbsession, $recording, $tools = ['protect', 'publish', 'delete']) {
1126
    global $USER;
1127
1128
    $row = null;
1129
1130
    $managerecordings = $bbbsession['managerecordings'];
1131
    if ($managerecordings || $recording['published'] == 'true') {
1132
        $row = new stdClass();
1133
1134
        // Set recording_types.
1135
        $row->recording = bigbluebuttonbn_get_recording_data_row_types($recording, $bbbsession['bigbluebuttonbn']->id);
1136
1137
        // Set activity name and description.
1138
        $row->activity = bigbluebuttonbn_get_recording_data_row_meta_activity($recording, $managerecordings);
1139
        $row->description = bigbluebuttonbn_get_recording_data_row_meta_description($recording, $managerecordings);
1140
1141
        // Set recording_preview.
1142
        $row->preview = bigbluebuttonbn_get_recording_data_row_preview($recording);
1143
1144
        // Set date.
1145
        $starttime = 0;
1146
        if (isset($recording['startTime'])) {
1147
            $starttime = floatval($recording['startTime']);
1148
        }
1149
        $row->date = $starttime;
1150
        $starttime = $starttime - ($starttime % 1000);
1151
1152
        // Set formatted date.
1153
        $dateformat = get_string('strftimerecentfull', 'langconfig').' %Z';
1154
        $row->date_formatted = userdate($starttime / 1000, $dateformat, usertimezone($USER->timezone));
1155
1156
        // Set formatted duration.
1157
        $firstplayback = array_values($recording['playbacks'])[0];
1158
        $length = isset($firstplayback['length']) ? $firstplayback['length'] : 0;
1159
        $row->duration_formatted = $row->duration = intval($length);
1160
1161
        // Set actionbar, if user is allowed to manage recordings.
1162
        if ($managerecordings) {
1163
            $row->actionbar = bigbluebuttonbn_get_recording_data_row_actionbar($recording, $tools);
1164
        }
1165
    }
1166
1167
    return $row;
1168
}
1169
1170
function bigbluebuttonbn_get_recording_data_row_actionbar($recording, $tools) {
1171
    $actionbar = '';
1172
    foreach ($tools as $tool) {
1173
        $actionbar .= bigbluebuttonbn_actionbar_render_button(
1174
            $recording,
1175
            bigbluebuttonbn_get_recording_data_row_actionbar_payload($recording, $tool)
1176
          );
1177
    }
1178
    $head = html_writer::start_tag('div', array(
1179
        'id' => 'recording-actionbar-' . $recording['recordID'],
1180
        'data-recordingid' => $recording['recordID'],
1181
        'data-meetingid' => $recording['meetingID']));
1182
    $tail = html_writer::end_tag('div');
1183
    return $head . $actionbar . $tail;
1184
}
1185
1186
function bigbluebuttonbn_get_recording_data_row_action_protect($protected) {
1187
    if ($protected == 'true') {
1188
        return array('action' => 'unprotect', 'tag' => 'unlock');
1189
    }
1190
1191
    return array('action' => 'protect', 'tag' => 'lock');
1192
}
1193
1194
function bigbluebuttonbn_get_recording_data_row_action_publish($published) {
1195
    if ($published == 'true') {
1196
        return array('action' => 'unpublish', 'tag' => 'hide');
1197
    }
1198
1199
    return array('action' => 'publish', 'tag' => 'show');
1200
}
1201
1202
function bigbluebuttonbn_get_recording_data_row_actionbar_payload($recording, $tool) {
1203
    if ($tool == 'protect' && isset($recording['protected'])) {
1204
        return bigbluebuttonbn_get_recording_data_row_action_protect($recording['protected']);
1205
    }
1206
1207
    if ($tool == 'publish') {
1208
        return bigbluebuttonbn_get_recording_data_row_action_publish($recording['published']);
1209
    }
1210
1211
    if ($tool == 'delete' || $tool == 'import') {
1212
        return array('action' => $tool, 'tag' => $tool);
1213
    }
1214
}
1215
1216
function bigbluebuttonbn_get_recording_data_row_preview($recording) {
1217
1218
    $visibility = '';
1219
    if ($recording['published'] === 'false') {
1220
        $visibility = 'hidden ';
1221
    }
1222
1223
    $recordingpreview = html_writer::start_tag('div',
1224
        array('id' => 'preview-'.$recording['recordID'], $visibility => $visibility));
1225
    foreach ($recording['playbacks'] as $playback) {
1226
        if (isset($playback['preview'])) {
1227
            foreach ($playback['preview'] as $image) {
1228
                $recordingpreview .= html_writer::empty_tag('img',
1229
                    array('src' => $image['url'] . '?' . time(), 'class' => 'thumbnail'));
1230
            }
1231
            $recordingpreview .= html_writer::empty_tag('br');
1232
            $recordingpreview .= html_writer::tag('div',
1233
                get_string('view_recording_preview_help', 'bigbluebuttonbn'), array('class' => 'text-muted small'));
1234
            break;
1235
        }
1236
    }
1237
    $recordingpreview .= html_writer::end_tag('div');
1238
1239
    return $recordingpreview;
1240
}
1241
1242
function bigbluebuttonbn_get_recording_data_row_types($recording, $bigbluebuttonbnid) {
1243
    global $CFG, $OUTPUT;
1244
1245
    $dataimported = 'false';
1246
    $title = '';
1247
    if (isset($recording['imported'])) {
1248
        $dataimported = 'true';
1249
        $title = get_string('view_recording_link_warning', 'bigbluebuttonbn');
1250
    }
1251
1252
    $visibility = '';
1253
    if ($recording['published'] === 'false') {
1254
        $visibility = 'hidden ';
1255
    }
1256
1257
    $id = 'playbacks-'.$recording['recordID'];
1258
    $recordingtypes = html_writer::start_tag('div', array('id' => $id, 'data-imported' => $dataimported,
1259
          'data-recordingid' => $recording['recordID'], 'data-meetingid' => $recording['meetingID'],
1260
          'title' => $title, $visibility => $visibility));
1261
    foreach ($recording['playbacks'] as $playback) {
1262
        $onclick = 'M.mod_bigbluebuttonbn.recordings.recording_play(this);';
1263
        $href = $CFG->wwwroot.'/mod/bigbluebuttonbn/bbb_view.php?action=playback&bn='.$bigbluebuttonbnid.
1264
            '&href='.urlencode($playback['url']).'&rid='.$recording['recordID'];
1265
        $linkattributes = array('title' => get_string('view_recording_format_'.$playback['type'], 'bigbluebuttonbn'),
1266
            'class' => 'btn btn-sm btn-default', 'onclick' => $onclick,
1267
            'data-action' => 'play', 'data-href' => $href);
1268
        $recordingtypes .= $OUTPUT->action_link('#', get_string('view_recording_format_'.$playback['type'],
1269
            'bigbluebuttonbn'), null, $linkattributes).'&#32;';
1270
    }
1271
    $recordingtypes .= html_writer::end_tag('div');
1272
1273
    return $recordingtypes;
1274
}
1275
1276
function bigbluebuttonbn_get_recording_data_row_meta_activity($recording, $editable) {
1277
    $payload = array();
1278 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...
1279
        $payload = array('recordingid' => $recording['recordID'], 'meetingid' => $recording['meetingID'],
1280
            'action' => 'edit', 'tag' => 'edit',
1281
            'target' => 'name', 'source' => 'meta_bbb-recording-name');
1282
    }
1283
    if (isset($recording['meta_contextactivity'])) {
1284
        $payload['source'] = 'meta_contextactivity';
1285
        return bigbluebuttonbn_get_recording_data_row_text($recording, $recording[$payload['source']], $payload);
1286
    }
1287
1288
    if (isset($recording['meta_bbb-recording-name'])) {
1289
        return bigbluebuttonbn_get_recording_data_row_text($recording, $recording[$payload['source']], $payload);
1290
    }
1291
1292
    return bigbluebuttonbn_get_recording_data_row_text($recording, $recording['meetingName'], $payload);
1293
}
1294
1295
function bigbluebuttonbn_get_recording_data_row_meta_description($recording, $editable) {
1296
    $payload = array();
1297 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...
1298
        $payload = array('recordingid' => $recording['recordID'], 'meetingid' => $recording['meetingID'],
1299
            'action' => 'edit', 'tag' => 'edit',
1300
            'target' => 'description', 'source' => 'meta_bbb-recording-description');
1301
    }
1302
1303 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...
1304
        $payload['source'] = 'meta_contextactivitydescription';
1305
        $metadescription = trim($recording[$payload['source']]);
1306
        if (!empty($metadescription)) {
1307
          return bigbluebuttonbn_get_recording_data_row_text($recording, $metadescription, $payload);
1308
        }
1309
    }
1310
1311 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...
1312
        $metadescription = trim($recording[$payload['source']]);
1313
        if (!empty($metadescription)) {
1314
            return bigbluebuttonbn_get_recording_data_row_text($recording, $metadescription, $payload);
1315
        }
1316
    }
1317
1318
    return bigbluebuttonbn_get_recording_data_row_text($recording, '', $payload);
1319
}
1320
1321
function bigbluebuttonbn_get_recording_data_row_text($recording, $text, $data) {
1322
    $htmltext = '<span>' . htmlentities($text) . '</span>';
1323
1324
    if (empty($data)) {
1325
        return $htmltext;
1326
    }
1327
1328
    $target = $data['action'] . '-' . $data['target'];
1329
    $id = 'recording-' . $target . '-' . $data['recordingid'];
1330
    $attributes = array('id' => $id, 'class' => 'quickeditlink col-md-20',
1331
        'data-recordingid' => $data['recordingid'], 'data-meetingid' => $data['meetingid'],
1332
        'data-target' => $data['target'], 'data-source' => $data['source']);
1333
    $head = html_writer::start_tag('div', $attributes);
1334
    $tail = html_writer::end_tag('div');
1335
1336
    $payload = array('action' => $data['action'], 'tag' => $data['tag'], 'target' => $data['target']);
1337
    $htmllink = bigbluebuttonbn_actionbar_render_button($recording, $payload);
1338
1339
    return $head . $htmltext . $htmllink . $tail;
1340
}
1341
1342
function bigbluebuttonbn_actionbar_render_button($recording, $data) {
1343
    global $OUTPUT;
1344
1345
    if (!$data) {
1346
        return '';
1347
    }
1348
1349
    $target = $data['action'];
1350
    if (isset($data['target'])) {
1351
        $target .= '-' . $data['target'];
1352
    }
1353
    $id = 'recording-' . $target . '-' . $recording['recordID'];
1354
    $onclick = 'M.mod_bigbluebuttonbn.recordings.recording_'.$data['action'].'(this);';
1355
    if (bigbluebuttonbn_get_cfg_recording_icons_enabled()) {
1356
        // With icon for $manageaction.
1357
        $iconattributes = array('id' => $id, 'class' => 'iconsmall');
1358
        $icon = new pix_icon('i/'.$data['tag'],
1359
            get_string('view_recording_list_actionbar_' . $data['action'], 'bigbluebuttonbn'),
1360
            'moodle', $iconattributes);
1361
        $linkattributes = array(
1362
            'id' => $id,
1363
            'onclick' => $onclick,
1364
            'data-action' => $data['action'],
1365
            'data-links' => bigbluebuttonbn_get_count_recording_imported_instances($recording['recordID'])
1366
          );
1367
        return $OUTPUT->action_icon('#', $icon, null, $linkattributes, false);
1368
    }
1369
1370
    // With text for $manageaction.
1371
    $linkattributes = array('title' => get_string($data['tag']), 'class' => 'btn btn-xs btn-danger',
1372
        'onclick' => $onclick);
1373
    return $OUTPUT->action_link('#', get_string($data['action']), null, $linkattributes);
1374
}
1375
1376
function bigbluebuttonbn_get_recording_columns($bbbsession) {
1377
    // Set strings to show.
1378
    $recording = get_string('view_recording_recording', 'bigbluebuttonbn');
1379
    $activity = get_string('view_recording_activity', 'bigbluebuttonbn');
1380
    $description = get_string('view_recording_description', 'bigbluebuttonbn');
1381
    $preview = get_string('view_recording_preview', 'bigbluebuttonbn');
1382
    $date = get_string('view_recording_date', 'bigbluebuttonbn');
1383
    $duration = get_string('view_recording_duration', 'bigbluebuttonbn');
1384
    $actionbar = get_string('view_recording_actionbar', 'bigbluebuttonbn');
1385
1386
    // Initialize table headers.
1387
    $recordingsbncolumns = array(
1388
        array('key' => 'recording', 'label' => $recording, 'width' => '125px', 'allowHTML' => true),
1389
        array('key' => 'activity', 'label' => $activity, 'sortable' => true, 'width' => '175px', 'allowHTML' => true),
1390
        array('key' => 'description', 'label' => $description, 'width' => '250px', 'sortable' => true,
1391
            'width' => '250px', 'allowHTML' => true),
1392
        array('key' => 'preview', 'label' => $preview, 'width' => '250px', 'allowHTML' => true),
1393
        array('key' => 'date', 'label' => $date, 'sortable' => true, 'width' => '225px', 'allowHTML' => true),
1394
        array('key' => 'duration', 'label' => $duration, 'width' => '50px'),
1395
        );
1396
1397
    if ($bbbsession['managerecordings']) {
1398
        array_push($recordingsbncolumns, array('key' => 'actionbar', 'label' => $actionbar, 'width' => '100px',
1399
            'allowHTML' => true));
1400
    }
1401
1402
    return $recordingsbncolumns;
1403
}
1404
1405
function bigbluebuttonbn_get_recording_data($bbbsession, $recordings, $tools = ['protect', 'publish', 'delete']) {
1406
    $tabledata = array();
1407
1408
    // Build table content.
1409
    if (isset($recordings) && !array_key_exists('messageKey', $recordings)) {
1410
        // There are recordings for this meeting.
1411
        foreach ($recordings as $recording) {
1412
            $row = bigbluebuttonbn_get_recording_data_row($bbbsession, $recording, $tools);
1413
            if ($row != null) {
1414
                array_push($tabledata, $row);
1415
            }
1416
        }
1417
    }
1418
1419
    return $tabledata;
1420
}
1421
1422
function bigbluebuttonbn_get_recording_table($bbbsession, $recordings, $tools = ['protect', 'publish', 'delete']) {
1423
    // Set strings to show.
1424
    $recording = get_string('view_recording_recording', 'bigbluebuttonbn');
1425
    $description = get_string('view_recording_description', 'bigbluebuttonbn');
1426
    $date = get_string('view_recording_date', 'bigbluebuttonbn');
1427
    $duration = get_string('view_recording_duration', 'bigbluebuttonbn');
1428
    $actionbar = get_string('view_recording_actionbar', 'bigbluebuttonbn');
1429
    $playback = get_string('view_recording_playback', 'bigbluebuttonbn');
1430
    $preview = get_string('view_recording_preview', 'bigbluebuttonbn');
1431
1432
    // Declare the table.
1433
    $table = new html_table();
1434
    $table->data = array();
1435
1436
    // Initialize table headers.
1437
    $table->head = array($playback, $recording, $description, $preview, $date, $duration);
1438
    $table->align = array('left', 'left', 'left', 'left', 'left', 'center');
1439
    if ($bbbsession['managerecordings']) {
1440
        $table->head[] = $actionbar;
1441
        $table->align[] = 'left';
1442
    }
1443
1444
    // Build table content.
1445
    if (isset($recordings) && !array_key_exists('messageKey', $recordings)) {
1446
        // There are recordings for this meeting.
1447
        foreach ($recordings as $recording) {
1448
            $row = new html_table_row();
1449
            $row->id = 'recording-td-'.$recording['recordID'];
1450
            $row->attributes['data-imported'] = 'false';
1451
            $texthead = '';
1452
            $texttail = '';
1453
            if (isset($recording['imported'])) {
1454
                $row->attributes['data-imported'] = 'true';
1455
                $row->attributes['title'] = get_string('view_recording_link_warning', 'bigbluebuttonbn');
1456
                $texthead = '<em>';
1457
                $texttail = '</em>';
1458
            }
1459
1460
            $rowdata = bigbluebuttonbn_get_recording_data_row($bbbsession, $recording, $tools);
1461
            if ($rowdata != null) {
1462
                $rowdata->date_formatted = str_replace(' ', '&nbsp;', $rowdata->date_formatted);
1463
                $row->cells = array($texthead.$rowdata->recording.$texttail,
1464
                    $texthead.$rowdata->activity.$texttail, $texthead.$rowdata->description.$texttail,
1465
                    $rowdata->preview, $texthead.$rowdata->date_formatted.$texttail,
1466
                    $rowdata->duration_formatted);
1467
                if ($bbbsession['managerecordings']) {
1468
                    $row->cells[] = $rowdata->actionbar;
1469
                }
1470
                array_push($table->data, $row);
1471
            }
1472
        }
1473
    }
1474
1475
    return $table;
1476
}
1477
1478
function bigbluebuttonbn_send_notification_recording_ready($bigbluebuttonbn) {
1479
    $sender = get_admin();
1480
1481
    // Prepare message.
1482
    $msg = new stdClass();
1483
1484
    // Build the message_body.
1485
    $msg->activity_type = '';
1486
    $msg->activity_title = $bigbluebuttonbn->name;
1487
    $messagetext = '<p>'.get_string('email_body_recording_ready_for', 'bigbluebuttonbn').' '.
1488
        $msg->activity_type.' &quot;'.$msg->activity_title.'&quot; '.
1489
        get_string('email_body_recording_ready_is_ready', 'bigbluebuttonbn').'.</p>';
1490
1491
    bigbluebuttonbn_send_notification($sender, $bigbluebuttonbn, $messagetext);
1492
}
1493
1494
function bigbluebuttonbn_is_bn_server() {
1495
    // Validates if the server may have extended capabilities.
1496
    $parsedurl = parse_url(bigbluebuttonbn_get_cfg_server_url());
1497
    if (!isset($parsedurl['host'])) {
1498
        return false;
1499
    }
1500
1501
    $h = $parsedurl['host'];
1502
    $hends = explode('.', $h);
1503
    $hendslength = count($hends);
1504
1505
    return ($hends[$hendslength - 1] == 'com' && $hends[$hendslength - 2] == 'blindsidenetworks');
1506
}
1507
1508
/**
1509
 * @return string
1510
 */
1511
function bigbluebuttonbn_get_cfg_server_url() {
1512
    global $CFG;
1513
1514
    if (isset($CFG->bigbluebuttonbn['server_url'])) {
1515
        return trim(trim($CFG->bigbluebuttonbn['server_url']), '/').'/';
1516
    }
1517
1518
    if (isset($CFG->bigbluebuttonbn_server_url)) {
1519
        return trim(trim($CFG->bigbluebuttonbn_server_url), '/').'/';
1520
    }
1521
1522
    if (isset($CFG->BigBlueButtonBNServerURL)) {
1523
        return trim(trim($CFG->BigBlueButtonBNServerURL), '/').'/';
1524
    }
1525
1526
    return  BIGBLUEBUTTONBN_DEFAULT_SERVER_URL;
1527
}
1528
1529
/**
1530
 * @return string
1531
 */
1532
function bigbluebuttonbn_get_cfg_shared_secret() {
1533
    global $CFG;
1534
1535
    if (isset($CFG->bigbluebuttonbn['shared_secret'])) {
1536
        return trim($CFG->bigbluebuttonbn['shared_secret']);
1537
    }
1538
1539
    if (isset($CFG->bigbluebuttonbn_shared_secret)) {
1540
        return trim($CFG->bigbluebuttonbn_shared_secret);
1541
    }
1542
1543
    if (isset($CFG->BigBlueButtonBNSecuritySalt)) {
1544
        return trim($CFG->BigBlueButtonBNSecuritySalt);
1545
    }
1546
1547
    return  BIGBLUEBUTTONBN_DEFAULT_SHARED_SECRET;
1548
}
1549
1550
/**
1551
 * @return boolean
1552
 */
1553
function bigbluebuttonbn_get_cfg_voicebridge_editable() {
1554
    global $CFG;
1555
1556
    if (isset($CFG->bigbluebuttonbn['voicebridge_editable'])) {
1557
        return $CFG->bigbluebuttonbn['voicebridge_editable'];
1558
    }
1559
1560
    if (isset($CFG->bigbluebuttonbn_voicebridge_editable)) {
1561
        return $CFG->bigbluebuttonbn_voicebridge_editable;
1562
    }
1563
1564
    return  false;
1565
}
1566
1567
/**
1568
 * @return boolean
1569
 */
1570
function bigbluebuttonbn_get_cfg_recording_default() {
1571
    global $CFG;
1572
1573
    if (isset($CFG->bigbluebuttonbn['recording_default'])) {
1574
        return $CFG->bigbluebuttonbn['recording_default'];
1575
    }
1576
1577
    if (isset($CFG->bigbluebuttonbn_recording_default)) {
1578
        return $CFG->bigbluebuttonbn_recording_default;
1579
    }
1580
1581
    return  true;
1582
}
1583
1584
/**
1585
 * @return string
1586
 */
1587
function bigbluebuttonbn_get_cfg_recording_editable() {
1588
    global $CFG;
1589
1590
    if (isset($CFG->bigbluebuttonbn['recording_editable'])) {
1591
        return $CFG->bigbluebuttonbn['recording_editable'];
1592
    }
1593
1594
    if (isset($CFG->bigbluebuttonbn_recording_editable)) {
1595
        return $CFG->bigbluebuttonbn_recording_editable;
1596
    }
1597
1598
    return  true;
1599
}
1600
1601
/**
1602
 * @return boolean
1603
 */
1604
function bigbluebuttonbn_get_cfg_recording_icons_enabled() {
1605
    global $CFG;
1606
1607
    if (isset($CFG->bigbluebuttonbn['recording_icons_enabled'])) {
1608
        return $CFG->bigbluebuttonbn['recording_icons_enabled'];
1609
    }
1610
1611
    if (isset($CFG->bigbluebuttonbn_recording_icons_enabled)) {
1612
        return $CFG->bigbluebuttonbn_recording_icons_enabled;
1613
    }
1614
1615
    return  true;
1616
}
1617
1618
/**
1619
 * @return boolean
1620
 */
1621
function bigbluebuttonbn_get_cfg_importrecordings_enabled() {
1622
    global $CFG;
1623
1624
    if (isset($CFG->bigbluebuttonbn['importrecordings_enabled'])) {
1625
        return $CFG->bigbluebuttonbn['importrecordings_enabled'];
1626
    }
1627
1628
    if (isset($CFG->bigbluebuttonbn_importrecordings_enabled)) {
1629
        return $CFG->bigbluebuttonbn_importrecordings_enabled;
1630
    }
1631
1632
    return  false;
1633
}
1634
1635
/**
1636
 * @return boolean
1637
 */
1638
function bigbluebuttonbn_get_cfg_importrecordings_from_deleted_activities_enabled() {
1639
    global $CFG;
1640
1641
    if (isset($CFG->bigbluebuttonbn['importrecordings_from_deleted_activities_enabled'])) {
1642
        return $CFG->bigbluebuttonbn['importrecordings_from_deleted_activities_enabled'];
1643
    }
1644
1645
    if (isset($CFG->bigbluebuttonbn_importrecordings_from_deleted_activities_enabled)) {
1646
        return $CFG->bigbluebuttonbn_importrecordings_from_deleted_activities_enabled;
1647
    }
1648
1649
    return  false;
1650
}
1651
1652
/**
1653
 * @return boolean
1654
 */
1655
function bigbluebuttonbn_get_cfg_waitformoderator_default() {
1656
    global $CFG;
1657
1658
    if (isset($CFG->bigbluebuttonbn['waitformoderator_default'])) {
1659
        return $CFG->bigbluebuttonbn['waitformoderator_default'];
1660
    }
1661
1662
    if (isset($CFG->bigbluebuttonbn_waitformoderator_default)) {
1663
        return $CFG->bigbluebuttonbn_waitformoderator_default;
1664
    }
1665
1666
    return  false;
1667
}
1668
1669
/**
1670
 * @return boolean
1671
 */
1672
function bigbluebuttonbn_get_cfg_waitformoderator_editable() {
1673
    global $CFG;
1674
1675
    if (isset($CFG->bigbluebuttonbn['waitformoderator_editable'])) {
1676
        return $CFG->bigbluebuttonbn['waitformoderator_editable'];
1677
    }
1678
1679
    if (isset($CFG->bigbluebuttonbn_waitformoderator_editable)) {
1680
        return $CFG->bigbluebuttonbn_waitformoderator_editable;
1681
    }
1682
1683
    return  true;
1684
}
1685
1686
/**
1687
 * @return number
1688
 */
1689
function bigbluebuttonbn_get_cfg_waitformoderator_ping_interval() {
1690
    global $CFG;
1691
1692
    if (isset($CFG->bigbluebuttonbn['waitformoderator_ping_interval'])) {
1693
        return $CFG->bigbluebuttonbn['waitformoderator_ping_interval'];
1694
    }
1695
1696
    if (isset($CFG->bigbluebuttonbn_waitformoderator_ping_interval)) {
1697
        return $CFG->bigbluebuttonbn_waitformoderator_ping_interval;
1698
    }
1699
1700
    return  10;
1701
}
1702
1703
/**
1704
 * @return number
1705
 */
1706
function bigbluebuttonbn_get_cfg_waitformoderator_cache_ttl() {
1707
    global $CFG;
1708
1709
    if (isset($CFG->bigbluebuttonbn['waitformoderator_cache_ttl'])) {
1710
        return $CFG->bigbluebuttonbn['waitformoderator_cache_ttl'];
1711
    }
1712
1713
    if (isset($CFG->bigbluebuttonbn_waitformoderator_cache_ttl)) {
1714
        return $CFG->bigbluebuttonbn_waitformoderator_cache_ttl;
1715
    }
1716
1717
    return  60;
1718
}
1719
1720
/**
1721
 * @return number
1722
 */
1723
function bigbluebuttonbn_get_cfg_userlimit_default() {
1724
    global $CFG;
1725
1726
    if (isset($CFG->bigbluebuttonbn['userlimit_default'])) {
1727
        return $CFG->bigbluebuttonbn['userlimit_default'];
1728
    }
1729
1730
    if (isset($CFG->bigbluebuttonbn_userlimit_default)) {
1731
        return $CFG->bigbluebuttonbn_userlimit_default;
1732
    }
1733
1734
    return  0;
1735
}
1736
1737
/**
1738
 * @return boolean
1739
 */
1740
function bigbluebuttonbn_get_cfg_userlimit_editable() {
1741
    global $CFG;
1742
1743
    if (isset($CFG->bigbluebuttonbn['userlimit_editable'])) {
1744
        return $CFG->bigbluebuttonbn['userlimit_editable'];
1745
    }
1746
1747
    if (isset($CFG->bigbluebuttonbn_userlimit_editable)) {
1748
        return $CFG->bigbluebuttonbn_userlimit_editable;
1749
    }
1750
1751
    return  false;
1752
}
1753
1754
/**
1755
 * @return boolean
1756
 */
1757
function bigbluebuttonbn_get_cfg_preuploadpresentation_enabled() {
1758
    global $CFG;
1759
1760
    if (!extension_loaded('curl')) {
1761
        return false;
1762
    }
1763
1764
    if (isset($CFG->bigbluebuttonbn['preuploadpresentation_enabled'])) {
1765
        return $CFG->bigbluebuttonbn['preuploadpresentation_enabled'];
1766
    }
1767
1768
    if (isset($CFG->bigbluebuttonbn_preuploadpresentation_enabled)) {
1769
        return $CFG->bigbluebuttonbn_preuploadpresentation_enabled;
1770
    }
1771
1772
    return  false;
1773
}
1774
1775
/**
1776
 * @return boolean
1777
 */
1778
function bigbluebuttonbn_get_cfg_sendnotifications_enabled() {
1779
    global $CFG;
1780
1781
    if (isset($CFG->bigbluebuttonbn['sendnotifications_enabled'])) {
1782
        return $CFG->bigbluebuttonbn['sendnotifications_enabled'];
1783
    }
1784
1785
    if (isset($CFG->bigbluebuttonbn_sendnotifications_enabled)) {
1786
        return $CFG->bigbluebuttonbn_sendnotifications_enabled;
1787
    }
1788
1789
    return  false;
1790
}
1791
1792
/**
1793
 * @return boolean
1794
 */
1795
function bigbluebuttonbn_get_cfg_recordingready_enabled() {
1796
    global $CFG;
1797
1798
    if (isset($CFG->bigbluebuttonbn['recordingready_enabled'])) {
1799
        return $CFG->bigbluebuttonbn['recordingready_enabled'];
1800
    }
1801
1802
    if (isset($CFG->bigbluebuttonbn_recordingready_enabled)) {
1803
        return $CFG->bigbluebuttonbn_recordingready_enabled;
1804
    }
1805
1806
    return  false;
1807
}
1808
1809
/**
1810
 * @return boolean
1811
 */
1812
function bigbluebuttonbn_get_cfg_recordingstatus_enabled() {
1813
    global $CFG;
1814
1815
    if (isset($CFG->bigbluebuttonbn['recordingstatus_enabled'])) {
1816
        return $CFG->bigbluebuttonbn['recordingstatus_enabled'];
1817
    }
1818
1819
    if (isset($CFG->bigbluebuttonbn_recordingstatus_enabled)) {
1820
        return $CFG->bigbluebuttonbn_recordingstatus_enabled;
1821
    }
1822
1823
    return  false;
1824
}
1825
1826
1827
/**
1828
 * @return boolean
1829
 */
1830
function bigbluebuttonbn_get_cfg_meetingevents_enabled() {
1831
    global $CFG;
1832
1833
    if (isset($CFG->bigbluebuttonbn['meetingevents_enabled'])) {
1834
        return $CFG->bigbluebuttonbn['meetingevents_enabled'];
1835
    }
1836
1837
    if (isset($CFG->bigbluebuttonbn_meetingevents_enabled)) {
1838
        return $CFG->bigbluebuttonbn_meetingevents_enabled;
1839
    }
1840
1841
    return  false;
1842
}
1843
1844
/**
1845
 * @return string
1846
 */
1847
function bigbluebuttonbn_get_cfg_moderator_default() {
1848
    global $CFG;
1849
1850
    if (isset($CFG->bigbluebuttonbn['moderator_default'])) {
1851
        return $CFG->bigbluebuttonbn['moderator_default'];
1852
    }
1853
1854
    if (isset($CFG->bigbluebuttonbn_moderator_default)) {
1855
        return $CFG->bigbluebuttonbn_moderator_default;
1856
    }
1857
1858
    return  'owner';
1859
}
1860
1861
/**
1862
 * @return boolean
1863
 */
1864
function bigbluebuttonbn_get_cfg_scheduled_duration_enabled() {
1865
    global $CFG;
1866
1867
    if (isset($CFG->bigbluebuttonbn['scheduled_duration_enabled'])) {
1868
        return $CFG->bigbluebuttonbn['scheduled_duration_enabled'];
1869
    }
1870
1871
    if (isset($CFG->bigbluebuttonbn_scheduled_duration_enabled)) {
1872
        return $CFG->bigbluebuttonbn_scheduled_duration_enabled;
1873
    }
1874
1875
    return  false;
1876
}
1877
1878
/**
1879
 * @return number
1880
 */
1881
function bigbluebuttonbn_get_cfg_scheduled_duration_compensation() {
1882
    global $CFG;
1883
1884
    if (isset($CFG->bigbluebuttonbn['scheduled_duration_compensation'])) {
1885
        return $CFG->bigbluebuttonbn['scheduled_duration_compensation'];
1886
    }
1887
1888
    if (isset($CFG->bigbluebuttonbn_scheduled_duration_compensation)) {
1889
        return $CFG->bigbluebuttonbn_scheduled_duration_compensation;
1890
    }
1891
1892
    return  10;
1893
}
1894
1895
/**
1896
 * @return number
1897
 */
1898
function bigbluebuttonbn_get_cfg_scheduled_pre_opening() {
1899
    global $CFG;
1900
1901
    if (isset($CFG->bigbluebuttonbn['scheduled_pre_opening'])) {
1902
        return $CFG->bigbluebuttonbn['scheduled_pre_opening'];
1903
    }
1904
1905
    if (isset($CFG->bigbluebuttonbn_scheduled_pre_opening)) {
1906
        return $CFG->bigbluebuttonbn_scheduled_pre_opening;
1907
    }
1908
1909
    return  10;
1910
}
1911
1912
/**
1913
 * @return boolean
1914
 */
1915
function bigbluebuttonbn_get_cfg_recordings_html_default() {
1916
    global $CFG;
1917
1918
    if (isset($CFG->bigbluebuttonbn['recordings_html_default'])) {
1919
        return $CFG->bigbluebuttonbn['recordings_html_default'];
1920
    }
1921
1922
    if (isset($CFG->bigbluebuttonbn_recordings_html_default)) {
1923
        return $CFG->bigbluebuttonbn_recordings_html_default;
1924
    }
1925
1926
    return  false;
1927
}
1928
1929
/**
1930
 * @return boolean
1931
 */
1932
function bigbluebuttonbn_get_cfg_recordings_html_editable() {
1933
    global $CFG;
1934
1935
    if (isset($CFG->bigbluebuttonbn['recordings_html_editable'])) {
1936
        return $CFG->bigbluebuttonbn['recordings_html_editable'];
1937
    }
1938
1939
    if (isset($CFG->bigbluebuttonbn_recordings_html_editable)) {
1940
        return $CFG->bigbluebuttonbn_recordings_html_editable;
1941
    }
1942
1943
    return  false;
1944
}
1945
1946
/**
1947
 * @return boolean
1948
 */
1949
function bigbluebuttonbn_get_cfg_recordings_deleted_activities_default() {
1950
    global $CFG;
1951
1952
    if (isset($CFG->bigbluebuttonbn['recordings_deleted_activities_default'])) {
1953
        return $CFG->bigbluebuttonbn['recordings_deleted_activities_default'];
1954
    }
1955
1956
    if (isset($CFG->bigbluebuttonbn_recordings_deleted_activities_default)) {
1957
        return $CFG->bigbluebuttonbn_recordings_deleted_activities_default;
1958
    }
1959
1960
    return  false;
1961
}
1962
1963
/**
1964
 * @return boolean
1965
 */
1966
function bigbluebuttonbn_get_cfg_recordings_deleted_activities_editable() {
1967
    global $CFG;
1968
1969
    if (isset($CFG->bigbluebuttonbn['recordings_deleted_activities_editable'])) {
1970
        return $CFG->bigbluebuttonbn['recordings_deleted_activities_editable'];
1971
    }
1972
1973
    if (isset($CFG->bigbluebuttonbn_recordings_deleted_activities_editable)) {
1974
        return $CFG->bigbluebuttonbn_recordings_deleted_activities_editable;
1975
    }
1976
1977
    return  false;
1978
}
1979
1980
/**
1981
 * @return array
1982
 */
1983
function bigbluebuttonbn_get_cfg_options() {
1984
    return [
1985
          'version_major' => bigbluebuttonbn_get_moodle_version_major(),
1986
          'voicebridge_editable' => bigbluebuttonbn_get_cfg_voicebridge_editable(),
1987
          'recording_default' => bigbluebuttonbn_get_cfg_recording_default(),
1988
          'recording_editable' => bigbluebuttonbn_get_cfg_recording_editable(),
1989
          'waitformoderator_default' => bigbluebuttonbn_get_cfg_waitformoderator_default(),
1990
          'waitformoderator_editable' => bigbluebuttonbn_get_cfg_waitformoderator_editable(),
1991
          'userlimit_default' => bigbluebuttonbn_get_cfg_userlimit_default(),
1992
          'userlimit_editable' => bigbluebuttonbn_get_cfg_userlimit_editable(),
1993
          'preuploadpresentation_enabled' => bigbluebuttonbn_get_cfg_preuploadpresentation_enabled(),
1994
          'sendnotifications_enabled' => bigbluebuttonbn_get_cfg_sendnotifications_enabled(),
1995
          'recordings_html_default' => bigbluebuttonbn_get_cfg_recordings_html_default(),
1996
          'recordings_html_editable' => bigbluebuttonbn_get_cfg_recordings_html_editable(),
1997
          'recordings_deleted_activities_default' => bigbluebuttonbn_get_cfg_recordings_deleted_activities_default(),
1998
          'recordings_deleted_activities_editable' => bigbluebuttonbn_get_cfg_recordings_deleted_activities_editable(),
1999
          'recording_icons_enabled' => bigbluebuttonbn_get_cfg_recording_icons_enabled(),
2000
          'instance_type_enabled' => bigbluebuttonbn_recordings_enabled(),
2001
          'instance_type_default' => BIGBLUEBUTTONBN_TYPE_ALL,
2002
        ];
2003
}
2004
2005
function bigbluebuttonbn_import_get_courses_for_select(array $bbbsession) {
2006
    if ($bbbsession['administrator']) {
2007
        $courses = get_courses('all', 'c.id ASC', 'c.id,c.shortname,c.fullname');
2008
        // It includes the name of the site as a course (category 0), so remove the first one.
2009
        unset($courses['1']);
2010
    } else {
2011
        $courses = enrol_get_users_courses($bbbsession['userID'], false, 'id,shortname,fullname');
2012
    }
2013
2014
    $coursesforselect = [];
2015
    foreach ($courses as $course) {
2016
        $coursesforselect[$course->id] = $course->fullname;
2017
    }
2018
2019
    return $coursesforselect;
2020
}
2021
2022
function bigbluebutton_output_recording_table($bbbsession, $recordings, $tools = ['protect', 'publish', 'delete']) {
2023
    if (isset($recordings) && !empty($recordings)) {
2024
        // There are recordings for this meeting.
2025
        $table = bigbluebuttonbn_get_recording_table($bbbsession, $recordings, $tools);
2026
    }
2027
2028
    if (!isset($table) || !isset($table->data)) {
2029
        // Render a table qith "No recordings".
2030
        return html_writer::div(get_string('view_message_norecordings', 'bigbluebuttonbn'), '',
2031
            array('id' => 'bigbluebuttonbn_html_table'));
2032
    }
2033
2034
    // Render the table.
2035
    return html_writer::div(html_writer::table($table), '', array('id' => 'bigbluebuttonbn_html_table'));
2036
}
2037
2038
function bigbluebuttonbn_html2text($html, $len) {
2039
    $text = strip_tags($html);
2040
    $text = str_replace('&nbsp;', ' ', $text);
2041
    $text = substr($text, 0, $len);
2042
    if (strlen($text) > $len) {
2043
        $text .= '...';
2044
    }
2045
2046
    return $text;
2047
}
2048
2049
/**
2050
 * helper function to obtain the tags linked to a bigbluebuttonbn activity
2051
 *
2052
 * @param string $id
2053
 *
2054
 * @return string containing the tags separated by commas
2055
 */
2056
function bigbluebuttonbn_get_tags($id) {
2057
    $tagsarray = core_tag_tag::get_item_tags_array('core', 'course_modules', $id);
2058
    return implode(',', $tagsarray);
2059
}
2060
2061
/**
2062
 * helper function to retrieve recordings from the BigBlueButton. The references are stored as events
2063
 * in bigbluebuttonbn_logs.
2064
 *
2065
 * @param string $courseid
2066
 * @param string $bigbluebuttonbnid
2067
 * @param bool   $subset
2068
 * @param bool   $includedeleted
2069
 *
2070
 * @return associative array containing the recordings indexed by recordID, each recording is also a
2071
 * non sequential associative array itself that corresponds to the actual recording in BBB
2072
 */
2073
function bigbluebuttonbn_get_recordings($courseid, $bigbluebuttonbnid = null,
2074
        $subset = true, $includedeleted = false) {
2075
    global $DB;
2076
2077
    // Gather the bigbluebuttonbnids whose meetingids should be included in the getRecordings request'.
2078
    $select = "id <> '{$bigbluebuttonbnid}' AND course = '{$courseid}'";
2079
    $selectdeleted = "courseid = '{$courseid}' AND bigbluebuttonbnid <> '{$bigbluebuttonbnid}' AND log = '".
2080
        BIGBLUEBUTTONBN_LOG_EVENT_DELETE."' AND meta like '%has_recordings%' AND meta like '%true%'";
2081
    if ($bigbluebuttonbnid === null) {
2082
        $select = "course = '{$courseid}'";
2083
        $selectdeleted = "courseid = '{$courseid}' AND log = '".BIGBLUEBUTTONBN_LOG_EVENT_DELETE.
2084
            "' AND meta like '%has_recordings%' AND meta like '%true%'";
2085
    } else if ($subset) {
2086
        $select = "id = '{$bigbluebuttonbnid}'";
2087
        $selectdeleted = "bigbluebuttonbnid = '{$bigbluebuttonbnid}' AND log = '".BIGBLUEBUTTONBN_LOG_EVENT_DELETE.
2088
            "' AND meta like '%has_recordings%' AND meta like '%true%'";
2089
    }
2090
    $bigbluebuttonbns = $DB->get_records_select_menu('bigbluebuttonbn', $select, null, 'id', 'id, meetingid');
2091
2092
    /* Consider logs from deleted bigbluebuttonbn instances whose meetingids should be included in
2093
     * the getRecordings request. */
2094
    if ($includedeleted) {
2095
        $bigbluebuttonbnsdel = $DB->get_records_select_menu('bigbluebuttonbn_logs', $selectdeleted, null,
2096
            'bigbluebuttonbnid', 'bigbluebuttonbnid, meetingid');
2097
        if (!empty($bigbluebuttonbnsdel)) {
2098
            // Merge bigbluebuttonbnis from deleted instances, only keys are relevant.
2099
            // Artimetic merge is used in order to keep the keys.
2100
            $bigbluebuttonbns += $bigbluebuttonbnsdel;
2101
        }
2102
    }
2103
2104
    // Gather the meetingids from bigbluebuttonbn logs that include a create with record=true.
2105
    $recordings = array();
2106
    if (!empty($bigbluebuttonbns)) {
2107
        // Prepare select for loading records based on existent bigbluebuttonbns.
2108
        $sql = 'SELECT DISTINCT meetingid, bigbluebuttonbnid FROM {bigbluebuttonbn_logs} WHERE ';
2109
        $sql .= '(bigbluebuttonbnid='.implode(' OR bigbluebuttonbnid=', array_keys($bigbluebuttonbns)).')';
2110
        // Include only Create events and exclude those with record not true.
2111
        $sql .= ' AND log = ? AND meta LIKE ? AND meta LIKE ?';
2112
        // Execute select for loading records based on existent bigbluebuttonbns.
2113
        $records = $DB->get_records_sql_menu($sql, array(BIGBLUEBUTTONBN_LOG_EVENT_CREATE, '%record%', '%true%'));
2114
        // Get actual recordings.
2115
        $recordings = bigbluebuttonbn_get_recordings_array(array_keys($records));
2116
    }
2117
2118
    // Get recording links.
2119
    $recordingsimported = bigbluebuttonbn_get_recordings_imported_array($courseid, $bigbluebuttonbnid, $subset);
2120
2121
    /* Perform aritmetic add instead of merge so the imported recordings corresponding to existent recordings
2122
     * are not included. */
2123
    return $recordings + $recordingsimported;
2124
}
2125
2126
function bigbluebuttonbn_unset_existent_recordings_already_imported($recordings, $courseid, $bigbluebuttonbnid) {
2127
    $recordingsimported = bigbluebuttonbn_get_recordings_imported_array($courseid, $bigbluebuttonbnid, true);
2128
2129
    foreach ($recordings as $key => $recording) {
2130
        if (isset($recordingsimported[$recording['recordID']])) {
2131
            unset($recordings[$key]);
2132
        }
2133
    }
2134
2135
    return $recordings;
2136
}
2137
2138
function bigbluebuttonbn_get_count_recording_imported_instances($recordid) {
2139
    global $DB;
2140
2141
    $sql = 'SELECT COUNT(DISTINCT id) FROM {bigbluebuttonbn_logs} WHERE log = ? AND meta LIKE ? AND meta LIKE ?';
2142
2143
    return $DB->count_records_sql($sql, array(BIGBLUEBUTTONBN_LOG_EVENT_IMPORT, '%recordID%', "%{$recordid}%"));
2144
}
2145
2146
function bigbluebuttonbn_get_recording_imported_instances($recordid) {
2147
    global $DB;
2148
2149
    $sql = 'SELECT * FROM {bigbluebuttonbn_logs} WHERE log = ? AND meta LIKE ? AND meta LIKE ?';
2150
    $recordingsimported = $DB->get_records_sql($sql, array(BIGBLUEBUTTONBN_LOG_EVENT_IMPORT, '%recordID%',
2151
        "%{$recordid}%"));
2152
2153
    return $recordingsimported;
2154
}
2155
2156
function bigbluebuttonbn_get_instance_type_profiles() {
2157
    $instanceprofiles = array(
2158
            array('id' => BIGBLUEBUTTONBN_TYPE_ALL, 'name' => get_string('instance_type_default', 'bigbluebuttonbn'),
2159
                'features' => array('all')),
2160
            array('id' => BIGBLUEBUTTONBN_TYPE_ROOM_ONLY, 'name' => get_string('instance_type_room_only', 'bigbluebuttonbn'),
2161
                'features' => array('showroom', 'welcomemessage', 'voicebridge', 'waitformoderator', 'userlimit', 'recording',
2162
                    'sendnotifications', 'preuploadpresentation', 'permissions', 'schedule', 'groups')),
2163
            array('id' => BIGBLUEBUTTONBN_TYPE_RECORDING_ONLY, 'name' => get_string('instance_type_recording_only',
2164
                'bigbluebuttonbn'), 'features' => array('showrecordings', 'importrecordings')),
2165
    );
2166
2167
    return $instanceprofiles;
2168
}
2169
2170
function bigbluebuttonbn_get_enabled_features($typeprofiles, $type = null) {
2171
    $enabledfeatures = array();
2172
2173
    $features = $typeprofiles[0]['features'];
2174
    if (!is_null($type)) {
2175
        $features = $typeprofiles[$type]['features'];
2176
    }
2177
    $enabledfeatures['showroom'] = (in_array('all', $features) || in_array('showroom', $features));
2178
    $enabledfeatures['showrecordings'] = (in_array('all', $features) || in_array('showrecordings', $features));
2179
    $enabledfeatures['importrecordings'] = (in_array('all', $features) || in_array('importrecordings', $features));
2180
2181
    return $enabledfeatures;
2182
}
2183
2184
function bigbluebuttonbn_get_instance_profiles_array($profiles = null) {
2185
    if (is_null($profiles) || empty($profiles)) {
2186
        $profiles = bigbluebuttonbn_get_instance_type_profiles();
2187
    }
2188
2189
    $profilesarray = array();
2190
2191
    foreach ($profiles as $profile) {
2192
        $profilesarray += array("{$profile['id']}" => $profile['name']);
2193
    }
2194
2195
    return $profilesarray;
2196
}
2197
2198
function bigbluebuttonbn_format_activity_time($time) {
2199
    $activitytime = '';
2200
    if ($time) {
2201
        $activitytime = calendar_day_representation($time).' '.
2202
          get_string('mod_form_field_notification_msg_at', 'bigbluebuttonbn').' '.
2203
          calendar_time_representation($time);
2204
    }
2205
2206
    return $activitytime;
2207
}
2208
2209
function bigbluebuttonbn_recordings_enabled() {
2210
    global $CFG;
2211
2212
    return !(isset($CFG->bigbluebuttonbn['recording_default)']) &&
2213
             isset($CFG->bigbluebuttonbn['recording_editable']));
2214
}
2215
2216
function bigbluebuttonbn_get_strings_for_js() {
2217
    $locale = bigbluebuttonbn_get_locale();
2218
    $stringman = get_string_manager();
2219
    $strings = $stringman->load_component_strings('bigbluebuttonbn', $locale);
2220
    return $strings;
2221
}
2222
2223
function bigbluebuttonbn_get_locale() {
2224
    $lang = get_string('locale', 'core_langconfig');
2225
    return substr($lang, 0, strpos($lang, '.'));
2226
}
2227
2228
function bigbluebuttonbn_get_localcode() {
2229
    $locale = bigbluebuttonbn_get_locale();
2230
    return substr($locale, 0, strpos($locale, '_'));
2231
}
2232
2233
function bigbluebuttonbn_get_moderator_email($context) {
2234
    $moderatoremails = array();
2235
    $users = (array) get_enrolled_users($context);
2236
    $counter = 0;
2237
    foreach ($users as $key => $user) {
2238
        if ($counter == 5) {
2239
            break;
2240
        }
2241
        if(has_capability('mod/bigbluebuttonbn:moderate', $context, $user)) {
2242
            array_push($moderatoremails, '"' . fullname($user) . '" <' . $user->email . '>');
2243
            $counter += 1;
2244
        }
2245
    }
2246
    return $moderatoremails;
2247
}
2248