Completed
Push — master ( 34b439...bbd578 )
by Jesus
02:21
created

locallib.php ➔ bigbluebuttonbn_get_enabled_features()   B

Complexity

Conditions 7
Paths 36

Size

Total Lines 18
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

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

Syntax error, unexpected '{'
Loading history...
Bug introduced by
Avoid IF statements that are always true or false
Loading history...
1848
        return true;
1849
    }
1850
    // When groups are enabled, exclude those to which the user doesn't have access to.
1851
    if (isset($bbbsession['group']) && $recording['meetingID'] != $bbbsession['meetingid']) {
1852
        return false;
1853
    }
1854
    return true;
1855
}
1856
1857
/**
1858
 * Helper function triggers a send notification when the recording is ready.
1859
 *
1860
 * @param object $bigbluebuttonbn
1861
 *
1862
 * @return void
1863
 */
1864
function bigbluebuttonbn_send_notification_recording_ready($bigbluebuttonbn) {
1865
    $sender = get_admin();
1866
    // Prepare message.
1867
    $messagetext = '<p>'.get_string('email_body_recording_ready_for', 'bigbluebuttonbn').
1868
        ' &quot;' . $bigbluebuttonbn->name . '&quot; '.
1869
        get_string('email_body_recording_ready_is_ready', 'bigbluebuttonbn').'.</p>';
1870
    $context = context_course::instance($bigbluebuttonbn->course);
1871
    \mod_bigbluebuttonbn\locallib\notifier::notification_send($context, $sender, $bigbluebuttonbn, $messagetext);
1872
}
1873
1874
/**
1875
 * Helper evaluates if the bigbluebutton server used belongs to blindsidenetworks domain.
1876
 *
1877
 * @return boolean
1878
 */
1879
function bigbluebuttonbn_is_bn_server() {
1880
    $parsedurl = parse_url(\mod_bigbluebuttonbn\locallib\config::get('server_url'));
1881
    if (!isset($parsedurl['host'])) {
1882
        return false;
1883
    }
1884
    $h = $parsedurl['host'];
1885
    $hends = explode('.', $h);
1886
    $hendslength = count($hends);
1887
    return ($hends[$hendslength - 1] == 'com' && $hends[$hendslength - 2] == 'blindsidenetworks');
1888
}
1889
1890
/**
1891
 * Helper function returns a list of courses a user has access to, wrapped in an array that can be used
1892
 * by a html select.
1893
 *
1894
 * @param array $bbbsession
1895
 *
1896
 * @return array
1897
 */
1898
function bigbluebuttonbn_import_get_courses_for_select(array $bbbsession) {
1899
    if ($bbbsession['administrator']) {
1900
        $courses = get_courses('all', 'c.fullname ASC', 'c.id,c.shortname,c.fullname');
1901
        // It includes the name of the site as a course (category 0), so remove the first one.
1902
        unset($courses['1']);
1903
    } else {
1904
        $courses = enrol_get_users_courses($bbbsession['userID'], false, 'id,shortname,fullname');
1905
    }
1906
    $coursesforselect = [];
1907
    foreach ($courses as $course) {
1908
        $coursesforselect[$course->id] = $course->fullname;
1909
    }
1910
    return $coursesforselect;
1911
}
1912
1913
/**
1914
 * Helper function renders recording table.
1915
 *
1916
 * @param array $bbbsession
1917
 * @param array $recordings
1918
 * @param array $tools
1919
 *
1920
 * @return array
1921
 */
1922
function bigbluebuttonbn_output_recording_table($bbbsession, $recordings, $tools = ['protect', 'publish', 'delete']) {
1923
    if (isset($recordings) && !empty($recordings)) {
1924
        // There are recordings for this meeting.
1925
        $table = bigbluebuttonbn_get_recording_table($bbbsession, $recordings, $tools);
1926
    }
1927
    if (!isset($table) || !isset($table->data)) {
1928
        // Render a table with "No recordings".
1929
        return html_writer::div(get_string('view_message_norecordings', 'bigbluebuttonbn'), '',
1930
            array('id' => 'bigbluebuttonbn_html_table'));
1931
    }
1932
    // Render the table.
1933
    return html_writer::div(html_writer::table($table), '', array('id' => 'bigbluebuttonbn_html_table'));
1934
}
1935
1936
/**
1937
 * Helper function to convert an html string to plain text.
1938
 *
1939
 * @param string $html
1940
 * @param integer $len
1941
 *
1942
 * @return string
1943
 */
1944
function bigbluebuttonbn_html2text($html, $len = 0) {
1945
    $text = strip_tags($html);
1946
    $text = str_replace('&nbsp;', ' ', $text);
1947
    $textlen = strlen($text);
1948
    $text = substr($text, 0, $len);
1949
    if ($textlen > $len) {
1950
        $text .= '...';
1951
    }
1952
    return $text;
1953
}
1954
1955
/**
1956
 * Helper function to obtain the tags linked to a bigbluebuttonbn activity
1957
 *
1958
 * @param string $id
1959
 *
1960
 * @return string containing the tags separated by commas
1961
 */
1962
function bigbluebuttonbn_get_tags($id) {
1963
    $tagsarray = core_tag_tag::get_item_tags_array('core', 'course_modules', $id);
1964
    return implode(',', $tagsarray);
1965
}
1966
1967
/**
1968
 * Helper function to define the sql used for gattering the bigbluebuttonbnids whose meetingids should be included
1969
 * in the getRecordings request
1970
 *
1971
 * @param string $courseid
1972
 * @param string $bigbluebuttonbnid
1973
 * @param bool   $subset
1974
 *
1975
 * @return string containing the sql used for getting the target bigbluebuttonbn instances
1976
 */
1977
function bigbluebuttonbn_get_recordings_sql_select($courseid, $bigbluebuttonbnid = null, $subset = true) {
1978
    if (empty($courseid)) {
1979
        $courseid = 0;
1980
    }
1981
    if (empty($bigbluebuttonbnid)) {
1982
        return "course = '{$courseid}'";
1983
    }
1984
    if ($subset) {
1985
        return "id = '{$bigbluebuttonbnid}'";
1986
    }
1987
    return "id <> '{$bigbluebuttonbnid}' AND course = '{$courseid}'";
1988
}
1989
1990
/**
1991
 * Helper function to define the sql used for gattering the bigbluebuttonbnids whose meetingids should be included
1992
 * in the getRecordings request considering only those that belong to deleted activities.
1993
 *
1994
 * @param string $courseid
1995
 * @param string $bigbluebuttonbnid
1996
 * @param bool   $subset
1997
 *
1998
 * @return string containing the sql used for getting the target bigbluebuttonbn instances
1999
 */
2000
function bigbluebuttonbn_get_recordings_deleted_sql_select($courseid = 0, $bigbluebuttonbnid = null, $subset = true) {
2001
    $sql = "log = '" . BIGBLUEBUTTONBN_LOG_EVENT_DELETE . "' AND meta like '%has_recordings%' AND meta like '%true%'";
2002
    if (empty($courseid)) {
2003
        $courseid = 0;
2004
    }
2005
    if (empty($bigbluebuttonbnid)) {
2006
        return $sql . " AND courseid = {$courseid}";
2007
    }
2008
    if ($subset) {
2009
        return $sql . " AND bigbluebuttonbnid = '{$bigbluebuttonbnid}'";
2010
    }
2011
    return $sql . " AND courseid = {$courseid} AND bigbluebuttonbnid <> '{$bigbluebuttonbnid}'";
2012
}
2013
2014
/**
2015
 * Helper function to define the sql used for gattering the bigbluebuttonbnids whose meetingids should be included
2016
 * in the getRecordings request considering only those that belong to imported recordings.
2017
 *
2018
 * @param string $courseid
2019
 * @param string $bigbluebuttonbnid
2020
 * @param bool   $subset
2021
 *
2022
 * @return string containing the sql used for getting the target bigbluebuttonbn instances
2023
 */
2024
function bigbluebuttonbn_get_recordings_imported_sql_select($courseid = 0, $bigbluebuttonbnid = null, $subset = true) {
2025
    $sql = "log = '" . BIGBLUEBUTTONBN_LOG_EVENT_IMPORT . "'";
2026
    if (empty($courseid)) {
2027
        $courseid = 0;
2028
    }
2029
    if (empty($bigbluebuttonbnid)) {
2030
        return $sql . " AND courseid = '{$courseid}'";
2031
    }
2032
    if ($subset) {
2033
        return $sql . " AND bigbluebuttonbnid = '{$bigbluebuttonbnid}'";
2034
    }
2035
    return $sql . " AND courseid = '{$courseid}' AND bigbluebuttonbnid <> '{$bigbluebuttonbnid}'";
2036
}
2037
2038
/**
2039
 * Helper function to get recordings  and imported recordings together.
2040
 *
2041
 * @param string $courseid
2042
 * @param string $bigbluebuttonbnid
2043
 * @param bool   $subset
2044
 * @param bool   $includedeleted
2045
 *
2046
 * @return associative array containing the recordings indexed by recordID, each recording is also a
2047
 * non sequential associative array itself that corresponds to the actual recording in BBB
2048
 */
2049
function bigbluebuttonbn_get_allrecordings($courseid = 0, $bigbluebuttonbnid = null, $subset = true, $includedeleted = false) {
2050
    $recordings = bigbluebuttonbn_get_recordings($courseid, $bigbluebuttonbnid, $subset, $includedeleted);
2051
    $recordingsimported = bigbluebuttonbn_get_recordings_imported_array($courseid, $bigbluebuttonbnid, $subset);
2052
    return ($recordings + $recordingsimported);
2053
}
2054
2055
/**
2056
 * Helper function to retrieve recordings from the BigBlueButton. The references are stored as events
2057
 * in bigbluebuttonbn_logs.
2058
 *
2059
 * @param string $courseid
2060
 * @param string $bigbluebuttonbnid
2061
 * @param bool   $subset
2062
 * @param bool   $includedeleted
2063
 *
2064
 * @return associative array containing the recordings indexed by recordID, each recording is also a
2065
 * non sequential associative array itself that corresponds to the actual recording in BBB
2066
 */
2067
function bigbluebuttonbn_get_recordings($courseid = 0, $bigbluebuttonbnid = null, $subset = true, $includedeleted = false) {
2068
    global $DB;
2069
    $select = bigbluebuttonbn_get_recordings_sql_select($courseid, $bigbluebuttonbnid, $subset);
2070
    $bigbluebuttonbns = $DB->get_records_select_menu('bigbluebuttonbn', $select, null, 'id', 'id, meetingid');
2071
    /* Consider logs from deleted bigbluebuttonbn instances whose meetingids should be included in
2072
     * the getRecordings request. */
2073
    if ($includedeleted) {
2074
        $selectdeleted = bigbluebuttonbn_get_recordings_deleted_sql_select($courseid, $bigbluebuttonbnid, $subset);
2075
        $bigbluebuttonbnsdel = $DB->get_records_select_menu('bigbluebuttonbn_logs', $selectdeleted, null,
2076
            'bigbluebuttonbnid', 'bigbluebuttonbnid, meetingid');
2077
        if (!empty($bigbluebuttonbnsdel)) {
2078
            // Merge bigbluebuttonbnis from deleted instances, only keys are relevant.
2079
            // Artimetic merge is used in order to keep the keys.
2080
            $bigbluebuttonbns += $bigbluebuttonbnsdel;
2081
        }
2082
    }
2083
    // Gather the meetingids from bigbluebuttonbn logs that include a create with record=true.
2084
    if (empty($bigbluebuttonbns)) {
2085
        return array();
2086
    }
2087
    // Prepare select for loading records based on existent bigbluebuttonbns.
2088
    $sql = 'SELECT DISTINCT meetingid, bigbluebuttonbnid FROM {bigbluebuttonbn_logs} WHERE ';
2089
    $sql .= '(bigbluebuttonbnid='.implode(' OR bigbluebuttonbnid=', array_keys($bigbluebuttonbns)).')';
2090
    // Include only Create events and exclude those with record not true.
2091
    $sql .= ' AND log = ? AND meta LIKE ? AND meta LIKE ?';
2092
    // Execute select for loading records based on existent bigbluebuttonbns.
2093
    $records = $DB->get_records_sql_menu($sql, array(BIGBLUEBUTTONBN_LOG_EVENT_CREATE, '%record%', '%true%'));
2094
    // Get actual recordings.
2095
    return bigbluebuttonbn_get_recordings_array(array_keys($records));
2096
}
2097
2098
/**
2099
 * Helper function iterates an array with recordings and unset those already imported.
2100
 *
2101
 * @param array $recordings
2102
 * @param integer $courseid
2103
 * @param integer $bigbluebuttonbnid
2104
 *
2105
 * @return array
2106
 */
2107
function bigbluebuttonbn_unset_existent_recordings_already_imported($recordings, $courseid, $bigbluebuttonbnid) {
2108
    $recordingsimported = bigbluebuttonbn_get_recordings_imported_array($courseid, $bigbluebuttonbnid, true);
2109
    foreach ($recordings as $key => $recording) {
2110
        if (isset($recordingsimported[$recording['recordID']])) {
2111
            unset($recordings[$key]);
2112
        }
2113
    }
2114
    return $recordings;
2115
}
2116
2117
/**
2118
 * Helper function to count the imported recordings for a recordingid.
2119
 *
2120
 * @param string $recordid
2121
 *
2122
 * @return integer
2123
 */
2124
function bigbluebuttonbn_count_recording_imported_instances($recordid) {
2125
    global $DB;
2126
    $sql = 'SELECT COUNT(DISTINCT id) FROM {bigbluebuttonbn_logs} WHERE log = ? AND meta LIKE ? AND meta LIKE ?';
2127
    return $DB->count_records_sql($sql, array(BIGBLUEBUTTONBN_LOG_EVENT_IMPORT, '%recordID%', "%{$recordid}%"));
2128
}
2129
2130
/**
2131
 * Helper function returns an array with all the instances of imported recordings for a recordingid.
2132
 *
2133
 * @param string $recordid
2134
 *
2135
 * @return array
2136
 */
2137
function bigbluebuttonbn_get_recording_imported_instances($recordid) {
2138
    global $DB;
2139
    $sql = 'SELECT * FROM {bigbluebuttonbn_logs} WHERE log = ? AND meta LIKE ? AND meta LIKE ?';
2140
    $recordingsimported = $DB->get_records_sql($sql, array(BIGBLUEBUTTONBN_LOG_EVENT_IMPORT, '%recordID%',
2141
        "%{$recordid}%"));
2142
    return $recordingsimported;
2143
}
2144
2145
/**
2146
 * Helper function returns an array with the profiles (with features per profile) for the different types
2147
 * of bigbluebuttonbn instances.
2148
 *
2149
 * @return array
2150
 */
2151
function bigbluebuttonbn_get_instance_type_profiles() {
2152
    $instanceprofiles = array(
2153
            array('id' => BIGBLUEBUTTONBN_TYPE_ALL, 'name' => get_string('instance_type_default', 'bigbluebuttonbn'),
2154
                'features' => array('all')),
2155
            array('id' => BIGBLUEBUTTONBN_TYPE_ROOM_ONLY, 'name' => get_string('instance_type_room_only', 'bigbluebuttonbn'),
2156
                'features' => array('showroom', 'welcomemessage', 'voicebridge', 'waitformoderator', 'userlimit', 'recording',
2157
                    'sendnotifications', 'preuploadpresentation', 'permissions', 'schedule', 'groups',
2158
                    'modstandardelshdr', 'availabilityconditionsheader', 'tagshdr', 'competenciessection')),
2159
            array('id' => BIGBLUEBUTTONBN_TYPE_RECORDING_ONLY, 'name' => get_string('instance_type_recording_only',
2160
                'bigbluebuttonbn'), 'features' => array('showrecordings', 'importrecordings')),
2161
    );
2162
    return $instanceprofiles;
2163
}
2164
2165
/**
2166
 * Helper function returns an array with enabled features for an specific profile type.
2167
 *
2168
 * @param array $typeprofiles
2169
 * @param string $type
2170
 *
2171
 * @return array
2172
 */
2173
function bigbluebuttonbn_get_enabled_features($typeprofiles, $type = null) {
2174
    $enabledfeatures = array();
2175
    $features = $typeprofiles[0]['features'];
2176
    if (!is_null($type)) {
2177
        $features = $typeprofiles[$type]['features'];
2178
    }
2179
    $enabledfeatures['showroom'] = (in_array('all', $features) || in_array('showroom', $features));
2180
    // Evaluates if recordings are enabled for the Moodle site.
2181
    $enabledfeatures['showrecordings'] = false;
2182
    if (\mod_bigbluebuttonbn\locallib\config::recordings_enabled()) {
2183
        $enabledfeatures['showrecordings'] = (in_array('all', $features) || in_array('showrecordings', $features));
2184
    }
2185
    $enabledfeatures['importrecordings'] = false;
2186
    if (\mod_bigbluebuttonbn\locallib\config::importrecordings_enabled()) {
2187
        $enabledfeatures['importrecordings'] = (in_array('all', $features) || in_array('importrecordings', $features));
2188
    }
2189
    return $enabledfeatures;
2190
}
2191
2192
/**
2193
 * Helper function returns an array with the profiles (with features per profile) for the different types
2194
 * of bigbluebuttonbn instances.
2195
 *
2196
 * @param array $profiles
2197
 *
2198
 * @return array
2199
 */
2200
function bigbluebuttonbn_get_instance_profiles_array($profiles = null) {
2201
    if (is_null($profiles) || empty($profiles)) {
2202
        $profiles = bigbluebuttonbn_get_instance_type_profiles();
2203
    }
2204
    $profilesarray = array();
2205
    foreach ($profiles as $profile) {
2206
        $profilesarray += array("{$profile['id']}" => $profile['name']);
2207
    }
2208
    return $profilesarray;
2209
}
2210
2211
/**
2212
 * Helper function returns time in a formatted string.
2213
 *
2214
 * @param integer $time
2215
 *
2216
 * @return string
2217
 */
2218
function bigbluebuttonbn_format_activity_time($time) {
2219
    $activitytime = '';
2220
    if ($time) {
2221
        $activitytime = calendar_day_representation($time).' '.
2222
          get_string('mod_form_field_notification_msg_at', 'bigbluebuttonbn').' '.
2223
          calendar_time_representation($time);
2224
    }
2225
    return $activitytime;
2226
}
2227
2228
/**
2229
 * Helper function returns array with all the strings to be used in javascript.
2230
 *
2231
 * @return array
2232
 */
2233
function bigbluebuttonbn_get_strings_for_js() {
2234
    $locale = bigbluebuttonbn_get_locale();
2235
    $stringman = get_string_manager();
2236
    $strings = $stringman->load_component_strings('bigbluebuttonbn', $locale);
2237
    return $strings;
2238
}
2239
2240
/**
2241
 * Helper function returns the locale set by moodle.
2242
 *
2243
 * @return string
2244
 */
2245
function bigbluebuttonbn_get_locale() {
2246
    $lang = get_string('locale', 'core_langconfig');
2247
    return substr($lang, 0, strpos($lang, '.'));
2248
}
2249
2250
/**
2251
 * Helper function returns the locale code based on the locale set by moodle.
2252
 *
2253
 * @return string
2254
 */
2255
function bigbluebuttonbn_get_localcode() {
2256
    $locale = bigbluebuttonbn_get_locale();
2257
    return substr($locale, 0, strpos($locale, '_'));
2258
}
2259
2260
/**
2261
 * Helper function returns array with the instance settings used in views.
2262
 *
2263
 * @param string $id
2264
 * @param object $bigbluebuttonbnid
2265
 *
2266
 * @return array
2267
 */
2268
function bigbluebuttonbn_views_validator($id, $bigbluebuttonbnid) {
2269
    if ($id) {
2270
        return bigbluebuttonbn_views_instance_id($id);
2271
    }
2272
    if ($bigbluebuttonbnid) {
2273
        return bigbluebuttonbn_views_instance_bigbluebuttonbn($bigbluebuttonbnid);
2274
    }
2275
    return;
2276
}
2277
2278
/**
2279
 * Helper function returns array with the instance settings used in views based on id.
2280
 *
2281
 * @param string $id
2282
 *
2283
 * @return array
2284
 */
2285
function bigbluebuttonbn_views_instance_id($id) {
2286
    global $DB;
2287
    $cm = get_coursemodule_from_id('bigbluebuttonbn', $id, 0, false, MUST_EXIST);
2288
    $course = $DB->get_record('course', array('id' => $cm->course), '*', MUST_EXIST);
2289
    $bigbluebuttonbn = $DB->get_record('bigbluebuttonbn', array('id' => $cm->instance), '*', MUST_EXIST);
2290
    return array('cm' => $cm, 'course' => $course, 'bigbluebuttonbn' => $bigbluebuttonbn);
2291
}
2292
2293
/**
2294
 * Helper function returns array with the instance settings used in views based on bigbluebuttonbnid.
2295
 *
2296
 * @param object $bigbluebuttonbnid
2297
 *
2298
 * @return array
2299
 */
2300
function bigbluebuttonbn_views_instance_bigbluebuttonbn($bigbluebuttonbnid) {
2301
    global $DB;
2302
    $bigbluebuttonbn = $DB->get_record('bigbluebuttonbn', array('id' => $bigbluebuttonbnid), '*', MUST_EXIST);
2303
    $course = $DB->get_record('course', array('id' => $bigbluebuttonbn->course), '*', MUST_EXIST);
2304
    $cm = get_coursemodule_from_instance('bigbluebuttonbn', $bigbluebuttonbn->id, $course->id, false, MUST_EXIST);
2305
    return array('cm' => $cm, 'course' => $course, 'bigbluebuttonbn' => $bigbluebuttonbn);
2306
}
2307
2308
/**
2309
 * Helper function renders general warning message for settings (if any).
2310
 *
2311
 * @param object $renderer
2312
 *
2313
 * @return void
2314
 */
2315
function bigbluebutonbn_settings_general_warning(&$renderer) {
2316
    global $BIGBLUEBUTTONBN_CFG;
2317
    if (isset($BIGBLUEBUTTONBN_CFG)) {
2318
        $msg = get_string('config_warning_bigbluebuttonbn_cfg_deprecated', 'bigbluebuttonbn');
2319
        $renderer->render_warning_message($msg);
2320
    }
2321
}
2322
2323
/**
2324
 * Helper function renders general settings if the feature is enabled.
2325
 *
2326
 * @param object $renderer
2327
 *
2328
 * @return void
2329
 */
2330
function bigbluebutonbn_settings_general(&$renderer) {
2331
    // Configuration for BigBlueButton.
2332
    if ((boolean)\mod_bigbluebuttonbn\settings\renderer::section_general_shown()) {
2333
        $renderer->render_group_header('general');
2334
        $renderer->render_group_element('server_url',
2335
            $renderer->render_group_element_text('server_url', BIGBLUEBUTTONBN_DEFAULT_SERVER_URL));
2336
        $renderer->render_group_element('shared_secret',
2337
            $renderer->render_group_element_text('shared_secret', BIGBLUEBUTTONBN_DEFAULT_SHARED_SECRET));
2338
    }
2339
}
2340
2341
/**
2342
 * Helper function renders record settings if the feature is enabled.
2343
 *
2344
 * @param object $renderer
2345
 *
2346
 * @return void
2347
 */
2348
function bigbluebutonbn_settings_record(&$renderer) {
2349
    // Configuration for 'recording' feature.
2350
    if ((boolean)\mod_bigbluebuttonbn\settings\renderer::section_record_meeting_shown()) {
2351
        $renderer->render_group_header('recording');
2352
        $renderer->render_group_element('recording_default',
2353
            $renderer->render_group_element_checkbox('recording_default', 1));
2354
        $renderer->render_group_element('recording_editable',
2355
            $renderer->render_group_element_checkbox('recording_editable', 1));
2356
        $renderer->render_group_element('recording_icons_enabled',
2357
            $renderer->render_group_element_checkbox('recording_icons_enabled', 1));
2358
    }
2359
}
2360
2361
/**
2362
 * Helper function renders import recording settings if the feature is enabled.
2363
 *
2364
 * @param object $renderer
2365
 *
2366
 * @return void
2367
 */
2368
function bigbluebutonbn_settings_importrecordings(&$renderer) {
2369
    // Configuration for 'import recordings' feature.
2370
    if ((boolean)\mod_bigbluebuttonbn\settings\renderer::section_import_recordings_shown()) {
2371
        $renderer->render_group_header('importrecordings');
2372
        $renderer->render_group_element('importrecordings_enabled',
2373
            $renderer->render_group_element_checkbox('importrecordings_enabled', 0));
2374
        $renderer->render_group_element('importrecordings_from_deleted_enabled',
2375
            $renderer->render_group_element_checkbox('importrecordings_from_deleted_enabled', 0));
2376
    }
2377
}
2378
2379
/**
2380
 * Helper function renders show recording settings if the feature is enabled.
2381
 *
2382
 * @param object $renderer
2383
 *
2384
 * @return void
2385
 */
2386
function bigbluebutonbn_settings_showrecordings(&$renderer) {
2387
    // Configuration for 'show recordings' feature.
2388
    if ((boolean)\mod_bigbluebuttonbn\settings\renderer::section_show_recordings_shown()) {
2389
        $renderer->render_group_header('recordings');
2390
        $renderer->render_group_element('recordings_html_default',
2391
            $renderer->render_group_element_checkbox('recordings_html_default', 1));
2392
        $renderer->render_group_element('recordings_html_editable',
2393
            $renderer->render_group_element_checkbox('recordings_html_editable', 0));
2394
        $renderer->render_group_element('recordings_deleted_default',
2395
            $renderer->render_group_element_checkbox('recordings_deleted_default', 1));
2396
        $renderer->render_group_element('recordings_deleted_editable',
2397
            $renderer->render_group_element_checkbox('recordings_deleted_editable', 0));
2398
        $renderer->render_group_element('recordings_imported_default',
2399
            $renderer->render_group_element_checkbox('recordings_imported_default', 0));
2400
        $renderer->render_group_element('recordings_imported_editable',
2401
            $renderer->render_group_element_checkbox('recordings_imported_editable', 1));
2402
    }
2403
}
2404
2405
/**
2406
 * Helper function renders wait for moderator settings if the feature is enabled.
2407
 *
2408
 * @param object $renderer
2409
 *
2410
 * @return void
2411
 */
2412
function bigbluebutonbn_settings_waitmoderator(&$renderer) {
2413
    // Configuration for wait for moderator feature.
2414
    if ((boolean)\mod_bigbluebuttonbn\settings\renderer::section_wait_moderator_shown()) {
2415
        $renderer->render_group_header('waitformoderator');
2416
        $renderer->render_group_element('waitformoderator_default',
2417
            $renderer->render_group_element_checkbox('waitformoderator_default', 0));
2418
        $renderer->render_group_element('waitformoderator_editable',
2419
            $renderer->render_group_element_checkbox('waitformoderator_editable', 1));
2420
        $renderer->render_group_element('waitformoderator_ping_interval',
2421
            $renderer->render_group_element_text('waitformoderator_ping_interval', 10, PARAM_INT));
2422
        $renderer->render_group_element('waitformoderator_cache_ttl',
2423
            $renderer->render_group_element_text('waitformoderator_cache_ttl', 60, PARAM_INT));
2424
    }
2425
}
2426
2427
/**
2428
 * Helper function renders static voice bridge settings if the feature is enabled.
2429
 *
2430
 * @param object $renderer
2431
 *
2432
 * @return void
2433
 */
2434
function bigbluebutonbn_settings_voicebridge(&$renderer) {
2435
    // Configuration for "static voice bridge" feature.
2436
    if ((boolean)\mod_bigbluebuttonbn\settings\renderer::section_static_voice_bridge_shown()) {
2437
        $renderer->render_group_header('voicebridge');
2438
        $renderer->render_group_element('voicebridge_editable',
2439
            $renderer->render_group_element_checkbox('voicebridge_editable', 0));
2440
    }
2441
}
2442
2443
/**
2444
 * Helper function renders preuploaded presentation settings if the feature is enabled.
2445
 *
2446
 * @param object $renderer
2447
 *
2448
 * @return void
2449
 */
2450
function bigbluebutonbn_settings_preupload(&$renderer) {
2451
    // Configuration for "preupload presentation" feature.
2452
    if ((boolean)\mod_bigbluebuttonbn\settings\renderer::section_preupload_presentation_shown()) {
2453
        // This feature only works if curl is installed.
2454
        $preuploaddescripion = get_string('config_preuploadpresentation_description', 'bigbluebuttonbn');
2455
        if (!extension_loaded('curl')) {
2456
            $preuploaddescripion .= '<div class="form-defaultinfo">';
2457
            $preuploaddescripion .= get_string('config_warning_curl_not_installed', 'bigbluebuttonbn');
2458
            $preuploaddescripion .= '</div><br>';
2459
        }
2460
        $renderer->render_group_header('preuploadpresentation', null, $preuploaddescripion);
2461
        if (extension_loaded('curl')) {
2462
            $renderer->render_group_element('preuploadpresentation_enabled',
2463
                $renderer->render_group_element_checkbox('preuploadpresentation_enabled', 0));
2464
        }
2465
    }
2466
}
2467
2468
/**
2469
 * Helper function renders userlimit settings if the feature is enabled.
2470
 *
2471
 * @param object $renderer
2472
 *
2473
 * @return void
2474
 */
2475
function bigbluebutonbn_settings_userlimit(&$renderer) {
2476
    // Configuration for "user limit" feature.
2477
    if ((boolean)\mod_bigbluebuttonbn\settings\renderer::section_user_limit_shown()) {
2478
        $renderer->render_group_header('userlimit');
2479
        $renderer->render_group_element('userlimit_default',
2480
            $renderer->render_group_element_text('userlimit_default', 0, PARAM_INT));
2481
        $renderer->render_group_element('userlimit_editable',
2482
            $renderer->render_group_element_checkbox('userlimit_editable', 0));
2483
    }
2484
}
2485
2486
/**
2487
 * Helper function renders duration settings if the feature is enabled.
2488
 *
2489
 * @param object $renderer
2490
 *
2491
 * @return void
2492
 */
2493
function bigbluebutonbn_settings_duration(&$renderer) {
2494
    // Configuration for "scheduled duration" feature.
2495
    if ((boolean)\mod_bigbluebuttonbn\settings\renderer::section_scheduled_duration_shown()) {
2496
        $renderer->render_group_header('scheduled');
2497
        $renderer->render_group_element('scheduled_duration_enabled',
2498
            $renderer->render_group_element_checkbox('scheduled_duration_enabled', 1));
2499
        $renderer->render_group_element('scheduled_duration_compensation',
2500
            $renderer->render_group_element_text('scheduled_duration_compensation', 10, PARAM_INT));
2501
        $renderer->render_group_element('scheduled_pre_opening',
2502
            $renderer->render_group_element_text('scheduled_pre_opening', 10, PARAM_INT));
2503
    }
2504
}
2505
2506
/**
2507
 * Helper function renders participant settings if the feature is enabled.
2508
 *
2509
 * @param object $renderer
2510
 *
2511
 * @return void
2512
 */
2513
function bigbluebutonbn_settings_participants(&$renderer) {
2514
    // Configuration for defining the default role/user that will be moderator on new activities.
2515
    if ((boolean)\mod_bigbluebuttonbn\settings\renderer::section_moderator_default_shown()) {
2516
        $renderer->render_group_header('participant');
2517
        // UI for 'participants' feature.
2518
        $roles = bigbluebuttonbn_get_roles();
2519
        $owner = array('0' => get_string('mod_form_field_participant_list_type_owner', 'bigbluebuttonbn'));
2520
        $renderer->render_group_element('participant_moderator_default',
2521
            $renderer->render_group_element_configmultiselect('participant_moderator_default',
2522
                array_keys($owner), array_merge($owner, $roles))
2523
          );
2524
    }
2525
}
2526
2527
/**
2528
 * Helper function renders notification settings if the feature is enabled.
2529
 *
2530
 * @param object $renderer
2531
 *
2532
 * @return void
2533
 */
2534
function bigbluebutonbn_settings_notifications(&$renderer) {
2535
    // Configuration for "send notifications" feature.
2536
    if ((boolean)\mod_bigbluebuttonbn\settings\renderer::section_send_notifications_shown()) {
2537
        $renderer->render_group_header('sendnotifications');
2538
        $renderer->render_group_element('sendnotifications_enabled',
2539
            $renderer->render_group_element_checkbox('sendnotifications_enabled', 1));
2540
    }
2541
}
2542
2543
/**
2544
 * Helper function renders extended settings if any of the features there is enabled.
2545
 *
2546
 * @param object $renderer
2547
 *
2548
 * @return void
2549
 */
2550
function bigbluebutonbn_settings_extended(&$renderer) {
2551
    // Configuration for extended BN capabilities.
2552
    if (!bigbluebuttonbn_is_bn_server()) {
2553
        return;
2554
    }
2555
    // Configuration for 'notify users when recording ready' feature.
2556
    if ((boolean)\mod_bigbluebuttonbn\settings\renderer::section_settings_extended_shown()) {
2557
        $renderer->render_group_header('extended_capabilities');
2558
        // UI for 'notify users when recording ready' feature.
2559
        $renderer->render_group_element('recordingready_enabled',
2560
            $renderer->render_group_element_checkbox('recordingready_enabled', 0));
2561
        // UI for 'register meeting events' feature.
2562
        $renderer->render_group_element('meetingevents_enabled',
2563
            $renderer->render_group_element_checkbox('meetingevents_enabled', 0));
2564
    }
2565
}
2566
2567
/**
2568
 * Helper function returns an encoded meetingid.
2569
 *
2570
 * @param string $seed
2571
 *
2572
 * @return string
2573
 */
2574
function bigbluebuttonbn_encode_meetingid($seed) {
2575
    global $CFG;
2576
    return sha1($CFG->wwwroot . $seed . \mod_bigbluebuttonbn\locallib\config::get('shared_secret'));
2577
}
2578
2579
/**
2580
 * Helper function renders the link used for recording type in row for the data used by the recording table.
2581
 *
2582
 * @param array $recording
2583
 * @param array $bbbsession
2584
 * @param array $playback
2585
 *
2586
 * @return boolean
2587
 */
2588
function bigbluebuttonbn_include_recording_data_row_type($recording, $bbbsession, $playback) {
2589
    // All types that are not statistics are included.
2590
    if ($playback['type'] != 'statistics') {
2591
        return true;
2592
    }
2593
    // Exclude imported recordings.
2594
    if (isset($recording['imported'])) {
2595
        return false;
2596
    }
2597
    // Exclude non moderators.
2598
    if (!$bbbsession['administrator'] && !$bbbsession['moderator']) {
2599
        return false;
2600
    }
2601
    return true;
2602
}
2603