Completed
Push — master ( 4da55a...13882c )
by Jesus
02:48
created

locallib.php ➔ bigbluebutonbn_settings_voicebridge()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

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