Completed
Push — master ( 58f2f2...86fc5a )
by Jesus
02:20
created

locallib.php ➔ bigbluebuttonbn_role_unknown()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 0
dl 0
loc 3
rs 10
c 0
b 0
f 0
1
<?php
2
// This file is part of Moodle - http://moodle.org/
3
//
4
// Moodle is free software: you can redistribute it and/or modify
5
// it under the terms of the GNU General Public License as published by
6
// the Free Software Foundation, either version 3 of the License, or
7
// (at your option) any later version.
8
//
9
// Moodle is distributed in the hope that it will be useful,
10
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
// GNU General Public License for more details.
13
//
14
// You should have received a copy of the GNU General Public License
15
// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
16
17
/**
18
 * Internal library of functions for module BigBlueButtonBN.
19
 *
20
 * @author    Fred Dixon  (ffdixon [at] blindsidenetworks [dt] com)
21
 * @author    Jesus Federico  (jesus [at] blindsidenetworks [dt] com)
22
 * @copyright 2010-2017 Blindside Networks Inc
23
 * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v2 or later
24
 */
25
26
defined('MOODLE_INTERNAL') || die;
27
28
global $CFG;
29
30
require_once(dirname(__FILE__).'/lib.php');
31
32
const BIGBLUEBUTTONBN_FORCED = true;
33
34
const BIGBLUEBUTTONBN_TYPE_ALL = 0;
35
const BIGBLUEBUTTONBN_TYPE_ROOM_ONLY = 1;
36
const BIGBLUEBUTTONBN_TYPE_RECORDING_ONLY = 2;
37
38
const BIGBLUEBUTTONBN_ROLE_VIEWER = 'viewer';
39
const BIGBLUEBUTTONBN_ROLE_MODERATOR = 'moderator';
40
const BIGBLUEBUTTONBN_METHOD_GET = 'GET';
41
const BIGBLUEBUTTONBN_METHOD_POST = 'POST';
42
43
const BIGBLUEBUTTON_EVENT_ACTIVITY_VIEWED = 'activity_viewed';
44
const BIGBLUEBUTTON_EVENT_ACTIVITY_MANAGEMENT_VIEWED = 'activity_management_viewed';
45
const BIGBLUEBUTTON_EVENT_LIVE_SESSION = 'live_session';
46
const BIGBLUEBUTTON_EVENT_MEETING_CREATED = 'meeting_created';
47
const BIGBLUEBUTTON_EVENT_MEETING_ENDED = 'meeting_ended';
48
const BIGBLUEBUTTON_EVENT_MEETING_JOINED = 'meeting_joined';
49
const BIGBLUEBUTTON_EVENT_MEETING_LEFT = 'meeting_left';
50
const BIGBLUEBUTTON_EVENT_RECORDING_DELETED = 'recording_deleted';
51
const BIGBLUEBUTTON_EVENT_RECORDING_IMPORTED = 'recording_imported';
52
const BIGBLUEBUTTON_EVENT_RECORDING_PROTECTED = 'recording_protected';
53
const BIGBLUEBUTTON_EVENT_RECORDING_PUBLISHED = 'recording_published';
54
const BIGBLUEBUTTON_EVENT_RECORDING_UNPROTECTED = 'recording_unprotected';
55
const BIGBLUEBUTTON_EVENT_RECORDING_UNPUBLISHED = 'recording_unpublished';
56
const BIGBLUEBUTTON_EVENT_RECORDING_EDITED = 'recording_edited';
57
const BIGBLUEBUTTON_EVENT_RECORDING_VIEWED = 'recording_viewed';
58
59
function bigbluebuttonbn_logs(array $bbbsession, $event, array $overrides = [], $meta = null) {
60
    global $DB;
61
62
    $log = new stdClass();
63
64
    // Default values.
65
    $log->courseid = $bbbsession['course']->id;
66
    $log->bigbluebuttonbnid = $bbbsession['bigbluebuttonbn']->id;
67
    $log->userid = $bbbsession['userID'];
68
    $log->meetingid = $bbbsession['meetingid'];
69
    $log->timecreated = time();
70
    // Overrides.
71
    foreach ($overrides as $key => $value) {
72
        $log->$key = $value;
73
    }
74
75
    $log->log = $event;
76
    if (isset($meta)) {
77
        $log->meta = $meta;
78
    } else if ($event == BIGBLUEBUTTONBN_LOG_EVENT_CREATE) {
79
        $log->meta = '{"record":'.($bbbsession['record'] ? 'true' : 'false').'}';
80
    }
81
82
    $DB->insert_record('bigbluebuttonbn_logs', $log);
83
}
84
85
// BigBlueButton API Calls.
86
function bigbluebuttonbn_get_join_url($meetingid, $username, $pw, $logouturl, $configtoken = null, $userid = null) {
87
    $data = ['meetingID' => $meetingid,
88
              'fullName' => $username,
89
              'password' => $pw,
90
              'logoutURL' => $logouturl,
91
            ];
92
93
    if (!is_null($configtoken)) {
94
        $data['configToken'] = $configtoken;
95
    }
96
    if (!is_null($userid)) {
97
        $data['userID'] = $userid;
98
    }
99
100
    return \mod_bigbluebuttonbn\locallib\bigbluebutton::action_url('join', $data);
101
}
102
103
/**
104
 * @param string $recordid
105
 * @param array  $metadata
106
 */
107
function bigbluebuttonbn_get_update_recordings_url($recordid, $metadata = array()) {
108
    return \mod_bigbluebuttonbn\locallib\bigbluebutton::action_url('updateRecordings', ['recordID' => $recordid], $metadata);
109
}
110
111
/**
112
 * @param array  $data
113
 * @param array  $metadata
114
 * @param string $pname
115
 * @param string $purl
116
 */
117
function bigbluebuttonbn_get_create_meeting_array($data, $metadata = array(), $pname = null, $purl = null) {
118
    $createmeetingurl = \mod_bigbluebuttonbn\locallib\bigbluebutton::action_url('create', $data, $metadata);
119
    $method = BIGBLUEBUTTONBN_METHOD_GET;
120
    $data = null;
121
122
    if (!is_null($pname) && !is_null($purl)) {
123
        $method = BIGBLUEBUTTONBN_METHOD_POST;
124
        $data = "<?xml version='1.0' encoding='UTF-8'?><modules><module name='" . $pname . "'><document url='".
125
            $purl."' /></module></modules>";
126
    }
127
128
    $xml = bigbluebuttonbn_wrap_xml_load_file($createmeetingurl, $method, $data);
129
130
    if ($xml) {
131
        $response = array('returncode' => $xml->returncode, 'message' => $xml->message, 'messageKey' => $xml->messageKey);
132
        if ($xml->meetingID) {
133
            $response += array('meetingID' => $xml->meetingID, 'attendeePW' => $xml->attendeePW,
134
                'moderatorPW' => $xml->moderatorPW, 'hasBeenForciblyEnded' => $xml->hasBeenForciblyEnded);
135
        }
136
137
        return $response;
138
    }
139
140
    return null;
141
}
142
143
/**
144
 * @param string $meetingid
145
 */
146
function bigbluebuttonbn_get_meeting_array($meetingid) {
147
    $meetings = bigbluebuttonbn_get_meetings_array();
148
    if ($meetings) {
149
        foreach ($meetings as $meeting) {
150
            if ($meeting['meetingID'] == $meetingid) {
151
                return $meeting;
152
            }
153
        }
154
    }
155
156
    return null;
157
}
158
159
function bigbluebuttonbn_get_meetings_array() {
160
    $xml = bigbluebuttonbn_wrap_xml_load_file(\mod_bigbluebuttonbn\locallib\bigbluebutton::action_url('getMeetings'));
161
162
    if ($xml && $xml->returncode == 'SUCCESS' && empty($xml->messageKey)) {
163
        // Meetings were returned.
164
        $meetings = array();
165
        foreach ($xml->meetings->meeting as $meeting) {
166
            $meetings[] = array('meetingID' => $meeting->meetingID,
167
                                'moderatorPW' => $meeting->moderatorPW,
168
                                'attendeePW' => $meeting->attendeePW,
169
                                'hasBeenForciblyEnded' => $meeting->hasBeenForciblyEnded,
170
                                'running' => $meeting->running, );
171
        }
172
173
        return $meetings;
174
    }
175
176 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...
177
        // Either failure or success without meetings.
178
        return array('returncode' => $xml->returncode, 'message' => $xml->message, 'messageKey' => $xml->messageKey);
179
    }
180
181
    // If the server is unreachable, then prompts the user of the necessary action.
182
    return null;
183
}
184
185
/**
186
 * @param string $meetingid
187
 */
188
function bigbluebuttonbn_get_meeting_info_array($meetingid) {
189
    $xml = bigbluebuttonbn_wrap_xml_load_file(
190
        \mod_bigbluebuttonbn\locallib\bigbluebutton::action_url('getMeetingInfo', ['meetingID' => $meetingid])
191
      );
192
193
    if ($xml && $xml->returncode == 'SUCCESS' && empty($xml->messageKey)) {
194
        // Meeting info was returned.
195
        return array('returncode' => $xml->returncode,
196
                     'meetingID' => $xml->meetingID,
197
                     'moderatorPW' => $xml->moderatorPW,
198
                     'attendeePW' => $xml->attendeePW,
199
                     'hasBeenForciblyEnded' => $xml->hasBeenForciblyEnded,
200
                     'running' => $xml->running,
201
                     'recording' => $xml->recording,
202
                     'startTime' => $xml->startTime,
203
                     'endTime' => $xml->endTime,
204
                     'participantCount' => $xml->participantCount,
205
                     'moderatorCount' => $xml->moderatorCount,
206
                     'attendees' => $xml->attendees,
207
                     'metadata' => $xml->metadata,
208
                   );
209
    }
210
211 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...
212
        // Either failure or success without meeting info.
213
        return array('returncode' => $xml->returncode, 'message' => $xml->message, 'messageKey' => $xml->messageKey);
214
    }
215
216
    // If the server is unreachable, then prompts the user of the necessary action.
217
    return null;
218
}
219
220
/**
221
 * helper function to retrieve recordings from a BigBlueButton server.
222
 *
223
 * @param string or array $meetingids   list of meetingIDs "mid1,mid2,mid3" or array("mid1","mid2","mid3")
224
 * @param string or array $recordingids list of $recordingids "rid1,rid2,rid3" or array("rid1","rid2","rid3") for filtering
225
 *
226
 * @return associative array with recordings indexed by recordID, each recording is a non sequential associative array
227
 */
228
function bigbluebuttonbn_get_recordings_array($meetingids, $recordingids = []) {
229
    $meetingidsarray = $meetingids;
230
    if (!is_array($meetingids)) {
231
        $meetingidsarray = explode(',', $meetingids);
232
    }
233
234
    // If $meetingidsarray is empty there is no need to go further.
235
    if (empty($meetingidsarray)) {
236
        return array();
237
    }
238
    $recordings = bigbluebuttonbn_get_recordings_array_fetch($meetingidsarray);
239
240
    // Filter recordings based on recordingIDs.
241
    $recordingidsarray = $recordingids;
242
    if (!is_array($recordingids)) {
243
        $recordingidsarray = explode(',', $recordingids);
244
    }
245
246
    if (empty($recordingidsarray)) {
247
        // No recording ids, no need to filter.
248
        return $recordings;
249
    }
250
251
    return bigbluebuttonbn_get_recordings_array_filter($recordingidsarray, $recordings);
252
}
253
254
/**
255
 * helper function to fetch recordings from a BigBlueButton server.
256
 *
257
 * @param array $meetingidsarray   array with meeting ids in the form array("mid1","mid2","mid3")
258
 *
259
 * @return associative array with recordings indexed by recordID, each recording is a non sequential associative array
260
 */
261
function bigbluebuttonbn_get_recordings_array_fetch($meetingidsarray) {
262
263
    $recordings = array();
264
265
    // Execute a paginated getRecordings request.
266
    $pages = floor(count($meetingidsarray) / 25) + 1;
267
    for ($page = 1; $page <= $pages; ++$page) {
268
        $mids = array_slice($meetingidsarray, ($page - 1) * 25, 25);
269
        // Do getRecordings is executed using a method GET (supported by all versions of BBB).
270
        $xml = bigbluebuttonbn_wrap_xml_load_file(
271
            \mod_bigbluebuttonbn\locallib\bigbluebutton::action_url('getRecordings', ['meetingID' => implode(',', $mids)])
272
          );
273
        if ($xml && $xml->returncode == 'SUCCESS' && isset($xml->recordings)) {
274
            // If there were meetings already created.
275
            foreach ($xml->recordings->recording as $recording) {
276
                $recordingarrayvalue = bigbluebuttonbn_get_recording_array_value($recording);
277
                $recordings[$recordingarrayvalue['recordID']] = $recordingarrayvalue;
278
            }
279
            uasort($recordings, 'bigbluebuttonbn_recording_build_sorter');
280
        }
281
    }
282
283
    return $recordings;
284
}
285
286
function bigbluebuttonbn_get_recordings_array_filter($recordingidsarray, &$recordings) {
287
288
    foreach ($recordings as $key => $recording) {
289
        if (!in_array($recording['recordID'], $recordingidsarray)) {
290
            unset($recordings[$key]);
291
        }
292
    }
293
294
    return $recordings;
295
}
296
297
/**
298
 * Helper function to retrieve imported recordings from the Moodle database.
299
 * The references are stored as events in bigbluebuttonbn_logs.
300
 *
301
 * @param string $courseid
302
 * @param string $bigbluebuttonbnid
303
 * @param bool   $subset
304
 *
305
 * @return associative array with imported recordings indexed by recordID, each recording is a non sequential associative
306
 * array that corresponds to the actual recording in BBB
307
 */
308
function bigbluebuttonbn_get_recordings_imported_array($courseid, $bigbluebuttonbnid = null, $subset = true) {
309
    global $DB;
310
311
    $select = "courseid = '{$courseid}' AND bigbluebuttonbnid <> '{$bigbluebuttonbnid}' AND log = '".
312
        BIGBLUEBUTTONBN_LOG_EVENT_IMPORT."'";
313
    if ($bigbluebuttonbnid === null) {
314
        $select = "courseid = '{$courseid}' AND log = '".BIGBLUEBUTTONBN_LOG_EVENT_IMPORT."'";
315
    } else if ($subset) {
316
        $select = "bigbluebuttonbnid = '{$bigbluebuttonbnid}' AND log = '".BIGBLUEBUTTONBN_LOG_EVENT_IMPORT."'";
317
    }
318
    $recordsimported = $DB->get_records_select('bigbluebuttonbn_logs', $select);
319
320
    $recordsimportedarray = array();
321
    foreach ($recordsimported as $recordimported) {
322
        $meta = json_decode($recordimported->meta, true);
323
        $recording = $meta['recording'];
324
        // Force protected.
325
        $recording['protected'] = 'true';
326
        $recordsimportedarray[$recording['recordID']] = $recording;
327
    }
328
329
    return $recordsimportedarray;
330
}
331
332
function bigbluebuttonbn_get_default_config_xml() {
333
    $xml = bigbluebuttonbn_wrap_xml_load_file(
334
        \mod_bigbluebuttonbn\locallib\bigbluebutton::action_url('getDefaultConfigXML')
335
      );
336
337
    return $xml;
338
}
339
340
function bigbluebuttonbn_get_default_config_xml_array() {
341
    $defaultconfigxml = bigbluebuttonbn_getDefaultConfigXML();
342
343
    return (array) $defaultconfigxml;
344
}
345
346
function bigbluebuttonbn_get_recording_array_value($recording) {
347
    // Add formats.
348
    $playbackarray = array();
349
    foreach ($recording->playback->format as $format) {
350
        $playbackarray[(string) $format->type] = array('type' => (string) $format->type,
351
            'url' => (string) $format->url, 'length' => (string) $format->length);
352
        // Add preview per format when existing.
353
        if ($format->preview) {
354
            $imagesarray = array();
355
            foreach ($format->preview->images->image as $image) {
356
                $imagearray = array('url' => (string) $image);
357
                foreach ($image->attributes() as $attkey => $attvalue) {
358
                    $imagearray[$attkey] = (string) $attvalue;
359
                }
360
                array_push($imagesarray, $imagearray);
361
            }
362
            $playbackarray[(string) $format->type]['preview'] = $imagesarray;
363
        }
364
    }
365
366
    // Add the metadata to the recordings array.
367
    $metadataarray = bigbluebuttonbn_get_recording_array_meta(get_object_vars($recording->metadata));
368
    $recordingarray = array('recordID' => (string) $recording->recordID,
369
        'meetingID' => (string) $recording->meetingID, 'meetingName' => (string) $recording->name,
370
        'published' => (string) $recording->published, 'startTime' => (string) $recording->startTime,
371
        'endTime' => (string) $recording->endTime, 'playbacks' => $playbackarray);
372
    if (isset($recording->protected)) {
373
        $recordingarray['protected'] = (string) $recording->protected;
374
    }
375
    // Force protected.
376
    $recordingarray['protected'] = 'false';
377
    return $recordingarray + $metadataarray;
378
}
379
380
function bigbluebuttonbn_get_recording_array_meta($metadata) {
381
    $metadataarray = array();
382
    foreach ($metadata as $key => $value) {
383
        if (is_object($value)) {
384
            $value = '';
385
        }
386
        $metadataarray['meta_'.$key] = $value;
387
    }
388
    return $metadataarray;
389
}
390
391
function bigbluebuttonbn_recording_build_sorter($a, $b) {
392
    if ($a['startTime'] < $b['startTime']) {
393
        return -1;
394
    }
395
    if ($a['startTime'] == $b['startTime']) {
396
        return 0;
397
    }
398
    return 1;
399
}
400
401
/**
402
 * @param string $recordids
403
 */
404 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...
405
    $ids = explode(',', $recordids);
406
    foreach ($ids as $id) {
407
        $xml = bigbluebuttonbn_wrap_xml_load_file(
408
            \mod_bigbluebuttonbn\locallib\bigbluebutton::action_url('deleteRecordings', ['recordID' => $id])
409
          );
410
        if ($xml && $xml->returncode != 'SUCCESS') {
411
            return false;
412
        }
413
    }
414
415
    return true;
416
}
417
418
/**
419
 * @param string $recordids
420
 * @param string $publish
421
 */
422 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...
423
    $ids = explode(',', $recordids);
424
    foreach ($ids as $id) {
425
        $xml = bigbluebuttonbn_wrap_xml_load_file(
426
            \mod_bigbluebuttonbn\locallib\bigbluebutton::action_url('publishRecordings', ['recordID' => $id, 'publish' => $publish])
427
          );
428
        if ($xml && $xml->returncode != 'SUCCESS') {
429
            return false;
430
        }
431
    }
432
433
    return true;
434
}
435
436
/**
437
 * @param string $recordids
438
 * @param array $params ['key'=>param_key, 'value']
439
 */
440 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...
441
    $ids = explode(',', $recordids);
442
    foreach ($ids as $id) {
443
        $xml = bigbluebuttonbn_wrap_xml_load_file(
444
            \mod_bigbluebuttonbn\locallib\bigbluebutton::action_url('updateRecordings', ['recordID' => $id] + (array) $params)
445
          );
446
        if ($xml && $xml->returncode != 'SUCCESS') {
447
            return false;
448
        }
449
    }
450
451
    return true;
452
}
453
454
/**
455
 * @param string $recordids
456
 * @param string $bigbluebuttonbnid
457
 * @param array $params ['key'=>param_key, 'value']
458
 */
459
function bigbluebuttonbn_update_recording_imported($recordids, $bigbluebuttonbnid, $params) {
460
    $ids = explode(',', $recordids);
461
    foreach ($ids as $id) {
462
        if (!bigbluebuttonbn_update_recording_imported_perform($id, $bigbluebuttonbnid, $params)) {
463
            return false;
464
        }
465
    }
466
    return true;
467
}
468
469
/**
470
 * @param string $recordid
471
 * @param string $bigbluebuttonbnid
472
 * @param array $params ['key'=>param_key, 'value']
473
 */
474
function bigbluebuttonbn_update_recording_imported_perform($recordid, $bigbluebuttonbnid, $params) {
475
    global $DB;
476
477
    // Locate the record to be updated.
478
    $records = $DB->get_records('bigbluebuttonbn_logs', array('bigbluebuttonbnid' => $bigbluebuttonbnid,
479
        'log' => BIGBLUEBUTTONBN_LOG_EVENT_IMPORT));
480
481
    foreach ($records as $key => $record) {
482
        $meta = json_decode($record->meta, true);
483
        if ($recordid == $meta['recording']['recordID']) {
484
            // Found, prepare data for the update.
485
            $meta['recording'] = $params + $meta['recording'];
486
            $records[$key]->meta = json_encode($meta);
487
488
            // Proceed with the update.
489
            if (!$DB->update_record('bigbluebuttonbn_logs', $records[$key])) {
490
                return false;
491
            }
492
        }
493
    }
494
    return true;
495
}
496
497
/**
498
 * @param string $meetingid
499
 * @param string $modpw
500
 */
501
function bigbluebuttonbn_end_meeting($meetingid, $modpw) {
502
    $xml = bigbluebuttonbn_wrap_xml_load_file(
503
        \mod_bigbluebuttonbn\locallib\bigbluebutton::action_url('end', ['meetingID' => $meetingid, 'password' => $modpw])
504
      );
505
506 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...
507
        // If the xml packet returned failure it displays the message to the user.
508
        return array('returncode' => $xml->returncode, 'message' => $xml->message, 'messageKey' => $xml->messageKey);
509
    }
510
511
    // If the server is unreachable, then prompts the user of the necessary action.
512
    return null;
513
}
514
515
/**
516
 * @param string $meetingid
517
 */
518
function bigbluebuttonbn_is_meeting_running($meetingid) {
519
    $xml = bigbluebuttonbn_wrap_xml_load_file(
520
        \mod_bigbluebuttonbn\locallib\bigbluebutton::action_url('isMeetingRunning', ['meetingID' => $meetingid])
521
      );
522
523
    if ($xml && $xml->returncode == 'SUCCESS') {
524
        return ($xml->running == 'true');
525
    }
526
527
    return false;
528
}
529
530
function bigbluebuttonbn_get_server_version() {
531
    $xml = bigbluebuttonbn_wrap_xml_load_file(
532
        \mod_bigbluebuttonbn\locallib\bigbluebutton::action_url()
533
      );
534
535
    if ($xml && $xml->returncode == 'SUCCESS') {
536
        return $xml->version;
537
    }
538
539
    return null;
540
}
541
542
/**
543
 * @param string $url
544
 * @param string $data
545
 */
546
function bigbluebuttonbn_wrap_xml_load_file($url, $method = BIGBLUEBUTTONBN_METHOD_GET,
547
    $data = null, $contenttype = 'text/xml') {
548
549
    if (extension_loaded('curl')) {
550
        $response = bigbluebuttonbn_wrap_xml_load_file_curl_request($url, $method, $data, $contenttype);
551
552
        if (!$response) {
553
            debugging('No response on wrap_simplexml_load_file', DEBUG_DEVELOPER);
554
            return null;
555
        }
556
557
        $previous = libxml_use_internal_errors(true);
558
        try {
559
            $xml = simplexml_load_string($response, 'SimpleXMLElement', LIBXML_NOCDATA | LIBXML_NOBLANKS);
560
561
            return $xml;
562
        } catch (Exception $e) {
563
            libxml_use_internal_errors($previous);
564
            $error = 'Caught exception: '.$e->getMessage();
565
            debugging($error, DEBUG_DEVELOPER);
566
            return null;
567
        }
568
    }
569
570
    // Alternative request non CURL based.
571
    $previous = libxml_use_internal_errors(true);
572
    try {
573
        $response = simplexml_load_file($url, 'SimpleXMLElement', LIBXML_NOCDATA | LIBXML_NOBLANKS);
574
        return $response;
575
    } catch (Exception $e) {
576
        $error = 'Caught exception: '.$e->getMessage();
577
        debugging($error, DEBUG_DEVELOPER);
578
        libxml_use_internal_errors($previous);
579
        return null;
580
    }
581
}
582
583
function bigbluebuttonbn_wrap_xml_load_file_curl_request($url, $method = BIGBLUEBUTTONBN_METHOD_GET,
584
    $data = null, $contenttype = 'text/xml') {
585
    $c = new curl();
586
    $c->setopt(array('SSL_VERIFYPEER' => true));
587
    if ($method == BIGBLUEBUTTONBN_METHOD_POST) {
588
        if (is_null($data) || is_array($data)) {
589
            return $c->post($url);
590
        }
591
592
        $options = array();
593
        $options['CURLOPT_HTTPHEADER'] = array(
594
                 'Content-Type: '.$contenttype,
595
                 'Content-Length: '.strlen($data),
596
                 'Content-Language: en-US',
597
               );
598
599
        return $c->post($url, $data, $options);
600
    }
601
602
    return $c->get($url);
603
}
604
605
function bigbluebuttonbn_get_user_roles($context, $userid) {
606
    global $DB;
607
608
    $userroles = get_user_roles($context, $userid);
609
    if ($userroles) {
610
        $where = '';
611
        foreach ($userroles as $value) {
612
            $where .= (empty($where) ? ' WHERE' : ' AND').' id='.$value->roleid;
613
        }
614
        $userroles = $DB->get_records_sql('SELECT * FROM {role}'.$where);
615
    }
616
617
    return $userroles;
618
}
619
620
function bigbluebuttonbn_get_guest_role() {
621
    $guestrole = get_guest_role();
622
623
    return array($guestrole->id => $guestrole);
624
}
625
626
function bigbluebuttonbn_get_users(context $context = null) {
627
    $users = (array) get_enrolled_users($context,'',0,'u.*',null,0,0,true);
628
    foreach ($users as $key => $value) {
629
        $users[$key] = fullname($value);
630
    }
631
    return $users;
632
}
633
634
function bigbluebuttonbn_get_users_select(context $context = null) {
635
    $users = (array) get_enrolled_users($context,'',0,'u.*',null,0,0,true);
636
    foreach ($users as $key => $value) {
637
        $users[$key] = array('id' => $value->id, 'name' => fullname($value));
638
    }
639
    return $users;
640
}
641
642
function bigbluebuttonbn_get_roles(context $context = null) {
643
    $roles = (array) role_get_names($context);
644
    foreach ($roles as $key => $value) {
645
        $roles[$key] = $value->localname;
646
    }
647
    return $roles;
648
}
649
650
function bigbluebuttonbn_get_roles_select(context $context = null) {
651
    $roles = (array) role_get_names($context);
652
    foreach ($roles as $key => $value) {
653
        $roles[$key] = array('id' => $value->id, 'name' => $value->localname);
654
    }
655
    return $roles;
656
}
657
658
function bigbluebuttonbn_get_role($id) {
659
    $roles = (array) role_get_names();
660
    if (is_numeric($id)) {
661
        return (object)$roles[$id];
662
    }
663
664
    foreach ($roles as $role) {
665
        if ($role->shortname == $id) {
666
            return $role;
667
        }
668
    }
669
}
670
671
function bigbluebuttonbn_role_unknown() {
672
    return array("id" => "0", "name" => "", "shortname" => "unknown", "description" => "", "sortorder" => "0", "archetype" => "guest", "localname" => "Unknown");
673
}
674
675
function bigbluebuttonbn_get_participant_data($context) {
676
    $data = array(
677
        'all' => array(
678
            'name' => get_string('mod_form_field_participant_list_type_all', 'bigbluebuttonbn'),
679
            'children' => []
680
          )
681
      );
682
683
    $data['role'] = array(
684
        'name' => get_string('mod_form_field_participant_list_type_role', 'bigbluebuttonbn'),
685
        'children' => bigbluebuttonbn_get_roles_select($context)
686
      );
687
688
    $data['user'] = array(
689
        'name' => get_string('mod_form_field_participant_list_type_user', 'bigbluebuttonbn'),
690
        'children' => bigbluebuttonbn_get_users_select($context)
691
      );
692
693
    return $data;
694
}
695
696
function bigbluebuttonbn_get_participant_list($bigbluebuttonbn, $context) {
697
    if ($bigbluebuttonbn == null) {
698
        return bigbluebuttonbn_get_participant_list_default($context);
699
    }
700
701
    return bigbluebuttonbn_get_participant_rules_encoded($bigbluebuttonbn);
702
}
703
704
function bigbluebuttonbn_get_participant_rules_encoded($bigbluebuttonbn) {
705
    $rules = json_decode($bigbluebuttonbn->participants, true);
706
    foreach ($rules as $key => $rule) {
707
        if ( $rule['selectiontype'] !== 'role' || is_numeric($rule['selectionid']) ) {
708
            continue;
709
        }
710
711
        $role = bigbluebuttonbn_get_role($rule['selectionid']);
712
        if ( $role == null ) {
713
            unset($rules[$key]);
714
            continue;
715
        }
716
717
        $rule['selectionid'] = $role->id;
718
        $rules[$key] = $rule;
719
    }
720
    return $rules;
721
}
722
723
function bigbluebuttonbn_get_participant_list_default($context) {
724
    global $USER;
725
726
    $participantlistarray = array();
727
    $participantlistarray[] = array(
728
        'selectiontype' => 'all',
729
        'selectionid' => 'all',
730
        'role' => BIGBLUEBUTTONBN_ROLE_VIEWER);
731
732
    $moderatordefaults = explode(',', \mod_bigbluebuttonbn\locallib\config::get('moderator_default'));
733
    foreach ($moderatordefaults as $moderatordefault) {
734
        if ($moderatordefault == 'owner') {
735
            if (is_enrolled($context, $USER->id)) {
736
                $participantlistarray[] = array(
737
                    'selectiontype' => 'user',
738
                    'selectionid' => $USER->id,
739
                    'role' => BIGBLUEBUTTONBN_ROLE_MODERATOR);
740
            }
741
            continue;
742
        }
743
744
        $participantlistarray[] = array(
745
              'selectiontype' => 'role',
746
              'selectionid' => $moderatordefault,
747
              'role' => BIGBLUEBUTTONBN_ROLE_MODERATOR);
748
    }
749
750
    return $participantlistarray;
751
}
752
753
function bigbluebuttonbn_get_participant_selection_data() {
754
    return [
755
        'type_options' => [
756
            'all' => get_string('mod_form_field_participant_list_type_all', 'bigbluebuttonbn'),
757
            'role' => get_string('mod_form_field_participant_list_type_role', 'bigbluebuttonbn'),
758
            'user' => get_string('mod_form_field_participant_list_type_user', 'bigbluebuttonbn'),
759
          ],
760
        'type_selected' => 'all',
761
        'options' => ['all' => '---------------'],
762
        'selected' => 'all',
763
      ];
764
}
765
766
function bigbluebuttonbn_is_moderator($context, $participants, $userid = null, $userroles = null) {
767
    global $USER;
768
769
    if (empty($userid)) {
770
        $userid = $USER->id;
771
    }
772
773
    if (empty($userroles)) {
774
        $userroles = get_user_roles($context, $userid, true);
775
    }
776
777
    if (empty($participants)) {
778
        // The room that is being used comes from a previous version.
779
        return has_capability('mod/bigbluebuttonbn:moderate', $context);
780
    }
781
782
    $participantlist = json_decode($participants);
783
    // Iterate participant rules.
784
    foreach ($participantlist as $participant) {
785
        if (bigbluebuttonbn_is_moderator_rule_validation($participant, $userid, $userroles)) {
786
            return true;
787
        }
788
    }
789
790
    return false;
791
}
792
793
function bigbluebuttonbn_is_moderator_rule_validation($participant, $userid, $userroles) {
794
795
    if ($participant->role == BIGBLUEBUTTONBN_ROLE_VIEWER) {
796
        return false;
797
    }
798
799
    // Looks for all configuration.
800
    if ($participant->selectiontype == 'all') {
801
        return true;
802
    }
803
804
    // Looks for users.
805
    if ($participant->selectiontype == 'user' && $participant->selectionid == $userid) {
806
        return true;
807
    }
808
809
    // Looks for roles.
810
    $role = bigbluebuttonbn_get_role($participant->selectionid);
811
    if (array_key_exists($role->id, $userroles)) {
812
        return true;
813
    }
814
815
    return false;
816
}
817
818
function bigbluebuttonbn_get_error_key($messagekey, $defaultkey = null) {
819
    if ($messagekey == 'checksumError') {
820
        return 'index_error_checksum';
821
    }
822
    if ($messagekey == 'maxConcurrent') {
823
        return 'view_error_max_concurrent';
824
    }
825
    return $defaultkey;
826
}
827
828
function bigbluebuttonbn_voicebridge_unique($voicebridge, $id = null) {
829
    global $DB;
830
831
    $isunique = true;
832
    if ($voicebridge != 0) {
833
        $table = 'bigbluebuttonbn';
834
        $select = 'voicebridge = '.$voicebridge;
835
        if ($id) {
836
            $select .= ' AND id <> '.$id;
837
        }
838
        if ($DB->get_records_select($table, $select)) {
839
            $isunique = false;
840
        }
841
    }
842
843
    return $isunique;
844
}
845
846
function bigbluebuttonbn_get_duration($closingtime) {
847
    $duration = 0;
848
    $now = time();
849
    if ($closingtime > 0 && $now < $closingtime) {
850
        $duration = ceil(($closingtime - $now) / 60);
851
        $compensationtime = intval((int)\mod_bigbluebuttonbn\locallib\config::get('scheduled_duration_compensation'));
852
        $duration = intval($duration) + $compensationtime;
853
    }
854
855
    return $duration;
856
}
857
858
function bigbluebuttonbn_get_presentation_array($context, $presentation, $id = null) {
859
    $pname = null;
860
    $purl = null;
861
    $picon = null;
862
    $pmimetypedescrip = null;
863
864
    if (!empty($presentation)) {
865
        $fs = get_file_storage();
866
        $files = $fs->get_area_files($context->id, 'mod_bigbluebuttonbn', 'presentation', 0,
867
            'itemid, filepath, filename', false);
868
        if (count($files) >= 1) {
869
            $file = reset($files);
870
            unset($files);
871
            $pname = $file->get_filename();
872
            $picon = file_file_icon($file, 24);
873
            $pmimetypedescrip = get_mimetype_description($file);
874
            $pnoncevalue = null;
875
876
            if (!is_null($id)) {
877
                // Create the nonce component for granting a temporary public access.
878
                $cache = cache::make_from_params(cache_store::MODE_APPLICATION, 'mod_bigbluebuttonbn',
879
                    'presentation_cache');
880
                $pnoncekey = sha1($id);
881
                /* The item id was adapted for granting public access to the presentation once in order
882
                 * to allow BigBlueButton to gather the file. */
883
                $pnoncevalue = bigbluebuttonbn_generate_nonce();
884
                $cache->set($pnoncekey, array('value' => $pnoncevalue, 'counter' => 0));
885
            }
886
            $url = moodle_url::make_pluginfile_url($file->get_contextid(), $file->get_component(),
887
                $file->get_filearea(), $pnoncevalue, $file->get_filepath(), $file->get_filename());
888
889
            $purl = $url->out(false);
890
        }
891
    }
892
893
    $parray = array('url' => $purl, 'name' => $pname,
894
                               'icon' => $picon,
895
                               'mimetype_description' => $pmimetypedescrip);
896
897
    return $parray;
898
}
899
900
function bigbluebuttonbn_generate_nonce() {
901
    $mt = microtime();
902
    $rand = mt_rand();
903
904
    return md5($mt.$rand);
905
}
906
907
function bigbluebuttonbn_random_password($length = 8) {
908
    $chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*()_-=+;:,.?';
909
    $password = substr(str_shuffle($chars), 0, $length);
910
911
    return $password;
912
}
913
914
function bigbluebuttonbn_events() {
915
    return array(
916
        (string) BIGBLUEBUTTON_EVENT_ACTIVITY_VIEWED,
917
        (string) BIGBLUEBUTTON_EVENT_ACTIVITY_MANAGEMENT_VIEWED,
918
        (string) BIGBLUEBUTTON_EVENT_LIVE_SESSION,
919
        (string) BIGBLUEBUTTON_EVENT_MEETING_CREATED,
920
        (string) BIGBLUEBUTTON_EVENT_MEETING_ENDED,
921
        (string) BIGBLUEBUTTON_EVENT_MEETING_JOINED,
922
        (string) BIGBLUEBUTTON_EVENT_MEETING_LEFT,
923
        (string) BIGBLUEBUTTON_EVENT_RECORDING_DELETED,
924
        (string) BIGBLUEBUTTON_EVENT_RECORDING_IMPORTED,
925
        (string) BIGBLUEBUTTON_EVENT_RECORDING_PROTECTED,
926
        (string) BIGBLUEBUTTON_EVENT_RECORDING_PUBLISHED,
927
        (string) BIGBLUEBUTTON_EVENT_RECORDING_UNPROTECTED,
928
        (string) BIGBLUEBUTTON_EVENT_RECORDING_UNPUBLISHED,
929
        (string) BIGBLUEBUTTON_EVENT_RECORDING_EDITED,
930
        (string) BIGBLUEBUTTON_EVENT_RECORDING_VIEWED
931
    );
932
}
933
934
function bigbluebuttonbn_events_action() {
935
    return array(
936
        'view' => (string) BIGBLUEBUTTON_EVENT_ACTIVITY_VIEWED,
937
        'view_management' => (string) BIGBLUEBUTTON_EVENT_ACTIVITY_MANAGEMENT_VIEWED,
938
        'live_action' => (string) BIGBLUEBUTTON_EVENT_LIVE_SESSION,
939
        'meeting_create' => (string) BIGBLUEBUTTON_EVENT_MEETING_CREATED,
940
        'meeting_end' => (string) BIGBLUEBUTTON_EVENT_MEETING_ENDED,
941
        'meeting_join' => (string) BIGBLUEBUTTON_EVENT_MEETING_JOINED,
942
        'meeting_left' => (string) BIGBLUEBUTTON_EVENT_MEETING_LEFT,
943
        'recording_delete' => (string) BIGBLUEBUTTON_EVENT_RECORDING_DELETED,
944
        'recording_import' => (string) BIGBLUEBUTTON_EVENT_RECORDING_IMPORTED,
945
        'recording_protect' => (string) BIGBLUEBUTTON_EVENT_RECORDING_PROTECTED,
946
        'recording_publish' => (string) BIGBLUEBUTTON_EVENT_RECORDING_PUBLISHED,
947
        'recording_unprotect' => (string) BIGBLUEBUTTON_EVENT_RECORDING_UNPROTECTED,
948
        'recording_unpublish' => (string) BIGBLUEBUTTON_EVENT_RECORDING_UNPUBLISHED,
949
        'recording_edit' => (string) BIGBLUEBUTTON_EVENT_RECORDING_EDITED,
950
        'recording_play' => (string) BIGBLUEBUTTON_EVENT_RECORDING_VIEWED
951
    );
952
}
953
954
function bigbluebuttonbn_event_log_standard($eventtype, $bigbluebuttonbn, $cm, $options = []) {
955
956
    $events = bigbluebuttonbn_events();
957
    if (!in_array($eventtype, $events)) {
958
        // No log will be created.
959
        return;
960
    }
961
962
    $context = context_module::instance($cm->id);
963
    $eventproperties = array('context' => $context, 'objectid' => $bigbluebuttonbn->id);
964
    if (array_key_exists('timecreated', $options)) {
965
        $eventproperties['timecreated'] = $options['timecreated'];
966
    }
967
    if (array_key_exists('userid', $options)) {
968
        $eventproperties['userid'] = $options['userid'];
969
    }
970
    if (array_key_exists('other', $options)) {
971
        $eventproperties['other'] = $options['other'];
972
    }
973
974
    $event = call_user_func_array('\mod_bigbluebuttonbn\event\bigbluebuttonbn_'.$eventtype.'::create',
975
      array($eventproperties));
976
    $event->trigger();
977
}
978
979
function bigbluebuttonbn_event_log($eventtype, $bigbluebuttonbn, $cm, $options = []) {
980
    bigbluebuttonbn_event_log_standard($eventtype, $bigbluebuttonbn, $cm, $options);
981
}
982
983
function bigbluebuttonbn_live_session_event_log($event, $bigbluebuttonbn, $cm) {
984
    bigbluebuttonbn_event_log_standard(BIGBLUEBUTTON_EVENT_LIVE_SESSION, $bigbluebuttonbn, $cm,
985
        ['timecreated' => $event->timestamp, 'userid' => $event->user, 'other' => $event->event]);
986
987
}
988
989
/**
990
 * @param string $meetingid
991
 * @param bool $ismoderator
992
 */
993
function bigbluebuttonbn_participant_joined($meetingid, $ismoderator) {
994
    $cache = cache::make_from_params(cache_store::MODE_APPLICATION, 'mod_bigbluebuttonbn', 'meetings_cache');
995
    $result = $cache->get($meetingid);
996
    $meetinginfo = json_decode($result['meeting_info']);
997
    $meetinginfo->participantCount += 1;
998
    if ($ismoderator) {
999
        $meetinginfo->moderatorCount += 1;
1000
    }
1001
    $cache->set($meetingid, array('creation_time' => $result['creation_time'],
1002
        'meeting_info' => json_encode($meetinginfo)));
1003
}
1004
1005
/**
1006
 * @param string $meetingid
1007
 * @param boolean $forced
1008
 */
1009
function bigbluebuttonbn_get_meeting_info($meetingid, $forced = false) {
1010
    $cachettl = (int)\mod_bigbluebuttonbn\locallib\config::get('waitformoderator_cache_ttl');
1011
1012
    $cache = cache::make_from_params(cache_store::MODE_APPLICATION, 'mod_bigbluebuttonbn', 'meetings_cache');
1013
    $result = $cache->get($meetingid);
1014
    $now = time();
1015
    if (!$forced && isset($result) && $now < ($result['creation_time'] + $cachettl)) {
1016
        // Use the value in the cache.
1017
        return (array) json_decode($result['meeting_info']);
1018
    }
1019
1020
    // Ping again and refresh the cache.
1021
    $meetinginfo = (array) bigbluebuttonbn_wrap_xml_load_file(
1022
        \mod_bigbluebuttonbn\locallib\bigbluebutton::action_url('getMeetingInfo', ['meetingID' => $meetingid])
1023
      );
1024
    $cache->set($meetingid, array('creation_time' => time(), 'meeting_info' => json_encode($meetinginfo)));
1025
1026
    return $meetinginfo;
1027
}
1028
1029
/**
1030
 * @param string $recordingid
1031
 * @param string $bigbluebuttonbnid
1032
 * @param boolean $publish
1033
 */
1034
function bigbluebuttonbn_publish_recording_imported($recordingid, $bigbluebuttonbnid, $publish = true) {
1035
    global $DB;
1036
1037
    // Locate the record to be updated.
1038
    $records = $DB->get_records('bigbluebuttonbn_logs', array('bigbluebuttonbnid' => $bigbluebuttonbnid,
1039
        'log' => BIGBLUEBUTTONBN_LOG_EVENT_IMPORT));
1040
1041
    foreach ($records as $key => $record) {
1042
        $meta = json_decode($record->meta, true);
1043
        if ($recordingid == $meta['recording']['recordID']) {
1044
            // Found, prepare data for the update.
1045
            $meta['recording']['published'] = ($publish) ? 'true' : 'false';
1046
            $records[$key]->meta = json_encode($meta);
1047
1048
            // Proceed with the update.
1049
            $DB->update_record('bigbluebuttonbn_logs', $records[$key]);
1050
        }
1051
    }
1052
}
1053
1054
/**
1055
 * @param string $recordingid
1056
 * @param string $bigbluebuttonbnid
1057
 */
1058
function bigbluebuttonbn_delete_recording_imported($recordingid, $bigbluebuttonbnid) {
1059
    global $DB;
1060
1061
    // Locate the record to be updated.
1062
    $records = $DB->get_records('bigbluebuttonbn_logs', array('bigbluebuttonbnid' => $bigbluebuttonbnid,
1063
        'log' => BIGBLUEBUTTONBN_LOG_EVENT_IMPORT));
1064
1065
    foreach ($records as $key => $record) {
1066
        $meta = json_decode($record->meta, true);
1067
        if ($recordingid == $meta['recording']['recordID']) {
1068
            // Execute delete.
1069
            $DB->delete_records('bigbluebuttonbn_logs', array('id' => $key));
1070
        }
1071
    }
1072
}
1073
1074
/**
1075
 * @param string $meetingid
1076
 * @param string $configxml
1077
 */
1078
function bigbluebuttonbn_set_config_xml_params($meetingid, $configxml) {
1079
    $params = 'configXML='.urlencode($configxml).'&meetingID='.urlencode($meetingid);
1080
    $configxmlparams = $params.'&checksum='.sha1('setConfigXML'.$params.\mod_bigbluebuttonbn\locallib\config::get('shared_secret'));
1081
1082
    return $configxmlparams;
1083
}
1084
1085
/**
1086
 * @param string $meetingid
1087
 * @param string $configxml
1088
 */
1089
function bigbluebuttonbn_set_config_xml($meetingid, $configxml) {
1090
    $urldefaultconfig = \mod_bigbluebuttonbn\locallib\config::get('server_url').'api/setConfigXML?';
1091
    $configxmlparams = bigbluebuttonbn_set_config_xml_params($meetingid, $configxml);
1092
    $xml = bigbluebuttonbn_wrap_xml_load_file($urldefaultconfig, BIGBLUEBUTTONBN_METHOD_POST,
1093
        $configxmlparams, 'application/x-www-form-urlencoded');
1094
1095
    return $xml;
1096
}
1097
1098
/**
1099
 * @param string $meetingid
1100
 * @param string $configxml
1101
 */
1102
function bigbluebuttonbn_set_config_xml_array($meetingid, $configxml) {
1103
    $configxml = bigbluebuttonbn_setConfigXML($meetingid, $configxml);
1104
    $configxmlarray = (array) $configxml;
1105
    if ($configxmlarray['returncode'] != 'SUCCESS') {
1106
        debugging('BigBlueButton was not able to set the custom config.xml file', DEBUG_DEVELOPER);
1107
        return '';
1108
    }
1109
1110
    return $configxmlarray['configToken'];
1111
}
1112
1113
function bigbluebuttonbn_get_recording_data_row($bbbsession, $recording, $tools = ['protect', 'publish', 'delete']) {
1114
    global $USER;
1115
1116
    $row = null;
1117
1118
    $managerecordings = $bbbsession['managerecordings'];
1119
    if ($managerecordings || $recording['published'] == 'true') {
1120
        $row = new stdClass();
1121
1122
        // Set recording_types.
1123
        $row->recording = bigbluebuttonbn_get_recording_data_row_types($recording, $bbbsession['bigbluebuttonbn']->id);
1124
1125
        // Set activity name and description.
1126
        $row->activity = bigbluebuttonbn_get_recording_data_row_meta_activity($recording, $managerecordings);
1127
        $row->description = bigbluebuttonbn_get_recording_data_row_meta_description($recording, $managerecordings);
1128
1129
        // Set recording_preview.
1130
        $row->preview = bigbluebuttonbn_get_recording_data_row_preview($recording);
1131
1132
        // Set date.
1133
        $starttime = 0;
1134
        if (isset($recording['startTime'])) {
1135
            $starttime = floatval($recording['startTime']);
1136
        }
1137
        $row->date = $starttime;
1138
        $starttime = $starttime - ($starttime % 1000);
1139
1140
        // Set formatted date.
1141
        $dateformat = get_string('strftimerecentfull', 'langconfig').' %Z';
1142
        $row->date_formatted = userdate($starttime / 1000, $dateformat, usertimezone($USER->timezone));
1143
1144
        // Set formatted duration.
1145
        $firstplayback = array_values($recording['playbacks'])[0];
1146
        $length = isset($firstplayback['length']) ? $firstplayback['length'] : 0;
1147
        $row->duration_formatted = $row->duration = intval($length);
1148
1149
        // Set actionbar, if user is allowed to manage recordings.
1150
        if ($managerecordings) {
1151
            $row->actionbar = bigbluebuttonbn_get_recording_data_row_actionbar($recording, $tools);
1152
        }
1153
    }
1154
1155
    return $row;
1156
}
1157
1158
function bigbluebuttonbn_get_recording_data_row_actionbar($recording, $tools) {
1159
    $actionbar = '';
1160
    foreach ($tools as $tool) {
1161
        $actionbar .= bigbluebuttonbn_actionbar_render_button(
1162
            $recording,
1163
            bigbluebuttonbn_get_recording_data_row_actionbar_payload($recording, $tool)
1164
          );
1165
    }
1166
    $head = html_writer::start_tag('div', array(
1167
        'id' => 'recording-actionbar-' . $recording['recordID'],
1168
        'data-recordingid' => $recording['recordID'],
1169
        'data-meetingid' => $recording['meetingID']));
1170
    $tail = html_writer::end_tag('div');
1171
    return $head . $actionbar . $tail;
1172
}
1173
1174
function bigbluebuttonbn_get_recording_data_row_action_protect($protected) {
1175
    if ($protected == 'true') {
1176
        return array('action' => 'unprotect', 'tag' => 'unlock');
1177
    }
1178
1179
    return array('action' => 'protect', 'tag' => 'lock');
1180
}
1181
1182
function bigbluebuttonbn_get_recording_data_row_action_publish($published) {
1183
    if ($published == 'true') {
1184
        return array('action' => 'unpublish', 'tag' => 'hide');
1185
    }
1186
1187
    return array('action' => 'publish', 'tag' => 'show');
1188
}
1189
1190
function bigbluebuttonbn_get_recording_data_row_actionbar_payload($recording, $tool) {
1191
    if ($tool == 'protect' && isset($recording['protected'])) {
1192
        return bigbluebuttonbn_get_recording_data_row_action_protect($recording['protected']);
1193
    }
1194
1195
    if ($tool == 'publish') {
1196
        return bigbluebuttonbn_get_recording_data_row_action_publish($recording['published']);
1197
    }
1198
1199
    if ($tool == 'delete' || $tool == 'import') {
1200
        return array('action' => $tool, 'tag' => $tool);
1201
    }
1202
}
1203
1204
function bigbluebuttonbn_get_recording_data_row_preview($recording) {
1205
1206
    $visibility = '';
1207
    if ($recording['published'] === 'false') {
1208
        $visibility = 'hidden ';
1209
    }
1210
1211
    $recordingpreview = html_writer::start_tag('div',
1212
        array('id' => 'preview-'.$recording['recordID'], $visibility => $visibility));
1213
    foreach ($recording['playbacks'] as $playback) {
1214
        if (isset($playback['preview'])) {
1215
            foreach ($playback['preview'] as $image) {
1216
                $recordingpreview .= html_writer::empty_tag('img',
1217
                    array('src' => $image['url'] . '?' . time(), 'class' => 'thumbnail'));
1218
            }
1219
            $recordingpreview .= html_writer::empty_tag('br');
1220
            $recordingpreview .= html_writer::tag('div',
1221
                get_string('view_recording_preview_help', 'bigbluebuttonbn'), array('class' => 'text-muted small'));
1222
            break;
1223
        }
1224
    }
1225
    $recordingpreview .= html_writer::end_tag('div');
1226
1227
    return $recordingpreview;
1228
}
1229
1230
function bigbluebuttonbn_get_recording_data_row_types($recording, $bigbluebuttonbnid) {
1231
    global $CFG, $OUTPUT;
1232
1233
    $dataimported = 'false';
1234
    $title = '';
1235
    if (isset($recording['imported'])) {
1236
        $dataimported = 'true';
1237
        $title = get_string('view_recording_link_warning', 'bigbluebuttonbn');
1238
    }
1239
1240
    $visibility = '';
1241
    if ($recording['published'] === 'false') {
1242
        $visibility = 'hidden ';
1243
    }
1244
1245
    $id = 'playbacks-'.$recording['recordID'];
1246
    $recordingtypes = html_writer::start_tag('div', array('id' => $id, 'data-imported' => $dataimported,
1247
          'data-recordingid' => $recording['recordID'], 'data-meetingid' => $recording['meetingID'],
1248
          'title' => $title, $visibility => $visibility));
1249
    foreach ($recording['playbacks'] as $playback) {
1250
        $onclick = 'M.mod_bigbluebuttonbn.recordings.recording_play(this);';
1251
        $href = $CFG->wwwroot.'/mod/bigbluebuttonbn/bbb_view.php?action=playback&bn='.$bigbluebuttonbnid.
1252
            '&href='.urlencode($playback['url']).'&rid='.$recording['recordID'];
1253
        $linkattributes = array('title' => get_string('view_recording_format_'.$playback['type'], 'bigbluebuttonbn'),
1254
            'class' => 'btn btn-sm btn-default', 'onclick' => $onclick,
1255
            'data-action' => 'play', 'data-href' => $href);
1256
        $recordingtypes .= $OUTPUT->action_link('#', get_string('view_recording_format_'.$playback['type'],
1257
            'bigbluebuttonbn'), null, $linkattributes).'&#32;';
1258
    }
1259
    $recordingtypes .= html_writer::end_tag('div');
1260
1261
    return $recordingtypes;
1262
}
1263
1264
function bigbluebuttonbn_get_recording_data_row_meta_activity($recording, $editable) {
1265
    $payload = array();
1266 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...
1267
        $payload = array('recordingid' => $recording['recordID'], 'meetingid' => $recording['meetingID'],
1268
            'action' => 'edit', 'tag' => 'edit',
1269
            'target' => 'name', 'source' => 'meta_bbb-recording-name');
1270
    }
1271
    if (isset($recording['meta_contextactivity'])) {
1272
        $payload['source'] = 'meta_contextactivity';
1273
        return bigbluebuttonbn_get_recording_data_row_text($recording, $recording[$payload['source']], $payload);
1274
    }
1275
1276
    if (isset($recording['meta_bbb-recording-name'])) {
1277
        return bigbluebuttonbn_get_recording_data_row_text($recording, $recording[$payload['source']], $payload);
1278
    }
1279
1280
    return bigbluebuttonbn_get_recording_data_row_text($recording, $recording['meetingName'], $payload);
1281
}
1282
1283
function bigbluebuttonbn_get_recording_data_row_meta_description($recording, $editable) {
1284
    $payload = array();
1285 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...
1286
        $payload = array('recordingid' => $recording['recordID'], 'meetingid' => $recording['meetingID'],
1287
            'action' => 'edit', 'tag' => 'edit',
1288
            'target' => 'description', 'source' => 'meta_bbb-recording-description');
1289
    }
1290
1291 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...
1292
        $payload['source'] = 'meta_contextactivitydescription';
1293
        $metadescription = trim($recording[$payload['source']]);
1294
        if (!empty($metadescription)) {
1295
            return bigbluebuttonbn_get_recording_data_row_text($recording, $metadescription, $payload);
1296
        }
1297
    }
1298
1299 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...
1300
        $metadescription = trim($recording[$payload['source']]);
1301
        if (!empty($metadescription)) {
1302
            return bigbluebuttonbn_get_recording_data_row_text($recording, $metadescription, $payload);
1303
        }
1304
    }
1305
1306
    return bigbluebuttonbn_get_recording_data_row_text($recording, '', $payload);
1307
}
1308
1309
function bigbluebuttonbn_get_recording_data_row_text($recording, $text, $data) {
1310
    $htmltext = '<span>' . htmlentities($text) . '</span>';
1311
1312
    if (empty($data)) {
1313
        return $htmltext;
1314
    }
1315
1316
    $target = $data['action'] . '-' . $data['target'];
1317
    $id = 'recording-' . $target . '-' . $data['recordingid'];
1318
    $attributes = array('id' => $id, 'class' => 'quickeditlink col-md-20',
1319
        'data-recordingid' => $data['recordingid'], 'data-meetingid' => $data['meetingid'],
1320
        'data-target' => $data['target'], 'data-source' => $data['source']);
1321
    $head = html_writer::start_tag('div', $attributes);
1322
    $tail = html_writer::end_tag('div');
1323
1324
    $payload = array('action' => $data['action'], 'tag' => $data['tag'], 'target' => $data['target']);
1325
    $htmllink = bigbluebuttonbn_actionbar_render_button($recording, $payload);
1326
1327
    return $head . $htmltext . $htmllink . $tail;
1328
}
1329
1330
function bigbluebuttonbn_actionbar_render_button($recording, $data) {
1331
    global $OUTPUT;
1332
1333
    if (!$data) {
1334
        return '';
1335
    }
1336
1337
    $target = $data['action'];
1338
    if (isset($data['target'])) {
1339
        $target .= '-' . $data['target'];
1340
    }
1341
    $id = 'recording-' . $target . '-' . $recording['recordID'];
1342
    $onclick = 'M.mod_bigbluebuttonbn.recordings.recording_'.$data['action'].'(this);';
1343
    if ((boolean)\mod_bigbluebuttonbn\locallib\config::get('recording_icons_enabled')) {
1344
        // With icon for $manageaction.
1345
        $iconattributes = array('id' => $id, 'class' => 'iconsmall');
1346
        $icon = new pix_icon('i/'.$data['tag'],
1347
            get_string('view_recording_list_actionbar_' . $data['action'], 'bigbluebuttonbn'),
1348
            'moodle', $iconattributes);
1349
        $linkattributes = array(
1350
            'id' => $id,
1351
            'onclick' => $onclick,
1352
            'data-action' => $data['action'],
1353
            'data-links' => bigbluebuttonbn_get_count_recording_imported_instances($recording['recordID'])
1354
          );
1355
        return $OUTPUT->action_icon('#', $icon, null, $linkattributes, false);
1356
    }
1357
1358
    // With text for $manageaction.
1359
    $linkattributes = array('title' => get_string($data['tag']), 'class' => 'btn btn-xs btn-danger',
1360
        'onclick' => $onclick);
1361
    return $OUTPUT->action_link('#', get_string($data['action']), null, $linkattributes);
1362
}
1363
1364
function bigbluebuttonbn_get_recording_columns($bbbsession) {
1365
    // Set strings to show.
1366
    $recording = get_string('view_recording_recording', 'bigbluebuttonbn');
1367
    $activity = get_string('view_recording_activity', 'bigbluebuttonbn');
1368
    $description = get_string('view_recording_description', 'bigbluebuttonbn');
1369
    $preview = get_string('view_recording_preview', 'bigbluebuttonbn');
1370
    $date = get_string('view_recording_date', 'bigbluebuttonbn');
1371
    $duration = get_string('view_recording_duration', 'bigbluebuttonbn');
1372
    $actionbar = get_string('view_recording_actionbar', 'bigbluebuttonbn');
1373
1374
    // Initialize table headers.
1375
    $recordingsbncolumns = array(
1376
        array('key' => 'recording', 'label' => $recording, 'width' => '125px', 'allowHTML' => true),
1377
        array('key' => 'activity', 'label' => $activity, 'sortable' => true, 'width' => '175px', 'allowHTML' => true),
1378
        array('key' => 'description', 'label' => $description, 'width' => '250px', 'sortable' => true,
1379
            'width' => '250px', 'allowHTML' => true),
1380
        array('key' => 'preview', 'label' => $preview, 'width' => '250px', 'allowHTML' => true),
1381
        array('key' => 'date', 'label' => $date, 'sortable' => true, 'width' => '225px', 'allowHTML' => true),
1382
        array('key' => 'duration', 'label' => $duration, 'width' => '50px'),
1383
        );
1384
1385
    if ($bbbsession['managerecordings']) {
1386
        array_push($recordingsbncolumns, array('key' => 'actionbar', 'label' => $actionbar, 'width' => '100px',
1387
            'allowHTML' => true));
1388
    }
1389
1390
    return $recordingsbncolumns;
1391
}
1392
1393
function bigbluebuttonbn_get_recording_data($bbbsession, $recordings, $tools = ['protect', 'publish', 'delete']) {
1394
    $tabledata = array();
1395
1396
    // Build table content.
1397 View Code Duplication
    if (isset($recordings) && !array_key_exists('messageKey', $recordings)) {
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...
1398
        // There are recordings for this meeting.
1399
        foreach ($recordings as $recording) {
1400
            $row = bigbluebuttonbn_get_recording_data_row($bbbsession, $recording, $tools);
1401
            if ($row != null) {
1402
                array_push($tabledata, $row);
1403
            }
1404
        }
1405
    }
1406
1407
    return $tabledata;
1408
}
1409
1410
function bigbluebuttonbn_get_recording_table($bbbsession, $recordings, $tools = ['protect', 'publish', 'delete']) {
1411
    // Set strings to show.
1412
    $recording = get_string('view_recording_recording', 'bigbluebuttonbn');
1413
    $description = get_string('view_recording_description', 'bigbluebuttonbn');
1414
    $date = get_string('view_recording_date', 'bigbluebuttonbn');
1415
    $duration = get_string('view_recording_duration', 'bigbluebuttonbn');
1416
    $actionbar = get_string('view_recording_actionbar', 'bigbluebuttonbn');
1417
    $playback = get_string('view_recording_playback', 'bigbluebuttonbn');
1418
    $preview = get_string('view_recording_preview', 'bigbluebuttonbn');
1419
1420
    // Declare the table.
1421
    $table = new html_table();
1422
    $table->data = array();
1423
1424
    // Initialize table headers.
1425
    $table->head = array($playback, $recording, $description, $preview, $date, $duration);
1426
    $table->align = array('left', 'left', 'left', 'left', 'left', 'center');
1427
    if ($bbbsession['managerecordings']) {
1428
        $table->head[] = $actionbar;
1429
        $table->align[] = 'left';
1430
    }
1431
1432
    // Build table content.
1433 View Code Duplication
    if (isset($recordings) && !array_key_exists('messageKey', $recordings)) {
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...
1434
        // There are recordings for this meeting.
1435
        foreach ($recordings as $recording) {
1436
            if ( !bigbluebuttonbn_include_recording_table_row($bbbsession, $recording) ) {
1437
                continue;
1438
            }
1439
            bigbluebuttonbn_get_recording_table_row($bbbsession, $recording, $tools, $table);
1440
        }
1441
    }
1442
1443
    return $table;
1444
}
1445
1446
function bigbluebuttonbn_get_recording_table_row($bbbsession, $recording, $tools, &$table) {
1447
    $row = new html_table_row();
1448
    $row->id = 'recording-td-'.$recording['recordID'];
1449
    $row->attributes['data-imported'] = 'false';
1450
    $texthead = '';
1451
    $texttail = '';
1452
    if (isset($recording['imported'])) {
1453
        $row->attributes['data-imported'] = 'true';
1454
        $row->attributes['title'] = get_string('view_recording_link_warning', 'bigbluebuttonbn');
1455
        $texthead = '<em>';
1456
        $texttail = '</em>';
1457
    }
1458
1459
    $rowdata = bigbluebuttonbn_get_recording_data_row($bbbsession, $recording, $tools);
1460
    if ($rowdata != null) {
1461
        $rowdata->date_formatted = str_replace(' ', '&nbsp;', $rowdata->date_formatted);
1462
        $row->cells = array($texthead.$rowdata->recording.$texttail,
1463
            $texthead.$rowdata->activity.$texttail, $texthead.$rowdata->description.$texttail,
1464
            $rowdata->preview, $texthead.$rowdata->date_formatted.$texttail,
1465
            $rowdata->duration_formatted);
1466
        if ($bbbsession['managerecordings']) {
1467
            $row->cells[] = $rowdata->actionbar;
1468
        }
1469
        array_push($table->data, $row);
1470
    }
1471
}
1472
1473
function bigbluebuttonbn_include_recording_table_row($bbbsession, $recording) {
1474
    return !( !isset($recording['imported']) && isset($bbbsession['group']) && $recording['meetingID'] != $bbbsession['meetingid'] );
1475
}
1476
1477
function bigbluebuttonbn_send_notification_recording_ready($bigbluebuttonbn) {
1478
    $sender = get_admin();
1479
1480
    // Prepare message.
1481
    $msg = new stdClass();
1482
1483
    // Build the message_body.
1484
    $msg->activity_type = '';
1485
    $msg->activity_title = $bigbluebuttonbn->name;
1486
    $messagetext = '<p>'.get_string('email_body_recording_ready_for', 'bigbluebuttonbn').' '.
1487
        $msg->activity_type.' &quot;'.$msg->activity_title.'&quot; '.
1488
        get_string('email_body_recording_ready_is_ready', 'bigbluebuttonbn').'.</p>';
1489
1490
    bigbluebuttonbn_send_notification($sender, $bigbluebuttonbn, $messagetext);
1491
}
1492
1493
function bigbluebuttonbn_is_bn_server() {
1494
    // Validates if the server may have extended capabilities.
1495
    $parsedurl = parse_url(\mod_bigbluebuttonbn\locallib\config::get('server_url'));
1496
    if (!isset($parsedurl['host'])) {
1497
        return false;
1498
    }
1499
1500
    $h = $parsedurl['host'];
1501
    $hends = explode('.', $h);
1502
    $hendslength = count($hends);
1503
1504
    return ($hends[$hendslength - 1] == 'com' && $hends[$hendslength - 2] == 'blindsidenetworks');
1505
}
1506
1507
function bigbluebuttonbn_import_get_courses_for_select(array $bbbsession) {
1508
    if ($bbbsession['administrator']) {
1509
        $courses = get_courses('all', 'c.id ASC', 'c.id,c.shortname,c.fullname');
1510
        // It includes the name of the site as a course (category 0), so remove the first one.
1511
        unset($courses['1']);
1512
    } else {
1513
        $courses = enrol_get_users_courses($bbbsession['userID'], false, 'id,shortname,fullname');
1514
    }
1515
1516
    $coursesforselect = [];
1517
    foreach ($courses as $course) {
1518
        $coursesforselect[$course->id] = $course->fullname;
1519
    }
1520
1521
    return $coursesforselect;
1522
}
1523
1524
function bigbluebutton_output_recording_table($bbbsession, $recordings, $tools = ['protect', 'publish', 'delete']) {
1525
    if (isset($recordings) && !empty($recordings)) {
1526
        // There are recordings for this meeting.
1527
        $table = bigbluebuttonbn_get_recording_table($bbbsession, $recordings, $tools);
1528
    }
1529
1530
    if (!isset($table) || !isset($table->data)) {
1531
        // Render a table qith "No recordings".
1532
        return html_writer::div(get_string('view_message_norecordings', 'bigbluebuttonbn'), '',
1533
            array('id' => 'bigbluebuttonbn_html_table'));
1534
    }
1535
1536
    // Render the table.
1537
    return html_writer::div(html_writer::table($table), '', array('id' => 'bigbluebuttonbn_html_table'));
1538
}
1539
1540
function bigbluebuttonbn_html2text($html, $len) {
1541
    $text = strip_tags($html);
1542
    $text = str_replace('&nbsp;', ' ', $text);
1543
    $text = substr($text, 0, $len);
1544
    if (strlen($text) > $len) {
1545
        $text .= '...';
1546
    }
1547
1548
    return $text;
1549
}
1550
1551
/**
1552
 * helper function to obtain the tags linked to a bigbluebuttonbn activity
1553
 *
1554
 * @param string $id
1555
 *
1556
 * @return string containing the tags separated by commas
1557
 */
1558
function bigbluebuttonbn_get_tags($id) {
1559
    $tagsarray = core_tag_tag::get_item_tags_array('core', 'course_modules', $id);
1560
    return implode(',', $tagsarray);
1561
}
1562
1563
/**
1564
 * helper function to retrieve recordings from the BigBlueButton. The references are stored as events
1565
 * in bigbluebuttonbn_logs.
1566
 *
1567
 * @param string $courseid
1568
 * @param string $bigbluebuttonbnid
1569
 * @param bool   $subset
1570
 * @param bool   $includedeleted
1571
 *
1572
 * @return associative array containing the recordings indexed by recordID, each recording is also a
1573
 * non sequential associative array itself that corresponds to the actual recording in BBB
1574
 */
1575
function bigbluebuttonbn_get_recordings($courseid, $bigbluebuttonbnid = null,
1576
        $subset = true, $includedeleted = false) {
1577
    global $DB;
1578
1579
    // Gather the bigbluebuttonbnids whose meetingids should be included in the getRecordings request'.
1580
    $select = "id <> '{$bigbluebuttonbnid}' AND course = '{$courseid}'";
1581
    $selectdeleted = "courseid = '{$courseid}' AND bigbluebuttonbnid <> '{$bigbluebuttonbnid}' AND log = '".
1582
        BIGBLUEBUTTONBN_LOG_EVENT_DELETE."' AND meta like '%has_recordings%' AND meta like '%true%'";
1583
    if ($bigbluebuttonbnid === null) {
1584
        $select = "course = '{$courseid}'";
1585
        $selectdeleted = "courseid = '{$courseid}' AND log = '".BIGBLUEBUTTONBN_LOG_EVENT_DELETE.
1586
            "' AND meta like '%has_recordings%' AND meta like '%true%'";
1587
    } else if ($subset) {
1588
        $select = "id = '{$bigbluebuttonbnid}'";
1589
        $selectdeleted = "bigbluebuttonbnid = '{$bigbluebuttonbnid}' AND log = '".BIGBLUEBUTTONBN_LOG_EVENT_DELETE.
1590
            "' AND meta like '%has_recordings%' AND meta like '%true%'";
1591
    }
1592
    $bigbluebuttonbns = $DB->get_records_select_menu('bigbluebuttonbn', $select, null, 'id', 'id, meetingid');
1593
1594
    /* Consider logs from deleted bigbluebuttonbn instances whose meetingids should be included in
1595
     * the getRecordings request. */
1596
    if ($includedeleted) {
1597
        $bigbluebuttonbnsdel = $DB->get_records_select_menu('bigbluebuttonbn_logs', $selectdeleted, null,
1598
            'bigbluebuttonbnid', 'bigbluebuttonbnid, meetingid');
1599
        if (!empty($bigbluebuttonbnsdel)) {
1600
            // Merge bigbluebuttonbnis from deleted instances, only keys are relevant.
1601
            // Artimetic merge is used in order to keep the keys.
1602
            $bigbluebuttonbns += $bigbluebuttonbnsdel;
1603
        }
1604
    }
1605
1606
    // Gather the meetingids from bigbluebuttonbn logs that include a create with record=true.
1607
    $recordings = array();
1608
    if (!empty($bigbluebuttonbns)) {
1609
        // Prepare select for loading records based on existent bigbluebuttonbns.
1610
        $sql = 'SELECT DISTINCT meetingid, bigbluebuttonbnid FROM {bigbluebuttonbn_logs} WHERE ';
1611
        $sql .= '(bigbluebuttonbnid='.implode(' OR bigbluebuttonbnid=', array_keys($bigbluebuttonbns)).')';
1612
        // Include only Create events and exclude those with record not true.
1613
        $sql .= ' AND log = ? AND meta LIKE ? AND meta LIKE ?';
1614
        // Execute select for loading records based on existent bigbluebuttonbns.
1615
        $records = $DB->get_records_sql_menu($sql, array(BIGBLUEBUTTONBN_LOG_EVENT_CREATE, '%record%', '%true%'));
1616
        // Get actual recordings.
1617
        $recordings = bigbluebuttonbn_get_recordings_array(array_keys($records));
1618
    }
1619
1620
    // Get recording links.
1621
    $recordingsimported = bigbluebuttonbn_get_recordings_imported_array($courseid, $bigbluebuttonbnid, $subset);
1622
1623
    /* Perform aritmetic add instead of merge so the imported recordings corresponding to existent recordings
1624
     * are not included. */
1625
    return $recordings + $recordingsimported;
1626
}
1627
1628
function bigbluebuttonbn_unset_existent_recordings_already_imported($recordings, $courseid, $bigbluebuttonbnid) {
1629
    $recordingsimported = bigbluebuttonbn_get_recordings_imported_array($courseid, $bigbluebuttonbnid, true);
1630
1631
    foreach ($recordings as $key => $recording) {
1632
        if (isset($recordingsimported[$recording['recordID']])) {
1633
            unset($recordings[$key]);
1634
        }
1635
    }
1636
1637
    return $recordings;
1638
}
1639
1640
function bigbluebuttonbn_get_count_recording_imported_instances($recordid) {
1641
    global $DB;
1642
1643
    $sql = 'SELECT COUNT(DISTINCT id) FROM {bigbluebuttonbn_logs} WHERE log = ? AND meta LIKE ? AND meta LIKE ?';
1644
1645
    return $DB->count_records_sql($sql, array(BIGBLUEBUTTONBN_LOG_EVENT_IMPORT, '%recordID%', "%{$recordid}%"));
1646
}
1647
1648
function bigbluebuttonbn_get_recording_imported_instances($recordid) {
1649
    global $DB;
1650
1651
    $sql = 'SELECT * FROM {bigbluebuttonbn_logs} WHERE log = ? AND meta LIKE ? AND meta LIKE ?';
1652
    $recordingsimported = $DB->get_records_sql($sql, array(BIGBLUEBUTTONBN_LOG_EVENT_IMPORT, '%recordID%',
1653
        "%{$recordid}%"));
1654
1655
    return $recordingsimported;
1656
}
1657
1658
function bigbluebuttonbn_get_instance_type_profiles() {
1659
    $instanceprofiles = array(
1660
            array('id' => BIGBLUEBUTTONBN_TYPE_ALL, 'name' => get_string('instance_type_default', 'bigbluebuttonbn'),
1661
                'features' => array('all')),
1662
            array('id' => BIGBLUEBUTTONBN_TYPE_ROOM_ONLY, 'name' => get_string('instance_type_room_only', 'bigbluebuttonbn'),
1663
                'features' => array('showroom', 'welcomemessage', 'voicebridge', 'waitformoderator', 'userlimit', 'recording',
1664
                    'sendnotifications', 'preuploadpresentation', 'permissions', 'schedule', 'groups')),
1665
            array('id' => BIGBLUEBUTTONBN_TYPE_RECORDING_ONLY, 'name' => get_string('instance_type_recording_only',
1666
                'bigbluebuttonbn'), 'features' => array('showrecordings', 'importrecordings')),
1667
    );
1668
1669
    return $instanceprofiles;
1670
}
1671
1672
function bigbluebuttonbn_get_enabled_features($typeprofiles, $type = null) {
1673
    $enabledfeatures = array();
1674
1675
    $features = $typeprofiles[0]['features'];
1676
    if (!is_null($type)) {
1677
        $features = $typeprofiles[$type]['features'];
1678
    }
1679
    $enabledfeatures['showroom'] = (in_array('all', $features) || in_array('showroom', $features));
1680
    $enabledfeatures['showrecordings'] = (in_array('all', $features) || in_array('showrecordings', $features));
1681
    $enabledfeatures['importrecordings'] = (in_array('all', $features) || in_array('importrecordings', $features));
1682
1683
    return $enabledfeatures;
1684
}
1685
1686
function bigbluebuttonbn_get_instance_profiles_array($profiles = null) {
1687
    if (is_null($profiles) || empty($profiles)) {
1688
        $profiles = bigbluebuttonbn_get_instance_type_profiles();
1689
    }
1690
1691
    $profilesarray = array();
1692
1693
    foreach ($profiles as $profile) {
1694
        $profilesarray += array("{$profile['id']}" => $profile['name']);
1695
    }
1696
1697
    return $profilesarray;
1698
}
1699
1700
function bigbluebuttonbn_format_activity_time($time) {
1701
    $activitytime = '';
1702
    if ($time) {
1703
        $activitytime = calendar_day_representation($time).' '.
1704
          get_string('mod_form_field_notification_msg_at', 'bigbluebuttonbn').' '.
1705
          calendar_time_representation($time);
1706
    }
1707
1708
    return $activitytime;
1709
}
1710
1711
function bigbluebuttonbn_get_strings_for_js() {
1712
    $locale = bigbluebuttonbn_get_locale();
1713
    $stringman = get_string_manager();
1714
    $strings = $stringman->load_component_strings('bigbluebuttonbn', $locale);
1715
    return $strings;
1716
}
1717
1718
function bigbluebuttonbn_get_locale() {
1719
    $lang = get_string('locale', 'core_langconfig');
1720
    return substr($lang, 0, strpos($lang, '.'));
1721
}
1722
1723
function bigbluebuttonbn_get_localcode() {
1724
    $locale = bigbluebuttonbn_get_locale();
1725
    return substr($locale, 0, strpos($locale, '_'));
1726
}
1727
1728
function bigbluebuttonbn_get_moderator_email($context) {
1729
    $moderatoremails = array();
1730
    $users = (array) get_enrolled_users($context,'',0,'u.*',null,0,0,true);
1731
    $counter = 0;
1732
    foreach ($users as $key => $user) {
1733
        if ($counter == 5) {
1734
            break;
1735
        }
1736
        if (has_capability('mod/bigbluebuttonbn:moderate', $context, $user)) {
1737
            array_push($moderatoremails, '"' . fullname($user) . '" <' . $user->email . '>');
1738
            $counter += 1;
1739
        }
1740
    }
1741
    return $moderatoremails;
1742
}
1743