Completed
Push — v2.2-stable ( 886b72...4931d8 )
by Jesus
02:19
created

locallib.php ➔ bigbluebuttonbn_get_role()   B

Complexity

Conditions 5
Paths 4

Size

Total Lines 11
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 5
eloc 7
nc 4
nop 1
dl 0
loc 11
rs 8.8571
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 array $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 View Code Duplication
function bigbluebuttonbn_delete_recordings($recordids) {
0 ignored issues
show
Duplication introduced by
This function seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
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 View Code Duplication
function bigbluebuttonbn_publish_recordings($recordids, $publish = 'true') {
0 ignored issues
show
Duplication introduced by
This function seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
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 View Code Duplication
function bigbluebuttonbn_update_recordings($recordids, $params) {
0 ignored issues
show
Duplication introduced by
This function seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
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 object $context
612
 * @param integer $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) && isset($roles[$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
 *
843
 * @return boolean
844
 */
845
function bigbluebuttonbn_is_moderator($context, $participants, $userid = null) {
846
    global $USER;
847
    if (empty($participants)) {
848
        // The room that is being used comes from a previous version.
849
        return has_capability('mod/bigbluebuttonbn:moderate', $context);
850
    }
851
    $participantlist = json_decode($participants);
852
    if (!is_array($participantlist)) {
853
        return false;
854
    }
855
    if (empty($userid)) {
856
        $userid = $USER->id;
857
    }
858
    $userroles = bigbluebuttonbn_get_guest_role();
859
    if (!isguestuser()) {
860
        $userroles = bigbluebuttonbn_get_user_roles($context, $userid);
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 ($role != null && 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 $instance
935
 * @param integer $voicebridge
936
 *
937
 * @return string
938
 */
939
function bigbluebuttonbn_voicebridge_unique($instance, $voicebridge) {
940
    global $DB;
941
    if ($voicebridge == 0) {
942
        return true;
943
    }
944
    $select = 'voicebridge = ' . $voicebridge;
945
    if ($instance != 0) {
946
        $select .= ' AND id <>' . $instance;
947
    }
948
    if (!$DB->get_records_select('bigbluebuttonbn', $select)) {
949
        return true;
950
    }
951
    return false;
952
}
953
954
/**
955
 * Helper estimate a duration for the meeting based on the closingtime.
956
 *
957
 * @param integer $closingtime
958
 *
959
 * @return integer
960
 */
961
function bigbluebuttonbn_get_duration($closingtime) {
962
    $duration = 0;
963
    $now = time();
964
    if ($closingtime > 0 && $now < $closingtime) {
965
        $duration = ceil(($closingtime - $now) / 60);
966
        $compensationtime = intval((int)\mod_bigbluebuttonbn\locallib\config::get('scheduled_duration_compensation'));
967
        $duration = intval($duration) + $compensationtime;
968
    }
969
    return $duration;
970
}
971
972
/**
973
 * Helper return array containing the file descriptor for a preuploaded presentation.
974
 *
975
 * @param context $context
976
 * @param string $presentation
977
 * @param integer $id
978
 *
979
 * @return array
980
 */
981
function bigbluebuttonbn_get_presentation_array($context, $presentation, $id = null) {
982
    if (empty($presentation)) {
983
        return array('url' => null, 'name' => null, 'icon' => null, 'mimetype_description' => null);
984
    }
985
    $fs = get_file_storage();
986
    $files = $fs->get_area_files($context->id, 'mod_bigbluebuttonbn', 'presentation', 0,
987
        'itemid, filepath, filename', false);
988
    if (count($files) == 0) {
989
        return array('url' => null, 'name' => null, 'icon' => null, 'mimetype_description' => null);
990
    }
991
    $file = reset($files);
992
    unset($files);
993
    $pnoncevalue = null;
994
    if (!is_null($id)) {
995
        // Create the nonce component for granting a temporary public access.
996
        $cache = cache::make_from_params(cache_store::MODE_APPLICATION, 'mod_bigbluebuttonbn',
997
            'presentation_cache');
998
        $pnoncekey = sha1($id);
999
        /* The item id was adapted for granting public access to the presentation once in order
1000
         * to allow BigBlueButton to gather the file. */
1001
        $pnoncevalue = bigbluebuttonbn_generate_nonce();
1002
        $cache->set($pnoncekey, array('value' => $pnoncevalue, 'counter' => 0));
1003
    }
1004
    $url = moodle_url::make_pluginfile_url($file->get_contextid(), $file->get_component(),
1005
        $file->get_filearea(), $pnoncevalue, $file->get_filepath(), $file->get_filename());
1006
    return array('name' => $file->get_filename(), 'icon' => file_file_icon($file, 24),
1007
            'url' => $url->out(false), 'mimetype_description' => get_mimetype_description($file));
1008
}
1009
1010
/**
1011
 * Helper generates a nonce used for the preuploaded presentation callback url.
1012
 *
1013
 * @return string
1014
 */
1015
function bigbluebuttonbn_generate_nonce() {
1016
    $mt = microtime();
1017
    $rand = mt_rand();
1018
    return md5($mt.$rand);
1019
}
1020
1021
/**
1022
 * Helper generates a random password.
1023
 *
1024
 * @param integer $length
1025
 * @param string $unique
1026
 *
1027
 * @return string
1028
 */
1029
function bigbluebuttonbn_random_password($length = 8, $unique = "") {
1030
    $chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*()_-=+;:,.?';
1031
    do {
1032
        $password = substr(str_shuffle($chars), 0, $length);
1033
    } while ($unique == $password);
1034
    return $password;
1035
}
1036
1037
/**
1038
 * Helper returns an array with all possible bigbluebuttonbn events.
1039
 *
1040
 * @return array
1041
 */
1042
function bigbluebuttonbn_events() {
1043
    return array(
1044
        (string) BIGBLUEBUTTON_EVENT_ACTIVITY_VIEWED,
1045
        (string) BIGBLUEBUTTON_EVENT_ACTIVITY_MANAGEMENT_VIEWED,
1046
        (string) BIGBLUEBUTTON_EVENT_LIVE_SESSION,
1047
        (string) BIGBLUEBUTTON_EVENT_MEETING_CREATED,
1048
        (string) BIGBLUEBUTTON_EVENT_MEETING_ENDED,
1049
        (string) BIGBLUEBUTTON_EVENT_MEETING_JOINED,
1050
        (string) BIGBLUEBUTTON_EVENT_MEETING_LEFT,
1051
        (string) BIGBLUEBUTTON_EVENT_RECORDING_DELETED,
1052
        (string) BIGBLUEBUTTON_EVENT_RECORDING_IMPORTED,
1053
        (string) BIGBLUEBUTTON_EVENT_RECORDING_PROTECTED,
1054
        (string) BIGBLUEBUTTON_EVENT_RECORDING_PUBLISHED,
1055
        (string) BIGBLUEBUTTON_EVENT_RECORDING_UNPROTECTED,
1056
        (string) BIGBLUEBUTTON_EVENT_RECORDING_UNPUBLISHED,
1057
        (string) BIGBLUEBUTTON_EVENT_RECORDING_EDITED,
1058
        (string) BIGBLUEBUTTON_EVENT_RECORDING_VIEWED
1059
    );
1060
}
1061
1062
/**
1063
 * Helper returns an array with the actions and their corresponding bigbluebuttonbn events.
1064
 *
1065
 * @return array
1066
 */
1067
function bigbluebuttonbn_events_action() {
1068
    return array(
1069
        'view' => (string) BIGBLUEBUTTON_EVENT_ACTIVITY_VIEWED,
1070
        'view_management' => (string) BIGBLUEBUTTON_EVENT_ACTIVITY_MANAGEMENT_VIEWED,
1071
        'live_action' => (string) BIGBLUEBUTTON_EVENT_LIVE_SESSION,
1072
        'meeting_create' => (string) BIGBLUEBUTTON_EVENT_MEETING_CREATED,
1073
        'meeting_end' => (string) BIGBLUEBUTTON_EVENT_MEETING_ENDED,
1074
        'meeting_join' => (string) BIGBLUEBUTTON_EVENT_MEETING_JOINED,
1075
        'meeting_left' => (string) BIGBLUEBUTTON_EVENT_MEETING_LEFT,
1076
        'recording_delete' => (string) BIGBLUEBUTTON_EVENT_RECORDING_DELETED,
1077
        'recording_import' => (string) BIGBLUEBUTTON_EVENT_RECORDING_IMPORTED,
1078
        'recording_protect' => (string) BIGBLUEBUTTON_EVENT_RECORDING_PROTECTED,
1079
        'recording_publish' => (string) BIGBLUEBUTTON_EVENT_RECORDING_PUBLISHED,
1080
        'recording_unprotect' => (string) BIGBLUEBUTTON_EVENT_RECORDING_UNPROTECTED,
1081
        'recording_unpublish' => (string) BIGBLUEBUTTON_EVENT_RECORDING_UNPUBLISHED,
1082
        'recording_edit' => (string) BIGBLUEBUTTON_EVENT_RECORDING_EDITED,
1083
        'recording_play' => (string) BIGBLUEBUTTON_EVENT_RECORDING_VIEWED
1084
    );
1085
}
1086
1087
/**
1088
 * Helper register a bigbluebuttonbn event.
1089
 *
1090
 * @param string $eventtype
1091
 * @param object $bigbluebuttonbn
1092
 * @param object $cm
1093
 * @param array $options
1094
 *
1095
 * @return void
1096
 */
1097
function bigbluebuttonbn_event_log($eventtype, $bigbluebuttonbn, $cm, $options = []) {
1098
    $events = bigbluebuttonbn_events();
1099
    if (!in_array($eventtype, $events)) {
1100
        // No log will be created.
1101
        return;
1102
    }
1103
    $context = context_module::instance($cm->id);
1104
    $eventproperties = array('context' => $context, 'objectid' => $bigbluebuttonbn->id);
1105
    if (array_key_exists('timecreated', $options)) {
1106
        $eventproperties['timecreated'] = $options['timecreated'];
1107
    }
1108
    if (array_key_exists('userid', $options)) {
1109
        $eventproperties['userid'] = $options['userid'];
1110
    }
1111
    if (array_key_exists('other', $options)) {
1112
        $eventproperties['other'] = $options['other'];
1113
    }
1114
    $event = call_user_func_array('\mod_bigbluebuttonbn\event\bigbluebuttonbn_'.$eventtype.'::create',
1115
      array($eventproperties));
1116
    $event->trigger();
1117
}
1118
1119
/**
1120
 * Updates the meeting info cached object when a participant has joined.
1121
 *
1122
 * @param string $meetingid
1123
 * @param bool $ismoderator
1124
 *
1125
 * @return void
1126
 */
1127
function bigbluebuttonbn_participant_joined($meetingid, $ismoderator) {
1128
    $cache = cache::make_from_params(cache_store::MODE_APPLICATION, 'mod_bigbluebuttonbn', 'meetings_cache');
1129
    $result = $cache->get($meetingid);
1130
    $meetinginfo = json_decode($result['meeting_info']);
1131
    $meetinginfo->participantCount += 1;
1132
    if ($ismoderator) {
1133
        $meetinginfo->moderatorCount += 1;
1134
    }
1135
    $cache->set($meetingid, array('creation_time' => $result['creation_time'],
1136
        'meeting_info' => json_encode($meetinginfo)));
1137
}
1138
1139
/**
1140
 * Gets a meeting info object cached or fetched from the live session.
1141
 *
1142
 * @param string $meetingid
1143
 * @param boolean $updatecache
1144
 *
1145
 * @return array
1146
 */
1147
function bigbluebuttonbn_get_meeting_info($meetingid, $updatecache = false) {
1148
    $cachettl = (int)\mod_bigbluebuttonbn\locallib\config::get('waitformoderator_cache_ttl');
1149
    $cache = cache::make_from_params(cache_store::MODE_APPLICATION, 'mod_bigbluebuttonbn', 'meetings_cache');
1150
    $result = $cache->get($meetingid);
1151
    $now = time();
1152
    if (!$updatecache && isset($result) && $now < ($result['creation_time'] + $cachettl)) {
1153
        // Use the value in the cache.
1154
        return (array) json_decode($result['meeting_info']);
1155
    }
1156
    // Ping again and refresh the cache.
1157
    $meetinginfo = (array) bigbluebuttonbn_wrap_xml_load_file(
1158
        \mod_bigbluebuttonbn\locallib\bigbluebutton::action_url('getMeetingInfo', ['meetingID' => $meetingid])
1159
      );
1160
    $cache->set($meetingid, array('creation_time' => time(), 'meeting_info' => json_encode($meetinginfo)));
1161
    return $meetinginfo;
1162
}
1163
1164
/**
1165
 * Publish an imported recording.
1166
 *
1167
 * @param string $id
1168
 * @param boolean $publish
1169
 *
1170
 * @return boolean
1171
 */
1172 View Code Duplication
function bigbluebuttonbn_publish_recording_imported($id, $publish = true) {
0 ignored issues
show
Duplication introduced by
This function seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1173
    global $DB;
1174
    // Locate the record to be updated.
1175
    $record = $DB->get_record('bigbluebuttonbn_logs', array('id' => $id));
1176
    $meta = json_decode($record->meta, true);
1177
    // Prepare data for the update.
1178
    $meta['recording']['published'] = ($publish) ? 'true' : 'false';
1179
    $record->meta = json_encode($meta);
1180
    // Proceed with the update.
1181
    $DB->update_record('bigbluebuttonbn_logs', $record);
1182
    return true;
1183
}
1184
1185
/**
1186
 * Delete an imported recording.
1187
 *
1188
 * @param string $id
1189
 *
1190
 * @return boolean
1191
 */
1192
function bigbluebuttonbn_delete_recording_imported($id) {
1193
    global $DB;
1194
    // Execute delete.
1195
    $DB->delete_records('bigbluebuttonbn_logs', array('id' => $id));
1196
    return true;
1197
}
1198
1199
/**
1200
 * Update an imported recording.
1201
 *
1202
 * @param string $id
1203
 * @param array $params ['key'=>param_key, 'value']
1204
 *
1205
 * @return boolean
1206
 */
1207
function bigbluebuttonbn_update_recording_imported($id, $params) {
1208
    global $DB;
1209
    // Locate the record to be updated.
1210
    $record = $DB->get_record('bigbluebuttonbn_logs', array('id' => $id));
1211
    $meta = json_decode($record->meta, true);
1212
    // Prepare data for the update.
1213
    $meta['recording'] = $params + $meta['recording'];
1214
    $record->meta = json_encode($meta);
1215
    // Proceed with the update.
1216
    if (!$DB->update_record('bigbluebuttonbn_logs', $record)) {
1217
        return false;
1218
    }
1219
    return true;
1220
}
1221
1222
/**
1223
 * Protect/Unprotect an imported recording.
1224
 *
1225
 * @param string $id
1226
 * @param boolean $protect
1227
 *
1228
 * @return boolean
1229
 */
1230 View Code Duplication
function bigbluebuttonbn_protect_recording_imported($id, $protect = true) {
0 ignored issues
show
Duplication introduced by
This function seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1231
    global $DB;
1232
    // Locate the record to be updated.
1233
    $record = $DB->get_record('bigbluebuttonbn_logs', array('id' => $id));
1234
    $meta = json_decode($record->meta, true);
1235
    // Prepare data for the update.
1236
    $meta['recording']['protected'] = ($protect) ? 'true' : 'false';
1237
    $record->meta = json_encode($meta);
1238
    // Proceed with the update.
1239
    $DB->update_record('bigbluebuttonbn_logs', $record);
1240
    return true;
1241
}
1242
1243
/**
1244
 * Sets a custom config.xml file for being used on create.
1245
 *
1246
 * @param string $meetingid
1247
 * @param string $configxml
1248
 *
1249
 * @return object
1250
 */
1251
function bigbluebuttonbn_set_config_xml($meetingid, $configxml) {
1252
    $urldefaultconfig = \mod_bigbluebuttonbn\locallib\config::get('server_url').'api/setConfigXML?';
1253
    $configxmlparams = bigbluebuttonbn_set_config_xml_params($meetingid, $configxml);
1254
    $xml = bigbluebuttonbn_wrap_xml_load_file($urldefaultconfig, 'POST',
1255
        $configxmlparams, 'application/x-www-form-urlencoded');
1256
    return $xml;
1257
}
1258
1259
/**
1260
 * Sets qs used with a custom config.xml file request.
1261
 *
1262
 * @param string $meetingid
1263
 * @param string $configxml
1264
 *
1265
 * @return string
1266
 */
1267
function bigbluebuttonbn_set_config_xml_params($meetingid, $configxml) {
1268
    $params = 'configXML='.urlencode($configxml).'&meetingID='.urlencode($meetingid);
1269
    $configxmlparams = $params.'&checksum='.sha1('setConfigXML'.$params.\mod_bigbluebuttonbn\locallib\config::get('shared_secret'));
1270
    return $configxmlparams;
1271
}
1272
1273
/**
1274
 * Sets a custom config.xml file for being used on create.
1275
 *
1276
 * @param string $meetingid
1277
 * @param string $configxml
1278
 *
1279
 * @return array
1280
 */
1281
function bigbluebuttonbn_set_config_xml_array($meetingid, $configxml) {
1282
    $configxml = bigbluebuttonbn_setConfigXML($meetingid, $configxml);
1283
    $configxmlarray = (array) $configxml;
1284
    if ($configxmlarray['returncode'] != 'SUCCESS') {
1285
        debugging('BigBlueButton was not able to set the custom config.xml file', DEBUG_DEVELOPER);
1286
        return '';
1287
    }
1288
    return $configxmlarray['configToken'];
1289
}
1290
1291
/**
1292
 * Helper function builds a row for the data used by the recording table.
1293
 *
1294
 * @param array $bbbsession
1295
 * @param array $recording
1296
 * @param array $tools
1297
 *
1298
 * @return array
1299
 */
1300
function bigbluebuttonbn_get_recording_data_row($bbbsession, $recording, $tools = ['protect', 'publish', 'delete']) {
1301
    if (!bigbluebuttonbn_include_recording_table_row($bbbsession, $recording)) {
1302
        return;
1303
    }
1304
    $rowdata = new stdClass();
1305
    // Set recording_types.
1306
    $rowdata->recording = bigbluebuttonbn_get_recording_data_row_types($recording, $bbbsession);
1307
    // Set activity name.
1308
    $rowdata->activity = bigbluebuttonbn_get_recording_data_row_meta_activity($recording, $bbbsession);
1309
    // Set activity description.
1310
    $rowdata->description = bigbluebuttonbn_get_recording_data_row_meta_description($recording, $bbbsession);
1311
    if (bigbluebuttonbn_get_recording_data_preview_enabled($bbbsession)) {
1312
        // Set recording_preview.
1313
        $rowdata->preview = bigbluebuttonbn_get_recording_data_row_preview($recording);
1314
    }
1315
    // Set date.
1316
    $rowdata->date = bigbluebuttonbn_get_recording_data_row_date($recording);
1317
    // Set formatted date.
1318
    $rowdata->date_formatted = bigbluebuttonbn_get_recording_data_row_date_formatted($rowdata->date);
1319
    // Set formatted duration.
1320
    $rowdata->duration_formatted = $rowdata->duration = bigbluebuttonbn_get_recording_data_row_duration($recording);
1321
    // Set actionbar, if user is allowed to manage recordings.
1322
    if ($bbbsession['managerecordings']) {
1323
        $rowdata->actionbar = bigbluebuttonbn_get_recording_data_row_actionbar($recording, $tools);
1324
    }
1325
    return $rowdata;
1326
}
1327
1328
/**
1329
 * Helper function evaluates if a row for the data used by the recording table is editable.
1330
 *
1331
 * @param array $bbbsession
1332
 *
1333
 * @return boolean
1334
 */
1335
function bigbluebuttonbn_get_recording_data_row_editable($bbbsession) {
1336
    return ($bbbsession['managerecordings'] && ((double)$bbbsession['serverversion'] >= 1.0 || $bbbsession['bnserver']));
1337
}
1338
1339
/**
1340
 * Helper function evaluates if recording preview should be included.
1341
 *
1342
 * @param array $bbbsession
1343
 *
1344
 * @return boolean
1345
 */
1346
function bigbluebuttonbn_get_recording_data_preview_enabled($bbbsession) {
1347
    return ((double)$bbbsession['serverversion'] >= 1.0 && $bbbsession['bigbluebuttonbn']->recordings_preview == '1');
1348
}
1349
1350
/**
1351
 * Helper function converts recording date used in row for the data used by the recording table.
1352
 *
1353
 * @param array $recording
1354
 *
1355
 * @return integer
1356
 */
1357
function bigbluebuttonbn_get_recording_data_row_date($recording) {
1358
    if (!isset($recording['startTime'])) {
1359
        return 0;
1360
    }
1361
    return floatval($recording['startTime']);
1362
}
1363
1364
/**
1365
 * Helper function format recording date used in row for the data used by the recording table.
1366
 *
1367
 * @param integer $starttime
1368
 *
1369
 * @return string
1370
 */
1371
function bigbluebuttonbn_get_recording_data_row_date_formatted($starttime) {
1372
    global $USER;
1373
    $starttime = $starttime - ($starttime % 1000);
1374
    // Set formatted date.
1375
    $dateformat = get_string('strftimerecentfull', 'langconfig').' %Z';
1376
    return userdate($starttime / 1000, $dateformat, usertimezone($USER->timezone));
1377
}
1378
1379
/**
1380
 * Helper function converts recording duration used in row for the data used by the recording table.
1381
 *
1382
 * @param array $recording
1383
 *
1384
 * @return integer
1385
 */
1386
function bigbluebuttonbn_get_recording_data_row_duration($recording) {
1387
    $firstplayback = array_values($recording['playbacks'])[0];
1388
    $length = 0;
1389
    if (isset($firstplayback['length'])) {
1390
        $length = $firstplayback['length'];
1391
    }
1392
    return intval($length);
1393
}
1394
1395
/**
1396
 * Helper function builds recording actionbar used in row for the data used by the recording table.
1397
 *
1398
 * @param array $recording
1399
 * @param array $tools
1400
 *
1401
 * @return string
1402
 */
1403
function bigbluebuttonbn_get_recording_data_row_actionbar($recording, $tools) {
1404
    $actionbar = '';
1405
    foreach ($tools as $tool) {
1406
        $buttonpayload = bigbluebuttonbn_get_recording_data_row_actionbar_payload($recording, $tool);
1407
        if ($tool == 'protect') {
1408
            if (isset($recording['imported'])) {
1409
                $buttonpayload['disabled'] = 'disabled';
1410
            }
1411
            if (!isset($recording['protected'])) {
1412
                $buttonpayload['disabled'] = 'invisible';
1413
            }
1414
        }
1415
        $actionbar .= bigbluebuttonbn_actionbar_render_button($recording, $buttonpayload);
1416
    }
1417
    $head = html_writer::start_tag('div', array(
1418
        'id' => 'recording-actionbar-' . $recording['recordID'],
1419
        'data-recordingid' => $recording['recordID'],
1420
        'data-meetingid' => $recording['meetingID']));
1421
    $tail = html_writer::end_tag('div');
1422
    return $head . $actionbar . $tail;
1423
}
1424
1425
/**
1426
 * Helper function returns the corresponding payload for an actionbar button used in row
1427
 * for the data used by the recording table.
1428
 *
1429
 * @param array $recording
1430
 * @param array $tool
1431
 *
1432
 * @return array
1433
 */
1434
function bigbluebuttonbn_get_recording_data_row_actionbar_payload($recording, $tool) {
1435
    if ($tool == 'protect') {
1436
        $protected = 'false';
1437
        if (isset($recording['protected'])) {
1438
            $protected = $recording['protected'];
1439
        }
1440
        return bigbluebuttonbn_get_recording_data_row_action_protect($protected);
1441
    }
1442
    if ($tool == 'publish') {
1443
        return bigbluebuttonbn_get_recording_data_row_action_publish($recording['published']);
1444
    }
1445
    return array('action' => $tool, 'tag' => $tool);
1446
}
1447
1448
/**
1449
 * Helper function returns the payload for protect action button used in row
1450
 * for the data used by the recording table.
1451
 *
1452
 * @param string $protected
1453
 *
1454
 * @return array
1455
 */
1456
function bigbluebuttonbn_get_recording_data_row_action_protect($protected) {
1457
    if ($protected == 'true') {
1458
        return array('action' => 'unprotect', 'tag' => 'lock');
1459
    }
1460
    return array('action' => 'protect', 'tag' => 'unlock');
1461
}
1462
1463
/**
1464
 * Helper function returns the payload for publish action button used in row
1465
 * for the data used by the recording table.
1466
 *
1467
 * @param string $published
1468
 *
1469
 * @return array
1470
 */
1471
function bigbluebuttonbn_get_recording_data_row_action_publish($published) {
1472
    if ($published == 'true') {
1473
        return array('action' => 'unpublish', 'tag' => 'hide');
1474
    }
1475
    return array('action' => 'publish', 'tag' => 'show');
1476
}
1477
1478
/**
1479
 * Helper function builds recording preview used in row for the data used by the recording table.
1480
 *
1481
 * @param array $recording
1482
 *
1483
 * @return string
1484
 */
1485
function bigbluebuttonbn_get_recording_data_row_preview($recording) {
1486
    $options = array('id' => 'preview-'.$recording['recordID'], 'class' => 'container');
1487
    if ($recording['published'] === 'false') {
1488
        $options['hidden'] = 'hidden';
1489
    }
1490
    $recordingpreview = html_writer::start_tag('div', $options);
1491
    foreach ($recording['playbacks'] as $playback) {
1492
        if (isset($playback['preview'])) {
1493
            $recordingpreview .= html_writer::start_tag('div', array('class' => 'row'));
1494
            foreach ($playback['preview'] as $image) {
1495
                $recordingpreview .= html_writer::empty_tag('img',
1496
                    array('src' => trim($image['url']) . '?' . time(), 'class' => 'recording-thumbnail col-sm'));
1497
            }
1498
            $recordingpreview .= html_writer::end_tag('div');
1499
            $recordingpreview .= html_writer::tag('div',
1500
                get_string('view_recording_preview_help', 'bigbluebuttonbn'), array('class' => 'row text-muted small'));
1501
            break;
1502
        }
1503
    }
1504
    $recordingpreview .= html_writer::end_tag('div');
1505
    return $recordingpreview;
1506
}
1507
1508
/**
1509
 * Helper function renders recording types to be used in row for the data used by the recording table.
1510
 *
1511
 * @param array $recording
1512
 * @param array $bbbsession
1513
 *
1514
 * @return string
1515
 */
1516
function bigbluebuttonbn_get_recording_data_row_types($recording, $bbbsession) {
1517
    $dataimported = 'false';
1518
    $title = '';
1519
    if (isset($recording['imported'])) {
1520
        $dataimported = 'true';
1521
        $title = get_string('view_recording_link_warning', 'bigbluebuttonbn');
1522
    }
1523
    $visibility = '';
1524
    if ($recording['published'] === 'false') {
1525
        $visibility = 'hidden ';
1526
    }
1527
    $id = 'playbacks-'.$recording['recordID'];
1528
    $recordingtypes = html_writer::start_tag('div', array('id' => $id, 'data-imported' => $dataimported,
1529
          'data-meetingid' => $recording['meetingID'], 'data-recordingid' => $recording['recordID'],
1530
          'title' => $title, $visibility => $visibility));
1531
    foreach ($recording['playbacks'] as $playback) {
1532
        $recordingtypes .= bigbluebuttonbn_get_recording_data_row_type($recording, $bbbsession, $playback);
1533
    }
1534
    $recordingtypes .= html_writer::end_tag('div');
1535
    return $recordingtypes;
1536
}
1537
1538
/**
1539
 * Helper function renders the link used for recording type in row for the data used by the recording table.
1540
 *
1541
 * @param array $recording
1542
 * @param array $bbbsession
1543
 * @param array $playback
1544
 *
1545
 * @return string
1546
 */
1547
function bigbluebuttonbn_get_recording_data_row_type($recording, $bbbsession, $playback) {
1548
    global $CFG, $OUTPUT;
1549
    if (!bigbluebuttonbn_include_recording_data_row_type($recording, $bbbsession, $playback)) {
1550
        return '';
1551
    }
1552
    $title = get_string('view_recording_format_'.$playback['type'], 'bigbluebuttonbn');
1553
    $onclick = 'M.mod_bigbluebuttonbn.recordings.recordingPlay(this);';
1554
    $href = $CFG->wwwroot . '/mod/bigbluebuttonbn/bbb_view.php?action=play&bn=' . $bbbsession['bigbluebuttonbn']->id .
1555
      '&mid='.$recording['meetingID'] . '&rid=' . $recording['recordID'] . '&rtype=' . $playback['type'];
1556
    if (!isset($recording['imported']) || !isset($recording['protected']) || $recording['protected'] === 'false') {
1557
        $href .= '&href='.urlencode(trim($playback['url']));
1558
    }
1559
    $id = 'recording-play-' . $playback['type'] . '-' . $recording['recordID'];
1560
    $linkattributes = array(
1561
        'id' => $id,
1562
        'onclick' => $onclick,
1563
        'data-action' => 'play',
1564
        'data-target' => $playback['type'],
1565
        'data-href' => $href,
1566
        'class' => 'btn btn-sm btn-default'
1567
      );
1568
    return $OUTPUT->action_link('#', $title, null, $linkattributes) . '&#32;';
1569
}
1570
1571
/**
1572
 * Helper function renders the name for recording used in row for the data used by the recording table.
1573
 *
1574
 * @param array $recording
1575
 * @param array $bbbsession
1576
 *
1577
 * @return string
1578
 */
1579
function bigbluebuttonbn_get_recording_data_row_meta_activity($recording, $bbbsession) {
1580
    $payload = array();
1581 View Code Duplication
    if (bigbluebuttonbn_get_recording_data_row_editable($bbbsession)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1582
        $payload = array('recordingid' => $recording['recordID'], 'meetingid' => $recording['meetingID'],
1583
            'action' => 'edit', 'tag' => 'edit',
1584
            'target' => 'name');
1585
    }
1586
    $oldsource = 'meta_contextactivity';
1587
    if (isset($recording[$oldsource])) {
1588
        $metaname = trim($recording[$oldsource]);
1589
        return bigbluebuttonbn_get_recording_data_row_text($recording, $metaname, $oldsource, $payload);
1590
    }
1591
    $newsource = 'meta_bbb-recording-name';
1592 View Code Duplication
    if (isset($recording[$newsource])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1593
        $metaname = trim($recording[$newsource]);
1594
        return bigbluebuttonbn_get_recording_data_row_text($recording, $metaname, $newsource, $payload);
1595
    }
1596
    $metaname = trim($recording['meetingName']);
1597
    return bigbluebuttonbn_get_recording_data_row_text($recording, $metaname, $newsource, $payload);
1598
}
1599
1600
/**
1601
 * Helper function renders the description for recording used in row for the data used by the recording table.
1602
 *
1603
 * @param array $recording
1604
 * @param array $bbbsession
1605
 *
1606
 * @return string
1607
 */
1608
function bigbluebuttonbn_get_recording_data_row_meta_description($recording, $bbbsession) {
1609
    $payload = array();
1610 View Code Duplication
    if (bigbluebuttonbn_get_recording_data_row_editable($bbbsession)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1611
        $payload = array('recordingid' => $recording['recordID'], 'meetingid' => $recording['meetingID'],
1612
            'action' => 'edit', 'tag' => 'edit',
1613
            'target' => 'description');
1614
    }
1615
    $oldsource = 'meta_contextactivitydescription';
1616 View Code Duplication
    if (isset($recording[$oldsource])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1617
        $metadescription = trim($recording[$oldsource]);
1618
        return bigbluebuttonbn_get_recording_data_row_text($recording, $metadescription, $oldsource, $payload);
1619
    }
1620
    $newsource = 'meta_bbb-recording-description';
1621 View Code Duplication
    if (isset($recording[$newsource])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1622
        $metadescription = trim($recording[$newsource]);
1623
        return bigbluebuttonbn_get_recording_data_row_text($recording, $metadescription, $newsource, $payload);
1624
    }
1625
    return bigbluebuttonbn_get_recording_data_row_text($recording, '', $newsource, $payload);
1626
}
1627
1628
/**
1629
 * Helper function renders text element for recording used in row for the data used by the recording table.
1630
 *
1631
 * @param array $recording
1632
 * @param string $text
1633
 * @param string $source
1634
 * @param array $data
1635
 *
1636
 * @return string
1637
 */
1638
function bigbluebuttonbn_get_recording_data_row_text($recording, $text, $source, $data) {
1639
    $htmltext = '<span>' . htmlentities($text) . '</span>';
1640
    if (empty($data)) {
1641
        return $htmltext;
1642
    }
1643
    $target = $data['action'] . '-' . $data['target'];
1644
    $id = 'recording-' . $target . '-' . $data['recordingid'];
1645
    $attributes = array('id' => $id, 'class' => 'quickeditlink col-md-20',
1646
        'data-recordingid' => $data['recordingid'], 'data-meetingid' => $data['meetingid'],
1647
        'data-target' => $data['target'], 'data-source' => $source);
1648
    $head = html_writer::start_tag('div', $attributes);
1649
    $tail = html_writer::end_tag('div');
1650
    $payload = array('action' => $data['action'], 'tag' => $data['tag'], 'target' => $data['target']);
1651
    $htmllink = bigbluebuttonbn_actionbar_render_button($recording, $payload);
1652
    return $head . $htmltext . $htmllink . $tail;
1653
}
1654
1655
/**
1656
 * Helper function render a button for the recording action bar
1657
 *
1658
 * @param array $recording
1659
 * @param array $data
1660
 *
1661
 * @return string
1662
 */
1663
function bigbluebuttonbn_actionbar_render_button($recording, $data) {
1664
    global $OUTPUT;
1665
    if (empty($data)) {
1666
        return '';
1667
    }
1668
    $target = $data['action'];
1669
    if (isset($data['target'])) {
1670
        $target .= '-' . $data['target'];
1671
    }
1672
    $id = 'recording-' . $target . '-' . $recording['recordID'];
1673
    $onclick = 'M.mod_bigbluebuttonbn.recordings.recording' . ucfirst($data['action']) . '(this);';
1674
    if ((boolean)\mod_bigbluebuttonbn\locallib\config::get('recording_icons_enabled')) {
1675
        // With icon for $manageaction.
1676
        $iconattributes = array('id' => $id, 'class' => 'iconsmall');
1677
        $linkattributes = array(
1678
            'id' => $id,
1679
            'onclick' => $onclick,
1680
            'data-action' => $data['action']
1681
          );
1682
        if (!isset($recording['imported'])) {
1683
            $linkattributes['data-links'] = bigbluebuttonbn_count_recording_imported_instances(
1684
              $recording['recordID']);
1685
        }
1686
        if (isset($data['disabled'])) {
1687
            $iconattributes['class'] .= ' fa-' . $data['disabled'];
1688
            $linkattributes['class'] = 'disabled';
1689
            unset($linkattributes['onclick']);
1690
        }
1691
        $icon = new pix_icon('i/'.$data['tag'],
1692
            get_string('view_recording_list_actionbar_' . $data['action'], 'bigbluebuttonbn'),
1693
            'moodle', $iconattributes);
1694
        return $OUTPUT->action_icon('#', $icon, null, $linkattributes, false);
1695
    }
1696
    // With text for $manageaction.
1697
    $linkattributes = array('title' => get_string($data['tag']), 'class' => 'btn btn-xs btn-danger',
1698
        'onclick' => $onclick);
1699
    return $OUTPUT->action_link('#', get_string($data['action']), null, $linkattributes);
1700
}
1701
1702
/**
1703
 * Helper function builds the data used for headers by the recording table.
1704
 *
1705
 * @param array $bbbsession
1706
 *
1707
 * @return array
1708
 */
1709
function bigbluebuttonbn_get_recording_columns($bbbsession) {
1710
    $columns = array();
1711
    // Initialize table headers.
1712
    $columns[] = array('key' => 'recording', 'label' => get_string('view_recording_recording', 'bigbluebuttonbn'),
1713
        'width' => '125px', 'allowHTML' => true);
1714
    $columns[] = array('key' => 'activity', 'label' => get_string('view_recording_activity', 'bigbluebuttonbn'),
1715
        'sortable' => true, 'width' => '175px', 'allowHTML' => true);
1716
    $columns[] = array('key' => 'description', 'label' => get_string('view_recording_description', 'bigbluebuttonbn'),
1717
        'sortable' => true, 'width' => '250px', 'allowHTML' => true);
1718
    if (bigbluebuttonbn_get_recording_data_preview_enabled($bbbsession)) {
1719
        $columns[] = array('key' => 'preview', 'label' => get_string('view_recording_preview', 'bigbluebuttonbn'),
1720
            'width' => '250px', 'allowHTML' => true);
1721
    }
1722
    $columns[] = array('key' => 'date', 'label' => get_string('view_recording_date', 'bigbluebuttonbn'),
1723
        'sortable' => true, 'width' => '225px', 'allowHTML' => true);
1724
    $columns[] = array('key' => 'duration', 'label' => get_string('view_recording_duration', 'bigbluebuttonbn'),
1725
        'width' => '50px');
1726
    if ($bbbsession['managerecordings']) {
1727
        $columns[] = array('key' => 'actionbar', 'label' => get_string('view_recording_actionbar', 'bigbluebuttonbn'),
1728
            'width' => '120px', 'allowHTML' => true);
1729
    }
1730
    return $columns;
1731
}
1732
1733
/**
1734
 * Helper function builds the data used by the recording table.
1735
 *
1736
 * @param array $bbbsession
1737
 * @param array $recordings
1738
 * @param array $tools
1739
 *
1740
 * @return array
1741
 */
1742
function bigbluebuttonbn_get_recording_data($bbbsession, $recordings, $tools = ['protect', 'publish', 'delete']) {
1743
    $tabledata = array();
1744
    // Build table content.
1745
    if (isset($recordings) && !array_key_exists('messageKey', $recordings)) {
1746
        // There are recordings for this meeting.
1747
        foreach ($recordings as $recording) {
1748
            $rowdata = bigbluebuttonbn_get_recording_data_row($bbbsession, $recording, $tools);
1749
            if (!empty($rowdata)) {
1750
                array_push($tabledata, $rowdata);
1751
            }
1752
        }
1753
    }
1754
    return $tabledata;
1755
}
1756
1757
/**
1758
 * Helper function builds the recording table.
1759
 *
1760
 * @param array $bbbsession
1761
 * @param array $recordings
1762
 * @param array $tools
1763
 *
1764
 * @return object
1765
 */
1766
function bigbluebuttonbn_get_recording_table($bbbsession, $recordings, $tools = ['protect', 'publish', 'delete']) {
1767
    // Declare the table.
1768
    $table = new html_table();
1769
    $table->data = array();
1770
    // Initialize table headers.
1771
    $table->head[] = get_string('view_recording_playback', 'bigbluebuttonbn');
1772
    $table->head[] = get_string('view_recording_recording', 'bigbluebuttonbn');
1773
    $table->head[] = get_string('view_recording_description', 'bigbluebuttonbn');
1774
    if (bigbluebuttonbn_get_recording_data_preview_enabled($bbbsession)) {
1775
        $table->head[] = get_string('view_recording_preview', 'bigbluebuttonbn');
1776
    }
1777
    $table->head[] = get_string('view_recording_date', 'bigbluebuttonbn');
1778
    $table->head[] = get_string('view_recording_duration', 'bigbluebuttonbn');
1779
    $table->align = array('left', 'left', 'left', 'left', 'left', 'center');
1780
    $table->size = array('', '', '', '', '', '');
1781
    if ($bbbsession['managerecordings']) {
1782
        $table->head[] = get_string('view_recording_actionbar', 'bigbluebuttonbn');
1783
        $table->align[] = 'left';
1784
        $table->size[] = (count($tools) * 40) . 'px';
1785
    }
1786
    // Build table content.
1787
    foreach ($recordings as $recording) {
1788
        $rowdata = bigbluebuttonbn_get_recording_data_row($bbbsession, $recording, $tools);
1789
        if (!empty($rowdata)) {
1790
            $row = bigbluebuttonbn_get_recording_table_row($bbbsession, $recording, $rowdata);
1791
            array_push($table->data, $row);
1792
        }
1793
    }
1794
    return $table;
1795
}
1796
1797
/**
1798
 * Helper function builds the recording table row and insert into table.
1799
 *
1800
 * @param array $bbbsession
1801
 * @param array $recording
1802
 * @param object $rowdata
1803
 *
1804
 * @return object
1805
 */
1806
function bigbluebuttonbn_get_recording_table_row($bbbsession, $recording, $rowdata) {
1807
    $row = new html_table_row();
1808
    $row->id = 'recording-td-'.$recording['recordID'];
1809
    $row->attributes['data-imported'] = 'false';
1810
    $texthead = '';
1811
    $texttail = '';
1812
    if (isset($recording['imported'])) {
1813
        $row->attributes['title'] = get_string('view_recording_link_warning', 'bigbluebuttonbn');
1814
        $row->attributes['data-imported'] = 'true';
1815
        $texthead = '<em>';
1816
        $texttail = '</em>';
1817
    }
1818
    $rowdata->date_formatted = str_replace(' ', '&nbsp;', $rowdata->date_formatted);
1819
    $row->cells = array();
1820
    $row->cells[] = $texthead . $rowdata->recording . $texttail;
1821
    $row->cells[] = $texthead . $rowdata->activity . $texttail;
1822
    $row->cells[] = $texthead . $rowdata->description . $texttail;
1823
    if (bigbluebuttonbn_get_recording_data_preview_enabled($bbbsession)) {
1824
        $row->cells[] = $rowdata->preview;
1825
    }
1826
    $row->cells[] = $texthead . $rowdata->date_formatted . $texttail;
1827
    $row->cells[] = $rowdata->duration_formatted;
1828
    if ($bbbsession['managerecordings']) {
1829
        $row->cells[] = $rowdata->actionbar;
1830
    }
1831
    return $row;
1832
}
1833
1834
/**
1835
 * Helper function evaluates if recording row should be included in the table.
1836
 *
1837
 * @param array $bbbsession
1838
 * @param array $recording
1839
 *
1840
 * @return boolean
1841
 */
1842
function bigbluebuttonbn_include_recording_table_row($bbbsession, $recording) {
1843
    // Exclude unpublished recordings, only if user has no rights to manage them.
1844
    if ($recording['published'] != 'true' && !$bbbsession['managerecordings']) {
1845
        return false;
1846
    }
1847
    // Imported recordings are always shown as long as they are published.
1848
    if (isset($recording['imported'])) {
1849
        return true;
1850
    }
1851
    // When groups are enabled, exclude those to which the user doesn't have access to.
1852
    if (isset($bbbsession['group']) && $recording['meetingID'] != $bbbsession['meetingid']) {
1853
        return false;
1854
    }
1855
    return true;
1856
}
1857
1858
/**
1859
 * Helper function triggers a send notification when the recording is ready.
1860
 *
1861
 * @param object $bigbluebuttonbn
1862
 *
1863
 * @return void
1864
 */
1865
function bigbluebuttonbn_send_notification_recording_ready($bigbluebuttonbn) {
1866
    $sender = get_admin();
1867
    // Prepare message.
1868
    $messagetext = '<p>'.get_string('email_body_recording_ready_for', 'bigbluebuttonbn').
1869
        ' &quot;' . $bigbluebuttonbn->name . '&quot; '.
1870
        get_string('email_body_recording_ready_is_ready', 'bigbluebuttonbn').'.</p>';
1871
    $context = context_course::instance($bigbluebuttonbn->course);
1872
    \mod_bigbluebuttonbn\locallib\notifier::notification_send($context, $sender, $bigbluebuttonbn, $messagetext);
1873
}
1874
1875
/**
1876
 * Helper evaluates if the bigbluebutton server used belongs to blindsidenetworks domain.
1877
 *
1878
 * @return boolean
1879
 */
1880
function bigbluebuttonbn_is_bn_server() {
1881
    $parsedurl = parse_url(\mod_bigbluebuttonbn\locallib\config::get('server_url'));
1882
    if (!isset($parsedurl['host'])) {
1883
        return false;
1884
    }
1885
    $h = $parsedurl['host'];
1886
    $hends = explode('.', $h);
1887
    $hendslength = count($hends);
1888
    return ($hends[$hendslength - 1] == 'com' && $hends[$hendslength - 2] == 'blindsidenetworks');
1889
}
1890
1891
/**
1892
 * Helper function returns a list of courses a user has access to, wrapped in an array that can be used
1893
 * by a html select.
1894
 *
1895
 * @param array $bbbsession
1896
 *
1897
 * @return array
1898
 */
1899
function bigbluebuttonbn_import_get_courses_for_select(array $bbbsession) {
1900
    if ($bbbsession['administrator']) {
1901
        $courses = get_courses('all', 'c.fullname ASC', 'c.id,c.shortname,c.fullname');
1902
        // It includes the name of the site as a course (category 0), so remove the first one.
1903
        unset($courses['1']);
1904
    } else {
1905
        $courses = enrol_get_users_courses($bbbsession['userID'], false, 'id,shortname,fullname');
1906
    }
1907
    $coursesforselect = [];
1908
    foreach ($courses as $course) {
1909
        $coursesforselect[$course->id] = $course->fullname;
1910
    }
1911
    return $coursesforselect;
1912
}
1913
1914
/**
1915
 * Helper function renders recording table.
1916
 *
1917
 * @param array $bbbsession
1918
 * @param array $recordings
1919
 * @param array $tools
1920
 *
1921
 * @return array
1922
 */
1923
function bigbluebuttonbn_output_recording_table($bbbsession, $recordings, $tools = ['protect', 'publish', 'delete']) {
1924
    if (isset($recordings) && !empty($recordings)) {
1925
        // There are recordings for this meeting.
1926
        $table = bigbluebuttonbn_get_recording_table($bbbsession, $recordings, $tools);
1927
    }
1928
    if (!isset($table) || !isset($table->data)) {
1929
        // Render a table with "No recordings".
1930
        return html_writer::div(get_string('view_message_norecordings', 'bigbluebuttonbn'), '',
1931
            array('id' => 'bigbluebuttonbn_recordings_table'));
1932
    }
1933
    // Render the table.
1934
    return html_writer::div(html_writer::table($table), '', array('id' => 'bigbluebuttonbn_recordings_table'));
1935
}
1936
1937
/**
1938
 * Helper function to convert an html string to plain text.
1939
 *
1940
 * @param string $html
1941
 * @param integer $len
1942
 *
1943
 * @return string
1944
 */
1945
function bigbluebuttonbn_html2text($html, $len = 0) {
1946
    $text = strip_tags($html);
1947
    $text = str_replace('&nbsp;', ' ', $text);
1948
    $textlen = strlen($text);
1949
    $text = substr($text, 0, $len);
1950
    if ($textlen > $len) {
1951
        $text .= '...';
1952
    }
1953
    return $text;
1954
}
1955
1956
/**
1957
 * Helper function to obtain the tags linked to a bigbluebuttonbn activity
1958
 *
1959
 * @param string $id
1960
 *
1961
 * @return string containing the tags separated by commas
1962
 */
1963
function bigbluebuttonbn_get_tags($id) {
1964
    if (class_exists('core_tag_tag')) {
1965
        return implode(',', core_tag_tag::get_item_tags_array('core', 'course_modules', $id));
1966
    }
1967
    return implode(',', tag_get_tags('bigbluebuttonbn', $id));
1968
}
1969
1970
/**
1971
 * Helper function to define the sql used for gattering the bigbluebuttonbnids whose meetingids should be included
1972
 * in the getRecordings request
1973
 *
1974
 * @param string $courseid
1975
 * @param string $bigbluebuttonbnid
1976
 * @param bool   $subset
1977
 *
1978
 * @return string containing the sql used for getting the target bigbluebuttonbn instances
1979
 */
1980
function bigbluebuttonbn_get_recordings_sql_select($courseid, $bigbluebuttonbnid = null, $subset = true) {
1981
    if (empty($courseid)) {
1982
        $courseid = 0;
1983
    }
1984
    if (empty($bigbluebuttonbnid)) {
1985
        return "course = '{$courseid}'";
1986
    }
1987
    if ($subset) {
1988
        return "id = '{$bigbluebuttonbnid}'";
1989
    }
1990
    return "id <> '{$bigbluebuttonbnid}' AND course = '{$courseid}'";
1991
}
1992
1993
/**
1994
 * Helper function to define the sql used for gattering the bigbluebuttonbnids whose meetingids should be included
1995
 * in the getRecordings request considering only those that belong to deleted activities.
1996
 *
1997
 * @param string $courseid
1998
 * @param string $bigbluebuttonbnid
1999
 * @param bool   $subset
2000
 *
2001
 * @return string containing the sql used for getting the target bigbluebuttonbn instances
2002
 */
2003 View Code Duplication
function bigbluebuttonbn_get_recordings_deleted_sql_select($courseid = 0, $bigbluebuttonbnid = null, $subset = true) {
0 ignored issues
show
Duplication introduced by
This function seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
2004
    $sql = "log = '" . BIGBLUEBUTTONBN_LOG_EVENT_DELETE . "' AND meta like '%has_recordings%' AND meta like '%true%'";
2005
    if (empty($courseid)) {
2006
        $courseid = 0;
2007
    }
2008
    if (empty($bigbluebuttonbnid)) {
2009
        return $sql . " AND courseid = {$courseid}";
2010
    }
2011
    if ($subset) {
2012
        return $sql . " AND bigbluebuttonbnid = '{$bigbluebuttonbnid}'";
2013
    }
2014
    return $sql . " AND courseid = {$courseid} AND bigbluebuttonbnid <> '{$bigbluebuttonbnid}'";
2015
}
2016
2017
/**
2018
 * Helper function to define the sql used for gattering the bigbluebuttonbnids whose meetingids should be included
2019
 * in the getRecordings request considering only those that belong to imported recordings.
2020
 *
2021
 * @param string $courseid
2022
 * @param string $bigbluebuttonbnid
2023
 * @param bool   $subset
2024
 *
2025
 * @return string containing the sql used for getting the target bigbluebuttonbn instances
2026
 */
2027 View Code Duplication
function bigbluebuttonbn_get_recordings_imported_sql_select($courseid = 0, $bigbluebuttonbnid = null, $subset = true) {
0 ignored issues
show
Duplication introduced by
This function seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
2028
    $sql = "log = '" . BIGBLUEBUTTONBN_LOG_EVENT_IMPORT . "'";
2029
    if (empty($courseid)) {
2030
        $courseid = 0;
2031
    }
2032
    if (empty($bigbluebuttonbnid)) {
2033
        return $sql . " AND courseid = '{$courseid}'";
2034
    }
2035
    if ($subset) {
2036
        return $sql . " AND bigbluebuttonbnid = '{$bigbluebuttonbnid}'";
2037
    }
2038
    return $sql . " AND courseid = '{$courseid}' AND bigbluebuttonbnid <> '{$bigbluebuttonbnid}'";
2039
}
2040
2041
/**
2042
 * Helper function to get recordings  and imported recordings together.
2043
 *
2044
 * @param string $courseid
2045
 * @param string $bigbluebuttonbnid
2046
 * @param bool   $subset
2047
 * @param bool   $includedeleted
2048
 *
2049
 * @return associative array containing the recordings indexed by recordID, each recording is also a
2050
 * non sequential associative array itself that corresponds to the actual recording in BBB
2051
 */
2052
function bigbluebuttonbn_get_allrecordings($courseid = 0, $bigbluebuttonbnid = null, $subset = true, $includedeleted = false) {
2053
    $recordings = bigbluebuttonbn_get_recordings($courseid, $bigbluebuttonbnid, $subset, $includedeleted);
2054
    $recordingsimported = bigbluebuttonbn_get_recordings_imported_array($courseid, $bigbluebuttonbnid, $subset);
2055
    return ($recordings + $recordingsimported);
2056
}
2057
2058
/**
2059
 * Helper function to retrieve recordings from the BigBlueButton. The references are stored as events
2060
 * in bigbluebuttonbn_logs.
2061
 *
2062
 * @param string $courseid
2063
 * @param string $bigbluebuttonbnid
2064
 * @param bool   $subset
2065
 * @param bool   $includedeleted
2066
 *
2067
 * @return associative array containing the recordings indexed by recordID, each recording is also a
2068
 * non sequential associative array itself that corresponds to the actual recording in BBB
2069
 */
2070
function bigbluebuttonbn_get_recordings($courseid = 0, $bigbluebuttonbnid = null, $subset = true, $includedeleted = false) {
2071
    global $DB;
2072
    $select = bigbluebuttonbn_get_recordings_sql_select($courseid, $bigbluebuttonbnid, $subset);
2073
    $bigbluebuttonbns = $DB->get_records_select_menu('bigbluebuttonbn', $select, null, 'id', 'id, meetingid');
2074
    /* Consider logs from deleted bigbluebuttonbn instances whose meetingids should be included in
2075
     * the getRecordings request. */
2076
    if ($includedeleted) {
2077
        $selectdeleted = bigbluebuttonbn_get_recordings_deleted_sql_select($courseid, $bigbluebuttonbnid, $subset);
2078
        $bigbluebuttonbnsdel = $DB->get_records_select_menu('bigbluebuttonbn_logs', $selectdeleted, null,
2079
            'bigbluebuttonbnid', 'bigbluebuttonbnid, meetingid');
2080
        if (!empty($bigbluebuttonbnsdel)) {
2081
            // Merge bigbluebuttonbnis from deleted instances, only keys are relevant.
2082
            // Artimetic merge is used in order to keep the keys.
2083
            $bigbluebuttonbns += $bigbluebuttonbnsdel;
2084
        }
2085
    }
2086
    // Gather the meetingids from bigbluebuttonbn logs that include a create with record=true.
2087
    if (empty($bigbluebuttonbns)) {
2088
        return array();
2089
    }
2090
    // Prepare select for loading records based on existent bigbluebuttonbns.
2091
    $sql = 'SELECT DISTINCT meetingid, bigbluebuttonbnid FROM {bigbluebuttonbn_logs} WHERE ';
2092
    $sql .= '(bigbluebuttonbnid='.implode(' OR bigbluebuttonbnid=', array_keys($bigbluebuttonbns)).')';
2093
    // Include only Create events and exclude those with record not true.
2094
    $sql .= ' AND log = ? AND meta LIKE ? AND meta LIKE ?';
2095
    // Execute select for loading records based on existent bigbluebuttonbns.
2096
    $records = $DB->get_records_sql_menu($sql, array(BIGBLUEBUTTONBN_LOG_EVENT_CREATE, '%record%', '%true%'));
2097
    // Get actual recordings.
2098
    return bigbluebuttonbn_get_recordings_array(array_keys($records));
2099
}
2100
2101
/**
2102
 * Helper function iterates an array with recordings and unset those already imported.
2103
 *
2104
 * @param array $recordings
2105
 * @param integer $courseid
2106
 * @param integer $bigbluebuttonbnid
2107
 *
2108
 * @return array
2109
 */
2110
function bigbluebuttonbn_unset_existent_recordings_already_imported($recordings, $courseid, $bigbluebuttonbnid) {
2111
    $recordingsimported = bigbluebuttonbn_get_recordings_imported_array($courseid, $bigbluebuttonbnid, true);
2112
    foreach ($recordings as $key => $recording) {
2113
        if (isset($recordingsimported[$recording['recordID']])) {
2114
            unset($recordings[$key]);
2115
        }
2116
    }
2117
    return $recordings;
2118
}
2119
2120
/**
2121
 * Helper function to count the imported recordings for a recordingid.
2122
 *
2123
 * @param string $recordid
2124
 *
2125
 * @return integer
2126
 */
2127
function bigbluebuttonbn_count_recording_imported_instances($recordid) {
2128
    global $DB;
2129
    $sql = 'SELECT COUNT(DISTINCT id) FROM {bigbluebuttonbn_logs} WHERE log = ? AND meta LIKE ? AND meta LIKE ?';
2130
    return $DB->count_records_sql($sql, array(BIGBLUEBUTTONBN_LOG_EVENT_IMPORT, '%recordID%', "%{$recordid}%"));
2131
}
2132
2133
/**
2134
 * Helper function returns an array with all the instances of imported recordings for a recordingid.
2135
 *
2136
 * @param string $recordid
2137
 *
2138
 * @return array
2139
 */
2140
function bigbluebuttonbn_get_recording_imported_instances($recordid) {
2141
    global $DB;
2142
    $sql = 'SELECT * FROM {bigbluebuttonbn_logs} WHERE log = ? AND meta LIKE ? AND meta LIKE ?';
2143
    $recordingsimported = $DB->get_records_sql($sql, array(BIGBLUEBUTTONBN_LOG_EVENT_IMPORT, '%recordID%',
2144
        "%{$recordid}%"));
2145
    return $recordingsimported;
2146
}
2147
2148
/**
2149
 * Helper function returns an array with the profiles (with features per profile) for the different types
2150
 * of bigbluebuttonbn instances.
2151
 *
2152
 * @return array
2153
 */
2154
function bigbluebuttonbn_get_instance_type_profiles() {
2155
    $instanceprofiles = array(
2156
            array('id' => BIGBLUEBUTTONBN_TYPE_ALL, 'name' => get_string('instance_type_default', 'bigbluebuttonbn'),
2157
                'features' => array('all')),
2158
            array('id' => BIGBLUEBUTTONBN_TYPE_ROOM_ONLY, 'name' => get_string('instance_type_room_only', 'bigbluebuttonbn'),
2159
                'features' => array('showroom', 'welcomemessage', 'voicebridge', 'waitformoderator', 'userlimit', 'recording',
2160
                    'sendnotifications', 'preuploadpresentation', 'permissions', 'schedule', 'groups',
2161
                    'modstandardelshdr', 'availabilityconditionsheader', 'tagshdr', 'competenciessection')),
2162
            array('id' => BIGBLUEBUTTONBN_TYPE_RECORDING_ONLY, 'name' => get_string('instance_type_recording_only',
2163
                'bigbluebuttonbn'), 'features' => array('showrecordings', 'importrecordings')),
2164
    );
2165
    return $instanceprofiles;
2166
}
2167
2168
/**
2169
 * Helper function returns an array with enabled features for an specific profile type.
2170
 *
2171
 * @param array $typeprofiles
2172
 * @param string $type
2173
 *
2174
 * @return array
2175
 */
2176
function bigbluebuttonbn_get_enabled_features($typeprofiles, $type = null) {
2177
    $enabledfeatures = array();
2178
    $features = $typeprofiles[0]['features'];
2179
    if (!is_null($type)) {
2180
        $features = $typeprofiles[$type]['features'];
2181
    }
2182
    $enabledfeatures['showroom'] = (in_array('all', $features) || in_array('showroom', $features));
2183
    // Evaluates if recordings are enabled for the Moodle site.
2184
    $enabledfeatures['showrecordings'] = false;
2185
    if (\mod_bigbluebuttonbn\locallib\config::recordings_enabled()) {
2186
        $enabledfeatures['showrecordings'] = (in_array('all', $features) || in_array('showrecordings', $features));
2187
    }
2188
    $enabledfeatures['importrecordings'] = false;
2189
    if (\mod_bigbluebuttonbn\locallib\config::importrecordings_enabled()) {
2190
        $enabledfeatures['importrecordings'] = (in_array('all', $features) || in_array('importrecordings', $features));
2191
    }
2192
    return $enabledfeatures;
2193
}
2194
2195
/**
2196
 * Helper function returns an array with the profiles (with features per profile) for the different types
2197
 * of bigbluebuttonbn instances.
2198
 *
2199
 * @param array $profiles
2200
 *
2201
 * @return array
2202
 */
2203
function bigbluebuttonbn_get_instance_profiles_array($profiles = null) {
2204
    if (is_null($profiles) || empty($profiles)) {
2205
        $profiles = bigbluebuttonbn_get_instance_type_profiles();
2206
    }
2207
    $profilesarray = array();
2208
    foreach ($profiles as $profile) {
2209
        $profilesarray += array("{$profile['id']}" => $profile['name']);
2210
    }
2211
    return $profilesarray;
2212
}
2213
2214
/**
2215
 * Helper function returns time in a formatted string.
2216
 *
2217
 * @param integer $time
2218
 *
2219
 * @return string
2220
 */
2221
function bigbluebuttonbn_format_activity_time($time) {
2222
    $activitytime = '';
2223
    if ($time) {
2224
        $activitytime = calendar_day_representation($time).' '.
2225
          get_string('mod_form_field_notification_msg_at', 'bigbluebuttonbn').' '.
2226
          calendar_time_representation($time);
2227
    }
2228
    return $activitytime;
2229
}
2230
2231
/**
2232
 * Helper function returns array with all the strings to be used in javascript.
2233
 *
2234
 * @return array
2235
 */
2236
function bigbluebuttonbn_get_strings_for_js() {
2237
    $locale = bigbluebuttonbn_get_locale();
2238
    $stringman = get_string_manager();
2239
    $strings = $stringman->load_component_strings('bigbluebuttonbn', $locale);
2240
    return $strings;
2241
}
2242
2243
/**
2244
 * Helper function returns the locale set by moodle.
2245
 *
2246
 * @return string
2247
 */
2248
function bigbluebuttonbn_get_locale() {
2249
    $lang = get_string('locale', 'core_langconfig');
2250
    return substr($lang, 0, strpos($lang, '.'));
2251
}
2252
2253
/**
2254
 * Helper function returns the locale code based on the locale set by moodle.
2255
 *
2256
 * @return string
2257
 */
2258
function bigbluebuttonbn_get_localcode() {
2259
    $locale = bigbluebuttonbn_get_locale();
2260
    return substr($locale, 0, strpos($locale, '_'));
2261
}
2262
2263
/**
2264
 * Helper function returns array with the instance settings used in views.
2265
 *
2266
 * @param string $id
2267
 * @param object $bigbluebuttonbnid
2268
 *
2269
 * @return array
2270
 */
2271
function bigbluebuttonbn_views_validator($id, $bigbluebuttonbnid) {
2272
    if ($id) {
2273
        return bigbluebuttonbn_views_instance_id($id);
2274
    }
2275
    if ($bigbluebuttonbnid) {
2276
        return bigbluebuttonbn_views_instance_bigbluebuttonbn($bigbluebuttonbnid);
2277
    }
2278
    return;
2279
}
2280
2281
/**
2282
 * Helper function returns array with the instance settings used in views based on id.
2283
 *
2284
 * @param string $id
2285
 *
2286
 * @return array
2287
 */
2288 View Code Duplication
function bigbluebuttonbn_views_instance_id($id) {
0 ignored issues
show
Duplication introduced by
This function seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
2289
    global $DB;
2290
    $cm = get_coursemodule_from_id('bigbluebuttonbn', $id, 0, false, MUST_EXIST);
2291
    $course = $DB->get_record('course', array('id' => $cm->course), '*', MUST_EXIST);
2292
    $bigbluebuttonbn = $DB->get_record('bigbluebuttonbn', array('id' => $cm->instance), '*', MUST_EXIST);
2293
    return array('cm' => $cm, 'course' => $course, 'bigbluebuttonbn' => $bigbluebuttonbn);
2294
}
2295
2296
/**
2297
 * Helper function returns array with the instance settings used in views based on bigbluebuttonbnid.
2298
 *
2299
 * @param object $bigbluebuttonbnid
2300
 *
2301
 * @return array
2302
 */
2303 View Code Duplication
function bigbluebuttonbn_views_instance_bigbluebuttonbn($bigbluebuttonbnid) {
0 ignored issues
show
Duplication introduced by
This function seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
2304
    global $DB;
2305
    $bigbluebuttonbn = $DB->get_record('bigbluebuttonbn', array('id' => $bigbluebuttonbnid), '*', MUST_EXIST);
2306
    $course = $DB->get_record('course', array('id' => $bigbluebuttonbn->course), '*', MUST_EXIST);
2307
    $cm = get_coursemodule_from_instance('bigbluebuttonbn', $bigbluebuttonbn->id, $course->id, false, MUST_EXIST);
2308
    return array('cm' => $cm, 'course' => $course, 'bigbluebuttonbn' => $bigbluebuttonbn);
2309
}
2310
2311
/**
2312
 * Helper function renders general warning message for settings (if any).
2313
 *
2314
 * @param object $renderer
2315
 *
2316
 * @return void
2317
 */
2318
function bigbluebuttonbn_settings_general_warning(&$renderer) {
2319
    global $BIGBLUEBUTTONBN_CFG;
2320
    if (isset($BIGBLUEBUTTONBN_CFG)) {
2321
        $renderer->render_warning_message('general_warning',
2322
             get_string('config_warning_bigbluebuttonbn_cfg_deprecated', 'bigbluebuttonbn'));
2323
    }
2324
}
2325
2326
/**
2327
 * Helper function renders general settings if the feature is enabled.
2328
 *
2329
 * @param object $renderer
2330
 *
2331
 * @return void
2332
 */
2333
function bigbluebuttonbn_settings_general(&$renderer) {
2334
    // Configuration for BigBlueButton.
2335
    if ((boolean)\mod_bigbluebuttonbn\settings\renderer::section_general_shown()) {
2336
        $renderer->render_group_header('general');
2337
        $renderer->render_group_element('server_url',
2338
            $renderer->render_group_element_text('server_url', BIGBLUEBUTTONBN_DEFAULT_SERVER_URL));
2339
        $renderer->render_group_element('shared_secret',
2340
            $renderer->render_group_element_text('shared_secret', BIGBLUEBUTTONBN_DEFAULT_SHARED_SECRET));
2341
    }
2342
}
2343
2344
/**
2345
 * Helper function renders record settings if the feature is enabled.
2346
 *
2347
 * @param object $renderer
2348
 *
2349
 * @return void
2350
 */
2351
function bigbluebuttonbn_settings_record(&$renderer) {
2352
    // Configuration for 'recording' feature.
2353 View Code Duplication
    if ((boolean)\mod_bigbluebuttonbn\settings\renderer::section_record_meeting_shown()) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
2354
        $renderer->render_group_header('recording');
2355
        $renderer->render_group_element('recording_default',
2356
            $renderer->render_group_element_checkbox('recording_default', 1));
2357
        $renderer->render_group_element('recording_editable',
2358
            $renderer->render_group_element_checkbox('recording_editable', 1));
2359
        $renderer->render_group_element('recording_icons_enabled',
2360
            $renderer->render_group_element_checkbox('recording_icons_enabled', 1));
2361
    }
2362
}
2363
2364
/**
2365
 * Helper function renders import recording settings if the feature is enabled.
2366
 *
2367
 * @param object $renderer
2368
 *
2369
 * @return void
2370
 */
2371 View Code Duplication
function bigbluebuttonbn_settings_importrecordings(&$renderer) {
0 ignored issues
show
Duplication introduced by
This function seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
2372
    // Configuration for 'import recordings' feature.
2373
    if ((boolean)\mod_bigbluebuttonbn\settings\renderer::section_import_recordings_shown()) {
2374
        $renderer->render_group_header('importrecordings');
2375
        $renderer->render_group_element('importrecordings_enabled',
2376
            $renderer->render_group_element_checkbox('importrecordings_enabled', 0));
2377
        $renderer->render_group_element('importrecordings_from_deleted_enabled',
2378
            $renderer->render_group_element_checkbox('importrecordings_from_deleted_enabled', 0));
2379
    }
2380
}
2381
2382
/**
2383
 * Helper function renders show recording settings if the feature is enabled.
2384
 *
2385
 * @param object $renderer
2386
 *
2387
 * @return void
2388
 */
2389
function bigbluebuttonbn_settings_showrecordings(&$renderer) {
2390
    // Configuration for 'show recordings' feature.
2391
    if ((boolean)\mod_bigbluebuttonbn\settings\renderer::section_show_recordings_shown()) {
2392
        $renderer->render_group_header('recordings');
2393
        $renderer->render_group_element('recordings_html_default',
2394
            $renderer->render_group_element_checkbox('recordings_html_default', 1));
2395
        $renderer->render_group_element('recordings_html_editable',
2396
            $renderer->render_group_element_checkbox('recordings_html_editable', 0));
2397
        $renderer->render_group_element('recordings_deleted_default',
2398
            $renderer->render_group_element_checkbox('recordings_deleted_default', 1));
2399
        $renderer->render_group_element('recordings_deleted_editable',
2400
            $renderer->render_group_element_checkbox('recordings_deleted_editable', 0));
2401
        $renderer->render_group_element('recordings_imported_default',
2402
            $renderer->render_group_element_checkbox('recordings_imported_default', 0));
2403
        $renderer->render_group_element('recordings_imported_editable',
2404
            $renderer->render_group_element_checkbox('recordings_imported_editable', 1));
2405
        $renderer->render_group_element('recordings_preview_default',
2406
            $renderer->render_group_element_checkbox('recordings_preview_default', 1));
2407
        $renderer->render_group_element('recordings_preview_editable',
2408
            $renderer->render_group_element_checkbox('recordings_preview_editable', 0));
2409
    }
2410
}
2411
2412
/**
2413
 * Helper function renders wait for moderator settings if the feature is enabled.
2414
 *
2415
 * @param object $renderer
2416
 *
2417
 * @return void
2418
 */
2419
function bigbluebuttonbn_settings_waitmoderator(&$renderer) {
2420
    // Configuration for wait for moderator feature.
2421
    if ((boolean)\mod_bigbluebuttonbn\settings\renderer::section_wait_moderator_shown()) {
2422
        $renderer->render_group_header('waitformoderator');
2423
        $renderer->render_group_element('waitformoderator_default',
2424
            $renderer->render_group_element_checkbox('waitformoderator_default', 0));
2425
        $renderer->render_group_element('waitformoderator_editable',
2426
            $renderer->render_group_element_checkbox('waitformoderator_editable', 1));
2427
        $renderer->render_group_element('waitformoderator_ping_interval',
2428
            $renderer->render_group_element_text('waitformoderator_ping_interval', 10, PARAM_INT));
2429
        $renderer->render_group_element('waitformoderator_cache_ttl',
2430
            $renderer->render_group_element_text('waitformoderator_cache_ttl', 60, PARAM_INT));
2431
    }
2432
}
2433
2434
/**
2435
 * Helper function renders static voice bridge settings if the feature is enabled.
2436
 *
2437
 * @param object $renderer
2438
 *
2439
 * @return void
2440
 */
2441
function bigbluebuttonbn_settings_voicebridge(&$renderer) {
2442
    // Configuration for "static voice bridge" feature.
2443
    if ((boolean)\mod_bigbluebuttonbn\settings\renderer::section_static_voice_bridge_shown()) {
2444
        $renderer->render_group_header('voicebridge');
2445
        $renderer->render_group_element('voicebridge_editable',
2446
            $renderer->render_group_element_checkbox('voicebridge_editable', 0));
2447
    }
2448
}
2449
2450
/**
2451
 * Helper function renders preuploaded presentation settings if the feature is enabled.
2452
 *
2453
 * @param object $renderer
2454
 *
2455
 * @return void
2456
 */
2457
function bigbluebuttonbn_settings_preupload(&$renderer) {
2458
    // Configuration for "preupload presentation" feature.
2459
    if ((boolean)\mod_bigbluebuttonbn\settings\renderer::section_preupload_presentation_shown()) {
2460
        // This feature only works if curl is installed.
2461
        $preuploaddescripion = get_string('config_preuploadpresentation_description', 'bigbluebuttonbn');
2462
        if (!extension_loaded('curl')) {
2463
            $preuploaddescripion .= '<div class="form-defaultinfo">';
2464
            $preuploaddescripion .= get_string('config_warning_curl_not_installed', 'bigbluebuttonbn');
2465
            $preuploaddescripion .= '</div><br>';
2466
        }
2467
        $renderer->render_group_header('preuploadpresentation', null, $preuploaddescripion);
2468
        if (extension_loaded('curl')) {
2469
            $renderer->render_group_element('preuploadpresentation_enabled',
2470
                $renderer->render_group_element_checkbox('preuploadpresentation_enabled', 0));
2471
        }
2472
    }
2473
}
2474
2475
/**
2476
 * Helper function renders userlimit settings if the feature is enabled.
2477
 *
2478
 * @param object $renderer
2479
 *
2480
 * @return void
2481
 */
2482
function bigbluebuttonbn_settings_userlimit(&$renderer) {
2483
    // Configuration for "user limit" feature.
2484
    if ((boolean)\mod_bigbluebuttonbn\settings\renderer::section_user_limit_shown()) {
2485
        $renderer->render_group_header('userlimit');
2486
        $renderer->render_group_element('userlimit_default',
2487
            $renderer->render_group_element_text('userlimit_default', 0, PARAM_INT));
2488
        $renderer->render_group_element('userlimit_editable',
2489
            $renderer->render_group_element_checkbox('userlimit_editable', 0));
2490
    }
2491
}
2492
2493
/**
2494
 * Helper function renders duration settings if the feature is enabled.
2495
 *
2496
 * @param object $renderer
2497
 *
2498
 * @return void
2499
 */
2500
function bigbluebuttonbn_settings_duration(&$renderer) {
2501
    // Configuration for "scheduled duration" feature.
2502 View Code Duplication
    if ((boolean)\mod_bigbluebuttonbn\settings\renderer::section_scheduled_duration_shown()) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
2503
        $renderer->render_group_header('scheduled');
2504
        $renderer->render_group_element('scheduled_duration_enabled',
2505
            $renderer->render_group_element_checkbox('scheduled_duration_enabled', 1));
2506
        $renderer->render_group_element('scheduled_duration_compensation',
2507
            $renderer->render_group_element_text('scheduled_duration_compensation', 10, PARAM_INT));
2508
        $renderer->render_group_element('scheduled_pre_opening',
2509
            $renderer->render_group_element_text('scheduled_pre_opening', 10, PARAM_INT));
2510
    }
2511
}
2512
2513
/**
2514
 * Helper function renders participant settings if the feature is enabled.
2515
 *
2516
 * @param object $renderer
2517
 *
2518
 * @return void
2519
 */
2520
function bigbluebuttonbn_settings_participants(&$renderer) {
2521
    // Configuration for defining the default role/user that will be moderator on new activities.
2522
    if ((boolean)\mod_bigbluebuttonbn\settings\renderer::section_moderator_default_shown()) {
2523
        $renderer->render_group_header('participant');
2524
        // UI for 'participants' feature.
2525
        $roles = bigbluebuttonbn_get_roles();
2526
        $owner = array('0' => get_string('mod_form_field_participant_list_type_owner', 'bigbluebuttonbn'));
2527
        $renderer->render_group_element('participant_moderator_default',
2528
            $renderer->render_group_element_configmultiselect('participant_moderator_default',
2529
                array_keys($owner), array_merge($owner, $roles))
2530
          );
2531
    }
2532
}
2533
2534
/**
2535
 * Helper function renders notification settings if the feature is enabled.
2536
 *
2537
 * @param object $renderer
2538
 *
2539
 * @return void
2540
 */
2541
function bigbluebuttonbn_settings_notifications(&$renderer) {
2542
    // Configuration for "send notifications" feature.
2543
    if ((boolean)\mod_bigbluebuttonbn\settings\renderer::section_send_notifications_shown()) {
2544
        $renderer->render_group_header('sendnotifications');
2545
        $renderer->render_group_element('sendnotifications_enabled',
2546
            $renderer->render_group_element_checkbox('sendnotifications_enabled', 1));
2547
    }
2548
}
2549
2550
/**
2551
 * Helper function renders extended settings if any of the features there is enabled.
2552
 *
2553
 * @param object $renderer
2554
 *
2555
 * @return void
2556
 */
2557 View Code Duplication
function bigbluebuttonbn_settings_extended(&$renderer) {
0 ignored issues
show
Duplication introduced by
This function seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
2558
    // Configuration for extended BN capabilities.
2559
    if (!bigbluebuttonbn_is_bn_server()) {
2560
        return;
2561
    }
2562
    // Configuration for 'notify users when recording ready' feature.
2563
    if ((boolean)\mod_bigbluebuttonbn\settings\renderer::section_settings_extended_shown()) {
2564
        $renderer->render_group_header('extended_capabilities');
2565
        // UI for 'notify users when recording ready' feature.
2566
        $renderer->render_group_element('recordingready_enabled',
2567
            $renderer->render_group_element_checkbox('recordingready_enabled', 0));
2568
        // UI for 'register meeting events' feature.
2569
        $renderer->render_group_element('meetingevents_enabled',
2570
            $renderer->render_group_element_checkbox('meetingevents_enabled', 0));
2571
    }
2572
}
2573
2574
/**
2575
 * Helper function returns an encoded meetingid.
2576
 *
2577
 * @param string $seed
2578
 *
2579
 * @return string
2580
 */
2581
function bigbluebuttonbn_encode_meetingid($seed) {
2582
    global $CFG;
2583
    return sha1($CFG->wwwroot . $seed . \mod_bigbluebuttonbn\locallib\config::get('shared_secret'));
2584
}
2585
2586
/**
2587
 * Helper function renders the link used for recording type in row for the data used by the recording table.
2588
 *
2589
 * @param array $recording
2590
 * @param array $bbbsession
2591
 * @param array $playback
2592
 *
2593
 * @return boolean
2594
 */
2595
function bigbluebuttonbn_include_recording_data_row_type($recording, $bbbsession, $playback) {
2596
    // All types that are not statistics are included.
2597
    if ($playback['type'] != 'statistics') {
2598
        return true;
2599
    }
2600
    // Exclude imported recordings.
2601
    if (isset($recording['imported'])) {
2602
        return false;
2603
    }
2604
    // Exclude non moderators.
2605
    if (!$bbbsession['administrator'] && !$bbbsession['moderator']) {
2606
        return false;
2607
    }
2608
    return true;
2609
}
2610
2611
/**
2612
 * Renders the general warning message.
2613
 *
2614
 * @param string $message
2615
 * @param string $type
2616
 * @param string $href
2617
 * @param string $text
2618
 * @param string $class
2619
 *
2620
 * @return string
2621
 */
2622
function bigbluebuttonbn_render_warning($message, $type='info', $href='', $text='', $class='') {
2623
    global $OUTPUT;
2624
    $output = "\n";
2625
    // Evaluates if config_warning is enabled.
2626
    if (empty($message)) {
2627
        return $output;
2628
    }
2629
    $output .= $OUTPUT->box_start('box boxalignleft adminerror alert alert-' . $type . ' alert-block fade in',
2630
      'bigbluebuttonbn_view_general_warning') . "\n";
2631
    $output .= '    ' . $message . "\n";
2632
    $output .= '  <div class="singlebutton pull-right">' . "\n";
2633
    if (!empty($href)) {
2634
        $output .= bigbluebuttonbn_render_warning_button($href, $text, $class);
2635
    }
2636
    $output .= '  </div>' . "\n";
2637
    $output .= $OUTPUT->box_end() . "\n";
2638
    return $output;
2639
}
2640
2641
/**
2642
 * Renders the general warning button.
2643
 *
2644
 * @param string $href
2645
 * @param string $text
2646
 * @param string $class
2647
 * @param string $title
2648
 *
2649
 * @return string
2650
 */
2651
function bigbluebuttonbn_render_warning_button($href, $text = '', $class = '', $title = '') {
2652
    if ($text == '') {
2653
        $text = get_string('ok', 'moodle');
2654
    }
2655
    if ($title == '') {
2656
        $title = $text;
2657
    }
2658
    if ($class == '') {
2659
        $class = 'btn btn-secondary';
2660
    }
2661
    $output  = '  <form method="post" action="' . $href . '" class="form-inline">'."\n";
2662
    $output .= '      <button type="submit" class="' . $class . '"'."\n";
2663
    $output .= '          title="' . $title . '"'."\n";
2664
    $output .= '          >' . $text . '</button>'."\n";
2665
    $output .= '  </form>'."\n";
2666
    return $output;
2667
}
2668