Completed
Push — master ( f92a9e...10847d )
by Jesus
02:50
created

locallib.php ➔ bigbluebuttonbn_events_action()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 18
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Importance

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

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $params is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
477
    $ids = explode(',', $recordids);
478
    foreach ($ids as $id) {
0 ignored issues
show
Unused Code introduced by
This foreach statement is empty and can be removed.

This check looks for foreach loops that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.

Consider removing the loop.

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