Completed
Pull Request — v2.2-stable (#330)
by Jesus
02:19
created

locallib.php ➔ bigbluebuttonbn_get_roles_select()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
nc 2
nop 1
dl 0
loc 7
rs 10
c 0
b 0
f 0
1
<?php
2
// This file is part of Moodle - http://moodle.org/
3
//
4
// Moodle is free software: you can redistribute it and/or modify
5
// it under the terms of the GNU General Public License as published by
6
// the Free Software Foundation, either version 3 of the License, or
7
// (at your option) any later version.
8
//
9
// Moodle is distributed in the hope that it will be useful,
10
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
// GNU General Public License for more details.
13
//
14
// You should have received a copy of the GNU General Public License
15
// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
16
17
/**
18
 * Internal library of functions for module BigBlueButtonBN.
19
 *
20
 * @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
/** @var BIGBLUEBUTTON_EVENT_MEETING_START string defines the bigbluebuttonbn meeting_start event */
76
const BIGBLUEBUTTON_EVENT_MEETING_START = 'meeting_start';
77
/** @var BIGBLUEBUTTON_CLIENTTYPE_FLASH integer that defines the bigbluebuttonbn default web client based on Adobe FLASH */
78
const BIGBLUEBUTTON_CLIENTTYPE_FLASH = 0;
79
/** @var BIGBLUEBUTTON_CLIENTTYPE_HTML5 integer that defines the bigbluebuttonbn default web client based on Adobe HTML5 */
80
const BIGBLUEBUTTON_CLIENTTYPE_HTML5 = 1;
81
82
/**
83
 * Builds and retunrs a url for joining a bigbluebutton meeting.
84
 *
85
 * @param string $meetingid
86
 * @param string $username
87
 * @param string $pw
88
 * @param string $logouturl
89
 * @param string $configtoken
90
 * @param string $userid
91
 * @param string $clienttype
92
 *
93
 * @return string
94
 */
95
function bigbluebuttonbn_get_join_url($meetingid, $username, $pw, $logouturl, $configtoken = null,
96
            $userid = null, $clienttype = BIGBLUEBUTTON_CLIENTTYPE_FLASH, $createtime = null) {
97
    $data = ['meetingID' => $meetingid,
98
              'fullName' => $username,
99
              'password' => $pw,
100
              'logoutURL' => $logouturl,
101
            ];
102
    // Choose between Adobe Flash or HTML5 Client.
103
    if ( $clienttype == BIGBLUEBUTTON_CLIENTTYPE_HTML5 ) {
104
        $data['joinViaHtml5'] = 'true';
105
    }
106
107
    if (!is_null($configtoken)) {
108
        $data['configToken'] = $configtoken;
109
    }
110
    if (!is_null($userid)) {
111
        $data['userID'] = $userid;
112
    }
113
    if (!is_null($createtime)) {
114
        $data['createTime'] = $createtime;
115
    }
116
    return \mod_bigbluebuttonbn\locallib\bigbluebutton::action_url('join', $data);
117
}
118
119
/**
120
 * Creates a bigbluebutton meeting and returns the response in an array.
121
 *
122
 * @param array  $data
123
 * @param array  $metadata
124
 * @param string $pname
125
 * @param string $purl
126
 *
127
 * @return array
128
 */
129
function bigbluebuttonbn_get_create_meeting_array($data, $metadata = array(), $pname = null, $purl = null) {
130
    $createmeetingurl = \mod_bigbluebuttonbn\locallib\bigbluebutton::action_url('create', $data, $metadata);
131
    $method = 'GET';
132
    $data = null;
133
    if (!is_null($pname) && !is_null($purl)) {
134
        $method = 'POST';
135
        $data = "<?xml version='1.0' encoding='UTF-8'?><modules><module name='presentation'><document url='".
136
            $purl."' /></module></modules>";
137
    }
138
    $xml = bigbluebuttonbn_wrap_xml_load_file($createmeetingurl, $method, $data);
139
    if ($xml) {
140
        $response = array('returncode' => $xml->returncode, 'message' => $xml->message, 'messageKey' => $xml->messageKey);
141
        if ($xml->meetingID) {
142
            $response += array('meetingID' => $xml->meetingID, 'attendeePW' => $xml->attendeePW,
143
                'moderatorPW' => $xml->moderatorPW, 'hasBeenForciblyEnded' => $xml->hasBeenForciblyEnded);
144
        }
145
        return $response;
146
    }
147
    return array('returncode' => 'FAILED', 'message' => 'unreachable', 'messageKey' => 'Server is unreachable');
148
}
149
150
/**
151
 * Fetch meeting info and wrap response in array.
152
 *
153
 * @param string $meetingid
154
 *
155
 * @return array
156
 */
157
function bigbluebuttonbn_get_meeting_info_array($meetingid) {
158
    $xml = bigbluebuttonbn_wrap_xml_load_file(
159
        \mod_bigbluebuttonbn\locallib\bigbluebutton::action_url('getMeetingInfo', ['meetingID' => $meetingid])
160
      );
161
    if ($xml && $xml->returncode == 'SUCCESS' && empty($xml->messageKey)) {
162
        // Meeting info was returned.
163
        return array('returncode' => $xml->returncode,
164
                     'meetingID' => $xml->meetingID,
165
                     'moderatorPW' => $xml->moderatorPW,
166
                     'attendeePW' => $xml->attendeePW,
167
                     'hasBeenForciblyEnded' => $xml->hasBeenForciblyEnded,
168
                     'running' => $xml->running,
169
                     'recording' => $xml->recording,
170
                     'startTime' => $xml->startTime,
171
                     'endTime' => $xml->endTime,
172
                     'participantCount' => $xml->participantCount,
173
                     'moderatorCount' => $xml->moderatorCount,
174
                     'attendees' => $xml->attendees,
175
                     'metadata' => $xml->metadata,
176
                   );
177
    }
178
    if ($xml) {
179
        // Either failure or success without meeting info.
180
        return (array)$xml;
181
    }
182
    // If the server is unreachable, then prompts the user of the necessary action.
183
    return array('returncode' => 'FAILED', 'message' => 'unreachable', 'messageKey' => 'Server is unreachable');
184
}
185
186
/**
187
 * Helper function to retrieve recordings from a BigBlueButton server.
188
 *
189
 * @param string|array $meetingids   list of meetingIDs "mid1,mid2,mid3" or array("mid1","mid2","mid3")
190
 * @param string|array $recordingids list of $recordingids "rid1,rid2,rid3" or array("rid1","rid2","rid3") for filtering
191
 *
192
 * @return associative array with recordings indexed by recordID, each recording is a non sequential associative array
193
 */
194
function bigbluebuttonbn_get_recordings_array($meetingids, $recordingids = []) {
195
    $meetingidsarray = $meetingids;
196
    if (!is_array($meetingids)) {
197
        $meetingidsarray = explode(',', $meetingids);
198
    }
199
    // If $meetingidsarray is empty there is no need to go further.
200
    if (empty($meetingidsarray)) {
201
        return array();
202
    }
203
    $recordings = bigbluebuttonbn_get_recordings_array_fetch($meetingidsarray);
0 ignored issues
show
Bug introduced by
It seems like $meetingidsarray defined by $meetingids on line 195 can also be of type string; however, bigbluebuttonbn_get_recordings_array_fetch() does only seem to accept array, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
204
    // Sort recordings.
205
    uasort($recordings, 'bigbluebuttonbn_recording_build_sorter');
206
    // Filter recordings based on recordingIDs.
207
    $recordingidsarray = $recordingids;
208
    if (!is_array($recordingids)) {
209
        $recordingidsarray = explode(',', $recordingids);
210
    }
211
    if (empty($recordingidsarray)) {
212
        // No recording ids, no need to filter.
213
        return $recordings;
214
    }
215
    return bigbluebuttonbn_get_recordings_array_filter($recordingidsarray, $recordings);
0 ignored issues
show
Bug introduced by
It seems like $recordingidsarray defined by $recordingids on line 207 can also be of type string; however, bigbluebuttonbn_get_recordings_array_filter() does only seem to accept array, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
216
}
217
218
/**
219
 * Helper function to fetch recordings from a BigBlueButton server.
220
 *
221
 * @param array $meetingidsarray   array with meeting ids in the form array("mid1","mid2","mid3")
222
 *
223
 * @return associative array with recordings indexed by recordID, each recording is a non sequential associative array
224
 */
225
function bigbluebuttonbn_get_recordings_array_fetch($meetingidsarray) {
226
    $recordings = array();
227
    // Execute a paginated getRecordings request.
228
    $pages = floor(count($meetingidsarray) / 25) + 1;
229
    for ($page = 1; $page <= $pages; ++$page) {
230
        $mids = array_slice($meetingidsarray, ($page - 1) * 25, 25);
231
        $recordings += bigbluebuttonbn_get_recordings_array_fetch_page($mids);
232
    }
233
    return $recordings;
234
}
235
236
/**
237
 * Helper function to fetch one page of upto 25 recordings from a BigBlueButton server.
238
 *
239
 * @param array  $mids
240
 *
241
 * @return array
242
 */
243
function bigbluebuttonbn_get_recordings_array_fetch_page($mids) {
244
    $recordings = array();
245
    // Do getRecordings is executed using a method GET (supported by all versions of BBB).
246
    $url = \mod_bigbluebuttonbn\locallib\bigbluebutton::action_url('getRecordings', ['meetingID' => implode(',', $mids)]);
247
    $xml = bigbluebuttonbn_wrap_xml_load_file($url);
248
    if ($xml && $xml->returncode == 'SUCCESS' && isset($xml->recordings)) {
249
        // If there were meetings already created.
250
        foreach ($xml->recordings->recording as $recordingxml) {
251
            $recording = bigbluebuttonbn_get_recording_array_value($recordingxml);
252
            $recordings[$recording['recordID']] = $recording;
253
        }
254
    }
255
    return $recordings;
256
}
257
258
/**
259
 * Helper function to remove a set of recordings from an array.
260
 *
261
 * @param array  $rids
262
 * @param array  $recordings
263
 *
264
 * @return array
265
 */
266
function bigbluebuttonbn_get_recordings_array_filter($rids, &$recordings) {
267
    foreach ($recordings as $key => $recording) {
268
        if (!in_array($recording['recordID'], $rids)) {
269
            unset($recordings[$key]);
270
        }
271
    }
272
    return $recordings;
273
}
274
275
/**
276
 * Helper function to retrieve imported recordings from the Moodle database.
277
 * The references are stored as events in bigbluebuttonbn_logs.
278
 *
279
 * @param string $courseid
280
 * @param string $bigbluebuttonbnid
281
 * @param bool   $subset
282
 *
283
 * @return associative array with imported recordings indexed by recordID, each recording
284
 * is a non sequential associative array that corresponds to the actual recording in BBB
285
 */
286
function bigbluebuttonbn_get_recordings_imported_array($courseid = 0, $bigbluebuttonbnid = null, $subset = true) {
287
    global $DB;
288
    $select = bigbluebuttonbn_get_recordings_imported_sql_select($courseid, $bigbluebuttonbnid, $subset);
289
    $recordsimported = $DB->get_records_select('bigbluebuttonbn_logs', $select);
290
    $recordsimportedarray = array();
291
    foreach ($recordsimported as $recordimported) {
292
        $meta = json_decode($recordimported->meta, true);
293
        $recording = $meta['recording'];
294
        // Override imported flag with actual ID.
295
        $recording['imported'] = $recordimported->id;
296
        if (isset($recordimported->protected)) {
297
            $recording['protected'] = (string) $recordimported->protected;
298
        }
299
        $recordsimportedarray[$recording['recordID']] = $recording;
300
    }
301
    return $recordsimportedarray;
302
}
303
304
/**
305
 * Helper function to retrive the default config.xml file.
306
 *
307
 * @return string
308
 */
309
function bigbluebuttonbn_get_default_config_xml() {
310
    $xml = bigbluebuttonbn_wrap_xml_load_file(
311
        \mod_bigbluebuttonbn\locallib\bigbluebutton::action_url('getDefaultConfigXML')
312
      );
313
    return $xml;
314
}
315
316
/**
317
 * Helper function to convert an xml recording object to an array in the format used by the plugin.
318
 *
319
 * @param object $recording
320
 *
321
 * @return array
322
 */
323
function bigbluebuttonbn_get_recording_array_value($recording) {
324
    // Add formats.
325
    $playbackarray = array();
326
    foreach ($recording->playback->format as $format) {
327
        $playbackarray[(string) $format->type] = array('type' => (string) $format->type,
328
            'url' => trim((string) $format->url), 'length' => (string) $format->length);
329
        // Add preview per format when existing.
330
        if ($format->preview) {
331
            $playbackarray[(string) $format->type]['preview'] = bigbluebuttonbn_get_recording_preview_images($format->preview);
332
        }
333
    }
334
    // Add the metadata to the recordings array.
335
    $metadataarray = bigbluebuttonbn_get_recording_array_meta(get_object_vars($recording->metadata));
336
    $recordingarray = array('recordID' => (string) $recording->recordID,
337
        'meetingID' => (string) $recording->meetingID, 'meetingName' => (string) $recording->name,
338
        'published' => (string) $recording->published, 'startTime' => (string) $recording->startTime,
339
        'endTime' => (string) $recording->endTime, 'playbacks' => $playbackarray);
340
    if (isset($recording->protected)) {
341
        $recordingarray['protected'] = (string) $recording->protected;
342
    }
343
    return $recordingarray + $metadataarray;
344
}
345
346
/**
347
 * Helper function to convert an xml recording preview images to an array in the format used by the plugin.
348
 *
349
 * @param object $preview
350
 *
351
 * @return array
352
 */
353
function bigbluebuttonbn_get_recording_preview_images($preview) {
354
    $imagesarray = array();
355
    foreach ($preview->images->image as $image) {
356
        $imagearray = array('url' => trim((string) $image));
357
        foreach ($image->attributes() as $attkey => $attvalue) {
358
            $imagearray[$attkey] = (string) $attvalue;
359
        }
360
        array_push($imagesarray, $imagearray);
361
    }
362
    return $imagesarray;
363
}
364
365
/**
366
 * Helper function to convert an xml recording metadata object to an array in the format used by the plugin.
367
 *
368
 * @param array $metadata
369
 *
370
 * @return array
371
 */
372
function bigbluebuttonbn_get_recording_array_meta($metadata) {
373
    $metadataarray = array();
374
    foreach ($metadata as $key => $value) {
375
        if (is_object($value)) {
376
            $value = '';
377
        }
378
        $metadataarray['meta_'.$key] = $value;
379
    }
380
    return $metadataarray;
381
}
382
383
/**
384
 * Helper function to sort an array of recordings. It compares the startTime in two recording objecs.
385
 *
386
 * @param object $a
387
 * @param object $b
388
 *
389
 * @return array
390
 */
391
function bigbluebuttonbn_recording_build_sorter($a, $b) {
392
    if ($a['startTime'] < $b['startTime']) {
393
        return -1;
394
    }
395
    if ($a['startTime'] == $b['startTime']) {
396
        return 0;
397
    }
398
    return 1;
399
}
400
401
/**
402
 * Perform deleteRecordings on BBB.
403
 *
404
 * @param string $recordids
405
 *
406
 * @return boolean
407
 */
408 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...
409
    $ids = explode(',', $recordids);
410
    foreach ($ids as $id) {
411
        $xml = bigbluebuttonbn_wrap_xml_load_file(
412
            \mod_bigbluebuttonbn\locallib\bigbluebutton::action_url('deleteRecordings', ['recordID' => $id])
413
          );
414
        if ($xml && $xml->returncode != 'SUCCESS') {
415
            return false;
416
        }
417
    }
418
    return true;
419
}
420
421
/**
422
 * Perform publishRecordings on BBB.
423
 *
424
 * @param string $recordids
425
 * @param string $publish
426
 */
427 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...
428
    $ids = explode(',', $recordids);
429
    foreach ($ids as $id) {
430
        $xml = bigbluebuttonbn_wrap_xml_load_file(
431
            \mod_bigbluebuttonbn\locallib\bigbluebutton::action_url('publishRecordings', ['recordID' => $id, 'publish' => $publish])
432
          );
433
        if ($xml && $xml->returncode != 'SUCCESS') {
434
            return false;
435
        }
436
    }
437
    return true;
438
}
439
440
/**
441
 * Perform updateRecordings on BBB.
442
 *
443
 * @param string $recordids
444
 * @param array $params ['key'=>param_key, 'value']
445
 */
446 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...
447
    $ids = explode(',', $recordids);
448
    foreach ($ids as $id) {
449
        $xml = bigbluebuttonbn_wrap_xml_load_file(
450
            \mod_bigbluebuttonbn\locallib\bigbluebutton::action_url('updateRecordings', ['recordID' => $id] + (array) $params)
451
          );
452
        if ($xml && $xml->returncode != 'SUCCESS') {
453
            return false;
454
        }
455
    }
456
    return true;
457
}
458
459
/**
460
 * Perform end on BBB.
461
 *
462
 * @param string $meetingid
463
 * @param string $modpw
464
 */
465
function bigbluebuttonbn_end_meeting($meetingid, $modpw) {
466
    $xml = bigbluebuttonbn_wrap_xml_load_file(
467
        \mod_bigbluebuttonbn\locallib\bigbluebutton::action_url('end', ['meetingID' => $meetingid, 'password' => $modpw])
468
      );
469
    if ($xml) {
470
        // If the xml packet returned failure it displays the message to the user.
471
        return array('returncode' => $xml->returncode, 'message' => $xml->message, 'messageKey' => $xml->messageKey);
472
    }
473
    // If the server is unreachable, then prompts the user of the necessary action.
474
    return null;
475
}
476
477
/**
478
 * Perform api request on BBB.
479
 *
480
 * @return string
481
 */
482
function bigbluebuttonbn_get_server_version() {
483
    $xml = bigbluebuttonbn_wrap_xml_load_file(
484
        \mod_bigbluebuttonbn\locallib\bigbluebutton::action_url()
485
      );
486
    if ($xml && $xml->returncode == 'SUCCESS') {
487
        return $xml->version;
488
    }
489
    return null;
490
}
491
492
/**
493
 * Perform api request on BBB and wraps the response in an XML object
494
 *
495
 * @param string $url
496
 * @param string $method
497
 * @param string $data
498
 * @param string $contenttype
499
 *
500
 * @return object
501
 */
502
function bigbluebuttonbn_wrap_xml_load_file($url, $method = 'GET', $data = null, $contenttype = 'text/xml') {
503
    if (extension_loaded('curl')) {
504
        $response = bigbluebuttonbn_wrap_xml_load_file_curl_request($url, $method, $data, $contenttype);
505
        if (!$response) {
506
            debugging('No response on wrap_simplexml_load_file', DEBUG_DEVELOPER);
507
            return null;
508
        }
509
        $previous = libxml_use_internal_errors(true);
510
        try {
511
            $xml = simplexml_load_string($response, 'SimpleXMLElement', LIBXML_NOCDATA | LIBXML_NOBLANKS);
512
            return $xml;
513
        } catch (Exception $e) {
514
            libxml_use_internal_errors($previous);
515
            $error = 'Caught exception: '.$e->getMessage();
516
            debugging($error, DEBUG_DEVELOPER);
517
            return null;
518
        }
519
    }
520
    // Alternative request non CURL based.
521
    $previous = libxml_use_internal_errors(true);
522
    try {
523
        $response = simplexml_load_file($url, 'SimpleXMLElement', LIBXML_NOCDATA | LIBXML_NOBLANKS);
524
        return $response;
525
    } catch (Exception $e) {
526
        $error = 'Caught exception: '.$e->getMessage();
527
        debugging($error, DEBUG_DEVELOPER);
528
        libxml_use_internal_errors($previous);
529
        return null;
530
    }
531
}
532
533
/**
534
 * Perform api request on BBB using CURL and wraps the response in an XML object
535
 *
536
 * @param string $url
537
 * @param string $method
538
 * @param string $data
539
 * @param string $contenttype
540
 *
541
 * @return object
542
 */
543
function bigbluebuttonbn_wrap_xml_load_file_curl_request($url, $method = 'GET', $data = null, $contenttype = 'text/xml') {
544
    $c = new curl();
545
    $c->setopt(array('SSL_VERIFYPEER' => true));
546
    if ($method == 'POST') {
547
        if (is_null($data) || is_array($data)) {
548
            return $c->post($url);
549
        }
550
        $options = array();
551
        $options['CURLOPT_HTTPHEADER'] = array(
552
                 'Content-Type: '.$contenttype,
553
                 'Content-Length: '.strlen($data),
554
                 'Content-Language: en-US',
555
               );
556
557
        return $c->post($url, $data, $options);
558
    }
559
    if ($method == 'HEAD') {
560
        $c->head($url, array('followlocation' => true, 'timeout' => 1));
561
        return $c->get_info();
562
    }
563
    return $c->get($url);
564
}
565
566
/**
567
 * End the session associated with this instance (if it's running).
568
 *
569
 * @param object $bigbluebuttonbn
570
 *
571
 * @return void
572
 */
573
function bigbluebuttonbn_end_meeting_if_running($bigbluebuttonbn) {
574
    $meetingid = $bigbluebuttonbn->meetingid.'-'.$bigbluebuttonbn->course.'-'.$bigbluebuttonbn->id;
575
    if (bigbluebuttonbn_is_meeting_running($meetingid)) {
576
        bigbluebuttonbn_end_meeting($meetingid, $bigbluebuttonbn->moderatorpass);
577
    }
578
}
579
580
/**
581
 * Returns user roles in a context.
582
 *
583
 * @param object $context
584
 * @param integer $userid
585
 *
586
 * @return array $userroles
587
 */
588
function bigbluebuttonbn_get_user_roles($context, $userid) {
589
    global $DB;
590
    $userroles = get_user_roles($context, $userid);
591
    if ($userroles) {
592
        $where = '';
593
        foreach ($userroles as $userrole) {
594
            $where .= (empty($where) ? ' WHERE' : ' OR').' id=' . $userrole->roleid;
595
        }
596
        $userroles = $DB->get_records_sql('SELECT * FROM {role}'.$where);
597
    }
598
    return $userroles;
599
}
600
601
/**
602
 * Returns guest role wrapped in an array.
603
 *
604
 * @return array
605
 */
606
function bigbluebuttonbn_get_guest_role() {
607
    $guestrole = get_guest_role();
608
    return array($guestrole->id => $guestrole);
609
}
610
611
/**
612
 * Returns an array containing all the users in a context.
613
 *
614
 * @param context $context
615
 *
616
 * @return array $users
617
 */
618
function bigbluebuttonbn_get_users(context $context = null) {
619
    $users = (array) get_enrolled_users($context, '', 0, 'u.*', null, 0, 0, true);
620
    foreach ($users as $key => $value) {
621
        $users[$key] = fullname($value);
622
    }
623
    return $users;
624
}
625
626
/**
627
 * Returns an array containing all the users in a context wrapped for html select element.
628
 *
629
 * @param context $context
630
 *
631
 * @return array $users
632
 */
633
function bigbluebuttonbn_get_users_select(context $context = null) {
634
    $users = (array) get_enrolled_users($context, '', 0, 'u.*', null, 0, 0, true);
635
    foreach ($users as $key => $value) {
636
        $users[$key] = array('id' => $value->id, 'name' => fullname($value));
637
    }
638
    return $users;
639
}
640
641
/**
642
 * Returns an array containing all the roles in a context.
643
 *
644
 * @param context $context
645
 *
646
 * @return array $roles
647
 */
648
function bigbluebuttonbn_get_roles(context $context = null) {
649
    $roles = (array) role_get_names($context);
650
    foreach ($roles as $key => $value) {
651
        $roles[$key] = $value->localname;
652
    }
653
    return $roles;
654
}
655
656
/**
657
 * Returns an array containing all the roles in a context wrapped for html select element.
658
 *
659
 * @param context $context
660
 *
661
 * @return array $users
662
 */
663
function bigbluebuttonbn_get_roles_select(context $context = null) {
664
    $roles = (array) role_get_names($context);
665
    foreach ($roles as $key => $value) {
666
        $roles[$key] = array('id' => $value->id, 'name' => $value->localname);
667
    }
668
    return $roles;
669
}
670
671
/**
672
 * Returns role that corresponds to an id.
673
 *
674
 * @param string|integer $id
675
 *
676
 * @return object $role
677
 */
678
function bigbluebuttonbn_get_role($id) {
679
    $roles = (array) role_get_names();
680
    if (is_numeric($id) && isset($roles[$id])) {
681
        return (object)$roles[$id];
682
    }
683
    foreach ($roles as $role) {
684
        if ($role->shortname == $id) {
685
            return $role;
686
        }
687
    }
688
}
689
690
/**
691
 * Returns an array to populate a list of participants used in mod_form.js.
692
 *
693
 * @param context $context
694
 *
695
 * @return array $data
696
 */
697
function bigbluebuttonbn_get_participant_data($context) {
698
    $data = array(
699
        'all' => array(
700
            'name' => get_string('mod_form_field_participant_list_type_all', 'bigbluebuttonbn'),
701
            'children' => []
702
          )
703
      );
704
    $data['role'] = array(
705
        'name' => get_string('mod_form_field_participant_list_type_role', 'bigbluebuttonbn'),
706
        'children' => bigbluebuttonbn_get_roles_select($context)
707
      );
708
    $data['user'] = array(
709
        'name' => get_string('mod_form_field_participant_list_type_user', 'bigbluebuttonbn'),
710
        'children' => bigbluebuttonbn_get_users_select($context)
711
      );
712
    return $data;
713
}
714
715
/**
716
 * Returns an array to populate a list of participants used in mod_form.php.
717
 *
718
 * @param object $bigbluebuttonbn
719
 * @param context $context
720
 *
721
 * @return array
722
 */
723
function bigbluebuttonbn_get_participant_list($bigbluebuttonbn, $context) {
724
    global $USER;
725
    if ($bigbluebuttonbn == null) {
726
        return bigbluebuttonbn_get_participant_rules_encoded(
727
            bigbluebuttonbn_get_participant_list_default($context, $USER->id)
728
        );
729
    }
730
    if (empty($bigbluebuttonbn->participants)) {
731
        $bigbluebuttonbn->participants = "[]";
732
    }
733
    $rules = json_decode($bigbluebuttonbn->participants, true);
734
    if (empty($rules)) {
735
        $rules = bigbluebuttonbn_get_participant_list_default($context, bigbluebuttonbn_instance_ownerid($bigbluebuttonbn));
736
    }
737
    return bigbluebuttonbn_get_participant_rules_encoded($rules);
738
}
739
740
/**
741
 * Returns an array to populate a list of participants used in mod_form.php with default values.
742
 *
743
 * @param context $context
744
 * @param integer $ownerid
745
 *
746
 * @return array
747
 */
748
function bigbluebuttonbn_get_participant_list_default($context, $ownerid = null) {
749
    $participantlist = array();
750
    $participantlist[] = array(
751
        'selectiontype' => 'all',
752
        'selectionid' => 'all',
753
        'role' => BIGBLUEBUTTONBN_ROLE_VIEWER
754
      );
755
    $defaultrules = explode(',', \mod_bigbluebuttonbn\locallib\config::get('participant_moderator_default'));
756
    foreach ($defaultrules as $defaultrule) {
757
        if ($defaultrule == '0') {
758
            if (!empty($ownerid) && is_enrolled($context, $ownerid)) {
759
                $participantlist[] = array(
760
                    'selectiontype' => 'user',
761
                    'selectionid' => (string)$ownerid,
762
                    'role' => BIGBLUEBUTTONBN_ROLE_MODERATOR);
763
            }
764
            continue;
765
        }
766
        $participantlist[] = array(
767
              'selectiontype' => 'role',
768
              'selectionid' => $defaultrule,
769
              'role' => BIGBLUEBUTTONBN_ROLE_MODERATOR);
770
    }
771
    return $participantlist;
772
}
773
774
/**
775
 * Returns an array to populate a list of participants used in mod_form.php with bigbluebuttonbn values.
776
 *
777
 * @param array $rules
778
 *
779
 * @return array
780
 */
781
function bigbluebuttonbn_get_participant_rules_encoded($rules) {
782
    foreach ($rules as $key => $rule) {
783
        if ($rule['selectiontype'] !== 'role' || is_numeric($rule['selectionid'])) {
784
            continue;
785
        }
786
        $role = bigbluebuttonbn_get_role($rule['selectionid']);
787
        if ($role == null) {
788
            unset($rules[$key]);
789
            continue;
790
        }
791
        $rule['selectionid'] = $role->id;
792
        $rules[$key] = $rule;
793
    }
794
    return $rules;
795
}
796
797
/**
798
 * Returns an array to populate a list of participant_selection used in mod_form.php.
799
 *
800
 * @return array
801
 */
802
function bigbluebuttonbn_get_participant_selection_data() {
803
    return [
804
        'type_options' => [
805
            'all' => get_string('mod_form_field_participant_list_type_all', 'bigbluebuttonbn'),
806
            'role' => get_string('mod_form_field_participant_list_type_role', 'bigbluebuttonbn'),
807
            'user' => get_string('mod_form_field_participant_list_type_user', 'bigbluebuttonbn'),
808
          ],
809
        'type_selected' => 'all',
810
        'options' => ['all' => '---------------'],
811
        'selected' => 'all',
812
      ];
813
}
814
815
/**
816
 * Evaluate if a user in a context is moderator based on roles and participation rules.
817
 *
818
 * @param context $context
819
 * @param array $participantlist
820
 * @param integer $userid
821
 *
822
 * @return boolean
823
 */
824
function bigbluebuttonbn_is_moderator($context, $participantlist, $userid = null) {
825
    global $USER;
826
    if (!is_array($participantlist)) {
827
        return false;
828
    }
829
    if (empty($userid)) {
830
        $userid = $USER->id;
831
    }
832
    $userroles = bigbluebuttonbn_get_guest_role();
833
    if (!isguestuser()) {
834
        $userroles = bigbluebuttonbn_get_user_roles($context, $userid);
835
    }
836
    return bigbluebuttonbn_is_moderator_validator($participantlist, $userid , $userroles);
837
}
838
839
/**
840
 * Iterates participant list rules to evaluate if a user is moderator.
841
 *
842
 * @param array $participantlist
843
 * @param integer $userid
844
 * @param array $userroles
845
 *
846
 * @return boolean
847
 */
848
function bigbluebuttonbn_is_moderator_validator($participantlist, $userid, $userroles) {
849
    // Iterate participant rules.
850
    foreach ($participantlist as $participant) {
851
        if (bigbluebuttonbn_is_moderator_validate_rule($participant, $userid, $userroles)) {
852
            return true;
853
        }
854
    }
855
    return false;
856
}
857
858
/**
859
 * Evaluate if a user is moderator based on roles and a particular participation rule.
860
 *
861
 * @param object $participant
862
 * @param integer $userid
863
 * @param array $userroles
864
 *
865
 * @return boolean
866
 */
867
function bigbluebuttonbn_is_moderator_validate_rule($participant, $userid, $userroles) {
868
    if ($participant['role'] == BIGBLUEBUTTONBN_ROLE_VIEWER) {
869
        return false;
870
    }
871
    // Validation for the 'all' rule.
872
    if ($participant['selectiontype'] == 'all') {
873
        return true;
874
    }
875
    // Validation for a 'user' rule.
876
    if ($participant['selectiontype'] == 'user') {
877
        if ($participant['selectionid'] == $userid) {
878
            return true;
879
        }
880
        return false;
881
    }
882
    // Validation for a 'role' rule.
883
    $role = bigbluebuttonbn_get_role($participant['selectionid']);
884
    if ($role != null && array_key_exists($role->id, $userroles)) {
885
        return true;
886
    }
887
    return false;
888
}
889
890
/**
891
 * Helper returns error message key for the language file that corresponds to a bigbluebutton error key.
892
 *
893
 * @param string $messagekey
894
 * @param string $defaultkey
895
 *
896
 * @return string
897
 */
898
function bigbluebuttonbn_get_error_key($messagekey, $defaultkey = null) {
899
    if ($messagekey == 'checksumError') {
900
        return 'index_error_checksum';
901
    }
902
    if ($messagekey == 'maxConcurrent') {
903
        return 'view_error_max_concurrent';
904
    }
905
    return $defaultkey;
906
}
907
908
/**
909
 * Helper evaluates if a voicebridge number is unique.
910
 *
911
 * @param integer $instance
912
 * @param integer $voicebridge
913
 *
914
 * @return string
915
 */
916
function bigbluebuttonbn_voicebridge_unique($instance, $voicebridge) {
917
    global $DB;
918
    if ($voicebridge == 0) {
919
        return true;
920
    }
921
    $select = 'voicebridge = ' . $voicebridge;
922
    if ($instance != 0) {
923
        $select .= ' AND id <>' . $instance;
924
    }
925
    if (!$DB->get_records_select('bigbluebuttonbn', $select)) {
926
        return true;
927
    }
928
    return false;
929
}
930
931
/**
932
 * Helper estimate a duration for the meeting based on the closingtime.
933
 *
934
 * @param integer $closingtime
935
 *
936
 * @return integer
937
 */
938
function bigbluebuttonbn_get_duration($closingtime) {
939
    $duration = 0;
940
    $now = time();
941
    if ($closingtime > 0 && $now < $closingtime) {
942
        $duration = ceil(($closingtime - $now) / 60);
943
        $compensationtime = intval((int)\mod_bigbluebuttonbn\locallib\config::get('scheduled_duration_compensation'));
944
        $duration = intval($duration) + $compensationtime;
945
    }
946
    return $duration;
947
}
948
949
/**
950
 * Helper return array containing the file descriptor for a preuploaded presentation.
951
 *
952
 * @param context $context
953
 * @param string $presentation
954
 * @param integer $id
955
 *
956
 * @return array
957
 */
958
function bigbluebuttonbn_get_presentation_array($context, $presentation, $id = null) {
959
    if (empty($presentation)) {
960
        return array('url' => null, 'name' => null, 'icon' => null, 'mimetype_description' => null);
961
    }
962
    $fs = get_file_storage();
963
    $files = $fs->get_area_files($context->id, 'mod_bigbluebuttonbn', 'presentation', 0,
964
        'itemid, filepath, filename', false);
965
    if (count($files) == 0) {
966
        return array('url' => null, 'name' => null, 'icon' => null, 'mimetype_description' => null);
967
    }
968
    $file = reset($files);
969
    unset($files);
970
    $pnoncevalue = null;
971
    if (!is_null($id)) {
972
        // Create the nonce component for granting a temporary public access.
973
        $cache = cache::make_from_params(cache_store::MODE_APPLICATION, 'mod_bigbluebuttonbn',
974
            'presentation_cache');
975
        $pnoncekey = sha1($id);
976
        /* The item id was adapted for granting public access to the presentation once in order
977
         * to allow BigBlueButton to gather the file. */
978
        $pnoncevalue = bigbluebuttonbn_generate_nonce();
979
        $cache->set($pnoncekey, array('value' => $pnoncevalue, 'counter' => 0));
980
    }
981
    $url = moodle_url::make_pluginfile_url($file->get_contextid(), $file->get_component(),
982
        $file->get_filearea(), $pnoncevalue, $file->get_filepath(), $file->get_filename());
983
    return array('name' => $file->get_filename(), 'icon' => file_file_icon($file, 24),
984
            'url' => $url->out(false), 'mimetype_description' => get_mimetype_description($file));
985
}
986
987
/**
988
 * Helper generates a nonce used for the preuploaded presentation callback url.
989
 *
990
 * @return string
991
 */
992
function bigbluebuttonbn_generate_nonce() {
993
    $mt = microtime();
994
    $rand = mt_rand();
995
    return md5($mt.$rand);
996
}
997
998
/**
999
 * Helper generates a random password.
1000
 *
1001
 * @param integer $length
1002
 * @param string $unique
1003
 *
1004
 * @return string
1005
 */
1006
function bigbluebuttonbn_random_password($length = 8, $unique = "") {
1007
    $chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*()_-=+;:,.?';
1008
    do {
1009
        $password = substr(str_shuffle($chars), 0, $length);
1010
    } while ($unique == $password);
1011
    return $password;
1012
}
1013
1014
/**
1015
 * Helper returns an array with all possible bigbluebuttonbn events.
1016
 *
1017
 * @return array
1018
 */
1019
function bigbluebuttonbn_events() {
1020
    return array(
1021
        (string) BIGBLUEBUTTON_EVENT_ACTIVITY_VIEWED,
1022
        (string) BIGBLUEBUTTON_EVENT_ACTIVITY_MANAGEMENT_VIEWED,
1023
        (string) BIGBLUEBUTTON_EVENT_LIVE_SESSION,
1024
        (string) BIGBLUEBUTTON_EVENT_MEETING_CREATED,
1025
        (string) BIGBLUEBUTTON_EVENT_MEETING_ENDED,
1026
        (string) BIGBLUEBUTTON_EVENT_MEETING_JOINED,
1027
        (string) BIGBLUEBUTTON_EVENT_MEETING_LEFT,
1028
        (string) BIGBLUEBUTTON_EVENT_RECORDING_DELETED,
1029
        (string) BIGBLUEBUTTON_EVENT_RECORDING_IMPORTED,
1030
        (string) BIGBLUEBUTTON_EVENT_RECORDING_PROTECTED,
1031
        (string) BIGBLUEBUTTON_EVENT_RECORDING_PUBLISHED,
1032
        (string) BIGBLUEBUTTON_EVENT_RECORDING_UNPROTECTED,
1033
        (string) BIGBLUEBUTTON_EVENT_RECORDING_UNPUBLISHED,
1034
        (string) BIGBLUEBUTTON_EVENT_RECORDING_EDITED,
1035
        (string) BIGBLUEBUTTON_EVENT_RECORDING_VIEWED
1036
    );
1037
}
1038
1039
/**
1040
 * Helper returns an array with the actions and their corresponding bigbluebuttonbn events.
1041
 *
1042
 * @return array
1043
 */
1044
function bigbluebuttonbn_events_action() {
1045
    return array(
1046
        'view' => (string) BIGBLUEBUTTON_EVENT_ACTIVITY_VIEWED,
1047
        'view_management' => (string) BIGBLUEBUTTON_EVENT_ACTIVITY_MANAGEMENT_VIEWED,
1048
        'live_action' => (string) BIGBLUEBUTTON_EVENT_LIVE_SESSION,
1049
        'meeting_create' => (string) BIGBLUEBUTTON_EVENT_MEETING_CREATED,
1050
        'meeting_end' => (string) BIGBLUEBUTTON_EVENT_MEETING_ENDED,
1051
        'meeting_join' => (string) BIGBLUEBUTTON_EVENT_MEETING_JOINED,
1052
        'meeting_left' => (string) BIGBLUEBUTTON_EVENT_MEETING_LEFT,
1053
        'recording_delete' => (string) BIGBLUEBUTTON_EVENT_RECORDING_DELETED,
1054
        'recording_import' => (string) BIGBLUEBUTTON_EVENT_RECORDING_IMPORTED,
1055
        'recording_protect' => (string) BIGBLUEBUTTON_EVENT_RECORDING_PROTECTED,
1056
        'recording_publish' => (string) BIGBLUEBUTTON_EVENT_RECORDING_PUBLISHED,
1057
        'recording_unprotect' => (string) BIGBLUEBUTTON_EVENT_RECORDING_UNPROTECTED,
1058
        'recording_unpublish' => (string) BIGBLUEBUTTON_EVENT_RECORDING_UNPUBLISHED,
1059
        'recording_edit' => (string) BIGBLUEBUTTON_EVENT_RECORDING_EDITED,
1060
        'recording_play' => (string) BIGBLUEBUTTON_EVENT_RECORDING_VIEWED
1061
    );
1062
}
1063
1064
/**
1065
 * Helper register a bigbluebuttonbn event.
1066
 *
1067
 * @param string $eventtype
1068
 * @param object $bigbluebuttonbn
1069
 * @param object $cm
1070
 * @param array $options
1071
 *
1072
 * @return void
1073
 */
1074
function bigbluebuttonbn_event_log($eventtype, $bigbluebuttonbn, $cm, $options = []) {
1075
    $events = bigbluebuttonbn_events();
1076
    if (!in_array($eventtype, $events)) {
1077
        // No log will be created.
1078
        return;
1079
    }
1080
    $context = context_module::instance($cm->id);
1081
1082
    $eventproperties = array('context' => $context, 'objectid' => $bigbluebuttonbn->id);
1083
    if (array_key_exists('timecreated', $options)) {
1084
        $eventproperties['timecreated'] = $options['timecreated'];
1085
    }
1086
    if (array_key_exists('userid', $options)) {
1087
        $eventproperties['userid'] = $options['userid'];
1088
    }
1089
    if (array_key_exists('other', $options)) {
1090
        $eventproperties['other'] = $options['other'];
1091
    }
1092
    $event = call_user_func_array('\mod_bigbluebuttonbn\event\bigbluebuttonbn_'.$eventtype.'::create',
1093
      array($eventproperties));
1094
    $event->trigger();
1095
}
1096
1097
/**
1098
 * Updates the meeting info cached object when a participant has joined.
1099
 *
1100
 * @param string $meetingid
1101
 * @param bool $ismoderator
1102
 *
1103
 * @return void
1104
 */
1105
function bigbluebuttonbn_participant_joined($meetingid, $ismoderator) {
1106
    $cache = cache::make_from_params(cache_store::MODE_APPLICATION, 'mod_bigbluebuttonbn', 'meetings_cache');
1107
    $result = $cache->get($meetingid);
1108
    $meetinginfo = json_decode($result['meeting_info']);
1109
    $meetinginfo->participantCount += 1;
1110
    if ($ismoderator) {
1111
        $meetinginfo->moderatorCount += 1;
1112
    }
1113
    $cache->set($meetingid, array('creation_time' => $result['creation_time'],
1114
        'meeting_info' => json_encode($meetinginfo)));
1115
}
1116
1117
/**
1118
 * Gets a meeting info object cached or fetched from the live session.
1119
 *
1120
 * @param string $meetingid
1121
 * @param boolean $updatecache
1122
 *
1123
 * @return array
1124
 */
1125
function bigbluebuttonbn_get_meeting_info($meetingid, $updatecache = false) {
1126
    $cachettl = (int)\mod_bigbluebuttonbn\locallib\config::get('waitformoderator_cache_ttl');
1127
    $cache = cache::make_from_params(cache_store::MODE_APPLICATION, 'mod_bigbluebuttonbn', 'meetings_cache');
1128
    $result = $cache->get($meetingid);
1129
    $now = time();
1130
    if (!$updatecache && isset($result) && $now < ($result['creation_time'] + $cachettl)) {
1131
        // Use the value in the cache.
1132
        return (array) json_decode($result['meeting_info']);
1133
    }
1134
    // Ping again and refresh the cache.
1135
    $meetinginfo = (array) bigbluebuttonbn_wrap_xml_load_file(
1136
        \mod_bigbluebuttonbn\locallib\bigbluebutton::action_url('getMeetingInfo', ['meetingID' => $meetingid])
1137
      );
1138
    $cache->set($meetingid, array('creation_time' => time(), 'meeting_info' => json_encode($meetinginfo)));
1139
    return $meetinginfo;
1140
}
1141
1142
/**
1143
 * Perform isMeetingRunning on BBB.
1144
 *
1145
 * @param string $meetingid
1146
 * @param boolean $updatecache
1147
 *
1148
 * @return boolean
1149
 */
1150
function bigbluebuttonbn_is_meeting_running($meetingid, $updatecache = false) {
1151
    /* As a workaround to isMeetingRunning that always return SUCCESS but only returns true
1152
     * when at least one user is in the session, we use getMeetingInfo instead.
1153
     */
1154
    $meetinginfo = bigbluebuttonbn_get_meeting_info($meetingid, $updatecache);
1155
    return ($meetinginfo['returncode'] === 'SUCCESS');
1156
}
1157
1158
/**
1159
 * Publish an imported recording.
1160
 *
1161
 * @param string $id
1162
 * @param boolean $publish
1163
 *
1164
 * @return boolean
1165
 */
1166 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...
1167
    global $DB;
1168
    // Locate the record to be updated.
1169
    $record = $DB->get_record('bigbluebuttonbn_logs', array('id' => $id));
1170
    $meta = json_decode($record->meta, true);
1171
    // Prepare data for the update.
1172
    $meta['recording']['published'] = ($publish) ? 'true' : 'false';
1173
    $record->meta = json_encode($meta);
1174
    // Proceed with the update.
1175
    $DB->update_record('bigbluebuttonbn_logs', $record);
1176
    return true;
1177
}
1178
1179
/**
1180
 * Delete an imported recording.
1181
 *
1182
 * @param string $id
1183
 *
1184
 * @return boolean
1185
 */
1186
function bigbluebuttonbn_delete_recording_imported($id) {
1187
    global $DB;
1188
    // Execute delete.
1189
    $DB->delete_records('bigbluebuttonbn_logs', array('id' => $id));
1190
    return true;
1191
}
1192
1193
/**
1194
 * Update an imported recording.
1195
 *
1196
 * @param string $id
1197
 * @param array $params ['key'=>param_key, 'value']
1198
 *
1199
 * @return boolean
1200
 */
1201
function bigbluebuttonbn_update_recording_imported($id, $params) {
1202
    global $DB;
1203
    // Locate the record to be updated.
1204
    $record = $DB->get_record('bigbluebuttonbn_logs', array('id' => $id));
1205
    $meta = json_decode($record->meta, true);
1206
    // Prepare data for the update.
1207
    $meta['recording'] = $params + $meta['recording'];
1208
    $record->meta = json_encode($meta);
1209
    // Proceed with the update.
1210
    if (!$DB->update_record('bigbluebuttonbn_logs', $record)) {
1211
        return false;
1212
    }
1213
    return true;
1214
}
1215
1216
/**
1217
 * Protect/Unprotect an imported recording.
1218
 *
1219
 * @param string $id
1220
 * @param boolean $protect
1221
 *
1222
 * @return boolean
1223
 */
1224 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...
1225
    global $DB;
1226
    // Locate the record to be updated.
1227
    $record = $DB->get_record('bigbluebuttonbn_logs', array('id' => $id));
1228
    $meta = json_decode($record->meta, true);
1229
    // Prepare data for the update.
1230
    $meta['recording']['protected'] = ($protect) ? 'true' : 'false';
1231
    $record->meta = json_encode($meta);
1232
    // Proceed with the update.
1233
    $DB->update_record('bigbluebuttonbn_logs', $record);
1234
    return true;
1235
}
1236
1237
/**
1238
 * Sets a custom config.xml file for being used on create.
1239
 *
1240
 * @param string $meetingid
1241
 * @param string $configxml
1242
 *
1243
 * @return object
1244
 */
1245
function bigbluebuttonbn_set_config_xml($meetingid, $configxml) {
1246
    $urldefaultconfig = \mod_bigbluebuttonbn\locallib\config::get('server_url').'api/setConfigXML?';
1247
    $configxmlparams = bigbluebuttonbn_set_config_xml_params($meetingid, $configxml);
1248
    $xml = bigbluebuttonbn_wrap_xml_load_file($urldefaultconfig, 'POST',
1249
        $configxmlparams, 'application/x-www-form-urlencoded');
1250
    return $xml;
1251
}
1252
1253
/**
1254
 * Sets qs used with a custom config.xml file request.
1255
 *
1256
 * @param string $meetingid
1257
 * @param string $configxml
1258
 *
1259
 * @return string
1260
 */
1261
function bigbluebuttonbn_set_config_xml_params($meetingid, $configxml) {
1262
    $params = 'configXML='.urlencode($configxml).'&meetingID='.urlencode($meetingid);
1263
    $configxmlparams = $params.'&checksum='.sha1('setConfigXML'.$params.\mod_bigbluebuttonbn\locallib\config::get('shared_secret'));
1264
    return $configxmlparams;
1265
}
1266
1267
/**
1268
 * Sets a custom config.xml file for being used on create.
1269
 *
1270
 * @param string $meetingid
1271
 * @param string $configxml
1272
 *
1273
 * @return array
1274
 */
1275
function bigbluebuttonbn_set_config_xml_array($meetingid, $configxml) {
1276
    $configxml = bigbluebuttonbn_setConfigXML($meetingid, $configxml);
1277
    $configxmlarray = (array) $configxml;
1278
    if ($configxmlarray['returncode'] != 'SUCCESS') {
1279
        debugging('BigBlueButton was not able to set the custom config.xml file', DEBUG_DEVELOPER);
1280
        return '';
1281
    }
1282
    return $configxmlarray['configToken'];
1283
}
1284
1285
/**
1286
 * Helper function builds a row for the data used by the recording table.
1287
 *
1288
 * @param array $bbbsession
1289
 * @param array $recording
1290
 * @param array $tools
1291
 *
1292
 * @return array
1293
 */
1294
function bigbluebuttonbn_get_recording_data_row($bbbsession, $recording, $tools = ['protect', 'publish', 'delete']) {
1295
    if (!bigbluebuttonbn_include_recording_table_row($bbbsession, $recording)) {
1296
        return;
1297
    }
1298
    $rowdata = new stdClass();
1299
    // Set recording_types.
1300
    $rowdata->recording = bigbluebuttonbn_get_recording_data_row_types($recording, $bbbsession);
1301
    // Set activity name.
1302
    $rowdata->activity = bigbluebuttonbn_get_recording_data_row_meta_activity($recording, $bbbsession);
1303
    // Set activity description.
1304
    $rowdata->description = bigbluebuttonbn_get_recording_data_row_meta_description($recording, $bbbsession);
1305
    if (bigbluebuttonbn_get_recording_data_preview_enabled($bbbsession)) {
1306
        // Set recording_preview.
1307
        $rowdata->preview = bigbluebuttonbn_get_recording_data_row_preview($recording);
1308
    }
1309
    // Set date.
1310
    $rowdata->date = bigbluebuttonbn_get_recording_data_row_date($recording);
1311
    // Set formatted date.
1312
    $rowdata->date_formatted = bigbluebuttonbn_get_recording_data_row_date_formatted($rowdata->date);
1313
    // Set formatted duration.
1314
    $rowdata->duration_formatted = $rowdata->duration = bigbluebuttonbn_get_recording_data_row_duration($recording);
1315
    // Set actionbar, if user is allowed to manage recordings.
1316
    if ($bbbsession['managerecordings']) {
1317
        $rowdata->actionbar = bigbluebuttonbn_get_recording_data_row_actionbar($recording, $tools);
1318
    }
1319
    return $rowdata;
1320
}
1321
1322
/**
1323
 * Helper function evaluates if a row for the data used by the recording table is editable.
1324
 *
1325
 * @param array $bbbsession
1326
 *
1327
 * @return boolean
1328
 */
1329
function bigbluebuttonbn_get_recording_data_row_editable($bbbsession) {
1330
    return ($bbbsession['managerecordings'] && ((double)$bbbsession['serverversion'] >= 1.0 || $bbbsession['bnserver']));
1331
}
1332
1333
/**
1334
 * Helper function evaluates if recording preview should be included.
1335
 *
1336
 * @param array $bbbsession
1337
 *
1338
 * @return boolean
1339
 */
1340
function bigbluebuttonbn_get_recording_data_preview_enabled($bbbsession) {
1341
    return ((double)$bbbsession['serverversion'] >= 1.0 && $bbbsession['bigbluebuttonbn']->recordings_preview == '1');
1342
}
1343
1344
/**
1345
 * Helper function converts recording date used in row for the data used by the recording table.
1346
 *
1347
 * @param array $recording
1348
 *
1349
 * @return integer
1350
 */
1351
function bigbluebuttonbn_get_recording_data_row_date($recording) {
1352
    if (!isset($recording['startTime'])) {
1353
        return 0;
1354
    }
1355
    return floatval($recording['startTime']);
1356
}
1357
1358
/**
1359
 * Helper function format recording date used in row for the data used by the recording table.
1360
 *
1361
 * @param integer $starttime
1362
 *
1363
 * @return string
1364
 */
1365
function bigbluebuttonbn_get_recording_data_row_date_formatted($starttime) {
1366
    global $USER;
1367
    $starttime = $starttime - ($starttime % 1000);
1368
    // Set formatted date.
1369
    $dateformat = get_string('strftimerecentfull', 'langconfig').' %Z';
1370
    return userdate($starttime / 1000, $dateformat, usertimezone($USER->timezone));
1371
}
1372
1373
/**
1374
 * Helper function converts recording duration used in row for the data used by the recording table.
1375
 *
1376
 * @param array $recording
1377
 *
1378
 * @return integer
1379
 */
1380
function bigbluebuttonbn_get_recording_data_row_duration($recording) {
1381
    foreach (array_values($recording['playbacks']) as $playback) {
1382
        // Ignore restricted playbacks.
1383
        if (array_key_exists('restricted', $playback) && strtolower($playback['restricted']) == 'true') {
1384
            continue;
1385
        }
1386
        // Take the lenght form the fist playback with an actual value.
1387
        if (!empty($playback['length'])) {
1388
            return intval($playback['length']);
1389
        }
1390
    }
1391
    return 0;
1392
}
1393
1394
/**
1395
 * Helper function builds recording actionbar used in row for the data used by the recording table.
1396
 *
1397
 * @param array $recording
1398
 * @param array $tools
1399
 *
1400
 * @return string
1401
 */
1402
function bigbluebuttonbn_get_recording_data_row_actionbar($recording, $tools) {
1403
    $actionbar = '';
1404
    foreach ($tools as $tool) {
1405
        $buttonpayload = bigbluebuttonbn_get_recording_data_row_actionbar_payload($recording, $tool);
1406
        if ($tool == 'protect') {
1407
            if (isset($recording['imported'])) {
1408
                $buttonpayload['disabled'] = 'disabled';
1409
            }
1410
            if (!isset($recording['protected'])) {
1411
                $buttonpayload['disabled'] = 'invisible';
1412
            }
1413
        }
1414
        $actionbar .= bigbluebuttonbn_actionbar_render_button($recording, $buttonpayload);
1415
    }
1416
    $head = html_writer::start_tag('div', array(
1417
        'id' => 'recording-actionbar-' . $recording['recordID'],
1418
        'data-recordingid' => $recording['recordID'],
1419
        'data-meetingid' => $recording['meetingID']));
1420
    $tail = html_writer::end_tag('div');
1421
    return $head . $actionbar . $tail;
1422
}
1423
1424
/**
1425
 * Helper function returns the corresponding payload for an actionbar button used in row
1426
 * for the data used by the recording table.
1427
 *
1428
 * @param array $recording
1429
 * @param array $tool
1430
 *
1431
 * @return array
1432
 */
1433
function bigbluebuttonbn_get_recording_data_row_actionbar_payload($recording, $tool) {
1434
    if ($tool == 'protect') {
1435
        $protected = 'false';
1436
        if (isset($recording['protected'])) {
1437
            $protected = $recording['protected'];
1438
        }
1439
        return bigbluebuttonbn_get_recording_data_row_action_protect($protected);
1440
    }
1441
    if ($tool == 'publish') {
1442
        return bigbluebuttonbn_get_recording_data_row_action_publish($recording['published']);
1443
    }
1444
    return array('action' => $tool, 'tag' => $tool);
1445
}
1446
1447
/**
1448
 * Helper function returns the payload for protect action button used in row
1449
 * for the data used by the recording table.
1450
 *
1451
 * @param string $protected
1452
 *
1453
 * @return array
1454
 */
1455
function bigbluebuttonbn_get_recording_data_row_action_protect($protected) {
1456
    if ($protected == 'true') {
1457
        return array('action' => 'unprotect', 'tag' => 'lock');
1458
    }
1459
    return array('action' => 'protect', 'tag' => 'unlock');
1460
}
1461
1462
/**
1463
 * Helper function returns the payload for publish action button used in row
1464
 * for the data used by the recording table.
1465
 *
1466
 * @param string $published
1467
 *
1468
 * @return array
1469
 */
1470
function bigbluebuttonbn_get_recording_data_row_action_publish($published) {
1471
    if ($published == 'true') {
1472
        return array('action' => 'unpublish', 'tag' => 'hide');
1473
    }
1474
    return array('action' => 'publish', 'tag' => 'show');
1475
}
1476
1477
/**
1478
 * Helper function builds recording preview used in row for the data used by the recording table.
1479
 *
1480
 * @param array $recording
1481
 *
1482
 * @return string
1483
 */
1484
function bigbluebuttonbn_get_recording_data_row_preview($recording) {
1485
    $options = array('id' => 'preview-'.$recording['recordID']);
1486
    if ($recording['published'] === 'false') {
1487
        $options['hidden'] = 'hidden';
1488
    }
1489
    $recordingpreview = html_writer::start_tag('div', $options);
1490
    foreach ($recording['playbacks'] as $playback) {
1491
        if (isset($playback['preview'])) {
1492
            $recordingpreview .= bigbluebuttonbn_get_recording_data_row_preview_images($playback);
1493
            break;
1494
        }
1495
    }
1496
    $recordingpreview .= html_writer::end_tag('div');
1497
    return $recordingpreview;
1498
}
1499
1500
/**
1501
 * Helper function builds element with actual images used in recording preview row based on a selected playback.
1502
 *
1503
 * @param array $playback
1504
 *
1505
 * @return string
1506
 */
1507
function bigbluebuttonbn_get_recording_data_row_preview_images($playback) {
1508
    $recordingpreview  = html_writer::start_tag('div', array('class' => 'container-fluid'));
1509
    $recordingpreview .= html_writer::start_tag('div', array('class' => 'row'));
1510
    foreach ($playback['preview'] as $image) {
1511
        if (!bigbluebuttonbn_is_valid_resource(trim($image['url']))) {
1512
            return '';
1513
        }
1514
        $recordingpreview .= html_writer::start_tag('div', array('class' => ''));
1515
        $recordingpreview .= html_writer::empty_tag('img',
1516
            array('src' => trim($image['url']) . '?' . time(), 'class' => 'recording-thumbnail pull-left'));
1517
        $recordingpreview .= html_writer::end_tag('div');
1518
    }
1519
    $recordingpreview .= html_writer::end_tag('div');
1520
    $recordingpreview .= html_writer::start_tag('div', array('class' => 'row'));
1521
    $recordingpreview .= html_writer::tag('div', get_string('view_recording_preview_help', 'bigbluebuttonbn'),
1522
        array('class' => 'text-center text-muted small'));
1523
    $recordingpreview .= html_writer::end_tag('div');
1524
    $recordingpreview .= html_writer::end_tag('div');
1525
    return $recordingpreview;
1526
}
1527
1528
/**
1529
 * Helper function renders recording types to be used in row for the data used by the recording table.
1530
 *
1531
 * @param array $recording
1532
 * @param array $bbbsession
1533
 *
1534
 * @return string
1535
 */
1536
function bigbluebuttonbn_get_recording_data_row_types($recording, $bbbsession) {
1537
    $dataimported = 'false';
1538
    $title = '';
1539
    if (isset($recording['imported'])) {
1540
        $dataimported = 'true';
1541
        $title = get_string('view_recording_link_warning', 'bigbluebuttonbn');
1542
    }
1543
    $visibility = '';
1544
    if ($recording['published'] === 'false') {
1545
        $visibility = 'hidden ';
1546
    }
1547
    $id = 'playbacks-'.$recording['recordID'];
1548
    $recordingtypes = html_writer::start_tag('div', array('id' => $id, 'data-imported' => $dataimported,
1549
          'data-meetingid' => $recording['meetingID'], 'data-recordingid' => $recording['recordID'],
1550
          'title' => $title, $visibility => $visibility));
1551
    foreach ($recording['playbacks'] as $playback) {
1552
        $recordingtypes .= bigbluebuttonbn_get_recording_data_row_type($recording, $bbbsession, $playback);
1553
    }
1554
    $recordingtypes .= html_writer::end_tag('div');
1555
    return $recordingtypes;
1556
}
1557
1558
/**
1559
 * Helper function renders the link used for recording type in row for the data used by the recording table.
1560
 *
1561
 * @param array $recording
1562
 * @param array $bbbsession
1563
 * @param array $playback
1564
 *
1565
 * @return string
1566
 */
1567
function bigbluebuttonbn_get_recording_data_row_type($recording, $bbbsession, $playback) {
1568
    global $CFG, $OUTPUT;
1569
    if (!bigbluebuttonbn_include_recording_data_row_type($recording, $bbbsession, $playback)) {
1570
        return '';
1571
    }
1572
    $text = get_string('view_recording_format_'.$playback['type'], 'bigbluebuttonbn');
1573
    $href = $CFG->wwwroot . '/mod/bigbluebuttonbn/bbb_view.php?action=play&bn=' . $bbbsession['bigbluebuttonbn']->id .
1574
      '&mid='.$recording['meetingID'] . '&rid=' . $recording['recordID'] . '&rtype=' . $playback['type'];
1575
    if (!isset($recording['imported']) || !isset($recording['protected']) || $recording['protected'] === 'false') {
1576
        $href .= '&href='.urlencode(trim($playback['url']));
1577
    }
1578
    $linkattributes = array(
1579
        'id' => 'recording-play-' . $playback['type'] . '-' . $recording['recordID'],
1580
        'class' => 'btn btn-sm btn-default',
1581
        'onclick' => 'M.mod_bigbluebuttonbn.recordings.recordingPlay(this);',
1582
        'data-action' => 'play',
1583
        'data-target' => $playback['type'],
1584
        'data-href' => $href,
1585
      );
1586
    if (!bigbluebuttonbn_is_bn_server() && !bigbluebuttonbn_is_valid_resource(trim($playback['url']))) {
1587
        $linkattributes['class'] = 'btn btn-sm btn-warning';
1588
        $linkattributes['title'] = get_string('view_recording_format_errror_unreachable', 'bigbluebuttonbn');
1589
        unset($linkattributes['data-href']);
1590
    }
1591
    return $OUTPUT->action_link('#', $text, null, $linkattributes) . '&#32;';
1592
}
1593
1594
/**
1595
 * Helper function validates a remote resource.
1596
 *
1597
 * @param string $url
1598
 *
1599
 * @return boolean
1600
 */
1601
function bigbluebuttonbn_is_valid_resource($url) {
1602
    $urlhost = parse_url($url, PHP_URL_HOST);
1603
    $serverurlhost = parse_url(\mod_bigbluebuttonbn\locallib\config::get('server_url'), PHP_URL_HOST);
1604
    // Skip validation when the recording URL host is the same as the configured BBB server.
1605
    if ($urlhost == $serverurlhost) {
1606
        return true;
1607
    }
1608
    // Skip validation when the recording URL was already validated.
1609
    $validatedurls = bigbluebuttonbn_cache_get('recordings_cache', 'validated_urls', array());
0 ignored issues
show
Documentation introduced by
array() is of type array, but the function expects a integer|null.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
1610
    if (array_key_exists($urlhost, $validatedurls)) {
1611
        return $validatedurls[$urlhost];
1612
    }
1613
    // Validate the recording URL.
1614
    $validatedurls[$urlhost] = true;
1615
    $curlinfo = bigbluebuttonbn_wrap_xml_load_file_curl_request($url, 'HEAD');
1616
    if (!isset($curlinfo['http_code']) || $curlinfo['http_code'] != 200) {
1617
        $error = "Resources hosted by " . $urlhost . " are unreachable. Server responded with code " . $curlinfo['http_code'];
1618
        debugging($error, DEBUG_DEVELOPER);
1619
        $validatedurls[$urlhost] = false;
1620
    }
1621
    bigbluebuttonbn_cache_set('recordings_cache', 'validated_urls', $validatedurls);
1622
    return $validatedurls[$urlhost];
1623
}
1624
1625
/**
1626
 * Helper function renders the name for recording used in row for the data used by the recording table.
1627
 *
1628
 * @param array $recording
1629
 * @param array $bbbsession
1630
 *
1631
 * @return string
1632
 */
1633
function bigbluebuttonbn_get_recording_data_row_meta_activity($recording, $bbbsession) {
1634
    $payload = array();
1635 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...
1636
        $payload = array('recordingid' => $recording['recordID'], 'meetingid' => $recording['meetingID'],
1637
            'action' => 'edit', 'tag' => 'edit',
1638
            'target' => 'name');
1639
    }
1640
    $oldsource = 'meta_contextactivity';
1641
    if (isset($recording[$oldsource])) {
1642
        $metaname = trim($recording[$oldsource]);
1643
        return bigbluebuttonbn_get_recording_data_row_text($recording, $metaname, $oldsource, $payload);
1644
    }
1645
    $newsource = 'meta_bbb-recording-name';
1646 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...
1647
        $metaname = trim($recording[$newsource]);
1648
        return bigbluebuttonbn_get_recording_data_row_text($recording, $metaname, $newsource, $payload);
1649
    }
1650
    $metaname = trim($recording['meetingName']);
1651
    return bigbluebuttonbn_get_recording_data_row_text($recording, $metaname, $newsource, $payload);
1652
}
1653
1654
/**
1655
 * Helper function renders the description for recording used in row for the data used by the recording table.
1656
 *
1657
 * @param array $recording
1658
 * @param array $bbbsession
1659
 *
1660
 * @return string
1661
 */
1662
function bigbluebuttonbn_get_recording_data_row_meta_description($recording, $bbbsession) {
1663
    $payload = array();
1664 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...
1665
        $payload = array('recordingid' => $recording['recordID'], 'meetingid' => $recording['meetingID'],
1666
            'action' => 'edit', 'tag' => 'edit',
1667
            'target' => 'description');
1668
    }
1669
    $oldsource = 'meta_contextactivitydescription';
1670 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...
1671
        $metadescription = trim($recording[$oldsource]);
1672
        return bigbluebuttonbn_get_recording_data_row_text($recording, $metadescription, $oldsource, $payload);
1673
    }
1674
    $newsource = 'meta_bbb-recording-description';
1675 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...
1676
        $metadescription = trim($recording[$newsource]);
1677
        return bigbluebuttonbn_get_recording_data_row_text($recording, $metadescription, $newsource, $payload);
1678
    }
1679
    return bigbluebuttonbn_get_recording_data_row_text($recording, '', $newsource, $payload);
1680
}
1681
1682
/**
1683
 * Helper function renders text element for recording used in row for the data used by the recording table.
1684
 *
1685
 * @param array $recording
1686
 * @param string $text
1687
 * @param string $source
1688
 * @param array $data
1689
 *
1690
 * @return string
1691
 */
1692
function bigbluebuttonbn_get_recording_data_row_text($recording, $text, $source, $data) {
1693
    $htmltext = '<span>' . htmlentities($text) . '</span>';
1694
    if (empty($data)) {
1695
        return $htmltext;
1696
    }
1697
    $target = $data['action'] . '-' . $data['target'];
1698
    $id = 'recording-' . $target . '-' . $data['recordingid'];
1699
    $attributes = array('id' => $id, 'class' => 'quickeditlink col-md-20',
1700
        'data-recordingid' => $data['recordingid'], 'data-meetingid' => $data['meetingid'],
1701
        'data-target' => $data['target'], 'data-source' => $source);
1702
    $head = html_writer::start_tag('div', $attributes);
1703
    $tail = html_writer::end_tag('div');
1704
    $payload = array('action' => $data['action'], 'tag' => $data['tag'], 'target' => $data['target']);
1705
    $htmllink = bigbluebuttonbn_actionbar_render_button($recording, $payload);
1706
    return $head . $htmltext . $htmllink . $tail;
1707
}
1708
1709
/**
1710
 * Helper function render a button for the recording action bar
1711
 *
1712
 * @param array $recording
1713
 * @param array $data
1714
 *
1715
 * @return string
1716
 */
1717
function bigbluebuttonbn_actionbar_render_button($recording, $data) {
1718
    global $OUTPUT;
1719
    if (empty($data)) {
1720
        return '';
1721
    }
1722
    $target = $data['action'];
1723
    if (isset($data['target'])) {
1724
        $target .= '-' . $data['target'];
1725
    }
1726
    $id = 'recording-' . $target . '-' . $recording['recordID'];
1727
    $onclick = 'M.mod_bigbluebuttonbn.recordings.recording' . ucfirst($data['action']) . '(this);';
1728
    if ((boolean)\mod_bigbluebuttonbn\locallib\config::get('recording_icons_enabled')) {
1729
        // With icon for $manageaction.
1730
        $iconattributes = array('id' => $id, 'class' => 'iconsmall');
1731
        $linkattributes = array(
1732
            'id' => $id,
1733
            'onclick' => $onclick,
1734
            'data-action' => $data['action']
1735
          );
1736
        if (!isset($recording['imported'])) {
1737
            $linkattributes['data-links'] = bigbluebuttonbn_count_recording_imported_instances(
1738
              $recording['recordID']);
1739
        }
1740
        if (isset($data['disabled'])) {
1741
            $iconattributes['class'] .= ' fa-' . $data['disabled'];
1742
            $linkattributes['class'] = 'disabled';
1743
            unset($linkattributes['onclick']);
1744
        }
1745
        $icon = new pix_icon('i/'.$data['tag'],
1746
            get_string('view_recording_list_actionbar_' . $data['action'], 'bigbluebuttonbn'),
1747
            'moodle', $iconattributes);
1748
        return $OUTPUT->action_icon('#', $icon, null, $linkattributes, false);
1749
    }
1750
    // With text for $manageaction.
1751
    $linkattributes = array('title' => get_string($data['tag']), 'class' => 'btn btn-xs btn-danger',
1752
        'onclick' => $onclick);
1753
    return $OUTPUT->action_link('#', get_string($data['action']), null, $linkattributes);
1754
}
1755
1756
/**
1757
 * Helper function builds the data used for headers by the recording table.
1758
 *
1759
 * @param array $bbbsession
1760
 *
1761
 * @return array
1762
 */
1763
function bigbluebuttonbn_get_recording_columns($bbbsession) {
1764
    $columns = array();
1765
    // Initialize table headers.
1766
    $columns[] = array('key' => 'recording', 'label' => get_string('view_recording_recording', 'bigbluebuttonbn'),
1767
        'width' => '125px', 'allowHTML' => true);
1768
    $columns[] = array('key' => 'activity', 'label' => get_string('view_recording_activity', 'bigbluebuttonbn'),
1769
        'sortable' => true, 'width' => '175px', 'allowHTML' => true);
1770
    $columns[] = array('key' => 'description', 'label' => get_string('view_recording_description', 'bigbluebuttonbn'),
1771
        'sortable' => true, 'width' => '250px', 'allowHTML' => true);
1772
    if (bigbluebuttonbn_get_recording_data_preview_enabled($bbbsession)) {
1773
        $columns[] = array('key' => 'preview', 'label' => get_string('view_recording_preview', 'bigbluebuttonbn'),
1774
            'width' => '250px', 'allowHTML' => true);
1775
    }
1776
    $columns[] = array('key' => 'date', 'label' => get_string('view_recording_date', 'bigbluebuttonbn'),
1777
        'sortable' => true, 'width' => '225px', 'allowHTML' => true);
1778
    $columns[] = array('key' => 'duration', 'label' => get_string('view_recording_duration', 'bigbluebuttonbn'),
1779
        'width' => '50px');
1780
    if ($bbbsession['managerecordings']) {
1781
        $columns[] = array('key' => 'actionbar', 'label' => get_string('view_recording_actionbar', 'bigbluebuttonbn'),
1782
            'width' => '120px', 'allowHTML' => true);
1783
    }
1784
    return $columns;
1785
}
1786
1787
/**
1788
 * Helper function builds the data used by the recording table.
1789
 *
1790
 * @param array $bbbsession
1791
 * @param array $recordings
1792
 * @param array $tools
1793
 *
1794
 * @return array
1795
 */
1796
function bigbluebuttonbn_get_recording_data($bbbsession, $recordings, $tools = ['protect', 'publish', 'delete']) {
1797
    $tabledata = array();
1798
    // Build table content.
1799
    if (isset($recordings) && !array_key_exists('messageKey', $recordings)) {
1800
        // There are recordings for this meeting.
1801
        foreach ($recordings as $recording) {
1802
            $rowdata = bigbluebuttonbn_get_recording_data_row($bbbsession, $recording, $tools);
1803
            if (!empty($rowdata)) {
1804
                array_push($tabledata, $rowdata);
1805
            }
1806
        }
1807
    }
1808
    return $tabledata;
1809
}
1810
1811
/**
1812
 * Helper function builds the recording table.
1813
 *
1814
 * @param array $bbbsession
1815
 * @param array $recordings
1816
 * @param array $tools
1817
 *
1818
 * @return object
1819
 */
1820
function bigbluebuttonbn_get_recording_table($bbbsession, $recordings, $tools = ['protect', 'publish', 'delete']) {
1821
    // Declare the table.
1822
    $table = new html_table();
1823
    $table->data = array();
1824
    // Initialize table headers.
1825
    $table->head[] = get_string('view_recording_playback', 'bigbluebuttonbn');
1826
    $table->head[] = get_string('view_recording_recording', 'bigbluebuttonbn');
1827
    $table->head[] = get_string('view_recording_description', 'bigbluebuttonbn');
1828
    if (bigbluebuttonbn_get_recording_data_preview_enabled($bbbsession)) {
1829
        $table->head[] = get_string('view_recording_preview', 'bigbluebuttonbn');
1830
    }
1831
    $table->head[] = get_string('view_recording_date', 'bigbluebuttonbn');
1832
    $table->head[] = get_string('view_recording_duration', 'bigbluebuttonbn');
1833
    $table->align = array('left', 'left', 'left', 'left', 'left', 'center');
1834
    $table->size = array('', '', '', '', '', '');
1835
    if ($bbbsession['managerecordings']) {
1836
        $table->head[] = get_string('view_recording_actionbar', 'bigbluebuttonbn');
1837
        $table->align[] = 'left';
1838
        $table->size[] = (count($tools) * 40) . 'px';
1839
    }
1840
    // Build table content.
1841
    foreach ($recordings as $recording) {
1842
        $rowdata = bigbluebuttonbn_get_recording_data_row($bbbsession, $recording, $tools);
1843
        if (!empty($rowdata)) {
1844
            $row = bigbluebuttonbn_get_recording_table_row($bbbsession, $recording, $rowdata);
1845
            array_push($table->data, $row);
1846
        }
1847
    }
1848
    return $table;
1849
}
1850
1851
/**
1852
 * Helper function builds the recording table row and insert into table.
1853
 *
1854
 * @param array $bbbsession
1855
 * @param array $recording
1856
 * @param object $rowdata
1857
 *
1858
 * @return object
1859
 */
1860
function bigbluebuttonbn_get_recording_table_row($bbbsession, $recording, $rowdata) {
1861
    $row = new html_table_row();
1862
    $row->id = 'recording-tr-'.$recording['recordID'];
1863
    $row->attributes['data-imported'] = 'false';
1864
    $texthead = '';
1865
    $texttail = '';
1866
    if (isset($recording['imported'])) {
1867
        $row->attributes['title'] = get_string('view_recording_link_warning', 'bigbluebuttonbn');
1868
        $row->attributes['data-imported'] = 'true';
1869
        $texthead = '<em>';
1870
        $texttail = '</em>';
1871
    }
1872
    $rowdata->date_formatted = str_replace(' ', '&nbsp;', $rowdata->date_formatted);
1873
    $row->cells = array();
1874
    $row->cells[] = $texthead . $rowdata->recording . $texttail;
1875
    $row->cells[] = $texthead . $rowdata->activity . $texttail;
1876
    $row->cells[] = $texthead . $rowdata->description . $texttail;
1877
    if (bigbluebuttonbn_get_recording_data_preview_enabled($bbbsession)) {
1878
        $row->cells[] = $rowdata->preview;
1879
    }
1880
    $row->cells[] = $texthead . $rowdata->date_formatted . $texttail;
1881
    $row->cells[] = $rowdata->duration_formatted;
1882
    if ($bbbsession['managerecordings']) {
1883
        $row->cells[] = $rowdata->actionbar;
1884
    }
1885
    return $row;
1886
}
1887
1888
/**
1889
 * Helper function evaluates if recording row should be included in the table.
1890
 *
1891
 * @param array $bbbsession
1892
 * @param array $recording
1893
 *
1894
 * @return boolean
1895
 */
1896
function bigbluebuttonbn_include_recording_table_row($bbbsession, $recording) {
1897
    // Exclude unpublished recordings, only if user has no rights to manage them.
1898
    if ($recording['published'] != 'true' && !$bbbsession['managerecordings']) {
1899
        return false;
1900
    }
1901
    // Imported recordings are always shown as long as they are published.
1902
    if (isset($recording['imported'])) {
1903
        return true;
1904
    }
1905
    // When groups are enabled, exclude those to which the user doesn't have access to.
1906
    if (isset($bbbsession['group']) && $recording['meetingID'] != $bbbsession['meetingid']) {
1907
        return false;
1908
    }
1909
    return true;
1910
}
1911
1912
/**
1913
 * Helper function triggers a send notification when the recording is ready.
1914
 *
1915
 * @param object $bigbluebuttonbn
1916
 *
1917
 * @return void
1918
 */
1919
function bigbluebuttonbn_send_notification_recording_ready($bigbluebuttonbn) {
1920
    $sender = get_admin();
1921
    // Prepare message.
1922
    $messagetext = '<p>'.get_string('email_body_recording_ready_for', 'bigbluebuttonbn').
1923
        ' "' . $bigbluebuttonbn->name . '" '.
1924
        get_string('email_body_recording_ready_is_ready', 'bigbluebuttonbn').'.</p>';
1925
    $context = context_course::instance($bigbluebuttonbn->course);
1926
    \mod_bigbluebuttonbn\locallib\notifier::notification_send($context, $sender, $bigbluebuttonbn, $messagetext);
1927
}
1928
1929
/**
1930
 * Helper evaluates if the bigbluebutton server used belongs to blindsidenetworks domain.
1931
 *
1932
 * @return boolean
1933
 */
1934
function bigbluebuttonbn_is_bn_server() {
1935
    $parsedurl = parse_url(\mod_bigbluebuttonbn\locallib\config::get('server_url'));
1936
    if (!isset($parsedurl['host'])) {
1937
        return false;
1938
    }
1939
    $h = $parsedurl['host'];
1940
    $hends = explode('.', $h);
1941
    $hendslength = count($hends);
1942
    return ($hends[$hendslength - 1] == 'com' && $hends[$hendslength - 2] == 'blindsidenetworks');
1943
}
1944
1945
/**
1946
 * Helper function returns a list of courses a user has access to, wrapped in an array that can be used
1947
 * by a html select.
1948
 *
1949
 * @param array $bbbsession
1950
 *
1951
 * @return array
1952
 */
1953
function bigbluebuttonbn_import_get_courses_for_select(array $bbbsession) {
1954
    if ($bbbsession['administrator']) {
1955
        $courses = get_courses('all', 'c.fullname ASC');
1956
        // It includes the name of the site as a course (category 0), so remove the first one.
1957
        unset($courses['1']);
1958
    } else {
1959
        $courses = enrol_get_users_courses($bbbsession['userID'], false, 'id,shortname,fullname');
1960
    }
1961
    $coursesforselect = [];
1962
    foreach ($courses as $course) {
1963
        $coursesforselect[$course->id] = $course->fullname;
1964
    }
1965
    return $coursesforselect;
1966
}
1967
1968
/**
1969
 * Helper function renders recording table.
1970
 *
1971
 * @param array $bbbsession
1972
 * @param array $recordings
1973
 * @param array $tools
1974
 *
1975
 * @return array
1976
 */
1977
function bigbluebuttonbn_output_recording_table($bbbsession, $recordings, $tools = ['protect', 'publish', 'delete']) {
1978
    if (isset($recordings) && !empty($recordings)) {
1979
        // There are recordings for this meeting.
1980
        $table = bigbluebuttonbn_get_recording_table($bbbsession, $recordings, $tools);
1981
    }
1982
    if (!isset($table) || !isset($table->data)) {
1983
        // Render a table with "No recordings".
1984
        return html_writer::div(get_string('view_message_norecordings', 'bigbluebuttonbn'), '',
1985
            array('id' => 'bigbluebuttonbn_recordings_table'));
1986
    }
1987
    // Render the table.
1988
    return html_writer::div(html_writer::table($table), '', array('id' => 'bigbluebuttonbn_recordings_table'));
1989
}
1990
1991
/**
1992
 * Helper function to convert an html string to plain text.
1993
 *
1994
 * @param string $html
1995
 * @param integer $len
1996
 *
1997
 * @return string
1998
 */
1999
function bigbluebuttonbn_html2text($html, $len = 0) {
2000
    $text = strip_tags($html);
2001
    $text = str_replace('&nbsp;', ' ', $text);
2002
    $textlen = strlen($text);
2003
    $text = substr($text, 0, $len);
2004
    if ($textlen > $len) {
2005
        $text .= '...';
2006
    }
2007
    return $text;
2008
}
2009
2010
/**
2011
 * Helper function to obtain the tags linked to a bigbluebuttonbn activity
2012
 *
2013
 * @param string $id
2014
 *
2015
 * @return string containing the tags separated by commas
2016
 */
2017
function bigbluebuttonbn_get_tags($id) {
2018
    if (class_exists('core_tag_tag')) {
2019
        return implode(',', core_tag_tag::get_item_tags_array('core', 'course_modules', $id));
2020
    }
2021
    return implode(',', tag_get_tags('bigbluebuttonbn', $id));
2022
}
2023
2024
/**
2025
 * Helper function to define the sql used for gattering the bigbluebuttonbnids whose meetingids should be included
2026
 * in the getRecordings request
2027
 *
2028
 * @param string $courseid
2029
 * @param string $bigbluebuttonbnid
2030
 * @param bool   $subset
2031
 *
2032
 * @return string containing the sql used for getting the target bigbluebuttonbn instances
2033
 */
2034
function bigbluebuttonbn_get_recordings_sql_select($courseid, $bigbluebuttonbnid = null, $subset = true) {
2035
    if (empty($courseid)) {
2036
        $courseid = 0;
2037
    }
2038
    if (empty($bigbluebuttonbnid)) {
2039
        return "course = '{$courseid}'";
2040
    }
2041
    if ($subset) {
2042
        return "id = '{$bigbluebuttonbnid}'";
2043
    }
2044
    return "id <> '{$bigbluebuttonbnid}' AND course = '{$courseid}'";
2045
}
2046
2047
/**
2048
 * Helper function to define the sql used for gattering the bigbluebuttonbnids whose meetingids should be included
2049
 * in the getRecordings request considering only those that belong to deleted activities.
2050
 *
2051
 * @param string $courseid
2052
 * @param string $bigbluebuttonbnid
2053
 * @param bool   $subset
2054
 *
2055
 * @return string containing the sql used for getting the target bigbluebuttonbn instances
2056
 */
2057 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...
2058
    $sql = "log = '" . BIGBLUEBUTTONBN_LOG_EVENT_DELETE . "' AND meta like '%has_recordings%' AND meta like '%true%'";
2059
    if (empty($courseid)) {
2060
        $courseid = 0;
2061
    }
2062
    if (empty($bigbluebuttonbnid)) {
2063
        return $sql . " AND courseid = {$courseid}";
2064
    }
2065
    if ($subset) {
2066
        return $sql . " AND bigbluebuttonbnid = '{$bigbluebuttonbnid}'";
2067
    }
2068
    return $sql . " AND courseid = {$courseid} AND bigbluebuttonbnid <> '{$bigbluebuttonbnid}'";
2069
}
2070
2071
/**
2072
 * Helper function to define the sql used for gattering the bigbluebuttonbnids whose meetingids should be included
2073
 * in the getRecordings request considering only those that belong to imported recordings.
2074
 *
2075
 * @param string $courseid
2076
 * @param string $bigbluebuttonbnid
2077
 * @param bool   $subset
2078
 *
2079
 * @return string containing the sql used for getting the target bigbluebuttonbn instances
2080
 */
2081 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...
2082
    $sql = "log = '" . BIGBLUEBUTTONBN_LOG_EVENT_IMPORT . "'";
2083
    if (empty($courseid)) {
2084
        $courseid = 0;
2085
    }
2086
    if (empty($bigbluebuttonbnid)) {
2087
        return $sql . " AND courseid = '{$courseid}'";
2088
    }
2089
    if ($subset) {
2090
        return $sql . " AND bigbluebuttonbnid = '{$bigbluebuttonbnid}'";
2091
    }
2092
    return $sql . " AND courseid = '{$courseid}' AND bigbluebuttonbnid <> '{$bigbluebuttonbnid}'";
2093
}
2094
2095
/**
2096
 * Helper function to get recordings  and imported recordings together.
2097
 *
2098
 * @param string $courseid
2099
 * @param string $bigbluebuttonbnid
2100
 * @param bool   $subset
2101
 * @param bool   $includedeleted
2102
 *
2103
 * @return associative array containing the recordings indexed by recordID, each recording is also a
2104
 * non sequential associative array itself that corresponds to the actual recording in BBB
2105
 */
2106
function bigbluebuttonbn_get_allrecordings($courseid = 0, $bigbluebuttonbnid = null, $subset = true, $includedeleted = false) {
2107
    $recordings = bigbluebuttonbn_get_recordings($courseid, $bigbluebuttonbnid, $subset, $includedeleted);
2108
    $recordingsimported = bigbluebuttonbn_get_recordings_imported_array($courseid, $bigbluebuttonbnid, $subset);
2109
    return ($recordings + $recordingsimported);
2110
}
2111
2112
/**
2113
 * Helper function to retrieve recordings from the BigBlueButton. The references are stored as events
2114
 * in bigbluebuttonbn_logs.
2115
 *
2116
 * @param string $courseid
2117
 * @param string $bigbluebuttonbnid
2118
 * @param bool   $subset
2119
 * @param bool   $includedeleted
2120
 *
2121
 * @return associative array containing the recordings indexed by recordID, each recording is also a
2122
 * non sequential associative array itself that corresponds to the actual recording in BBB
2123
 */
2124
function bigbluebuttonbn_get_recordings($courseid = 0, $bigbluebuttonbnid = null, $subset = true, $includedeleted = false) {
2125
    global $DB;
2126
    $select = bigbluebuttonbn_get_recordings_sql_select($courseid, $bigbluebuttonbnid, $subset);
2127
    $bigbluebuttonbns = $DB->get_records_select_menu('bigbluebuttonbn', $select, null, 'id', 'id, meetingid');
2128
    /* Consider logs from deleted bigbluebuttonbn instances whose meetingids should be included in
2129
     * the getRecordings request. */
2130
    if ($includedeleted) {
2131
        $selectdeleted = bigbluebuttonbn_get_recordings_deleted_sql_select($courseid, $bigbluebuttonbnid, $subset);
2132
        $bigbluebuttonbnsdel = $DB->get_records_select_menu('bigbluebuttonbn_logs', $selectdeleted, null,
2133
            'bigbluebuttonbnid', 'bigbluebuttonbnid, meetingid');
2134
        if (!empty($bigbluebuttonbnsdel)) {
2135
            // Merge bigbluebuttonbnis from deleted instances, only keys are relevant.
2136
            // Artimetic merge is used in order to keep the keys.
2137
            $bigbluebuttonbns += $bigbluebuttonbnsdel;
2138
        }
2139
    }
2140
    // Gather the meetingids from bigbluebuttonbn logs that include a create with record=true.
2141
    if (empty($bigbluebuttonbns)) {
2142
        return array();
2143
    }
2144
    // Prepare select for loading records based on existent bigbluebuttonbns.
2145
    $sql = 'SELECT DISTINCT meetingid, bigbluebuttonbnid FROM {bigbluebuttonbn_logs} WHERE ';
2146
    $sql .= '(bigbluebuttonbnid='.implode(' OR bigbluebuttonbnid=', array_keys($bigbluebuttonbns)).')';
2147
    // Include only Create events and exclude those with record not true.
2148
    $sql .= ' AND log = ? AND meta LIKE ? AND meta LIKE ?';
2149
    // Execute select for loading records based on existent bigbluebuttonbns.
2150
    $records = $DB->get_records_sql_menu($sql, array(BIGBLUEBUTTONBN_LOG_EVENT_CREATE, '%record%', '%true%'));
2151
    // Get actual recordings.
2152
    return bigbluebuttonbn_get_recordings_array(array_keys($records));
2153
}
2154
2155
/**
2156
 * Helper function iterates an array with recordings and unset those already imported.
2157
 *
2158
 * @param array $recordings
2159
 * @param integer $courseid
2160
 * @param integer $bigbluebuttonbnid
2161
 *
2162
 * @return array
2163
 */
2164
function bigbluebuttonbn_unset_existent_recordings_already_imported($recordings, $courseid, $bigbluebuttonbnid) {
2165
    $recordingsimported = bigbluebuttonbn_get_recordings_imported_array($courseid, $bigbluebuttonbnid, true);
2166
    foreach ($recordings as $key => $recording) {
2167
        if (isset($recordingsimported[$recording['recordID']])) {
2168
            unset($recordings[$key]);
2169
        }
2170
    }
2171
    return $recordings;
2172
}
2173
2174
/**
2175
 * Helper function to count the imported recordings for a recordingid.
2176
 *
2177
 * @param string $recordid
2178
 *
2179
 * @return integer
2180
 */
2181
function bigbluebuttonbn_count_recording_imported_instances($recordid) {
2182
    global $DB;
2183
    $sql = 'SELECT COUNT(DISTINCT id) FROM {bigbluebuttonbn_logs} WHERE log = ? AND meta LIKE ? AND meta LIKE ?';
2184
    return $DB->count_records_sql($sql, array(BIGBLUEBUTTONBN_LOG_EVENT_IMPORT, '%recordID%', "%{$recordid}%"));
2185
}
2186
2187
/**
2188
 * Helper function to get how much callback events are logged.
2189
 *
2190
 * @param string $recordid
2191
 *
2192
 * @return integer
2193
 */
2194
function bigbluebuttonbn_get_count_callback_event_log($recordid) {
2195
    global $DB;
2196
    $sql = 'SELECT count(DISTINCT id) FROM {bigbluebuttonbn_logs} WHERE log = ? AND meta LIKE ? AND meta LIKE ?';
2197
    return $DB->count_records_sql($sql, array(BIGBLUEBUTTON_LOG_EVENT_CALLBACK, '%recordid%', "%{$recordid}%"));
2198
}
2199
2200
/**
2201
 * Helper function returns an array with all the instances of imported recordings for a recordingid.
2202
 *
2203
 * @param string $recordid
2204
 *
2205
 * @return array
2206
 */
2207
function bigbluebuttonbn_get_recording_imported_instances($recordid) {
2208
    global $DB;
2209
    $sql = 'SELECT * FROM {bigbluebuttonbn_logs} WHERE log = ? AND meta LIKE ? AND meta LIKE ?';
2210
    $recordingsimported = $DB->get_records_sql($sql, array(BIGBLUEBUTTONBN_LOG_EVENT_IMPORT, '%recordID%',
2211
        "%{$recordid}%"));
2212
    return $recordingsimported;
2213
}
2214
2215
/**
2216
 * Helper function returns an array with the profiles (with features per profile) for the different types
2217
 * of bigbluebuttonbn instances.
2218
 *
2219
 * @return array
2220
 */
2221
function bigbluebuttonbn_get_instance_type_profiles() {
2222
    $instanceprofiles = array(
2223
            array('id' => BIGBLUEBUTTONBN_TYPE_ALL, 'name' => get_string('instance_type_default', 'bigbluebuttonbn'),
2224
                'features' => array('all')),
2225
            array('id' => BIGBLUEBUTTONBN_TYPE_ROOM_ONLY, 'name' => get_string('instance_type_room_only', 'bigbluebuttonbn'),
2226
                'features' => array('showroom', 'welcomemessage', 'voicebridge', 'waitformoderator', 'userlimit', 'recording',
2227
                    'sendnotifications', 'preuploadpresentation', 'permissions', 'schedule', 'groups',
2228
                    'modstandardelshdr', 'availabilityconditionsheader', 'tagshdr', 'competenciessection', 'clienttype')),
2229
            array('id' => BIGBLUEBUTTONBN_TYPE_RECORDING_ONLY, 'name' => get_string('instance_type_recording_only',
2230
                'bigbluebuttonbn'), 'features' => array('showrecordings', 'importrecordings')),
2231
    );
2232
    return $instanceprofiles;
2233
}
2234
2235
/**
2236
 * Helper function returns an array with enabled features for an specific profile type.
2237
 *
2238
 * @param array $typeprofiles
2239
 * @param string $type
2240
 *
2241
 * @return array
2242
 */
2243
function bigbluebuttonbn_get_enabled_features($typeprofiles, $type = null) {
2244
    $enabledfeatures = array();
2245
    $features = $typeprofiles[0]['features'];
2246
    if (!is_null($type)) {
2247
        $features = $typeprofiles[$type]['features'];
2248
    }
2249
    $enabledfeatures['showroom'] = (in_array('all', $features) || in_array('showroom', $features));
2250
    // Evaluates if recordings are enabled for the Moodle site.
2251
    $enabledfeatures['showrecordings'] = false;
2252
    if (\mod_bigbluebuttonbn\locallib\config::recordings_enabled()) {
2253
        $enabledfeatures['showrecordings'] = (in_array('all', $features) || in_array('showrecordings', $features));
2254
    }
2255
    $enabledfeatures['importrecordings'] = false;
2256
    if (\mod_bigbluebuttonbn\locallib\config::importrecordings_enabled()) {
2257
        $enabledfeatures['importrecordings'] = (in_array('all', $features) || in_array('importrecordings', $features));
2258
    }
2259
    // Evaluates if clienttype is enabled for the Moodle site.
2260
    $enabledfeatures['clienttype'] = false;
2261
    if (\mod_bigbluebuttonbn\locallib\config::clienttype_enabled()) {
2262
        $enabledfeatures['clienttype'] = (in_array('all', $features) || in_array('clienttype', $features));
2263
    }
2264
    return $enabledfeatures;
2265
}
2266
2267
/**
2268
 * Helper function returns an array with the profiles (with features per profile) for the different types
2269
 * of bigbluebuttonbn instances.
2270
 *
2271
 * @param array $profiles
2272
 *
2273
 * @return array
2274
 */
2275
function bigbluebuttonbn_get_instance_profiles_array($profiles = null) {
2276
    if (is_null($profiles) || empty($profiles)) {
2277
        $profiles = bigbluebuttonbn_get_instance_type_profiles();
2278
    }
2279
    $profilesarray = array();
2280
    foreach ($profiles as $profile) {
2281
        $profilesarray += array("{$profile['id']}" => $profile['name']);
2282
    }
2283
    return $profilesarray;
2284
}
2285
2286
/**
2287
 * Helper function returns time in a formatted string.
2288
 *
2289
 * @param integer $time
2290
 *
2291
 * @return string
2292
 */
2293
function bigbluebuttonbn_format_activity_time($time) {
2294
    $activitytime = '';
2295
    if ($time) {
2296
        $activitytime = calendar_day_representation($time).' '.
2297
          get_string('mod_form_field_notification_msg_at', 'bigbluebuttonbn').' '.
2298
          calendar_time_representation($time);
2299
    }
2300
    return $activitytime;
2301
}
2302
2303
/**
2304
 * Helper function returns array with all the strings to be used in javascript.
2305
 *
2306
 * @return array
2307
 */
2308
function bigbluebuttonbn_get_strings_for_js() {
2309
    $locale = bigbluebuttonbn_get_locale();
2310
    $stringman = get_string_manager();
2311
    $strings = $stringman->load_component_strings('bigbluebuttonbn', $locale);
2312
    return $strings;
2313
}
2314
2315
/**
2316
 * Helper function returns the locale set by moodle.
2317
 *
2318
 * @return string
2319
 */
2320
function bigbluebuttonbn_get_locale() {
2321
    $lang = get_string('locale', 'core_langconfig');
2322
    return substr($lang, 0, strpos($lang, '.'));
2323
}
2324
2325
/**
2326
 * Helper function returns the locale code based on the locale set by moodle.
2327
 *
2328
 * @return string
2329
 */
2330
function bigbluebuttonbn_get_localcode() {
2331
    $locale = bigbluebuttonbn_get_locale();
2332
    return substr($locale, 0, strpos($locale, '_'));
2333
}
2334
2335
/**
2336
 * Helper function returns array with the instance settings used in views.
2337
 *
2338
 * @param string $id
2339
 * @param object $bigbluebuttonbnid
2340
 *
2341
 * @return array
2342
 */
2343
function bigbluebuttonbn_views_validator($id, $bigbluebuttonbnid) {
2344
    if ($id) {
2345
        return bigbluebuttonbn_views_instance_id($id);
2346
    }
2347
    if ($bigbluebuttonbnid) {
2348
        return bigbluebuttonbn_views_instance_bigbluebuttonbn($bigbluebuttonbnid);
2349
    }
2350
    return;
2351
}
2352
2353
/**
2354
 * Helper function returns array with the instance settings used in views based on id.
2355
 *
2356
 * @param string $id
2357
 *
2358
 * @return array
2359
 */
2360 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...
2361
    global $DB;
2362
    $cm = get_coursemodule_from_id('bigbluebuttonbn', $id, 0, false, MUST_EXIST);
2363
    $course = $DB->get_record('course', array('id' => $cm->course), '*', MUST_EXIST);
2364
    $bigbluebuttonbn = $DB->get_record('bigbluebuttonbn', array('id' => $cm->instance), '*', MUST_EXIST);
2365
    return array('cm' => $cm, 'course' => $course, 'bigbluebuttonbn' => $bigbluebuttonbn);
2366
}
2367
2368
/**
2369
 * Helper function returns array with the instance settings used in views based on bigbluebuttonbnid.
2370
 *
2371
 * @param object $bigbluebuttonbnid
2372
 *
2373
 * @return array
2374
 */
2375 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...
2376
    global $DB;
2377
    $bigbluebuttonbn = $DB->get_record('bigbluebuttonbn', array('id' => $bigbluebuttonbnid), '*', MUST_EXIST);
2378
    $course = $DB->get_record('course', array('id' => $bigbluebuttonbn->course), '*', MUST_EXIST);
2379
    $cm = get_coursemodule_from_instance('bigbluebuttonbn', $bigbluebuttonbn->id, $course->id, false, MUST_EXIST);
2380
    return array('cm' => $cm, 'course' => $course, 'bigbluebuttonbn' => $bigbluebuttonbn);
2381
}
2382
2383
/**
2384
 * Helper function renders general warning message for settings (if any).
2385
 *
2386
 * @param object $renderer
2387
 *
2388
 * @return void
2389
 */
2390
function bigbluebuttonbn_settings_general_warning(&$renderer) {
2391
    global $BIGBLUEBUTTONBN_CFG;
2392
    if (isset($BIGBLUEBUTTONBN_CFG)) {
2393
        $renderer->render_warning_message('general_warning',
2394
             get_string('config_warning_bigbluebuttonbn_cfg_deprecated', 'bigbluebuttonbn'));
2395
    }
2396
}
2397
2398
/**
2399
 * Helper function renders general settings if the feature is enabled.
2400
 *
2401
 * @param object $renderer
2402
 *
2403
 * @return void
2404
 */
2405
function bigbluebuttonbn_settings_general(&$renderer) {
2406
    // Configuration for BigBlueButton.
2407
    if ((boolean)\mod_bigbluebuttonbn\settings\renderer::section_general_shown()) {
2408
        $renderer->render_group_header('general');
2409
        $renderer->render_group_element('server_url',
2410
            $renderer->render_group_element_text('server_url', BIGBLUEBUTTONBN_DEFAULT_SERVER_URL));
2411
        $renderer->render_group_element('shared_secret',
2412
            $renderer->render_group_element_text('shared_secret', BIGBLUEBUTTONBN_DEFAULT_SHARED_SECRET));
2413
    }
2414
}
2415
2416
/**
2417
 * Helper function renders record settings if the feature is enabled.
2418
 *
2419
 * @param object $renderer
2420
 *
2421
 * @return void
2422
 */
2423
function bigbluebuttonbn_settings_record(&$renderer) {
2424
    // Configuration for 'recording' feature.
2425 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...
2426
        $renderer->render_group_header('recording');
2427
        $renderer->render_group_element('recording_default',
2428
            $renderer->render_group_element_checkbox('recording_default', 1));
2429
        $renderer->render_group_element('recording_editable',
2430
            $renderer->render_group_element_checkbox('recording_editable', 1));
2431
        $renderer->render_group_element('recording_icons_enabled',
2432
            $renderer->render_group_element_checkbox('recording_icons_enabled', 1));
2433
    }
2434
}
2435
2436
/**
2437
 * Helper function renders import recording settings if the feature is enabled.
2438
 *
2439
 * @param object $renderer
2440
 *
2441
 * @return void
2442
 */
2443 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...
2444
    // Configuration for 'import recordings' feature.
2445
    if ((boolean)\mod_bigbluebuttonbn\settings\renderer::section_import_recordings_shown()) {
2446
        $renderer->render_group_header('importrecordings');
2447
        $renderer->render_group_element('importrecordings_enabled',
2448
            $renderer->render_group_element_checkbox('importrecordings_enabled', 0));
2449
        $renderer->render_group_element('importrecordings_from_deleted_enabled',
2450
            $renderer->render_group_element_checkbox('importrecordings_from_deleted_enabled', 0));
2451
    }
2452
}
2453
2454
/**
2455
 * Helper function renders show recording settings if the feature is enabled.
2456
 *
2457
 * @param object $renderer
2458
 *
2459
 * @return void
2460
 */
2461
function bigbluebuttonbn_settings_showrecordings(&$renderer) {
2462
    // Configuration for 'show recordings' feature.
2463
    if ((boolean)\mod_bigbluebuttonbn\settings\renderer::section_show_recordings_shown()) {
2464
        $renderer->render_group_header('recordings');
2465
        $renderer->render_group_element('recordings_html_default',
2466
            $renderer->render_group_element_checkbox('recordings_html_default', 1));
2467
        $renderer->render_group_element('recordings_html_editable',
2468
            $renderer->render_group_element_checkbox('recordings_html_editable', 0));
2469
        $renderer->render_group_element('recordings_deleted_default',
2470
            $renderer->render_group_element_checkbox('recordings_deleted_default', 1));
2471
        $renderer->render_group_element('recordings_deleted_editable',
2472
            $renderer->render_group_element_checkbox('recordings_deleted_editable', 0));
2473
        $renderer->render_group_element('recordings_imported_default',
2474
            $renderer->render_group_element_checkbox('recordings_imported_default', 0));
2475
        $renderer->render_group_element('recordings_imported_editable',
2476
            $renderer->render_group_element_checkbox('recordings_imported_editable', 1));
2477
        $renderer->render_group_element('recordings_preview_default',
2478
            $renderer->render_group_element_checkbox('recordings_preview_default', 1));
2479
        $renderer->render_group_element('recordings_preview_editable',
2480
            $renderer->render_group_element_checkbox('recordings_preview_editable', 0));
2481
    }
2482
}
2483
2484
/**
2485
 * Helper function renders wait for moderator settings if the feature is enabled.
2486
 *
2487
 * @param object $renderer
2488
 *
2489
 * @return void
2490
 */
2491
function bigbluebuttonbn_settings_waitmoderator(&$renderer) {
2492
    // Configuration for wait for moderator feature.
2493
    if ((boolean)\mod_bigbluebuttonbn\settings\renderer::section_wait_moderator_shown()) {
2494
        $renderer->render_group_header('waitformoderator');
2495
        $renderer->render_group_element('waitformoderator_default',
2496
            $renderer->render_group_element_checkbox('waitformoderator_default', 0));
2497
        $renderer->render_group_element('waitformoderator_editable',
2498
            $renderer->render_group_element_checkbox('waitformoderator_editable', 1));
2499
        $renderer->render_group_element('waitformoderator_ping_interval',
2500
            $renderer->render_group_element_text('waitformoderator_ping_interval', 10, PARAM_INT));
2501
        $renderer->render_group_element('waitformoderator_cache_ttl',
2502
            $renderer->render_group_element_text('waitformoderator_cache_ttl', 60, PARAM_INT));
2503
    }
2504
}
2505
2506
/**
2507
 * Helper function renders static voice bridge settings if the feature is enabled.
2508
 *
2509
 * @param object $renderer
2510
 *
2511
 * @return void
2512
 */
2513
function bigbluebuttonbn_settings_voicebridge(&$renderer) {
2514
    // Configuration for "static voice bridge" feature.
2515
    if ((boolean)\mod_bigbluebuttonbn\settings\renderer::section_static_voice_bridge_shown()) {
2516
        $renderer->render_group_header('voicebridge');
2517
        $renderer->render_group_element('voicebridge_editable',
2518
            $renderer->render_group_element_checkbox('voicebridge_editable', 0));
2519
    }
2520
}
2521
2522
/**
2523
 * Helper function renders preuploaded presentation settings if the feature is enabled.
2524
 *
2525
 * @param object $renderer
2526
 *
2527
 * @return void
2528
 */
2529
function bigbluebuttonbn_settings_preupload(&$renderer) {
2530
    // Configuration for "preupload presentation" feature.
2531
    if ((boolean)\mod_bigbluebuttonbn\settings\renderer::section_preupload_presentation_shown()) {
2532
        // This feature only works if curl is installed.
2533
        $preuploaddescripion = get_string('config_preuploadpresentation_description', 'bigbluebuttonbn');
2534
        if (!extension_loaded('curl')) {
2535
            $preuploaddescripion .= '<div class="form-defaultinfo">';
2536
            $preuploaddescripion .= get_string('config_warning_curl_not_installed', 'bigbluebuttonbn');
2537
            $preuploaddescripion .= '</div><br>';
2538
        }
2539
        $renderer->render_group_header('preuploadpresentation', null, $preuploaddescripion);
2540
        if (extension_loaded('curl')) {
2541
            $renderer->render_group_element('preuploadpresentation_enabled',
2542
                $renderer->render_group_element_checkbox('preuploadpresentation_enabled', 0));
2543
        }
2544
    }
2545
}
2546
2547
/**
2548
 * Helper function renders userlimit settings if the feature is enabled.
2549
 *
2550
 * @param object $renderer
2551
 *
2552
 * @return void
2553
 */
2554
function bigbluebuttonbn_settings_userlimit(&$renderer) {
2555
    // Configuration for "user limit" feature.
2556
    if ((boolean)\mod_bigbluebuttonbn\settings\renderer::section_user_limit_shown()) {
2557
        $renderer->render_group_header('userlimit');
2558
        $renderer->render_group_element('userlimit_default',
2559
            $renderer->render_group_element_text('userlimit_default', 0, PARAM_INT));
2560
        $renderer->render_group_element('userlimit_editable',
2561
            $renderer->render_group_element_checkbox('userlimit_editable', 0));
2562
    }
2563
}
2564
2565
/**
2566
 * Helper function renders duration settings if the feature is enabled.
2567
 *
2568
 * @param object $renderer
2569
 *
2570
 * @return void
2571
 */
2572
function bigbluebuttonbn_settings_duration(&$renderer) {
2573
    // Configuration for "scheduled duration" feature.
2574 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...
2575
        $renderer->render_group_header('scheduled');
2576
        $renderer->render_group_element('scheduled_duration_enabled',
2577
            $renderer->render_group_element_checkbox('scheduled_duration_enabled', 1));
2578
        $renderer->render_group_element('scheduled_duration_compensation',
2579
            $renderer->render_group_element_text('scheduled_duration_compensation', 10, PARAM_INT));
2580
        $renderer->render_group_element('scheduled_pre_opening',
2581
            $renderer->render_group_element_text('scheduled_pre_opening', 10, PARAM_INT));
2582
    }
2583
}
2584
2585
/**
2586
 * Helper function renders participant settings if the feature is enabled.
2587
 *
2588
 * @param object $renderer
2589
 *
2590
 * @return void
2591
 */
2592
function bigbluebuttonbn_settings_participants(&$renderer) {
2593
    // Configuration for defining the default role/user that will be moderator on new activities.
2594
    if ((boolean)\mod_bigbluebuttonbn\settings\renderer::section_moderator_default_shown()) {
2595
        $renderer->render_group_header('participant');
2596
        // UI for 'participants' feature.
2597
        $roles = bigbluebuttonbn_get_roles();
2598
        $owner = array('0' => get_string('mod_form_field_participant_list_type_owner', 'bigbluebuttonbn'));
2599
        $renderer->render_group_element('participant_moderator_default',
2600
            $renderer->render_group_element_configmultiselect('participant_moderator_default',
2601
                array_keys($owner), array_merge($owner, $roles))
2602
          );
2603
    }
2604
}
2605
2606
/**
2607
 * Helper function renders notification settings if the feature is enabled.
2608
 *
2609
 * @param object $renderer
2610
 *
2611
 * @return void
2612
 */
2613
function bigbluebuttonbn_settings_notifications(&$renderer) {
2614
    // Configuration for "send notifications" feature.
2615
    if ((boolean)\mod_bigbluebuttonbn\settings\renderer::section_send_notifications_shown()) {
2616
        $renderer->render_group_header('sendnotifications');
2617
        $renderer->render_group_element('sendnotifications_enabled',
2618
            $renderer->render_group_element_checkbox('sendnotifications_enabled', 1));
2619
    }
2620
}
2621
2622
/**
2623
 * Helper function renders client type settings if the feature is enabled.
2624
 *
2625
 * @param object $renderer
2626
 *
2627
 * @return void
2628
 */
2629
function bigbluebuttonbn_settings_clienttype(&$renderer) {
2630
    // Configuration for "clienttype" feature.
2631
    if ((boolean)\mod_bigbluebuttonbn\settings\renderer::section_clienttype_shown()) {
2632
        $renderer->render_group_header('clienttype');
2633
        $renderer->render_group_element('clienttype_editable',
2634
            $renderer->render_group_element_checkbox('clienttype_editable', 0));
2635
2636
        // Web Client default.
2637
        $default = intval((int)\mod_bigbluebuttonbn\locallib\config::get('clienttype_default'));
2638
2639
        $choices = array(BIGBLUEBUTTON_CLIENTTYPE_FLASH => get_string('mod_form_block_clienttype_flash', 'bigbluebuttonbn'),
2640
                         BIGBLUEBUTTON_CLIENTTYPE_HTML5 => get_string('mod_form_block_clienttype_html5', 'bigbluebuttonbn'));
2641
        $renderer->render_group_element('clienttype_default',
2642
            $renderer->render_group_element_configselect('clienttype_default',
2643
                $default, $choices));
2644
    }
2645
}
2646
2647
/**
2648
 * Helper function renders extended settings if any of the features there is enabled.
2649
 *
2650
 * @param object $renderer
2651
 *
2652
 * @return void
2653
 */
2654 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...
2655
    // Configuration for extended BN capabilities.
2656
    if (!bigbluebuttonbn_is_bn_server()) {
2657
        return;
2658
    }
2659
    // Configuration for 'notify users when recording ready' feature.
2660
    if ((boolean)\mod_bigbluebuttonbn\settings\renderer::section_settings_extended_shown()) {
2661
        $renderer->render_group_header('extended_capabilities');
2662
        // UI for 'notify users when recording ready' feature.
2663
        $renderer->render_group_element('recordingready_enabled',
2664
            $renderer->render_group_element_checkbox('recordingready_enabled', 0));
2665
        // UI for 'register meeting events' feature.
2666
        $renderer->render_group_element('meetingevents_enabled',
2667
            $renderer->render_group_element_checkbox('meetingevents_enabled', 0));
2668
    }
2669
}
2670
2671
/**
2672
 * Helper function returns a sha1 encoded string that is unique and will be used as a seed for meetingid.
2673
 *
2674
 * @return string
2675
 */
2676
function bigbluebuttonbn_unique_meetingid_seed() {
2677
    global $DB;
2678
    do {
2679
        $encodedseed = sha1(bigbluebuttonbn_random_password(12));
2680
        $meetingid = (string)$DB->get_field('bigbluebuttonbn', 'meetingid', array('meetingid' => $encodedseed));
2681
    } while ($meetingid == $encodedseed);
2682
    return $encodedseed;
2683
}
2684
2685
/**
2686
 * Helper function renders the link used for recording type in row for the data used by the recording table.
2687
 *
2688
 * @param array $recording
2689
 * @param array $bbbsession
2690
 * @param array $playback
2691
 *
2692
 * @return boolean
2693
 */
2694
function bigbluebuttonbn_include_recording_data_row_type($recording, $bbbsession, $playback) {
2695
    // All types that are not restricted are included.
2696
    if (array_key_exists('restricted', $playback) && strtolower($playback['restricted']) == 'false') {
2697
        return true;
2698
    }
2699
    // All types that are not statistics are included.
2700
    if ($playback['type'] != 'statistics') {
2701
        return true;
2702
    }
2703
    // Exclude imported recordings.
2704
    if (isset($recording['imported'])) {
2705
        return false;
2706
    }
2707
    // Exclude non moderators.
2708
    if (!$bbbsession['administrator'] && !$bbbsession['moderator']) {
2709
        return false;
2710
    }
2711
    return true;
2712
}
2713
2714
/**
2715
 * Renders the general warning message.
2716
 *
2717
 * @param string $message
2718
 * @param string $type
2719
 * @param string $href
2720
 * @param string $text
2721
 * @param string $class
2722
 *
2723
 * @return string
2724
 */
2725
function bigbluebuttonbn_render_warning($message, $type='info', $href='', $text='', $class='') {
2726
    global $OUTPUT;
2727
    $output = "\n";
2728
    // Evaluates if config_warning is enabled.
2729
    if (empty($message)) {
2730
        return $output;
2731
    }
2732
    $output .= $OUTPUT->box_start('box boxalignleft adminerror alert alert-' . $type . ' alert-block fade in',
2733
      'bigbluebuttonbn_view_general_warning') . "\n";
2734
    $output .= '    ' . $message . "\n";
2735
    $output .= '  <div class="singlebutton pull-right">' . "\n";
2736
    if (!empty($href)) {
2737
        $output .= bigbluebuttonbn_render_warning_button($href, $text, $class);
2738
    }
2739
    $output .= '  </div>' . "\n";
2740
    $output .= $OUTPUT->box_end() . "\n";
2741
    return $output;
2742
}
2743
2744
/**
2745
 * Renders the general warning button.
2746
 *
2747
 * @param string $href
2748
 * @param string $text
2749
 * @param string $class
2750
 * @param string $title
2751
 *
2752
 * @return string
2753
 */
2754
function bigbluebuttonbn_render_warning_button($href, $text = '', $class = '', $title = '') {
2755
    if ($text == '') {
2756
        $text = get_string('ok', 'moodle');
2757
    }
2758
    if ($title == '') {
2759
        $title = $text;
2760
    }
2761
    if ($class == '') {
2762
        $class = 'btn btn-secondary';
2763
    }
2764
    $output  = '  <form method="post" action="' . $href . '" class="form-inline">'."\n";
2765
    $output .= '      <button type="submit" class="' . $class . '"'."\n";
2766
    $output .= '          title="' . $title . '"'."\n";
2767
    $output .= '          >' . $text . '</button>'."\n";
2768
    $output .= '  </form>'."\n";
2769
    return $output;
2770
}
2771
2772
/**
2773
 * Check if a BigBlueButtonBN is available to be used by the current user.
2774
 *
2775
 * @param  stdClass  $bigbluebuttonbn  BigBlueButtonBN instance
2776
 *
2777
 * @return boolean                     status if room available and current user allowed to join
2778
 */
2779
function bigbluebuttonbn_get_availability_status($bigbluebuttonbn) {
2780
    list($roomavailable) = bigbluebuttonbn_room_is_available($bigbluebuttonbn);
2781
    list($usercanjoin) = bigbluebuttonbn_user_can_join_meeting($bigbluebuttonbn);
2782
2783
    return ($roomavailable && $usercanjoin);
2784
}
2785
2786
/**
2787
 * Helper for evaluating if scheduled activity is avaiable.
2788
 *
2789
 * @param  stdClass  $bigbluebuttonbn  BigBlueButtonBN instance
2790
 *
2791
 * @return array                       status (room available or not and possible warnings)
2792
 */
2793
function bigbluebuttonbn_room_is_available($bigbluebuttonbn) {
2794
    $open = true;
2795
    $closed = false;
2796
    $warnings = array();
2797
2798
    $timenow = time();
2799
    $timeopen = $bigbluebuttonbn->openingtime;
2800
    $timeclose = $bigbluebuttonbn->closingtime;
2801
    if (!empty($timeopen) && $timeopen > $timenow) {
2802
        $open = false;
2803
    }
2804
    if (!empty($timeclose) && $timenow > $timeclose) {
2805
        $closed = true;
2806
    }
2807
2808
    if (!$open || $closed) {
2809
        if (!$open) {
2810
            $warnings['notopenyet'] = userdate($timeopen);
2811
        }
2812
        if ($closed) {
2813
            $warnings['expired'] = userdate($timeclose);
2814
        }
2815
        return array(false, $warnings);
2816
    }
2817
2818
    return array(true, $warnings);
2819
}
2820
2821
/**
2822
 * Helper for evaluating if meeting can be joined.
2823
 *
2824
 * @param  stdClass $bigbluebuttonbn  BigBlueButtonBN instance
2825
 * @param  string   $mid
2826
 * @param  integer  $userid
2827
 *
2828
 * @return array    status (user allowed to join or not and possible message)
2829
 */
2830
function bigbluebuttonbn_user_can_join_meeting($bigbluebuttonbn, $mid = null, $userid = null) {
2831
2832
    // By default, use a meetingid without groups.
2833
    if (empty($mid)) {
2834
        $mid = $bigbluebuttonbn->meetingid . '-' . $bigbluebuttonbn->course . '-' . $bigbluebuttonbn->id;
2835
    }
2836
2837
    // When meeting is running, all authorized users can join right in.
2838
    if (bigbluebuttonbn_is_meeting_running($mid)) {
2839
        return array(true, get_string('view_message_conference_in_progress', 'bigbluebuttonbn'));
2840
    }
2841
2842
    // When meeting is not running, see if the user can join.
2843
    $context = context_course::instance($bigbluebuttonbn->course);
2844
    $participantlist = bigbluebuttonbn_get_participant_list($bigbluebuttonbn, $context);
2845
    $isadmin = is_siteadmin($userid);
2846
    $ismoderator = bigbluebuttonbn_is_moderator($context, $participantlist, $userid);
2847
    // If user is administrator, moderator or if is viewer and no waiting is required, join allowed.
2848
    if ($isadmin || $ismoderator || !$bigbluebuttonbn->wait) {
2849
        return array(true, get_string('view_message_conference_room_ready', 'bigbluebuttonbn'));
2850
    }
2851
    // Otherwise, no join allowed.
2852
    return array(false, get_string('view_message_conference_wait_for_moderator', 'bigbluebuttonbn'));
2853
}
2854
2855
/**
2856
 * Helper for getting a value from a bigbluebuttonbn cache.
2857
 *
2858
 * @param  string   $name       BigBlueButtonBN cache
2859
 * @param  string   $key        Key to be retrieved
2860
 * @param  integer  $default    Default value in case key is not found or it is empty
2861
 *
2862
 * @return variable key value
2863
 */
2864
function bigbluebuttonbn_cache_get($name, $key, $default = null) {
2865
    $cache = cache::make_from_params(cache_store::MODE_APPLICATION, 'mod_bigbluebuttonbn', $name);
2866
    $result = $cache->get($key);
2867
    if (!empty($result)) {
2868
        return $result;
2869
    }
2870
    return $default;
2871
}
2872
2873
/**
2874
 * Helper for setting a value in a bigbluebuttonbn cache.
2875
 *
2876
 * @param  string   $name       BigBlueButtonBN cache
2877
 * @param  string   $key        Key to be created/updated
2878
 * @param  variable $value      Default value to be set
2879
 */
2880
function bigbluebuttonbn_cache_set($name, $key, $value) {
2881
    $cache = cache::make_from_params(cache_store::MODE_APPLICATION, 'mod_bigbluebuttonbn', $name);
2882
    $cache->set($key, $value);
2883
}
2884
2885
/**
2886
 * Helper for getting the owner userid of a bigbluebuttonbn instance.
2887
 *
2888
 * @param  stdClass $bigbluebuttonbn  BigBlueButtonBN instance
2889
 *
2890
 * @return integer ownerid (a valid user id or null if not registered/found)
2891
 */
2892
function bigbluebuttonbn_instance_ownerid($bigbluebuttonbn) {
2893
    global $DB;
2894
    $filters = array('bigbluebuttonbnid' => $bigbluebuttonbn->id, 'log' => 'Add');
2895
    $ownerid = (integer)$DB->get_field('bigbluebuttonbn_logs', 'userid', $filters);
2896
    return $ownerid;
2897
}
2898
2899
/**
2900
 * Helper evaluates if the bigbluebutton server used belongs to blindsidenetworks domain.
2901
 *
2902
 * @return boolean
2903
 */
2904
function bigbluebuttonbn_has_html5_client() {
2905
    $checkurl = \mod_bigbluebuttonbn\locallib\bigbluebutton::root() . "html5client/check";
2906
    $curlinfo = bigbluebuttonbn_wrap_xml_load_file_curl_request($checkurl, 'HEAD');
2907
    return (isset($curlinfo['http_code']) && $curlinfo['http_code'] == 200);
2908
}
2909