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

locallib.php ➔ bigbluebuttonbn_unique_meetingid_seed()   A

Complexity

Conditions 2
Paths 1

Size

Total Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
nc 1
nop 0
dl 0
loc 8
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) {
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
    return \mod_bigbluebuttonbn\locallib\bigbluebutton::action_url('join', $data);
114
}
115
116
/**
117
 * Creates a bigbluebutton meeting and returns the response in an array.
118
 *
119
 * @param array  $data
120
 * @param array  $metadata
121
 * @param string $pname
122
 * @param string $purl
123
 *
124
 * @return array
125
 */
126
function bigbluebuttonbn_get_create_meeting_array($data, $metadata = array(), $pname = null, $purl = null) {
127
    $createmeetingurl = \mod_bigbluebuttonbn\locallib\bigbluebutton::action_url('create', $data, $metadata);
128
    $method = 'GET';
129
    $data = null;
130
    if (!is_null($pname) && !is_null($purl)) {
131
        $method = 'POST';
132
        $data = "<?xml version='1.0' encoding='UTF-8'?><modules><module name='presentation'><document url='".
133
            $purl."' /></module></modules>";
134
    }
135
    $xml = bigbluebuttonbn_wrap_xml_load_file($createmeetingurl, $method, $data);
136
    if ($xml) {
137
        $response = array('returncode' => $xml->returncode, 'message' => $xml->message, 'messageKey' => $xml->messageKey);
138
        if ($xml->meetingID) {
139
            $response += array('meetingID' => $xml->meetingID, 'attendeePW' => $xml->attendeePW,
140
                'moderatorPW' => $xml->moderatorPW, 'hasBeenForciblyEnded' => $xml->hasBeenForciblyEnded);
141
        }
142
        return $response;
143
    }
144
    return array('returncode' => 'FAILED', 'message' => 'unreachable', 'messageKey' => 'Server is unreachable');
145
}
146
147
/**
148
 * Fetch meeting info and wrap response in array.
149
 *
150
 * @param string $meetingid
151
 *
152
 * @return array
153
 */
154
function bigbluebuttonbn_get_meeting_info_array($meetingid) {
155
    $xml = bigbluebuttonbn_wrap_xml_load_file(
156
        \mod_bigbluebuttonbn\locallib\bigbluebutton::action_url('getMeetingInfo', ['meetingID' => $meetingid])
157
      );
158
    if ($xml && $xml->returncode == 'SUCCESS' && empty($xml->messageKey)) {
159
        // Meeting info was returned.
160
        return array('returncode' => $xml->returncode,
161
                     'meetingID' => $xml->meetingID,
162
                     'moderatorPW' => $xml->moderatorPW,
163
                     'attendeePW' => $xml->attendeePW,
164
                     'hasBeenForciblyEnded' => $xml->hasBeenForciblyEnded,
165
                     'running' => $xml->running,
166
                     'recording' => $xml->recording,
167
                     'startTime' => $xml->startTime,
168
                     'endTime' => $xml->endTime,
169
                     'participantCount' => $xml->participantCount,
170
                     'moderatorCount' => $xml->moderatorCount,
171
                     'attendees' => $xml->attendees,
172
                     'metadata' => $xml->metadata,
173
                   );
174
    }
175
    if ($xml) {
176
        // Either failure or success without meeting info.
177
        return (array)$xml;
178
    }
179
    // If the server is unreachable, then prompts the user of the necessary action.
180
    return array('returncode' => 'FAILED', 'message' => 'unreachable', 'messageKey' => 'Server is unreachable');
181
}
182
183
/**
184
 * Helper function to retrieve recordings from a BigBlueButton server.
185
 *
186
 * @param string|array $meetingids   list of meetingIDs "mid1,mid2,mid3" or array("mid1","mid2","mid3")
187
 * @param string|array $recordingids list of $recordingids "rid1,rid2,rid3" or array("rid1","rid2","rid3") for filtering
188
 *
189
 * @return associative array with recordings indexed by recordID, each recording is a non sequential associative array
190
 */
191
function bigbluebuttonbn_get_recordings_array($meetingids, $recordingids = []) {
192
    $meetingidsarray = $meetingids;
193
    if (!is_array($meetingids)) {
194
        $meetingidsarray = explode(',', $meetingids);
195
    }
196
    // If $meetingidsarray is empty there is no need to go further.
197
    if (empty($meetingidsarray)) {
198
        return array();
199
    }
200
    $recordings = bigbluebuttonbn_get_recordings_array_fetch($meetingidsarray);
0 ignored issues
show
Bug introduced by
It seems like $meetingidsarray defined by $meetingids on line 192 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...
201
    // Sort recordings.
202
    uasort($recordings, 'bigbluebuttonbn_recording_build_sorter');
203
    // Filter recordings based on recordingIDs.
204
    $recordingidsarray = $recordingids;
205
    if (!is_array($recordingids)) {
206
        $recordingidsarray = explode(',', $recordingids);
207
    }
208
    if (empty($recordingidsarray)) {
209
        // No recording ids, no need to filter.
210
        return $recordings;
211
    }
212
    return bigbluebuttonbn_get_recordings_array_filter($recordingidsarray, $recordings);
0 ignored issues
show
Bug introduced by
It seems like $recordingidsarray defined by $recordingids on line 204 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...
213
}
214
215
/**
216
 * Helper function to fetch recordings from a BigBlueButton server.
217
 *
218
 * @param array $meetingidsarray   array with meeting ids in the form array("mid1","mid2","mid3")
219
 *
220
 * @return associative array with recordings indexed by recordID, each recording is a non sequential associative array
221
 */
222
function bigbluebuttonbn_get_recordings_array_fetch($meetingidsarray) {
223
    $recordings = array();
224
    // Execute a paginated getRecordings request.
225
    $pages = floor(count($meetingidsarray) / 25) + 1;
226
    for ($page = 1; $page <= $pages; ++$page) {
227
        $mids = array_slice($meetingidsarray, ($page - 1) * 25, 25);
228
        $recordings += bigbluebuttonbn_get_recordings_array_fetch_page($mids);
229
    }
230
    return $recordings;
231
}
232
233
/**
234
 * Helper function to fetch one page of upto 25 recordings from a BigBlueButton server.
235
 *
236
 * @param array  $mids
237
 *
238
 * @return array
239
 */
240
function bigbluebuttonbn_get_recordings_array_fetch_page($mids) {
241
    $recordings = array();
242
    // Do getRecordings is executed using a method GET (supported by all versions of BBB).
243
    $url = \mod_bigbluebuttonbn\locallib\bigbluebutton::action_url('getRecordings', ['meetingID' => implode(',', $mids)]);
244
    $xml = bigbluebuttonbn_wrap_xml_load_file($url);
245
    if ($xml && $xml->returncode == 'SUCCESS' && isset($xml->recordings)) {
246
        // If there were meetings already created.
247
        foreach ($xml->recordings->recording as $recordingxml) {
248
            $recording = bigbluebuttonbn_get_recording_array_value($recordingxml);
249
            $recordings[$recording['recordID']] = $recording;
250
        }
251
    }
252
    return $recordings;
253
}
254
255
/**
256
 * Helper function to remove a set of recordings from an array.
257
 *
258
 * @param array  $rids
259
 * @param array  $recordings
260
 *
261
 * @return array
262
 */
263
function bigbluebuttonbn_get_recordings_array_filter($rids, &$recordings) {
264
    foreach ($recordings as $key => $recording) {
265
        if (!in_array($recording['recordID'], $rids)) {
266
            unset($recordings[$key]);
267
        }
268
    }
269
    return $recordings;
270
}
271
272
/**
273
 * Helper function to retrieve imported recordings from the Moodle database.
274
 * The references are stored as events in bigbluebuttonbn_logs.
275
 *
276
 * @param string $courseid
277
 * @param string $bigbluebuttonbnid
278
 * @param bool   $subset
279
 *
280
 * @return associative array with imported recordings indexed by recordID, each recording
281
 * is a non sequential associative array that corresponds to the actual recording in BBB
282
 */
283
function bigbluebuttonbn_get_recordings_imported_array($courseid = 0, $bigbluebuttonbnid = null, $subset = true) {
284
    global $DB;
285
    $select = bigbluebuttonbn_get_recordings_imported_sql_select($courseid, $bigbluebuttonbnid, $subset);
286
    $recordsimported = $DB->get_records_select('bigbluebuttonbn_logs', $select);
287
    $recordsimportedarray = array();
288
    foreach ($recordsimported as $recordimported) {
289
        $meta = json_decode($recordimported->meta, true);
290
        $recording = $meta['recording'];
291
        // Override imported flag with actual ID.
292
        $recording['imported'] = $recordimported->id;
293
        if (isset($recordimported->protected)) {
294
            $recording['protected'] = (string) $recordimported->protected;
295
        }
296
        $recordsimportedarray[$recording['recordID']] = $recording;
297
    }
298
    return $recordsimportedarray;
299
}
300
301
/**
302
 * Helper function to retrive the default config.xml file.
303
 *
304
 * @return string
305
 */
306
function bigbluebuttonbn_get_default_config_xml() {
307
    $xml = bigbluebuttonbn_wrap_xml_load_file(
308
        \mod_bigbluebuttonbn\locallib\bigbluebutton::action_url('getDefaultConfigXML')
309
      );
310
    return $xml;
311
}
312
313
/**
314
 * Helper function to convert an xml recording object to an array in the format used by the plugin.
315
 *
316
 * @param object $recording
317
 *
318
 * @return array
319
 */
320
function bigbluebuttonbn_get_recording_array_value($recording) {
321
    // Add formats.
322
    $playbackarray = array();
323
    foreach ($recording->playback->format as $format) {
324
        $playbackarray[(string) $format->type] = array('type' => (string) $format->type,
325
            'url' => trim((string) $format->url), 'length' => (string) $format->length);
326
        // Add preview per format when existing.
327
        if ($format->preview) {
328
            $playbackarray[(string) $format->type]['preview'] = bigbluebuttonbn_get_recording_preview_images($format->preview);
329
        }
330
    }
331
    // Add the metadata to the recordings array.
332
    $metadataarray = bigbluebuttonbn_get_recording_array_meta(get_object_vars($recording->metadata));
333
    $recordingarray = array('recordID' => (string) $recording->recordID,
334
        'meetingID' => (string) $recording->meetingID, 'meetingName' => (string) $recording->name,
335
        'published' => (string) $recording->published, 'startTime' => (string) $recording->startTime,
336
        'endTime' => (string) $recording->endTime, 'playbacks' => $playbackarray);
337
    if (isset($recording->protected)) {
338
        $recordingarray['protected'] = (string) $recording->protected;
339
    }
340
    return $recordingarray + $metadataarray;
341
}
342
343
/**
344
 * Helper function to convert an xml recording preview images to an array in the format used by the plugin.
345
 *
346
 * @param object $preview
347
 *
348
 * @return array
349
 */
350
function bigbluebuttonbn_get_recording_preview_images($preview) {
351
    $imagesarray = array();
352
    foreach ($preview->images->image as $image) {
353
        $imagearray = array('url' => trim((string) $image));
354
        foreach ($image->attributes() as $attkey => $attvalue) {
355
            $imagearray[$attkey] = (string) $attvalue;
356
        }
357
        array_push($imagesarray, $imagearray);
358
    }
359
    return $imagesarray;
360
}
361
362
/**
363
 * Helper function to convert an xml recording metadata object to an array in the format used by the plugin.
364
 *
365
 * @param array $metadata
366
 *
367
 * @return array
368
 */
369
function bigbluebuttonbn_get_recording_array_meta($metadata) {
370
    $metadataarray = array();
371
    foreach ($metadata as $key => $value) {
372
        if (is_object($value)) {
373
            $value = '';
374
        }
375
        $metadataarray['meta_'.$key] = $value;
376
    }
377
    return $metadataarray;
378
}
379
380
/**
381
 * Helper function to sort an array of recordings. It compares the startTime in two recording objecs.
382
 *
383
 * @param object $a
384
 * @param object $b
385
 *
386
 * @return array
387
 */
388
function bigbluebuttonbn_recording_build_sorter($a, $b) {
389
    if ($a['startTime'] < $b['startTime']) {
390
        return -1;
391
    }
392
    if ($a['startTime'] == $b['startTime']) {
393
        return 0;
394
    }
395
    return 1;
396
}
397
398
/**
399
 * Perform deleteRecordings on BBB.
400
 *
401
 * @param string $recordids
402
 *
403
 * @return boolean
404
 */
405 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...
406
    $ids = explode(',', $recordids);
407
    foreach ($ids as $id) {
408
        $xml = bigbluebuttonbn_wrap_xml_load_file(
409
            \mod_bigbluebuttonbn\locallib\bigbluebutton::action_url('deleteRecordings', ['recordID' => $id])
410
          );
411
        if ($xml && $xml->returncode != 'SUCCESS') {
412
            return false;
413
        }
414
    }
415
    return true;
416
}
417
418
/**
419
 * Perform publishRecordings on BBB.
420
 *
421
 * @param string $recordids
422
 * @param string $publish
423
 */
424 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...
425
    $ids = explode(',', $recordids);
426
    foreach ($ids as $id) {
427
        $xml = bigbluebuttonbn_wrap_xml_load_file(
428
            \mod_bigbluebuttonbn\locallib\bigbluebutton::action_url('publishRecordings', ['recordID' => $id, 'publish' => $publish])
429
          );
430
        if ($xml && $xml->returncode != 'SUCCESS') {
431
            return false;
432
        }
433
    }
434
    return true;
435
}
436
437
/**
438
 * Perform updateRecordings on BBB.
439
 *
440
 * @param string $recordids
441
 * @param array $params ['key'=>param_key, 'value']
442
 */
443 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...
444
    $ids = explode(',', $recordids);
445
    foreach ($ids as $id) {
446
        $xml = bigbluebuttonbn_wrap_xml_load_file(
447
            \mod_bigbluebuttonbn\locallib\bigbluebutton::action_url('updateRecordings', ['recordID' => $id] + (array) $params)
448
          );
449
        if ($xml && $xml->returncode != 'SUCCESS') {
450
            return false;
451
        }
452
    }
453
    return true;
454
}
455
456
/**
457
 * Perform end on BBB.
458
 *
459
 * @param string $meetingid
460
 * @param string $modpw
461
 */
462
function bigbluebuttonbn_end_meeting($meetingid, $modpw) {
463
    $xml = bigbluebuttonbn_wrap_xml_load_file(
464
        \mod_bigbluebuttonbn\locallib\bigbluebutton::action_url('end', ['meetingID' => $meetingid, 'password' => $modpw])
465
      );
466
    if ($xml) {
467
        // If the xml packet returned failure it displays the message to the user.
468
        return array('returncode' => $xml->returncode, 'message' => $xml->message, 'messageKey' => $xml->messageKey);
469
    }
470
    // If the server is unreachable, then prompts the user of the necessary action.
471
    return null;
472
}
473
474
/**
475
 * Perform api request on BBB.
476
 *
477
 * @return string
478
 */
479
function bigbluebuttonbn_get_server_version() {
480
    $xml = bigbluebuttonbn_wrap_xml_load_file(
481
        \mod_bigbluebuttonbn\locallib\bigbluebutton::action_url()
482
      );
483
    if ($xml && $xml->returncode == 'SUCCESS') {
484
        return $xml->version;
485
    }
486
    return null;
487
}
488
489
/**
490
 * Perform api request on BBB and wraps the response in an XML object
491
 *
492
 * @param string $url
493
 * @param string $method
494
 * @param string $data
495
 * @param string $contenttype
496
 *
497
 * @return object
498
 */
499
function bigbluebuttonbn_wrap_xml_load_file($url, $method = 'GET', $data = null, $contenttype = 'text/xml') {
500
    if (extension_loaded('curl')) {
501
        $response = bigbluebuttonbn_wrap_xml_load_file_curl_request($url, $method, $data, $contenttype);
502
        if (!$response) {
503
            debugging('No response on wrap_simplexml_load_file', DEBUG_DEVELOPER);
504
            return null;
505
        }
506
        $previous = libxml_use_internal_errors(true);
507
        try {
508
            $xml = simplexml_load_string($response, 'SimpleXMLElement', LIBXML_NOCDATA | LIBXML_NOBLANKS);
509
            return $xml;
510
        } catch (Exception $e) {
511
            libxml_use_internal_errors($previous);
512
            $error = 'Caught exception: '.$e->getMessage();
513
            debugging($error, DEBUG_DEVELOPER);
514
            return null;
515
        }
516
    }
517
    // Alternative request non CURL based.
518
    $previous = libxml_use_internal_errors(true);
519
    try {
520
        $response = simplexml_load_file($url, 'SimpleXMLElement', LIBXML_NOCDATA | LIBXML_NOBLANKS);
521
        return $response;
522
    } catch (Exception $e) {
523
        $error = 'Caught exception: '.$e->getMessage();
524
        debugging($error, DEBUG_DEVELOPER);
525
        libxml_use_internal_errors($previous);
526
        return null;
527
    }
528
}
529
530
/**
531
 * Perform api request on BBB using CURL and wraps the response in an XML object
532
 *
533
 * @param string $url
534
 * @param string $method
535
 * @param string $data
536
 * @param string $contenttype
537
 *
538
 * @return object
539
 */
540
function bigbluebuttonbn_wrap_xml_load_file_curl_request($url, $method = 'GET', $data = null, $contenttype = 'text/xml') {
541
    $c = new curl();
542
    $c->setopt(array('SSL_VERIFYPEER' => true));
543
    if ($method == 'POST') {
544
        if (is_null($data) || is_array($data)) {
545
            return $c->post($url);
546
        }
547
        $options = array();
548
        $options['CURLOPT_HTTPHEADER'] = array(
549
                 'Content-Type: '.$contenttype,
550
                 'Content-Length: '.strlen($data),
551
                 'Content-Language: en-US',
552
               );
553
554
        return $c->post($url, $data, $options);
555
    }
556
    if ($method == 'HEAD') {
557
        $c->head($url, array('followlocation' => true, 'timeout' => 1));
558
        return $c->get_info();
559
    }
560
    return $c->get($url);
561
}
562
563
/**
564
 * End the session associated with this instance (if it's running).
565
 *
566
 * @param object $bigbluebuttonbn
567
 *
568
 * @return void
569
 */
570
function bigbluebuttonbn_end_meeting_if_running($bigbluebuttonbn) {
571
    $meetingid = $bigbluebuttonbn->meetingid.'-'.$bigbluebuttonbn->course.'-'.$bigbluebuttonbn->id;
572
    if (bigbluebuttonbn_is_meeting_running($meetingid)) {
573
        bigbluebuttonbn_end_meeting($meetingid, $bigbluebuttonbn->moderatorpass);
574
    }
575
}
576
577
/**
578
 * Returns user roles in a context.
579
 *
580
 * @param object $context
581
 * @param integer $userid
582
 *
583
 * @return array $userroles
584
 */
585
function bigbluebuttonbn_get_user_roles($context, $userid) {
586
    global $DB;
587
    $userroles = get_user_roles($context, $userid);
588
    if ($userroles) {
589
        $where = '';
590
        foreach ($userroles as $userrole) {
591
            $where .= (empty($where) ? ' WHERE' : ' OR').' id=' . $userrole->roleid;
592
        }
593
        $userroles = $DB->get_records_sql('SELECT * FROM {role}'.$where);
594
    }
595
    return $userroles;
596
}
597
598
/**
599
 * Returns guest role wrapped in an array.
600
 *
601
 * @return array
602
 */
603
function bigbluebuttonbn_get_guest_role() {
604
    $guestrole = get_guest_role();
605
    return array($guestrole->id => $guestrole);
606
}
607
608
/**
609
 * Returns an array containing all the users in a context.
610
 *
611
 * @param context $context
612
 *
613
 * @return array $users
614
 */
615
function bigbluebuttonbn_get_users(context $context = null) {
616
    $users = (array) get_enrolled_users($context, '', 0, 'u.*', null, 0, 0, true);
617
    foreach ($users as $key => $value) {
618
        $users[$key] = fullname($value);
619
    }
620
    return $users;
621
}
622
623
/**
624
 * Returns an array containing all the users in a context wrapped for html select element.
625
 *
626
 * @param context $context
627
 *
628
 * @return array $users
629
 */
630
function bigbluebuttonbn_get_users_select(context $context = null) {
631
    $users = (array) get_enrolled_users($context, '', 0, 'u.*', null, 0, 0, true);
632
    foreach ($users as $key => $value) {
633
        $users[$key] = array('id' => $value->id, 'name' => fullname($value));
634
    }
635
    return $users;
636
}
637
638
/**
639
 * Returns an array containing all the roles in a context.
640
 *
641
 * @param context $context
642
 *
643
 * @return array $roles
644
 */
645
function bigbluebuttonbn_get_roles(context $context = null) {
646
    $roles = (array) role_get_names($context);
647
    foreach ($roles as $key => $value) {
648
        $roles[$key] = $value->localname;
649
    }
650
    return $roles;
651
}
652
653
/**
654
 * Returns an array containing all the roles in a context wrapped for html select element.
655
 *
656
 * @param context $context
657
 *
658
 * @return array $users
659
 */
660
function bigbluebuttonbn_get_roles_select(context $context = null) {
661
    $roles = (array) role_get_names($context);
662
    foreach ($roles as $key => $value) {
663
        $roles[$key] = array('id' => $value->id, 'name' => $value->localname);
664
    }
665
    return $roles;
666
}
667
668
/**
669
 * Returns role that corresponds to an id.
670
 *
671
 * @param string|integer $id
672
 *
673
 * @return object $role
674
 */
675
function bigbluebuttonbn_get_role($id) {
676
    $roles = (array) role_get_names();
677
    if (is_numeric($id) && isset($roles[$id])) {
678
        return (object)$roles[$id];
679
    }
680
    foreach ($roles as $role) {
681
        if ($role->shortname == $id) {
682
            return $role;
683
        }
684
    }
685
}
686
687
/**
688
 * Returns an array to populate a list of participants used in mod_form.js.
689
 *
690
 * @param context $context
691
 *
692
 * @return array $data
693
 */
694
function bigbluebuttonbn_get_participant_data($context) {
695
    $data = array(
696
        'all' => array(
697
            'name' => get_string('mod_form_field_participant_list_type_all', 'bigbluebuttonbn'),
698
            'children' => []
699
          )
700
      );
701
    $data['role'] = array(
702
        'name' => get_string('mod_form_field_participant_list_type_role', 'bigbluebuttonbn'),
703
        'children' => bigbluebuttonbn_get_roles_select($context)
704
      );
705
    $data['user'] = array(
706
        'name' => get_string('mod_form_field_participant_list_type_user', 'bigbluebuttonbn'),
707
        'children' => bigbluebuttonbn_get_users_select($context)
708
      );
709
    return $data;
710
}
711
712
/**
713
 * Returns an array to populate a list of participants used in mod_form.php.
714
 *
715
 * @param object $bigbluebuttonbn
716
 * @param context $context
717
 *
718
 * @return array
719
 */
720
function bigbluebuttonbn_get_participant_list($bigbluebuttonbn, $context) {
721
    global $USER;
722
    if ($bigbluebuttonbn == null) {
723
        return bigbluebuttonbn_get_participant_rules_encoded(
724
            bigbluebuttonbn_get_participant_list_default($context, $USER->id)
725
        );
726
    }
727
    if (empty($bigbluebuttonbn->participants)) {
728
        $bigbluebuttonbn->participants = "[]";
729
    }
730
    $rules = json_decode($bigbluebuttonbn->participants, true);
731
    if (empty($rules)) {
732
        $rules = bigbluebuttonbn_get_participant_list_default($context, bigbluebuttonbn_instance_ownerid($bigbluebuttonbn));
733
    }
734
    return bigbluebuttonbn_get_participant_rules_encoded($rules);
735
}
736
737
/**
738
 * Returns an array to populate a list of participants used in mod_form.php with default values.
739
 *
740
 * @param context $context
741
 * @param integer $ownerid
742
 *
743
 * @return array
744
 */
745
function bigbluebuttonbn_get_participant_list_default($context, $ownerid = null) {
746
    $participantlist = array();
747
    $participantlist[] = array(
748
        'selectiontype' => 'all',
749
        'selectionid' => 'all',
750
        'role' => BIGBLUEBUTTONBN_ROLE_VIEWER
751
      );
752
    $defaultrules = explode(',', \mod_bigbluebuttonbn\locallib\config::get('participant_moderator_default'));
753
    foreach ($defaultrules as $defaultrule) {
754
        if ($defaultrule == '0') {
755
            if (!empty($ownerid) && is_enrolled($context, $ownerid)) {
756
                $participantlist[] = array(
757
                    'selectiontype' => 'user',
758
                    'selectionid' => (string)$ownerid,
759
                    'role' => BIGBLUEBUTTONBN_ROLE_MODERATOR);
760
            }
761
            continue;
762
        }
763
        $participantlist[] = array(
764
              'selectiontype' => 'role',
765
              'selectionid' => $defaultrule,
766
              'role' => BIGBLUEBUTTONBN_ROLE_MODERATOR);
767
    }
768
    return $participantlist;
769
}
770
771
/**
772
 * Returns an array to populate a list of participants used in mod_form.php with bigbluebuttonbn values.
773
 *
774
 * @param array $rules
775
 *
776
 * @return array
777
 */
778
function bigbluebuttonbn_get_participant_rules_encoded($rules) {
779
    foreach ($rules as $key => $rule) {
780
        if ($rule['selectiontype'] !== 'role' || is_numeric($rule['selectionid'])) {
781
            continue;
782
        }
783
        $role = bigbluebuttonbn_get_role($rule['selectionid']);
784
        if ($role == null) {
785
            unset($rules[$key]);
786
            continue;
787
        }
788
        $rule['selectionid'] = $role->id;
789
        $rules[$key] = $rule;
790
    }
791
    return $rules;
792
}
793
794
/**
795
 * Returns an array to populate a list of participant_selection used in mod_form.php.
796
 *
797
 * @return array
798
 */
799
function bigbluebuttonbn_get_participant_selection_data() {
800
    return [
801
        'type_options' => [
802
            'all' => get_string('mod_form_field_participant_list_type_all', 'bigbluebuttonbn'),
803
            'role' => get_string('mod_form_field_participant_list_type_role', 'bigbluebuttonbn'),
804
            'user' => get_string('mod_form_field_participant_list_type_user', 'bigbluebuttonbn'),
805
          ],
806
        'type_selected' => 'all',
807
        'options' => ['all' => '---------------'],
808
        'selected' => 'all',
809
      ];
810
}
811
812
/**
813
 * Evaluate if a user in a context is moderator based on roles and participation rules.
814
 *
815
 * @param context $context
816
 * @param array $participantlist
817
 * @param integer $userid
818
 *
819
 * @return boolean
820
 */
821
function bigbluebuttonbn_is_moderator($context, $participantlist, $userid = null) {
822
    global $USER;
823
    if (!is_array($participantlist)) {
824
        return false;
825
    }
826
    if (empty($userid)) {
827
        $userid = $USER->id;
828
    }
829
    $userroles = bigbluebuttonbn_get_guest_role();
830
    if (!isguestuser()) {
831
        $userroles = bigbluebuttonbn_get_user_roles($context, $userid);
832
    }
833
    return bigbluebuttonbn_is_moderator_validator($participantlist, $userid , $userroles);
834
}
835
836
/**
837
 * Iterates participant list rules to evaluate if a user is moderator.
838
 *
839
 * @param array $participantlist
840
 * @param integer $userid
841
 * @param array $userroles
842
 *
843
 * @return boolean
844
 */
845
function bigbluebuttonbn_is_moderator_validator($participantlist, $userid, $userroles) {
846
    // Iterate participant rules.
847
    foreach ($participantlist as $participant) {
848
        if (bigbluebuttonbn_is_moderator_validate_rule($participant, $userid, $userroles)) {
849
            return true;
850
        }
851
    }
852
    return false;
853
}
854
855
/**
856
 * Evaluate if a user is moderator based on roles and a particular participation rule.
857
 *
858
 * @param object $participant
859
 * @param integer $userid
860
 * @param array $userroles
861
 *
862
 * @return boolean
863
 */
864
function bigbluebuttonbn_is_moderator_validate_rule($participant, $userid, $userroles) {
865
    if ($participant['role'] == BIGBLUEBUTTONBN_ROLE_VIEWER) {
866
        return false;
867
    }
868
    // Looks for all configuration.
869
    if ($participant['selectiontype'] == 'all') {
870
        return true;
871
    }
872
    // Looks for users.
873
    if ($participant['selectiontype'] == 'user' && $participant['selectionid'] == $userid) {
874
        return true;
875
    }
876
    // Looks for roles.
877
    $role = bigbluebuttonbn_get_role($participant['selectionid']);
878
    if ($role != null && array_key_exists($role->id, $userroles)) {
879
        return true;
880
    }
881
    return false;
882
}
883
884
/**
885
 * Helper returns error message key for the language file that corresponds to a bigbluebutton error key.
886
 *
887
 * @param string $messagekey
888
 * @param string $defaultkey
889
 *
890
 * @return string
891
 */
892
function bigbluebuttonbn_get_error_key($messagekey, $defaultkey = null) {
893
    if ($messagekey == 'checksumError') {
894
        return 'index_error_checksum';
895
    }
896
    if ($messagekey == 'maxConcurrent') {
897
        return 'view_error_max_concurrent';
898
    }
899
    return $defaultkey;
900
}
901
902
/**
903
 * Helper evaluates if a voicebridge number is unique.
904
 *
905
 * @param integer $instance
906
 * @param integer $voicebridge
907
 *
908
 * @return string
909
 */
910
function bigbluebuttonbn_voicebridge_unique($instance, $voicebridge) {
911
    global $DB;
912
    if ($voicebridge == 0) {
913
        return true;
914
    }
915
    $select = 'voicebridge = ' . $voicebridge;
916
    if ($instance != 0) {
917
        $select .= ' AND id <>' . $instance;
918
    }
919
    if (!$DB->get_records_select('bigbluebuttonbn', $select)) {
920
        return true;
921
    }
922
    return false;
923
}
924
925
/**
926
 * Helper estimate a duration for the meeting based on the closingtime.
927
 *
928
 * @param integer $closingtime
929
 *
930
 * @return integer
931
 */
932
function bigbluebuttonbn_get_duration($closingtime) {
933
    $duration = 0;
934
    $now = time();
935
    if ($closingtime > 0 && $now < $closingtime) {
936
        $duration = ceil(($closingtime - $now) / 60);
937
        $compensationtime = intval((int)\mod_bigbluebuttonbn\locallib\config::get('scheduled_duration_compensation'));
938
        $duration = intval($duration) + $compensationtime;
939
    }
940
    return $duration;
941
}
942
943
/**
944
 * Helper return array containing the file descriptor for a preuploaded presentation.
945
 *
946
 * @param context $context
947
 * @param string $presentation
948
 * @param integer $id
949
 *
950
 * @return array
951
 */
952
function bigbluebuttonbn_get_presentation_array($context, $presentation, $id = null) {
953
    if (empty($presentation)) {
954
        return array('url' => null, 'name' => null, 'icon' => null, 'mimetype_description' => null);
955
    }
956
    $fs = get_file_storage();
957
    $files = $fs->get_area_files($context->id, 'mod_bigbluebuttonbn', 'presentation', 0,
958
        'itemid, filepath, filename', false);
959
    if (count($files) == 0) {
960
        return array('url' => null, 'name' => null, 'icon' => null, 'mimetype_description' => null);
961
    }
962
    $file = reset($files);
963
    unset($files);
964
    $pnoncevalue = null;
965
    if (!is_null($id)) {
966
        // Create the nonce component for granting a temporary public access.
967
        $cache = cache::make_from_params(cache_store::MODE_APPLICATION, 'mod_bigbluebuttonbn',
968
            'presentation_cache');
969
        $pnoncekey = sha1($id);
970
        /* The item id was adapted for granting public access to the presentation once in order
971
         * to allow BigBlueButton to gather the file. */
972
        $pnoncevalue = bigbluebuttonbn_generate_nonce();
973
        $cache->set($pnoncekey, array('value' => $pnoncevalue, 'counter' => 0));
974
    }
975
    $url = moodle_url::make_pluginfile_url($file->get_contextid(), $file->get_component(),
976
        $file->get_filearea(), $pnoncevalue, $file->get_filepath(), $file->get_filename());
977
    return array('name' => $file->get_filename(), 'icon' => file_file_icon($file, 24),
978
            'url' => $url->out(false), 'mimetype_description' => get_mimetype_description($file));
979
}
980
981
/**
982
 * Helper generates a nonce used for the preuploaded presentation callback url.
983
 *
984
 * @return string
985
 */
986
function bigbluebuttonbn_generate_nonce() {
987
    $mt = microtime();
988
    $rand = mt_rand();
989
    return md5($mt.$rand);
990
}
991
992
/**
993
 * Helper generates a random password.
994
 *
995
 * @param integer $length
996
 * @param string $unique
997
 *
998
 * @return string
999
 */
1000
function bigbluebuttonbn_random_password($length = 8, $unique = "") {
1001
    $chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*()_-=+;:,.?';
1002
    do {
1003
        $password = substr(str_shuffle($chars), 0, $length);
1004
    } while ($unique == $password);
1005
    return $password;
1006
}
1007
1008
/**
1009
 * Helper returns an array with all possible bigbluebuttonbn events.
1010
 *
1011
 * @return array
1012
 */
1013
function bigbluebuttonbn_events() {
1014
    return array(
1015
        (string) BIGBLUEBUTTON_EVENT_ACTIVITY_VIEWED,
1016
        (string) BIGBLUEBUTTON_EVENT_ACTIVITY_MANAGEMENT_VIEWED,
1017
        (string) BIGBLUEBUTTON_EVENT_LIVE_SESSION,
1018
        (string) BIGBLUEBUTTON_EVENT_MEETING_CREATED,
1019
        (string) BIGBLUEBUTTON_EVENT_MEETING_ENDED,
1020
        (string) BIGBLUEBUTTON_EVENT_MEETING_JOINED,
1021
        (string) BIGBLUEBUTTON_EVENT_MEETING_LEFT,
1022
        (string) BIGBLUEBUTTON_EVENT_RECORDING_DELETED,
1023
        (string) BIGBLUEBUTTON_EVENT_RECORDING_IMPORTED,
1024
        (string) BIGBLUEBUTTON_EVENT_RECORDING_PROTECTED,
1025
        (string) BIGBLUEBUTTON_EVENT_RECORDING_PUBLISHED,
1026
        (string) BIGBLUEBUTTON_EVENT_RECORDING_UNPROTECTED,
1027
        (string) BIGBLUEBUTTON_EVENT_RECORDING_UNPUBLISHED,
1028
        (string) BIGBLUEBUTTON_EVENT_RECORDING_EDITED,
1029
        (string) BIGBLUEBUTTON_EVENT_RECORDING_VIEWED
1030
    );
1031
}
1032
1033
/**
1034
 * Helper returns an array with the actions and their corresponding bigbluebuttonbn events.
1035
 *
1036
 * @return array
1037
 */
1038
function bigbluebuttonbn_events_action() {
1039
    return array(
1040
        'view' => (string) BIGBLUEBUTTON_EVENT_ACTIVITY_VIEWED,
1041
        'view_management' => (string) BIGBLUEBUTTON_EVENT_ACTIVITY_MANAGEMENT_VIEWED,
1042
        'live_action' => (string) BIGBLUEBUTTON_EVENT_LIVE_SESSION,
1043
        'meeting_create' => (string) BIGBLUEBUTTON_EVENT_MEETING_CREATED,
1044
        'meeting_end' => (string) BIGBLUEBUTTON_EVENT_MEETING_ENDED,
1045
        'meeting_join' => (string) BIGBLUEBUTTON_EVENT_MEETING_JOINED,
1046
        'meeting_left' => (string) BIGBLUEBUTTON_EVENT_MEETING_LEFT,
1047
        'recording_delete' => (string) BIGBLUEBUTTON_EVENT_RECORDING_DELETED,
1048
        'recording_import' => (string) BIGBLUEBUTTON_EVENT_RECORDING_IMPORTED,
1049
        'recording_protect' => (string) BIGBLUEBUTTON_EVENT_RECORDING_PROTECTED,
1050
        'recording_publish' => (string) BIGBLUEBUTTON_EVENT_RECORDING_PUBLISHED,
1051
        'recording_unprotect' => (string) BIGBLUEBUTTON_EVENT_RECORDING_UNPROTECTED,
1052
        'recording_unpublish' => (string) BIGBLUEBUTTON_EVENT_RECORDING_UNPUBLISHED,
1053
        'recording_edit' => (string) BIGBLUEBUTTON_EVENT_RECORDING_EDITED,
1054
        'recording_play' => (string) BIGBLUEBUTTON_EVENT_RECORDING_VIEWED
1055
    );
1056
}
1057
1058
/**
1059
 * Helper register a bigbluebuttonbn event.
1060
 *
1061
 * @param string $eventtype
1062
 * @param object $bigbluebuttonbn
1063
 * @param object $cm
1064
 * @param array $options
1065
 *
1066
 * @return void
1067
 */
1068
function bigbluebuttonbn_event_log($eventtype, $bigbluebuttonbn, $cm, $options = []) {
1069
    $events = bigbluebuttonbn_events();
1070
    if (!in_array($eventtype, $events)) {
1071
        // No log will be created.
1072
        return;
1073
    }
1074
    $context = context_module::instance($cm->id);
1075
1076
    $eventproperties = array('context' => $context, 'objectid' => $bigbluebuttonbn->id);
1077
    if (array_key_exists('timecreated', $options)) {
1078
        $eventproperties['timecreated'] = $options['timecreated'];
1079
    }
1080
    if (array_key_exists('userid', $options)) {
1081
        $eventproperties['userid'] = $options['userid'];
1082
    }
1083
    if (array_key_exists('other', $options)) {
1084
        $eventproperties['other'] = $options['other'];
1085
    }
1086
    $event = call_user_func_array('\mod_bigbluebuttonbn\event\bigbluebuttonbn_'.$eventtype.'::create',
1087
      array($eventproperties));
1088
    $event->trigger();
1089
}
1090
1091
/**
1092
 * Updates the meeting info cached object when a participant has joined.
1093
 *
1094
 * @param string $meetingid
1095
 * @param bool $ismoderator
1096
 *
1097
 * @return void
1098
 */
1099
function bigbluebuttonbn_participant_joined($meetingid, $ismoderator) {
1100
    $cache = cache::make_from_params(cache_store::MODE_APPLICATION, 'mod_bigbluebuttonbn', 'meetings_cache');
1101
    $result = $cache->get($meetingid);
1102
    $meetinginfo = json_decode($result['meeting_info']);
1103
    $meetinginfo->participantCount += 1;
1104
    if ($ismoderator) {
1105
        $meetinginfo->moderatorCount += 1;
1106
    }
1107
    $cache->set($meetingid, array('creation_time' => $result['creation_time'],
1108
        'meeting_info' => json_encode($meetinginfo)));
1109
}
1110
1111
/**
1112
 * Gets a meeting info object cached or fetched from the live session.
1113
 *
1114
 * @param string $meetingid
1115
 * @param boolean $updatecache
1116
 *
1117
 * @return array
1118
 */
1119
function bigbluebuttonbn_get_meeting_info($meetingid, $updatecache = false) {
1120
    $cachettl = (int)\mod_bigbluebuttonbn\locallib\config::get('waitformoderator_cache_ttl');
1121
    $cache = cache::make_from_params(cache_store::MODE_APPLICATION, 'mod_bigbluebuttonbn', 'meetings_cache');
1122
    $result = $cache->get($meetingid);
1123
    $now = time();
1124
    if (!$updatecache && isset($result) && $now < ($result['creation_time'] + $cachettl)) {
1125
        // Use the value in the cache.
1126
        return (array) json_decode($result['meeting_info']);
1127
    }
1128
    // Ping again and refresh the cache.
1129
    $meetinginfo = (array) bigbluebuttonbn_wrap_xml_load_file(
1130
        \mod_bigbluebuttonbn\locallib\bigbluebutton::action_url('getMeetingInfo', ['meetingID' => $meetingid])
1131
      );
1132
    $cache->set($meetingid, array('creation_time' => time(), 'meeting_info' => json_encode($meetinginfo)));
1133
    return $meetinginfo;
1134
}
1135
1136
/**
1137
 * Perform isMeetingRunning on BBB.
1138
 *
1139
 * @param string $meetingid
1140
 * @param boolean $updatecache
1141
 *
1142
 * @return boolean
1143
 */
1144
function bigbluebuttonbn_is_meeting_running($meetingid, $updatecache = false) {
1145
    /* As a workaround to isMeetingRunning that always return SUCCESS but only returns true
1146
     * when at least one user is in the session, we use getMeetingInfo instead.
1147
     */
1148
    $meetinginfo = bigbluebuttonbn_get_meeting_info($meetingid, $updatecache);
1149
    return ($meetinginfo['returncode'] === 'SUCCESS');
1150
}
1151
1152
/**
1153
 * Publish an imported recording.
1154
 *
1155
 * @param string $id
1156
 * @param boolean $publish
1157
 *
1158
 * @return boolean
1159
 */
1160 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...
1161
    global $DB;
1162
    // Locate the record to be updated.
1163
    $record = $DB->get_record('bigbluebuttonbn_logs', array('id' => $id));
1164
    $meta = json_decode($record->meta, true);
1165
    // Prepare data for the update.
1166
    $meta['recording']['published'] = ($publish) ? 'true' : 'false';
1167
    $record->meta = json_encode($meta);
1168
    // Proceed with the update.
1169
    $DB->update_record('bigbluebuttonbn_logs', $record);
1170
    return true;
1171
}
1172
1173
/**
1174
 * Delete an imported recording.
1175
 *
1176
 * @param string $id
1177
 *
1178
 * @return boolean
1179
 */
1180
function bigbluebuttonbn_delete_recording_imported($id) {
1181
    global $DB;
1182
    // Execute delete.
1183
    $DB->delete_records('bigbluebuttonbn_logs', array('id' => $id));
1184
    return true;
1185
}
1186
1187
/**
1188
 * Update an imported recording.
1189
 *
1190
 * @param string $id
1191
 * @param array $params ['key'=>param_key, 'value']
1192
 *
1193
 * @return boolean
1194
 */
1195
function bigbluebuttonbn_update_recording_imported($id, $params) {
1196
    global $DB;
1197
    // Locate the record to be updated.
1198
    $record = $DB->get_record('bigbluebuttonbn_logs', array('id' => $id));
1199
    $meta = json_decode($record->meta, true);
1200
    // Prepare data for the update.
1201
    $meta['recording'] = $params + $meta['recording'];
1202
    $record->meta = json_encode($meta);
1203
    // Proceed with the update.
1204
    if (!$DB->update_record('bigbluebuttonbn_logs', $record)) {
1205
        return false;
1206
    }
1207
    return true;
1208
}
1209
1210
/**
1211
 * Protect/Unprotect an imported recording.
1212
 *
1213
 * @param string $id
1214
 * @param boolean $protect
1215
 *
1216
 * @return boolean
1217
 */
1218 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...
1219
    global $DB;
1220
    // Locate the record to be updated.
1221
    $record = $DB->get_record('bigbluebuttonbn_logs', array('id' => $id));
1222
    $meta = json_decode($record->meta, true);
1223
    // Prepare data for the update.
1224
    $meta['recording']['protected'] = ($protect) ? 'true' : 'false';
1225
    $record->meta = json_encode($meta);
1226
    // Proceed with the update.
1227
    $DB->update_record('bigbluebuttonbn_logs', $record);
1228
    return true;
1229
}
1230
1231
/**
1232
 * Sets a custom config.xml file for being used on create.
1233
 *
1234
 * @param string $meetingid
1235
 * @param string $configxml
1236
 *
1237
 * @return object
1238
 */
1239
function bigbluebuttonbn_set_config_xml($meetingid, $configxml) {
1240
    $urldefaultconfig = \mod_bigbluebuttonbn\locallib\config::get('server_url').'api/setConfigXML?';
1241
    $configxmlparams = bigbluebuttonbn_set_config_xml_params($meetingid, $configxml);
1242
    $xml = bigbluebuttonbn_wrap_xml_load_file($urldefaultconfig, 'POST',
1243
        $configxmlparams, 'application/x-www-form-urlencoded');
1244
    return $xml;
1245
}
1246
1247
/**
1248
 * Sets qs used with a custom config.xml file request.
1249
 *
1250
 * @param string $meetingid
1251
 * @param string $configxml
1252
 *
1253
 * @return string
1254
 */
1255
function bigbluebuttonbn_set_config_xml_params($meetingid, $configxml) {
1256
    $params = 'configXML='.urlencode($configxml).'&meetingID='.urlencode($meetingid);
1257
    $configxmlparams = $params.'&checksum='.sha1('setConfigXML'.$params.\mod_bigbluebuttonbn\locallib\config::get('shared_secret'));
1258
    return $configxmlparams;
1259
}
1260
1261
/**
1262
 * Sets a custom config.xml file for being used on create.
1263
 *
1264
 * @param string $meetingid
1265
 * @param string $configxml
1266
 *
1267
 * @return array
1268
 */
1269
function bigbluebuttonbn_set_config_xml_array($meetingid, $configxml) {
1270
    $configxml = bigbluebuttonbn_setConfigXML($meetingid, $configxml);
1271
    $configxmlarray = (array) $configxml;
1272
    if ($configxmlarray['returncode'] != 'SUCCESS') {
1273
        debugging('BigBlueButton was not able to set the custom config.xml file', DEBUG_DEVELOPER);
1274
        return '';
1275
    }
1276
    return $configxmlarray['configToken'];
1277
}
1278
1279
/**
1280
 * Helper function builds a row for the data used by the recording table.
1281
 *
1282
 * @param array $bbbsession
1283
 * @param array $recording
1284
 * @param array $tools
1285
 *
1286
 * @return array
1287
 */
1288
function bigbluebuttonbn_get_recording_data_row($bbbsession, $recording, $tools = ['protect', 'publish', 'delete']) {
1289
    if (!bigbluebuttonbn_include_recording_table_row($bbbsession, $recording)) {
1290
        return;
1291
    }
1292
    $rowdata = new stdClass();
1293
    // Set recording_types.
1294
    $rowdata->recording = bigbluebuttonbn_get_recording_data_row_types($recording, $bbbsession);
1295
    // Set activity name.
1296
    $rowdata->activity = bigbluebuttonbn_get_recording_data_row_meta_activity($recording, $bbbsession);
1297
    // Set activity description.
1298
    $rowdata->description = bigbluebuttonbn_get_recording_data_row_meta_description($recording, $bbbsession);
1299
    if (bigbluebuttonbn_get_recording_data_preview_enabled($bbbsession)) {
1300
        // Set recording_preview.
1301
        $rowdata->preview = bigbluebuttonbn_get_recording_data_row_preview($recording);
1302
    }
1303
    // Set date.
1304
    $rowdata->date = bigbluebuttonbn_get_recording_data_row_date($recording);
1305
    // Set formatted date.
1306
    $rowdata->date_formatted = bigbluebuttonbn_get_recording_data_row_date_formatted($rowdata->date);
1307
    // Set formatted duration.
1308
    $rowdata->duration_formatted = $rowdata->duration = bigbluebuttonbn_get_recording_data_row_duration($recording);
1309
    // Set actionbar, if user is allowed to manage recordings.
1310
    if ($bbbsession['managerecordings']) {
1311
        $rowdata->actionbar = bigbluebuttonbn_get_recording_data_row_actionbar($recording, $tools);
1312
    }
1313
    return $rowdata;
1314
}
1315
1316
/**
1317
 * Helper function evaluates if a row for the data used by the recording table is editable.
1318
 *
1319
 * @param array $bbbsession
1320
 *
1321
 * @return boolean
1322
 */
1323
function bigbluebuttonbn_get_recording_data_row_editable($bbbsession) {
1324
    return ($bbbsession['managerecordings'] && ((double)$bbbsession['serverversion'] >= 1.0 || $bbbsession['bnserver']));
1325
}
1326
1327
/**
1328
 * Helper function evaluates if recording preview should be included.
1329
 *
1330
 * @param array $bbbsession
1331
 *
1332
 * @return boolean
1333
 */
1334
function bigbluebuttonbn_get_recording_data_preview_enabled($bbbsession) {
1335
    return ((double)$bbbsession['serverversion'] >= 1.0 && $bbbsession['bigbluebuttonbn']->recordings_preview == '1');
1336
}
1337
1338
/**
1339
 * Helper function converts recording date used in row for the data used by the recording table.
1340
 *
1341
 * @param array $recording
1342
 *
1343
 * @return integer
1344
 */
1345
function bigbluebuttonbn_get_recording_data_row_date($recording) {
1346
    if (!isset($recording['startTime'])) {
1347
        return 0;
1348
    }
1349
    return floatval($recording['startTime']);
1350
}
1351
1352
/**
1353
 * Helper function format recording date used in row for the data used by the recording table.
1354
 *
1355
 * @param integer $starttime
1356
 *
1357
 * @return string
1358
 */
1359
function bigbluebuttonbn_get_recording_data_row_date_formatted($starttime) {
1360
    global $USER;
1361
    $starttime = $starttime - ($starttime % 1000);
1362
    // Set formatted date.
1363
    $dateformat = get_string('strftimerecentfull', 'langconfig').' %Z';
1364
    return userdate($starttime / 1000, $dateformat, usertimezone($USER->timezone));
1365
}
1366
1367
/**
1368
 * Helper function converts recording duration used in row for the data used by the recording table.
1369
 *
1370
 * @param array $recording
1371
 *
1372
 * @return integer
1373
 */
1374
function bigbluebuttonbn_get_recording_data_row_duration($recording) {
1375
    foreach (array_values($recording['playbacks']) as $playback) {
1376
        // Ignore restricted playbacks.
1377
        if (array_key_exists('restricted', $playback) && strtolower($playback['restricted']) == 'true') {
1378
            continue;
1379
        }
1380
        // Take the lenght form the fist playback with an actual value.
1381
        if (!empty($playback['length'])) {
1382
            return intval($playback['length']);
1383
        }
1384
    }
1385
    return 0;
1386
}
1387
1388
/**
1389
 * Helper function builds recording actionbar used in row for the data used by the recording table.
1390
 *
1391
 * @param array $recording
1392
 * @param array $tools
1393
 *
1394
 * @return string
1395
 */
1396
function bigbluebuttonbn_get_recording_data_row_actionbar($recording, $tools) {
1397
    $actionbar = '';
1398
    foreach ($tools as $tool) {
1399
        $buttonpayload = bigbluebuttonbn_get_recording_data_row_actionbar_payload($recording, $tool);
1400
        if ($tool == 'protect') {
1401
            if (isset($recording['imported'])) {
1402
                $buttonpayload['disabled'] = 'disabled';
1403
            }
1404
            if (!isset($recording['protected'])) {
1405
                $buttonpayload['disabled'] = 'invisible';
1406
            }
1407
        }
1408
        $actionbar .= bigbluebuttonbn_actionbar_render_button($recording, $buttonpayload);
1409
    }
1410
    $head = html_writer::start_tag('div', array(
1411
        'id' => 'recording-actionbar-' . $recording['recordID'],
1412
        'data-recordingid' => $recording['recordID'],
1413
        'data-meetingid' => $recording['meetingID']));
1414
    $tail = html_writer::end_tag('div');
1415
    return $head . $actionbar . $tail;
1416
}
1417
1418
/**
1419
 * Helper function returns the corresponding payload for an actionbar button used in row
1420
 * for the data used by the recording table.
1421
 *
1422
 * @param array $recording
1423
 * @param array $tool
1424
 *
1425
 * @return array
1426
 */
1427
function bigbluebuttonbn_get_recording_data_row_actionbar_payload($recording, $tool) {
1428
    if ($tool == 'protect') {
1429
        $protected = 'false';
1430
        if (isset($recording['protected'])) {
1431
            $protected = $recording['protected'];
1432
        }
1433
        return bigbluebuttonbn_get_recording_data_row_action_protect($protected);
1434
    }
1435
    if ($tool == 'publish') {
1436
        return bigbluebuttonbn_get_recording_data_row_action_publish($recording['published']);
1437
    }
1438
    return array('action' => $tool, 'tag' => $tool);
1439
}
1440
1441
/**
1442
 * Helper function returns the payload for protect action button used in row
1443
 * for the data used by the recording table.
1444
 *
1445
 * @param string $protected
1446
 *
1447
 * @return array
1448
 */
1449
function bigbluebuttonbn_get_recording_data_row_action_protect($protected) {
1450
    if ($protected == 'true') {
1451
        return array('action' => 'unprotect', 'tag' => 'lock');
1452
    }
1453
    return array('action' => 'protect', 'tag' => 'unlock');
1454
}
1455
1456
/**
1457
 * Helper function returns the payload for publish action button used in row
1458
 * for the data used by the recording table.
1459
 *
1460
 * @param string $published
1461
 *
1462
 * @return array
1463
 */
1464
function bigbluebuttonbn_get_recording_data_row_action_publish($published) {
1465
    if ($published == 'true') {
1466
        return array('action' => 'unpublish', 'tag' => 'hide');
1467
    }
1468
    return array('action' => 'publish', 'tag' => 'show');
1469
}
1470
1471
/**
1472
 * Helper function builds recording preview used in row for the data used by the recording table.
1473
 *
1474
 * @param array $recording
1475
 *
1476
 * @return string
1477
 */
1478
function bigbluebuttonbn_get_recording_data_row_preview($recording) {
1479
    $options = array('id' => 'preview-'.$recording['recordID']);
1480
    if ($recording['published'] === 'false') {
1481
        $options['hidden'] = 'hidden';
1482
    }
1483
    $recordingpreview = html_writer::start_tag('div', $options);
1484
    foreach ($recording['playbacks'] as $playback) {
1485
        if (isset($playback['preview'])) {
1486
            $recordingpreview .= bigbluebuttonbn_get_recording_data_row_preview_images($playback);
1487
            break;
1488
        }
1489
    }
1490
    $recordingpreview .= html_writer::end_tag('div');
1491
    return $recordingpreview;
1492
}
1493
1494
/**
1495
 * Helper function builds element with actual images used in recording preview row based on a selected playback.
1496
 *
1497
 * @param array $playback
1498
 *
1499
 * @return string
1500
 */
1501
function bigbluebuttonbn_get_recording_data_row_preview_images($playback) {
1502
    $recordingpreview  = html_writer::start_tag('div', array('class' => 'container-fluid'));
1503
    $recordingpreview .= html_writer::start_tag('div', array('class' => 'row'));
1504
    foreach ($playback['preview'] as $image) {
1505
        if (!bigbluebuttonbn_is_valid_resource(trim($image['url']))) {
1506
            return '';
1507
        }
1508
        $recordingpreview .= html_writer::start_tag('div', array('class' => ''));
1509
        $recordingpreview .= html_writer::empty_tag('img',
1510
            array('src' => trim($image['url']) . '?' . time(), 'class' => 'recording-thumbnail pull-left'));
1511
        $recordingpreview .= html_writer::end_tag('div');
1512
    }
1513
    $recordingpreview .= html_writer::end_tag('div');
1514
    $recordingpreview .= html_writer::start_tag('div', array('class' => 'row'));
1515
    $recordingpreview .= html_writer::tag('div', get_string('view_recording_preview_help', 'bigbluebuttonbn'),
1516
        array('class' => 'text-center text-muted small'));
1517
    $recordingpreview .= html_writer::end_tag('div');
1518
    $recordingpreview .= html_writer::end_tag('div');
1519
    return $recordingpreview;
1520
}
1521
1522
/**
1523
 * Helper function renders recording types to be used in row for the data used by the recording table.
1524
 *
1525
 * @param array $recording
1526
 * @param array $bbbsession
1527
 *
1528
 * @return string
1529
 */
1530
function bigbluebuttonbn_get_recording_data_row_types($recording, $bbbsession) {
1531
    $dataimported = 'false';
1532
    $title = '';
1533
    if (isset($recording['imported'])) {
1534
        $dataimported = 'true';
1535
        $title = get_string('view_recording_link_warning', 'bigbluebuttonbn');
1536
    }
1537
    $visibility = '';
1538
    if ($recording['published'] === 'false') {
1539
        $visibility = 'hidden ';
1540
    }
1541
    $id = 'playbacks-'.$recording['recordID'];
1542
    $recordingtypes = html_writer::start_tag('div', array('id' => $id, 'data-imported' => $dataimported,
1543
          'data-meetingid' => $recording['meetingID'], 'data-recordingid' => $recording['recordID'],
1544
          'title' => $title, $visibility => $visibility));
1545
    foreach ($recording['playbacks'] as $playback) {
1546
        $recordingtypes .= bigbluebuttonbn_get_recording_data_row_type($recording, $bbbsession, $playback);
1547
    }
1548
    $recordingtypes .= html_writer::end_tag('div');
1549
    return $recordingtypes;
1550
}
1551
1552
/**
1553
 * Helper function renders the link used for recording type in row for the data used by the recording table.
1554
 *
1555
 * @param array $recording
1556
 * @param array $bbbsession
1557
 * @param array $playback
1558
 *
1559
 * @return string
1560
 */
1561
function bigbluebuttonbn_get_recording_data_row_type($recording, $bbbsession, $playback) {
1562
    global $CFG, $OUTPUT;
1563
    if (!bigbluebuttonbn_include_recording_data_row_type($recording, $bbbsession, $playback)) {
1564
        return '';
1565
    }
1566
    $text = get_string('view_recording_format_'.$playback['type'], 'bigbluebuttonbn');
1567
    $href = $CFG->wwwroot . '/mod/bigbluebuttonbn/bbb_view.php?action=play&bn=' . $bbbsession['bigbluebuttonbn']->id .
1568
      '&mid='.$recording['meetingID'] . '&rid=' . $recording['recordID'] . '&rtype=' . $playback['type'];
1569
    if (!isset($recording['imported']) || !isset($recording['protected']) || $recording['protected'] === 'false') {
1570
        $href .= '&href='.urlencode(trim($playback['url']));
1571
    }
1572
    $linkattributes = array(
1573
        'id' => 'recording-play-' . $playback['type'] . '-' . $recording['recordID'],
1574
        'class' => 'btn btn-sm btn-default',
1575
        'onclick' => 'M.mod_bigbluebuttonbn.recordings.recordingPlay(this);',
1576
        'data-action' => 'play',
1577
        'data-target' => $playback['type'],
1578
        'data-href' => $href,
1579
      );
1580
    if (!bigbluebuttonbn_is_bn_server() && !bigbluebuttonbn_is_valid_resource(trim($playback['url']))) {
1581
        $linkattributes['class'] = 'btn btn-sm btn-warning';
1582
        $linkattributes['title'] = get_string('view_recording_format_errror_unreachable', 'bigbluebuttonbn');
1583
        unset($linkattributes['data-href']);
1584
    }
1585
    return $OUTPUT->action_link('#', $text, null, $linkattributes) . '&#32;';
1586
}
1587
1588
/**
1589
 * Helper function validates a remote resource.
1590
 *
1591
 * @param string $url
1592
 *
1593
 * @return boolean
1594
 */
1595
function bigbluebuttonbn_is_valid_resource($url) {
1596
    $urlhost = parse_url($url, PHP_URL_HOST);
1597
    $serverurlhost = parse_url(\mod_bigbluebuttonbn\locallib\config::get('server_url'), PHP_URL_HOST);
1598
    // Skip validation when the recording URL host is the same as the configured BBB server.
1599
    if ($urlhost == $serverurlhost) {
1600
        return true;
1601
    }
1602
    // Skip validation when the recording URL was already validated.
1603
    $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...
1604
    if (array_key_exists($urlhost, $validatedurls)) {
1605
        return $validatedurls[$urlhost];
1606
    }
1607
    // Validate the recording URL.
1608
    $validatedurls[$urlhost] = true;
1609
    $curlinfo = bigbluebuttonbn_wrap_xml_load_file_curl_request($url, 'HEAD');
1610
    if (!isset($curlinfo['http_code']) || $curlinfo['http_code'] != 200) {
1611
        $error = "Resources hosted by " . $urlhost . " are unreachable. Server responded with code " . $curlinfo['http_code'];
1612
        debugging($error, DEBUG_DEVELOPER);
1613
        $validatedurls[$urlhost] = false;
1614
    }
1615
    bigbluebuttonbn_cache_set('recordings_cache', 'validated_urls', $validatedurls);
1616
    return $validatedurls[$urlhost];
1617
}
1618
1619
/**
1620
 * Helper function renders the name for recording used in row for the data used by the recording table.
1621
 *
1622
 * @param array $recording
1623
 * @param array $bbbsession
1624
 *
1625
 * @return string
1626
 */
1627
function bigbluebuttonbn_get_recording_data_row_meta_activity($recording, $bbbsession) {
1628
    $payload = array();
1629 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...
1630
        $payload = array('recordingid' => $recording['recordID'], 'meetingid' => $recording['meetingID'],
1631
            'action' => 'edit', 'tag' => 'edit',
1632
            'target' => 'name');
1633
    }
1634
    $oldsource = 'meta_contextactivity';
1635
    if (isset($recording[$oldsource])) {
1636
        $metaname = trim($recording[$oldsource]);
1637
        return bigbluebuttonbn_get_recording_data_row_text($recording, $metaname, $oldsource, $payload);
1638
    }
1639
    $newsource = 'meta_bbb-recording-name';
1640 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...
1641
        $metaname = trim($recording[$newsource]);
1642
        return bigbluebuttonbn_get_recording_data_row_text($recording, $metaname, $newsource, $payload);
1643
    }
1644
    $metaname = trim($recording['meetingName']);
1645
    return bigbluebuttonbn_get_recording_data_row_text($recording, $metaname, $newsource, $payload);
1646
}
1647
1648
/**
1649
 * Helper function renders the description for recording used in row for the data used by the recording table.
1650
 *
1651
 * @param array $recording
1652
 * @param array $bbbsession
1653
 *
1654
 * @return string
1655
 */
1656
function bigbluebuttonbn_get_recording_data_row_meta_description($recording, $bbbsession) {
1657
    $payload = array();
1658 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...
1659
        $payload = array('recordingid' => $recording['recordID'], 'meetingid' => $recording['meetingID'],
1660
            'action' => 'edit', 'tag' => 'edit',
1661
            'target' => 'description');
1662
    }
1663
    $oldsource = 'meta_contextactivitydescription';
1664 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...
1665
        $metadescription = trim($recording[$oldsource]);
1666
        return bigbluebuttonbn_get_recording_data_row_text($recording, $metadescription, $oldsource, $payload);
1667
    }
1668
    $newsource = 'meta_bbb-recording-description';
1669 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...
1670
        $metadescription = trim($recording[$newsource]);
1671
        return bigbluebuttonbn_get_recording_data_row_text($recording, $metadescription, $newsource, $payload);
1672
    }
1673
    return bigbluebuttonbn_get_recording_data_row_text($recording, '', $newsource, $payload);
1674
}
1675
1676
/**
1677
 * Helper function renders text element for recording used in row for the data used by the recording table.
1678
 *
1679
 * @param array $recording
1680
 * @param string $text
1681
 * @param string $source
1682
 * @param array $data
1683
 *
1684
 * @return string
1685
 */
1686
function bigbluebuttonbn_get_recording_data_row_text($recording, $text, $source, $data) {
1687
    $htmltext = '<span>' . htmlentities($text) . '</span>';
1688
    if (empty($data)) {
1689
        return $htmltext;
1690
    }
1691
    $target = $data['action'] . '-' . $data['target'];
1692
    $id = 'recording-' . $target . '-' . $data['recordingid'];
1693
    $attributes = array('id' => $id, 'class' => 'quickeditlink col-md-20',
1694
        'data-recordingid' => $data['recordingid'], 'data-meetingid' => $data['meetingid'],
1695
        'data-target' => $data['target'], 'data-source' => $source);
1696
    $head = html_writer::start_tag('div', $attributes);
1697
    $tail = html_writer::end_tag('div');
1698
    $payload = array('action' => $data['action'], 'tag' => $data['tag'], 'target' => $data['target']);
1699
    $htmllink = bigbluebuttonbn_actionbar_render_button($recording, $payload);
1700
    return $head . $htmltext . $htmllink . $tail;
1701
}
1702
1703
/**
1704
 * Helper function render a button for the recording action bar
1705
 *
1706
 * @param array $recording
1707
 * @param array $data
1708
 *
1709
 * @return string
1710
 */
1711
function bigbluebuttonbn_actionbar_render_button($recording, $data) {
1712
    global $OUTPUT;
1713
    if (empty($data)) {
1714
        return '';
1715
    }
1716
    $target = $data['action'];
1717
    if (isset($data['target'])) {
1718
        $target .= '-' . $data['target'];
1719
    }
1720
    $id = 'recording-' . $target . '-' . $recording['recordID'];
1721
    $onclick = 'M.mod_bigbluebuttonbn.recordings.recording' . ucfirst($data['action']) . '(this);';
1722
    if ((boolean)\mod_bigbluebuttonbn\locallib\config::get('recording_icons_enabled')) {
1723
        // With icon for $manageaction.
1724
        $iconattributes = array('id' => $id, 'class' => 'iconsmall');
1725
        $linkattributes = array(
1726
            'id' => $id,
1727
            'onclick' => $onclick,
1728
            'data-action' => $data['action']
1729
          );
1730
        if (!isset($recording['imported'])) {
1731
            $linkattributes['data-links'] = bigbluebuttonbn_count_recording_imported_instances(
1732
              $recording['recordID']);
1733
        }
1734
        if (isset($data['disabled'])) {
1735
            $iconattributes['class'] .= ' fa-' . $data['disabled'];
1736
            $linkattributes['class'] = 'disabled';
1737
            unset($linkattributes['onclick']);
1738
        }
1739
        $icon = new pix_icon('i/'.$data['tag'],
1740
            get_string('view_recording_list_actionbar_' . $data['action'], 'bigbluebuttonbn'),
1741
            'moodle', $iconattributes);
1742
        return $OUTPUT->action_icon('#', $icon, null, $linkattributes, false);
1743
    }
1744
    // With text for $manageaction.
1745
    $linkattributes = array('title' => get_string($data['tag']), 'class' => 'btn btn-xs btn-danger',
1746
        'onclick' => $onclick);
1747
    return $OUTPUT->action_link('#', get_string($data['action']), null, $linkattributes);
1748
}
1749
1750
/**
1751
 * Helper function builds the data used for headers by the recording table.
1752
 *
1753
 * @param array $bbbsession
1754
 *
1755
 * @return array
1756
 */
1757
function bigbluebuttonbn_get_recording_columns($bbbsession) {
1758
    $columns = array();
1759
    // Initialize table headers.
1760
    $columns[] = array('key' => 'recording', 'label' => get_string('view_recording_recording', 'bigbluebuttonbn'),
1761
        'width' => '125px', 'allowHTML' => true);
1762
    $columns[] = array('key' => 'activity', 'label' => get_string('view_recording_activity', 'bigbluebuttonbn'),
1763
        'sortable' => true, 'width' => '175px', 'allowHTML' => true);
1764
    $columns[] = array('key' => 'description', 'label' => get_string('view_recording_description', 'bigbluebuttonbn'),
1765
        'sortable' => true, 'width' => '250px', 'allowHTML' => true);
1766
    if (bigbluebuttonbn_get_recording_data_preview_enabled($bbbsession)) {
1767
        $columns[] = array('key' => 'preview', 'label' => get_string('view_recording_preview', 'bigbluebuttonbn'),
1768
            'width' => '250px', 'allowHTML' => true);
1769
    }
1770
    $columns[] = array('key' => 'date', 'label' => get_string('view_recording_date', 'bigbluebuttonbn'),
1771
        'sortable' => true, 'width' => '225px', 'allowHTML' => true);
1772
    $columns[] = array('key' => 'duration', 'label' => get_string('view_recording_duration', 'bigbluebuttonbn'),
1773
        'width' => '50px');
1774
    if ($bbbsession['managerecordings']) {
1775
        $columns[] = array('key' => 'actionbar', 'label' => get_string('view_recording_actionbar', 'bigbluebuttonbn'),
1776
            'width' => '120px', 'allowHTML' => true);
1777
    }
1778
    return $columns;
1779
}
1780
1781
/**
1782
 * Helper function builds the data used by the recording table.
1783
 *
1784
 * @param array $bbbsession
1785
 * @param array $recordings
1786
 * @param array $tools
1787
 *
1788
 * @return array
1789
 */
1790
function bigbluebuttonbn_get_recording_data($bbbsession, $recordings, $tools = ['protect', 'publish', 'delete']) {
1791
    $tabledata = array();
1792
    // Build table content.
1793
    if (isset($recordings) && !array_key_exists('messageKey', $recordings)) {
1794
        // There are recordings for this meeting.
1795
        foreach ($recordings as $recording) {
1796
            $rowdata = bigbluebuttonbn_get_recording_data_row($bbbsession, $recording, $tools);
1797
            if (!empty($rowdata)) {
1798
                array_push($tabledata, $rowdata);
1799
            }
1800
        }
1801
    }
1802
    return $tabledata;
1803
}
1804
1805
/**
1806
 * Helper function builds the recording table.
1807
 *
1808
 * @param array $bbbsession
1809
 * @param array $recordings
1810
 * @param array $tools
1811
 *
1812
 * @return object
1813
 */
1814
function bigbluebuttonbn_get_recording_table($bbbsession, $recordings, $tools = ['protect', 'publish', 'delete']) {
1815
    // Declare the table.
1816
    $table = new html_table();
1817
    $table->data = array();
1818
    // Initialize table headers.
1819
    $table->head[] = get_string('view_recording_playback', 'bigbluebuttonbn');
1820
    $table->head[] = get_string('view_recording_recording', 'bigbluebuttonbn');
1821
    $table->head[] = get_string('view_recording_description', 'bigbluebuttonbn');
1822
    if (bigbluebuttonbn_get_recording_data_preview_enabled($bbbsession)) {
1823
        $table->head[] = get_string('view_recording_preview', 'bigbluebuttonbn');
1824
    }
1825
    $table->head[] = get_string('view_recording_date', 'bigbluebuttonbn');
1826
    $table->head[] = get_string('view_recording_duration', 'bigbluebuttonbn');
1827
    $table->align = array('left', 'left', 'left', 'left', 'left', 'center');
1828
    $table->size = array('', '', '', '', '', '');
1829
    if ($bbbsession['managerecordings']) {
1830
        $table->head[] = get_string('view_recording_actionbar', 'bigbluebuttonbn');
1831
        $table->align[] = 'left';
1832
        $table->size[] = (count($tools) * 40) . 'px';
1833
    }
1834
    // Build table content.
1835
    foreach ($recordings as $recording) {
1836
        $rowdata = bigbluebuttonbn_get_recording_data_row($bbbsession, $recording, $tools);
1837
        if (!empty($rowdata)) {
1838
            $row = bigbluebuttonbn_get_recording_table_row($bbbsession, $recording, $rowdata);
1839
            array_push($table->data, $row);
1840
        }
1841
    }
1842
    return $table;
1843
}
1844
1845
/**
1846
 * Helper function builds the recording table row and insert into table.
1847
 *
1848
 * @param array $bbbsession
1849
 * @param array $recording
1850
 * @param object $rowdata
1851
 *
1852
 * @return object
1853
 */
1854
function bigbluebuttonbn_get_recording_table_row($bbbsession, $recording, $rowdata) {
1855
    $row = new html_table_row();
1856
    $row->id = 'recording-tr-'.$recording['recordID'];
1857
    $row->attributes['data-imported'] = 'false';
1858
    $texthead = '';
1859
    $texttail = '';
1860
    if (isset($recording['imported'])) {
1861
        $row->attributes['title'] = get_string('view_recording_link_warning', 'bigbluebuttonbn');
1862
        $row->attributes['data-imported'] = 'true';
1863
        $texthead = '<em>';
1864
        $texttail = '</em>';
1865
    }
1866
    $rowdata->date_formatted = str_replace(' ', '&nbsp;', $rowdata->date_formatted);
1867
    $row->cells = array();
1868
    $row->cells[] = $texthead . $rowdata->recording . $texttail;
1869
    $row->cells[] = $texthead . $rowdata->activity . $texttail;
1870
    $row->cells[] = $texthead . $rowdata->description . $texttail;
1871
    if (bigbluebuttonbn_get_recording_data_preview_enabled($bbbsession)) {
1872
        $row->cells[] = $rowdata->preview;
1873
    }
1874
    $row->cells[] = $texthead . $rowdata->date_formatted . $texttail;
1875
    $row->cells[] = $rowdata->duration_formatted;
1876
    if ($bbbsession['managerecordings']) {
1877
        $row->cells[] = $rowdata->actionbar;
1878
    }
1879
    return $row;
1880
}
1881
1882
/**
1883
 * Helper function evaluates if recording row should be included in the table.
1884
 *
1885
 * @param array $bbbsession
1886
 * @param array $recording
1887
 *
1888
 * @return boolean
1889
 */
1890
function bigbluebuttonbn_include_recording_table_row($bbbsession, $recording) {
1891
    // Exclude unpublished recordings, only if user has no rights to manage them.
1892
    if ($recording['published'] != 'true' && !$bbbsession['managerecordings']) {
1893
        return false;
1894
    }
1895
    // Imported recordings are always shown as long as they are published.
1896
    if (isset($recording['imported'])) {
1897
        return true;
1898
    }
1899
    // When groups are enabled, exclude those to which the user doesn't have access to.
1900
    if (isset($bbbsession['group']) && $recording['meetingID'] != $bbbsession['meetingid']) {
1901
        return false;
1902
    }
1903
    return true;
1904
}
1905
1906
/**
1907
 * Helper function triggers a send notification when the recording is ready.
1908
 *
1909
 * @param object $bigbluebuttonbn
1910
 *
1911
 * @return void
1912
 */
1913
function bigbluebuttonbn_send_notification_recording_ready($bigbluebuttonbn) {
1914
    $sender = get_admin();
1915
    // Prepare message.
1916
    $messagetext = '<p>'.get_string('email_body_recording_ready_for', 'bigbluebuttonbn').
1917
        ' "' . $bigbluebuttonbn->name . '" '.
1918
        get_string('email_body_recording_ready_is_ready', 'bigbluebuttonbn').'.</p>';
1919
    $context = context_course::instance($bigbluebuttonbn->course);
1920
    \mod_bigbluebuttonbn\locallib\notifier::notification_send($context, $sender, $bigbluebuttonbn, $messagetext);
1921
}
1922
1923
/**
1924
 * Helper evaluates if the bigbluebutton server used belongs to blindsidenetworks domain.
1925
 *
1926
 * @return boolean
1927
 */
1928
function bigbluebuttonbn_is_bn_server() {
1929
    $parsedurl = parse_url(\mod_bigbluebuttonbn\locallib\config::get('server_url'));
1930
    if (!isset($parsedurl['host'])) {
1931
        return false;
1932
    }
1933
    $h = $parsedurl['host'];
1934
    $hends = explode('.', $h);
1935
    $hendslength = count($hends);
1936
    return ($hends[$hendslength - 1] == 'com' && $hends[$hendslength - 2] == 'blindsidenetworks');
1937
}
1938
1939
/**
1940
 * Helper function returns a list of courses a user has access to, wrapped in an array that can be used
1941
 * by a html select.
1942
 *
1943
 * @param array $bbbsession
1944
 *
1945
 * @return array
1946
 */
1947
function bigbluebuttonbn_import_get_courses_for_select(array $bbbsession) {
1948
    if ($bbbsession['administrator']) {
1949
        $courses = get_courses('all', 'c.fullname ASC', 'c.id,c.shortname,c.fullname');
1950
        // It includes the name of the site as a course (category 0), so remove the first one.
1951
        unset($courses['1']);
1952
    } else {
1953
        $courses = enrol_get_users_courses($bbbsession['userID'], false, 'id,shortname,fullname');
1954
    }
1955
    $coursesforselect = [];
1956
    foreach ($courses as $course) {
1957
        $coursesforselect[$course->id] = $course->fullname;
1958
    }
1959
    return $coursesforselect;
1960
}
1961
1962
/**
1963
 * Helper function renders recording table.
1964
 *
1965
 * @param array $bbbsession
1966
 * @param array $recordings
1967
 * @param array $tools
1968
 *
1969
 * @return array
1970
 */
1971
function bigbluebuttonbn_output_recording_table($bbbsession, $recordings, $tools = ['protect', 'publish', 'delete']) {
1972
    if (isset($recordings) && !empty($recordings)) {
1973
        // There are recordings for this meeting.
1974
        $table = bigbluebuttonbn_get_recording_table($bbbsession, $recordings, $tools);
1975
    }
1976
    if (!isset($table) || !isset($table->data)) {
1977
        // Render a table with "No recordings".
1978
        return html_writer::div(get_string('view_message_norecordings', 'bigbluebuttonbn'), '',
1979
            array('id' => 'bigbluebuttonbn_recordings_table'));
1980
    }
1981
    // Render the table.
1982
    return html_writer::div(html_writer::table($table), '', array('id' => 'bigbluebuttonbn_recordings_table'));
1983
}
1984
1985
/**
1986
 * Helper function to convert an html string to plain text.
1987
 *
1988
 * @param string $html
1989
 * @param integer $len
1990
 *
1991
 * @return string
1992
 */
1993
function bigbluebuttonbn_html2text($html, $len = 0) {
1994
    $text = strip_tags($html);
1995
    $text = str_replace('&nbsp;', ' ', $text);
1996
    $textlen = strlen($text);
1997
    $text = substr($text, 0, $len);
1998
    if ($textlen > $len) {
1999
        $text .= '...';
2000
    }
2001
    return $text;
2002
}
2003
2004
/**
2005
 * Helper function to obtain the tags linked to a bigbluebuttonbn activity
2006
 *
2007
 * @param string $id
2008
 *
2009
 * @return string containing the tags separated by commas
2010
 */
2011
function bigbluebuttonbn_get_tags($id) {
2012
    if (class_exists('core_tag_tag')) {
2013
        return implode(',', core_tag_tag::get_item_tags_array('core', 'course_modules', $id));
2014
    }
2015
    return implode(',', tag_get_tags('bigbluebuttonbn', $id));
2016
}
2017
2018
/**
2019
 * Helper function to define the sql used for gattering the bigbluebuttonbnids whose meetingids should be included
2020
 * in the getRecordings request
2021
 *
2022
 * @param string $courseid
2023
 * @param string $bigbluebuttonbnid
2024
 * @param bool   $subset
2025
 *
2026
 * @return string containing the sql used for getting the target bigbluebuttonbn instances
2027
 */
2028
function bigbluebuttonbn_get_recordings_sql_select($courseid, $bigbluebuttonbnid = null, $subset = true) {
2029
    if (empty($courseid)) {
2030
        $courseid = 0;
2031
    }
2032
    if (empty($bigbluebuttonbnid)) {
2033
        return "course = '{$courseid}'";
2034
    }
2035
    if ($subset) {
2036
        return "id = '{$bigbluebuttonbnid}'";
2037
    }
2038
    return "id <> '{$bigbluebuttonbnid}' AND course = '{$courseid}'";
2039
}
2040
2041
/**
2042
 * Helper function to define the sql used for gattering the bigbluebuttonbnids whose meetingids should be included
2043
 * in the getRecordings request considering only those that belong to deleted activities.
2044
 *
2045
 * @param string $courseid
2046
 * @param string $bigbluebuttonbnid
2047
 * @param bool   $subset
2048
 *
2049
 * @return string containing the sql used for getting the target bigbluebuttonbn instances
2050
 */
2051 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...
2052
    $sql = "log = '" . BIGBLUEBUTTONBN_LOG_EVENT_DELETE . "' AND meta like '%has_recordings%' AND meta like '%true%'";
2053
    if (empty($courseid)) {
2054
        $courseid = 0;
2055
    }
2056
    if (empty($bigbluebuttonbnid)) {
2057
        return $sql . " AND courseid = {$courseid}";
2058
    }
2059
    if ($subset) {
2060
        return $sql . " AND bigbluebuttonbnid = '{$bigbluebuttonbnid}'";
2061
    }
2062
    return $sql . " AND courseid = {$courseid} AND bigbluebuttonbnid <> '{$bigbluebuttonbnid}'";
2063
}
2064
2065
/**
2066
 * Helper function to define the sql used for gattering the bigbluebuttonbnids whose meetingids should be included
2067
 * in the getRecordings request considering only those that belong to imported recordings.
2068
 *
2069
 * @param string $courseid
2070
 * @param string $bigbluebuttonbnid
2071
 * @param bool   $subset
2072
 *
2073
 * @return string containing the sql used for getting the target bigbluebuttonbn instances
2074
 */
2075 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...
2076
    $sql = "log = '" . BIGBLUEBUTTONBN_LOG_EVENT_IMPORT . "'";
2077
    if (empty($courseid)) {
2078
        $courseid = 0;
2079
    }
2080
    if (empty($bigbluebuttonbnid)) {
2081
        return $sql . " AND courseid = '{$courseid}'";
2082
    }
2083
    if ($subset) {
2084
        return $sql . " AND bigbluebuttonbnid = '{$bigbluebuttonbnid}'";
2085
    }
2086
    return $sql . " AND courseid = '{$courseid}' AND bigbluebuttonbnid <> '{$bigbluebuttonbnid}'";
2087
}
2088
2089
/**
2090
 * Helper function to get recordings  and imported recordings together.
2091
 *
2092
 * @param string $courseid
2093
 * @param string $bigbluebuttonbnid
2094
 * @param bool   $subset
2095
 * @param bool   $includedeleted
2096
 *
2097
 * @return associative array containing the recordings indexed by recordID, each recording is also a
2098
 * non sequential associative array itself that corresponds to the actual recording in BBB
2099
 */
2100
function bigbluebuttonbn_get_allrecordings($courseid = 0, $bigbluebuttonbnid = null, $subset = true, $includedeleted = false) {
2101
    $recordings = bigbluebuttonbn_get_recordings($courseid, $bigbluebuttonbnid, $subset, $includedeleted);
2102
    $recordingsimported = bigbluebuttonbn_get_recordings_imported_array($courseid, $bigbluebuttonbnid, $subset);
2103
    return ($recordings + $recordingsimported);
2104
}
2105
2106
/**
2107
 * Helper function to retrieve recordings from the BigBlueButton. The references are stored as events
2108
 * in bigbluebuttonbn_logs.
2109
 *
2110
 * @param string $courseid
2111
 * @param string $bigbluebuttonbnid
2112
 * @param bool   $subset
2113
 * @param bool   $includedeleted
2114
 *
2115
 * @return associative array containing the recordings indexed by recordID, each recording is also a
2116
 * non sequential associative array itself that corresponds to the actual recording in BBB
2117
 */
2118
function bigbluebuttonbn_get_recordings($courseid = 0, $bigbluebuttonbnid = null, $subset = true, $includedeleted = false) {
2119
    global $DB;
2120
    $select = bigbluebuttonbn_get_recordings_sql_select($courseid, $bigbluebuttonbnid, $subset);
2121
    $bigbluebuttonbns = $DB->get_records_select_menu('bigbluebuttonbn', $select, null, 'id', 'id, meetingid');
2122
    /* Consider logs from deleted bigbluebuttonbn instances whose meetingids should be included in
2123
     * the getRecordings request. */
2124
    if ($includedeleted) {
2125
        $selectdeleted = bigbluebuttonbn_get_recordings_deleted_sql_select($courseid, $bigbluebuttonbnid, $subset);
2126
        $bigbluebuttonbnsdel = $DB->get_records_select_menu('bigbluebuttonbn_logs', $selectdeleted, null,
2127
            'bigbluebuttonbnid', 'bigbluebuttonbnid, meetingid');
2128
        if (!empty($bigbluebuttonbnsdel)) {
2129
            // Merge bigbluebuttonbnis from deleted instances, only keys are relevant.
2130
            // Artimetic merge is used in order to keep the keys.
2131
            $bigbluebuttonbns += $bigbluebuttonbnsdel;
2132
        }
2133
    }
2134
    // Gather the meetingids from bigbluebuttonbn logs that include a create with record=true.
2135
    if (empty($bigbluebuttonbns)) {
2136
        return array();
2137
    }
2138
    // Prepare select for loading records based on existent bigbluebuttonbns.
2139
    $sql = 'SELECT DISTINCT meetingid, bigbluebuttonbnid FROM {bigbluebuttonbn_logs} WHERE ';
2140
    $sql .= '(bigbluebuttonbnid='.implode(' OR bigbluebuttonbnid=', array_keys($bigbluebuttonbns)).')';
2141
    // Include only Create events and exclude those with record not true.
2142
    $sql .= ' AND log = ? AND meta LIKE ? AND meta LIKE ?';
2143
    // Execute select for loading records based on existent bigbluebuttonbns.
2144
    $records = $DB->get_records_sql_menu($sql, array(BIGBLUEBUTTONBN_LOG_EVENT_CREATE, '%record%', '%true%'));
2145
    // Get actual recordings.
2146
    return bigbluebuttonbn_get_recordings_array(array_keys($records));
2147
}
2148
2149
/**
2150
 * Helper function iterates an array with recordings and unset those already imported.
2151
 *
2152
 * @param array $recordings
2153
 * @param integer $courseid
2154
 * @param integer $bigbluebuttonbnid
2155
 *
2156
 * @return array
2157
 */
2158
function bigbluebuttonbn_unset_existent_recordings_already_imported($recordings, $courseid, $bigbluebuttonbnid) {
2159
    $recordingsimported = bigbluebuttonbn_get_recordings_imported_array($courseid, $bigbluebuttonbnid, true);
2160
    foreach ($recordings as $key => $recording) {
2161
        if (isset($recordingsimported[$recording['recordID']])) {
2162
            unset($recordings[$key]);
2163
        }
2164
    }
2165
    return $recordings;
2166
}
2167
2168
/**
2169
 * Helper function to count the imported recordings for a recordingid.
2170
 *
2171
 * @param string $recordid
2172
 *
2173
 * @return integer
2174
 */
2175
function bigbluebuttonbn_count_recording_imported_instances($recordid) {
2176
    global $DB;
2177
    $sql = 'SELECT COUNT(DISTINCT id) FROM {bigbluebuttonbn_logs} WHERE log = ? AND meta LIKE ? AND meta LIKE ?';
2178
    return $DB->count_records_sql($sql, array(BIGBLUEBUTTONBN_LOG_EVENT_IMPORT, '%recordID%', "%{$recordid}%"));
2179
}
2180
2181
/**
2182
 * Helper function to get how much callback events are logged.
2183
 *
2184
 * @param string $recordid
2185
 *
2186
 * @return integer
2187
 */
2188
function bigbluebuttonbn_get_count_callback_event_log($recordid) {
2189
    global $DB;
2190
    $sql = 'SELECT count(DISTINCT id) FROM {bigbluebuttonbn_logs} WHERE log = ? AND meta LIKE ? AND meta LIKE ?';
2191
    return $DB->count_records_sql($sql, array(BIGBLUEBUTTON_LOG_EVENT_CALLBACK, '%recordid%', "%{$recordid}%"));
2192
}
2193
2194
/**
2195
 * Helper function returns an array with all the instances of imported recordings for a recordingid.
2196
 *
2197
 * @param string $recordid
2198
 *
2199
 * @return array
2200
 */
2201
function bigbluebuttonbn_get_recording_imported_instances($recordid) {
2202
    global $DB;
2203
    $sql = 'SELECT * FROM {bigbluebuttonbn_logs} WHERE log = ? AND meta LIKE ? AND meta LIKE ?';
2204
    $recordingsimported = $DB->get_records_sql($sql, array(BIGBLUEBUTTONBN_LOG_EVENT_IMPORT, '%recordID%',
2205
        "%{$recordid}%"));
2206
    return $recordingsimported;
2207
}
2208
2209
/**
2210
 * Helper function returns an array with the profiles (with features per profile) for the different types
2211
 * of bigbluebuttonbn instances.
2212
 *
2213
 * @return array
2214
 */
2215
function bigbluebuttonbn_get_instance_type_profiles() {
2216
    $instanceprofiles = array(
2217
            array('id' => BIGBLUEBUTTONBN_TYPE_ALL, 'name' => get_string('instance_type_default', 'bigbluebuttonbn'),
2218
                'features' => array('all')),
2219
            array('id' => BIGBLUEBUTTONBN_TYPE_ROOM_ONLY, 'name' => get_string('instance_type_room_only', 'bigbluebuttonbn'),
2220
                'features' => array('showroom', 'welcomemessage', 'voicebridge', 'waitformoderator', 'userlimit', 'recording',
2221
                    'sendnotifications', 'preuploadpresentation', 'permissions', 'schedule', 'groups',
2222
                    'modstandardelshdr', 'availabilityconditionsheader', 'tagshdr', 'competenciessection', 'clienttype')),
2223
            array('id' => BIGBLUEBUTTONBN_TYPE_RECORDING_ONLY, 'name' => get_string('instance_type_recording_only',
2224
                'bigbluebuttonbn'), 'features' => array('showrecordings', 'importrecordings')),
2225
    );
2226
    return $instanceprofiles;
2227
}
2228
2229
/**
2230
 * Helper function returns an array with enabled features for an specific profile type.
2231
 *
2232
 * @param array $typeprofiles
2233
 * @param string $type
2234
 *
2235
 * @return array
2236
 */
2237
function bigbluebuttonbn_get_enabled_features($typeprofiles, $type = null) {
2238
    $enabledfeatures = array();
2239
    $features = $typeprofiles[0]['features'];
2240
    if (!is_null($type)) {
2241
        $features = $typeprofiles[$type]['features'];
2242
    }
2243
    $enabledfeatures['showroom'] = (in_array('all', $features) || in_array('showroom', $features));
2244
    // Evaluates if recordings are enabled for the Moodle site.
2245
    $enabledfeatures['showrecordings'] = false;
2246
    if (\mod_bigbluebuttonbn\locallib\config::recordings_enabled()) {
2247
        $enabledfeatures['showrecordings'] = (in_array('all', $features) || in_array('showrecordings', $features));
2248
    }
2249
    $enabledfeatures['importrecordings'] = false;
2250
    if (\mod_bigbluebuttonbn\locallib\config::importrecordings_enabled()) {
2251
        $enabledfeatures['importrecordings'] = (in_array('all', $features) || in_array('importrecordings', $features));
2252
    }
2253
    // Evaluates if clienttype is enabled for the Moodle site.
2254
    $enabledfeatures['clienttype'] = false;
2255
    if (\mod_bigbluebuttonbn\locallib\config::clienttype_enabled()) {
2256
        $enabledfeatures['clienttype'] = (in_array('all', $features) || in_array('clienttype', $features));
2257
    }
2258
    return $enabledfeatures;
2259
}
2260
2261
/**
2262
 * Helper function returns an array with the profiles (with features per profile) for the different types
2263
 * of bigbluebuttonbn instances.
2264
 *
2265
 * @param array $profiles
2266
 *
2267
 * @return array
2268
 */
2269
function bigbluebuttonbn_get_instance_profiles_array($profiles = null) {
2270
    if (is_null($profiles) || empty($profiles)) {
2271
        $profiles = bigbluebuttonbn_get_instance_type_profiles();
2272
    }
2273
    $profilesarray = array();
2274
    foreach ($profiles as $profile) {
2275
        $profilesarray += array("{$profile['id']}" => $profile['name']);
2276
    }
2277
    return $profilesarray;
2278
}
2279
2280
/**
2281
 * Helper function returns time in a formatted string.
2282
 *
2283
 * @param integer $time
2284
 *
2285
 * @return string
2286
 */
2287
function bigbluebuttonbn_format_activity_time($time) {
2288
    $activitytime = '';
2289
    if ($time) {
2290
        $activitytime = calendar_day_representation($time).' '.
2291
          get_string('mod_form_field_notification_msg_at', 'bigbluebuttonbn').' '.
2292
          calendar_time_representation($time);
2293
    }
2294
    return $activitytime;
2295
}
2296
2297
/**
2298
 * Helper function returns array with all the strings to be used in javascript.
2299
 *
2300
 * @return array
2301
 */
2302
function bigbluebuttonbn_get_strings_for_js() {
2303
    $locale = bigbluebuttonbn_get_locale();
2304
    $stringman = get_string_manager();
2305
    $strings = $stringman->load_component_strings('bigbluebuttonbn', $locale);
2306
    return $strings;
2307
}
2308
2309
/**
2310
 * Helper function returns the locale set by moodle.
2311
 *
2312
 * @return string
2313
 */
2314
function bigbluebuttonbn_get_locale() {
2315
    $lang = get_string('locale', 'core_langconfig');
2316
    return substr($lang, 0, strpos($lang, '.'));
2317
}
2318
2319
/**
2320
 * Helper function returns the locale code based on the locale set by moodle.
2321
 *
2322
 * @return string
2323
 */
2324
function bigbluebuttonbn_get_localcode() {
2325
    $locale = bigbluebuttonbn_get_locale();
2326
    return substr($locale, 0, strpos($locale, '_'));
2327
}
2328
2329
/**
2330
 * Helper function returns array with the instance settings used in views.
2331
 *
2332
 * @param string $id
2333
 * @param object $bigbluebuttonbnid
2334
 *
2335
 * @return array
2336
 */
2337
function bigbluebuttonbn_views_validator($id, $bigbluebuttonbnid) {
2338
    if ($id) {
2339
        return bigbluebuttonbn_views_instance_id($id);
2340
    }
2341
    if ($bigbluebuttonbnid) {
2342
        return bigbluebuttonbn_views_instance_bigbluebuttonbn($bigbluebuttonbnid);
2343
    }
2344
    return;
2345
}
2346
2347
/**
2348
 * Helper function returns array with the instance settings used in views based on id.
2349
 *
2350
 * @param string $id
2351
 *
2352
 * @return array
2353
 */
2354 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...
2355
    global $DB;
2356
    $cm = get_coursemodule_from_id('bigbluebuttonbn', $id, 0, false, MUST_EXIST);
2357
    $course = $DB->get_record('course', array('id' => $cm->course), '*', MUST_EXIST);
2358
    $bigbluebuttonbn = $DB->get_record('bigbluebuttonbn', array('id' => $cm->instance), '*', MUST_EXIST);
2359
    return array('cm' => $cm, 'course' => $course, 'bigbluebuttonbn' => $bigbluebuttonbn);
2360
}
2361
2362
/**
2363
 * Helper function returns array with the instance settings used in views based on bigbluebuttonbnid.
2364
 *
2365
 * @param object $bigbluebuttonbnid
2366
 *
2367
 * @return array
2368
 */
2369 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...
2370
    global $DB;
2371
    $bigbluebuttonbn = $DB->get_record('bigbluebuttonbn', array('id' => $bigbluebuttonbnid), '*', MUST_EXIST);
2372
    $course = $DB->get_record('course', array('id' => $bigbluebuttonbn->course), '*', MUST_EXIST);
2373
    $cm = get_coursemodule_from_instance('bigbluebuttonbn', $bigbluebuttonbn->id, $course->id, false, MUST_EXIST);
2374
    return array('cm' => $cm, 'course' => $course, 'bigbluebuttonbn' => $bigbluebuttonbn);
2375
}
2376
2377
/**
2378
 * Helper function renders general warning message for settings (if any).
2379
 *
2380
 * @param object $renderer
2381
 *
2382
 * @return void
2383
 */
2384
function bigbluebuttonbn_settings_general_warning(&$renderer) {
2385
    global $BIGBLUEBUTTONBN_CFG;
2386
    if (isset($BIGBLUEBUTTONBN_CFG)) {
2387
        $renderer->render_warning_message('general_warning',
2388
             get_string('config_warning_bigbluebuttonbn_cfg_deprecated', 'bigbluebuttonbn'));
2389
    }
2390
}
2391
2392
/**
2393
 * Helper function renders general settings if the feature is enabled.
2394
 *
2395
 * @param object $renderer
2396
 *
2397
 * @return void
2398
 */
2399
function bigbluebuttonbn_settings_general(&$renderer) {
2400
    // Configuration for BigBlueButton.
2401
    if ((boolean)\mod_bigbluebuttonbn\settings\renderer::section_general_shown()) {
2402
        $renderer->render_group_header('general');
2403
        $renderer->render_group_element('server_url',
2404
            $renderer->render_group_element_text('server_url', BIGBLUEBUTTONBN_DEFAULT_SERVER_URL));
2405
        $renderer->render_group_element('shared_secret',
2406
            $renderer->render_group_element_text('shared_secret', BIGBLUEBUTTONBN_DEFAULT_SHARED_SECRET));
2407
    }
2408
}
2409
2410
/**
2411
 * Helper function renders record settings if the feature is enabled.
2412
 *
2413
 * @param object $renderer
2414
 *
2415
 * @return void
2416
 */
2417
function bigbluebuttonbn_settings_record(&$renderer) {
2418
    // Configuration for 'recording' feature.
2419 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...
2420
        $renderer->render_group_header('recording');
2421
        $renderer->render_group_element('recording_default',
2422
            $renderer->render_group_element_checkbox('recording_default', 1));
2423
        $renderer->render_group_element('recording_editable',
2424
            $renderer->render_group_element_checkbox('recording_editable', 1));
2425
        $renderer->render_group_element('recording_icons_enabled',
2426
            $renderer->render_group_element_checkbox('recording_icons_enabled', 1));
2427
    }
2428
}
2429
2430
/**
2431
 * Helper function renders import recording settings if the feature is enabled.
2432
 *
2433
 * @param object $renderer
2434
 *
2435
 * @return void
2436
 */
2437 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...
2438
    // Configuration for 'import recordings' feature.
2439
    if ((boolean)\mod_bigbluebuttonbn\settings\renderer::section_import_recordings_shown()) {
2440
        $renderer->render_group_header('importrecordings');
2441
        $renderer->render_group_element('importrecordings_enabled',
2442
            $renderer->render_group_element_checkbox('importrecordings_enabled', 0));
2443
        $renderer->render_group_element('importrecordings_from_deleted_enabled',
2444
            $renderer->render_group_element_checkbox('importrecordings_from_deleted_enabled', 0));
2445
    }
2446
}
2447
2448
/**
2449
 * Helper function renders show recording settings if the feature is enabled.
2450
 *
2451
 * @param object $renderer
2452
 *
2453
 * @return void
2454
 */
2455
function bigbluebuttonbn_settings_showrecordings(&$renderer) {
2456
    // Configuration for 'show recordings' feature.
2457
    if ((boolean)\mod_bigbluebuttonbn\settings\renderer::section_show_recordings_shown()) {
2458
        $renderer->render_group_header('recordings');
2459
        $renderer->render_group_element('recordings_html_default',
2460
            $renderer->render_group_element_checkbox('recordings_html_default', 1));
2461
        $renderer->render_group_element('recordings_html_editable',
2462
            $renderer->render_group_element_checkbox('recordings_html_editable', 0));
2463
        $renderer->render_group_element('recordings_deleted_default',
2464
            $renderer->render_group_element_checkbox('recordings_deleted_default', 1));
2465
        $renderer->render_group_element('recordings_deleted_editable',
2466
            $renderer->render_group_element_checkbox('recordings_deleted_editable', 0));
2467
        $renderer->render_group_element('recordings_imported_default',
2468
            $renderer->render_group_element_checkbox('recordings_imported_default', 0));
2469
        $renderer->render_group_element('recordings_imported_editable',
2470
            $renderer->render_group_element_checkbox('recordings_imported_editable', 1));
2471
        $renderer->render_group_element('recordings_preview_default',
2472
            $renderer->render_group_element_checkbox('recordings_preview_default', 1));
2473
        $renderer->render_group_element('recordings_preview_editable',
2474
            $renderer->render_group_element_checkbox('recordings_preview_editable', 0));
2475
    }
2476
}
2477
2478
/**
2479
 * Helper function renders wait for moderator settings if the feature is enabled.
2480
 *
2481
 * @param object $renderer
2482
 *
2483
 * @return void
2484
 */
2485
function bigbluebuttonbn_settings_waitmoderator(&$renderer) {
2486
    // Configuration for wait for moderator feature.
2487
    if ((boolean)\mod_bigbluebuttonbn\settings\renderer::section_wait_moderator_shown()) {
2488
        $renderer->render_group_header('waitformoderator');
2489
        $renderer->render_group_element('waitformoderator_default',
2490
            $renderer->render_group_element_checkbox('waitformoderator_default', 0));
2491
        $renderer->render_group_element('waitformoderator_editable',
2492
            $renderer->render_group_element_checkbox('waitformoderator_editable', 1));
2493
        $renderer->render_group_element('waitformoderator_ping_interval',
2494
            $renderer->render_group_element_text('waitformoderator_ping_interval', 10, PARAM_INT));
2495
        $renderer->render_group_element('waitformoderator_cache_ttl',
2496
            $renderer->render_group_element_text('waitformoderator_cache_ttl', 60, PARAM_INT));
2497
    }
2498
}
2499
2500
/**
2501
 * Helper function renders static voice bridge settings if the feature is enabled.
2502
 *
2503
 * @param object $renderer
2504
 *
2505
 * @return void
2506
 */
2507
function bigbluebuttonbn_settings_voicebridge(&$renderer) {
2508
    // Configuration for "static voice bridge" feature.
2509
    if ((boolean)\mod_bigbluebuttonbn\settings\renderer::section_static_voice_bridge_shown()) {
2510
        $renderer->render_group_header('voicebridge');
2511
        $renderer->render_group_element('voicebridge_editable',
2512
            $renderer->render_group_element_checkbox('voicebridge_editable', 0));
2513
    }
2514
}
2515
2516
/**
2517
 * Helper function renders preuploaded presentation settings if the feature is enabled.
2518
 *
2519
 * @param object $renderer
2520
 *
2521
 * @return void
2522
 */
2523
function bigbluebuttonbn_settings_preupload(&$renderer) {
2524
    // Configuration for "preupload presentation" feature.
2525
    if ((boolean)\mod_bigbluebuttonbn\settings\renderer::section_preupload_presentation_shown()) {
2526
        // This feature only works if curl is installed.
2527
        $preuploaddescripion = get_string('config_preuploadpresentation_description', 'bigbluebuttonbn');
2528
        if (!extension_loaded('curl')) {
2529
            $preuploaddescripion .= '<div class="form-defaultinfo">';
2530
            $preuploaddescripion .= get_string('config_warning_curl_not_installed', 'bigbluebuttonbn');
2531
            $preuploaddescripion .= '</div><br>';
2532
        }
2533
        $renderer->render_group_header('preuploadpresentation', null, $preuploaddescripion);
2534
        if (extension_loaded('curl')) {
2535
            $renderer->render_group_element('preuploadpresentation_enabled',
2536
                $renderer->render_group_element_checkbox('preuploadpresentation_enabled', 0));
2537
        }
2538
    }
2539
}
2540
2541
/**
2542
 * Helper function renders userlimit settings if the feature is enabled.
2543
 *
2544
 * @param object $renderer
2545
 *
2546
 * @return void
2547
 */
2548
function bigbluebuttonbn_settings_userlimit(&$renderer) {
2549
    // Configuration for "user limit" feature.
2550
    if ((boolean)\mod_bigbluebuttonbn\settings\renderer::section_user_limit_shown()) {
2551
        $renderer->render_group_header('userlimit');
2552
        $renderer->render_group_element('userlimit_default',
2553
            $renderer->render_group_element_text('userlimit_default', 0, PARAM_INT));
2554
        $renderer->render_group_element('userlimit_editable',
2555
            $renderer->render_group_element_checkbox('userlimit_editable', 0));
2556
    }
2557
}
2558
2559
/**
2560
 * Helper function renders duration settings if the feature is enabled.
2561
 *
2562
 * @param object $renderer
2563
 *
2564
 * @return void
2565
 */
2566
function bigbluebuttonbn_settings_duration(&$renderer) {
2567
    // Configuration for "scheduled duration" feature.
2568 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...
2569
        $renderer->render_group_header('scheduled');
2570
        $renderer->render_group_element('scheduled_duration_enabled',
2571
            $renderer->render_group_element_checkbox('scheduled_duration_enabled', 1));
2572
        $renderer->render_group_element('scheduled_duration_compensation',
2573
            $renderer->render_group_element_text('scheduled_duration_compensation', 10, PARAM_INT));
2574
        $renderer->render_group_element('scheduled_pre_opening',
2575
            $renderer->render_group_element_text('scheduled_pre_opening', 10, PARAM_INT));
2576
    }
2577
}
2578
2579
/**
2580
 * Helper function renders participant settings if the feature is enabled.
2581
 *
2582
 * @param object $renderer
2583
 *
2584
 * @return void
2585
 */
2586
function bigbluebuttonbn_settings_participants(&$renderer) {
2587
    // Configuration for defining the default role/user that will be moderator on new activities.
2588
    if ((boolean)\mod_bigbluebuttonbn\settings\renderer::section_moderator_default_shown()) {
2589
        $renderer->render_group_header('participant');
2590
        // UI for 'participants' feature.
2591
        $roles = bigbluebuttonbn_get_roles();
2592
        $owner = array('0' => get_string('mod_form_field_participant_list_type_owner', 'bigbluebuttonbn'));
2593
        $renderer->render_group_element('participant_moderator_default',
2594
            $renderer->render_group_element_configmultiselect('participant_moderator_default',
2595
                array_keys($owner), array_merge($owner, $roles))
2596
          );
2597
    }
2598
}
2599
2600
/**
2601
 * Helper function renders notification settings if the feature is enabled.
2602
 *
2603
 * @param object $renderer
2604
 *
2605
 * @return void
2606
 */
2607
function bigbluebuttonbn_settings_notifications(&$renderer) {
2608
    // Configuration for "send notifications" feature.
2609
    if ((boolean)\mod_bigbluebuttonbn\settings\renderer::section_send_notifications_shown()) {
2610
        $renderer->render_group_header('sendnotifications');
2611
        $renderer->render_group_element('sendnotifications_enabled',
2612
            $renderer->render_group_element_checkbox('sendnotifications_enabled', 1));
2613
    }
2614
}
2615
2616
/**
2617
 * Helper function renders client type settings if the feature is enabled.
2618
 *
2619
 * @param object $renderer
2620
 *
2621
 * @return void
2622
 */
2623
function bigbluebuttonbn_settings_clienttype(&$renderer) {
2624
    // Configuration for "clienttype" feature.
2625
    if ((boolean)\mod_bigbluebuttonbn\settings\renderer::section_clienttype_shown()) {
2626
        $renderer->render_group_header('clienttype');
2627
        $renderer->render_group_element('clienttype_editable',
2628
            $renderer->render_group_element_checkbox('clienttype_editable', 0));
2629
2630
        // Web Client default.
2631
        $default = intval((int)\mod_bigbluebuttonbn\locallib\config::get('clienttype_default'));
2632
2633
        $choices = array(BIGBLUEBUTTON_CLIENTTYPE_FLASH => get_string('mod_form_block_clienttype_flash', 'bigbluebuttonbn'),
2634
                         BIGBLUEBUTTON_CLIENTTYPE_HTML5 => get_string('mod_form_block_clienttype_html5', 'bigbluebuttonbn'));
2635
        $renderer->render_group_element('clienttype_default',
2636
            $renderer->render_group_element_configselect('clienttype_default',
2637
                $default, $choices));
2638
    }
2639
}
2640
2641
/**
2642
 * Helper function renders extended settings if any of the features there is enabled.
2643
 *
2644
 * @param object $renderer
2645
 *
2646
 * @return void
2647
 */
2648 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...
2649
    // Configuration for extended BN capabilities.
2650
    if (!bigbluebuttonbn_is_bn_server()) {
2651
        return;
2652
    }
2653
    // Configuration for 'notify users when recording ready' feature.
2654
    if ((boolean)\mod_bigbluebuttonbn\settings\renderer::section_settings_extended_shown()) {
2655
        $renderer->render_group_header('extended_capabilities');
2656
        // UI for 'notify users when recording ready' feature.
2657
        $renderer->render_group_element('recordingready_enabled',
2658
            $renderer->render_group_element_checkbox('recordingready_enabled', 0));
2659
        // UI for 'register meeting events' feature.
2660
        $renderer->render_group_element('meetingevents_enabled',
2661
            $renderer->render_group_element_checkbox('meetingevents_enabled', 0));
2662
    }
2663
}
2664
2665
/**
2666
 * Helper function returns a sha1 encoded string that is unique and will be used as a seed for meetingid.
2667
 *
2668
 * @return string
2669
 */
2670
function bigbluebuttonbn_unique_meetingid_seed() {
2671
    global $DB;
2672
    do {
2673
        $encodedseed = sha1(bigbluebuttonbn_random_password(12));
2674
        $meetingid = (string)$DB->get_field('bigbluebuttonbn', 'meetingid', array('meetingid' => $encodedseed));
2675
    } while ($meetingid == $encodedseed);
2676
    return $encodedseed;
2677
}
2678
2679
/**
2680
 * Helper function renders the link used for recording type in row for the data used by the recording table.
2681
 *
2682
 * @param array $recording
2683
 * @param array $bbbsession
2684
 * @param array $playback
2685
 *
2686
 * @return boolean
2687
 */
2688
function bigbluebuttonbn_include_recording_data_row_type($recording, $bbbsession, $playback) {
2689
    // All types that are not restricted are included.
2690
    if (array_key_exists('restricted', $playback) && strtolower($playback['restricted']) == 'false') {
2691
        return true;
2692
    }
2693
    // All types that are not statistics are included.
2694
    if ($playback['type'] != 'statistics') {
2695
        return true;
2696
    }
2697
    // Exclude imported recordings.
2698
    if (isset($recording['imported'])) {
2699
        return false;
2700
    }
2701
    // Exclude non moderators.
2702
    if (!$bbbsession['administrator'] && !$bbbsession['moderator']) {
2703
        return false;
2704
    }
2705
    return true;
2706
}
2707
2708
/**
2709
 * Renders the general warning message.
2710
 *
2711
 * @param string $message
2712
 * @param string $type
2713
 * @param string $href
2714
 * @param string $text
2715
 * @param string $class
2716
 *
2717
 * @return string
2718
 */
2719
function bigbluebuttonbn_render_warning($message, $type='info', $href='', $text='', $class='') {
2720
    global $OUTPUT;
2721
    $output = "\n";
2722
    // Evaluates if config_warning is enabled.
2723
    if (empty($message)) {
2724
        return $output;
2725
    }
2726
    $output .= $OUTPUT->box_start('box boxalignleft adminerror alert alert-' . $type . ' alert-block fade in',
2727
      'bigbluebuttonbn_view_general_warning') . "\n";
2728
    $output .= '    ' . $message . "\n";
2729
    $output .= '  <div class="singlebutton pull-right">' . "\n";
2730
    if (!empty($href)) {
2731
        $output .= bigbluebuttonbn_render_warning_button($href, $text, $class);
2732
    }
2733
    $output .= '  </div>' . "\n";
2734
    $output .= $OUTPUT->box_end() . "\n";
2735
    return $output;
2736
}
2737
2738
/**
2739
 * Renders the general warning button.
2740
 *
2741
 * @param string $href
2742
 * @param string $text
2743
 * @param string $class
2744
 * @param string $title
2745
 *
2746
 * @return string
2747
 */
2748
function bigbluebuttonbn_render_warning_button($href, $text = '', $class = '', $title = '') {
2749
    if ($text == '') {
2750
        $text = get_string('ok', 'moodle');
2751
    }
2752
    if ($title == '') {
2753
        $title = $text;
2754
    }
2755
    if ($class == '') {
2756
        $class = 'btn btn-secondary';
2757
    }
2758
    $output  = '  <form method="post" action="' . $href . '" class="form-inline">'."\n";
2759
    $output .= '      <button type="submit" class="' . $class . '"'."\n";
2760
    $output .= '          title="' . $title . '"'."\n";
2761
    $output .= '          >' . $text . '</button>'."\n";
2762
    $output .= '  </form>'."\n";
2763
    return $output;
2764
}
2765
2766
/**
2767
 * Check if a BigBlueButtonBN is available to be used by the current user.
2768
 *
2769
 * @param  stdClass  $bigbluebuttonbn  BigBlueButtonBN instance
2770
 *
2771
 * @return boolean                     status if room available and current user allowed to join
2772
 */
2773
function bigbluebuttonbn_get_availability_status($bigbluebuttonbn) {
2774
    list($roomavailable) = bigbluebuttonbn_room_is_available($bigbluebuttonbn);
2775
    list($usercanjoin) = bigbluebuttonbn_user_can_join_meeting($bigbluebuttonbn);
2776
2777
    return ($roomavailable && $usercanjoin);
2778
}
2779
2780
/**
2781
 * Helper for evaluating if scheduled activity is avaiable.
2782
 *
2783
 * @param  stdClass  $bigbluebuttonbn  BigBlueButtonBN instance
2784
 *
2785
 * @return array                       status (room available or not and possible warnings)
2786
 */
2787
function bigbluebuttonbn_room_is_available($bigbluebuttonbn) {
2788
    $open = true;
2789
    $closed = false;
2790
    $warnings = array();
2791
2792
    $timenow = time();
2793
    $timeopen = $bigbluebuttonbn->openingtime;
2794
    $timeclose = $bigbluebuttonbn->closingtime;
2795
    if (!empty($timeopen) && $timeopen > $timenow) {
2796
        $open = false;
2797
    }
2798
    if (!empty($timeclose) && $timenow > $timeclose) {
2799
        $closed = true;
2800
    }
2801
2802
    if (!$open || $closed) {
2803
        if (!$open) {
2804
            $warnings['notopenyet'] = userdate($timeopen);
2805
        }
2806
        if ($closed) {
2807
            $warnings['expired'] = userdate($timeclose);
2808
        }
2809
        return array(false, $warnings);
2810
    }
2811
2812
    return array(true, $warnings);
2813
}
2814
2815
/**
2816
 * Helper for evaluating if meeting can be joined.
2817
 *
2818
 * @param  stdClass $bigbluebuttonbn  BigBlueButtonBN instance
2819
 * @param  string   $mid
2820
 * @param  integer  $userid
2821
 *
2822
 * @return array    status (user allowed to join or not and possible message)
2823
 */
2824
function bigbluebuttonbn_user_can_join_meeting($bigbluebuttonbn, $mid = null, $userid = null) {
2825
2826
    // By default, use a meetingid without groups.
2827
    if (empty($mid)) {
2828
        $mid = $bigbluebuttonbn->meetingid . '-' . $bigbluebuttonbn->course . '-' . $bigbluebuttonbn->id;
2829
    }
2830
2831
    // When meeting is running, all authorized users can join right in.
2832
    if (bigbluebuttonbn_is_meeting_running($mid)) {
2833
        return array(true, get_string('view_message_conference_in_progress', 'bigbluebuttonbn'));
2834
    }
2835
2836
    // When meeting is not running, see if the user can join.
2837
    $context = context_course::instance($bigbluebuttonbn->course);
2838
    $participantlist = bigbluebuttonbn_get_participant_list($bigbluebuttonbn, $context);
2839
    $isadmin = is_siteadmin($userid);
2840
    $ismoderator = bigbluebuttonbn_is_moderator($context, $participantlist, $userid);
2841
    // If user is administrator, moderator or if is viewer and no waiting is required, join allowed.
2842
    if ($isadmin || $ismoderator || !$bigbluebuttonbn->wait) {
2843
        return array(true, get_string('view_message_conference_room_ready', 'bigbluebuttonbn'));
2844
    }
2845
    // Otherwise, no join allowed.
2846
    return array(false, get_string('view_message_conference_wait_for_moderator', 'bigbluebuttonbn'));
2847
}
2848
2849
/**
2850
 * Helper for getting a value from a bigbluebuttonbn cache.
2851
 *
2852
 * @param  string   $name       BigBlueButtonBN cache
2853
 * @param  string   $key        Key to be retrieved
2854
 * @param  integer  $default    Default value in case key is not found or it is empty
2855
 *
2856
 * @return variable key value
2857
 */
2858
function bigbluebuttonbn_cache_get($name, $key, $default = null) {
2859
    $cache = cache::make_from_params(cache_store::MODE_APPLICATION, 'mod_bigbluebuttonbn', $name);
2860
    $result = $cache->get($key);
2861
    if (!empty($result)) {
2862
        return $result;
2863
    }
2864
    return $default;
2865
}
2866
2867
/**
2868
 * Helper for setting a value in a bigbluebuttonbn cache.
2869
 *
2870
 * @param  string   $name       BigBlueButtonBN cache
2871
 * @param  string   $key        Key to be created/updated
2872
 * @param  variable $value      Default value to be set
2873
 */
2874
function bigbluebuttonbn_cache_set($name, $key, $value) {
2875
    $cache = cache::make_from_params(cache_store::MODE_APPLICATION, 'mod_bigbluebuttonbn', $name);
2876
    $cache->set($key, $value);
2877
}
2878
2879
/**
2880
 * Helper for getting the owner userid of a bigbluebuttonbn instance.
2881
 *
2882
 * @param  stdClass $bigbluebuttonbn  BigBlueButtonBN instance
2883
 *
2884
 * @return integer ownerid (a valid user id or null if not registered/found)
2885
 */
2886
function bigbluebuttonbn_instance_ownerid($bigbluebuttonbn) {
2887
    global $DB;
2888
    $filters = array('bigbluebuttonbnid' => $bigbluebuttonbn->id, 'log' => 'Add');
2889
    $ownerid = (integer)$DB->get_field('bigbluebuttonbn_logs', 'userid', $filters);
2890
    return $ownerid;
2891
}
2892
2893
/**
2894
 * Helper evaluates if the bigbluebutton server used belongs to blindsidenetworks domain.
2895
 *
2896
 * @return boolean
2897
 */
2898
function bigbluebuttonbn_has_html5_client() {
2899
    $checkurl = \mod_bigbluebuttonbn\locallib\bigbluebutton::root() . "html5client/check";
2900
    $curlinfo = bigbluebuttonbn_wrap_xml_load_file_curl_request($checkurl, 'HEAD');
2901
    return (isset($curlinfo['http_code']) && $curlinfo['http_code'] == 200);
2902
}
2903