Completed
Pull Request — master (#155)
by Jesus
01:57
created

locallib.php ➔ bigbluebuttonbn_create_meeting_metadata()   A

Complexity

Conditions 4
Paths 8

Size

Total Lines 34

Duplication

Lines 0
Ratio 0 %

Importance

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

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
1654
    $payload = array();
1655
    $source = 'meetingName';
1656
    $metaname = trim($recording['meetingName']);
1657
    return bigbluebuttonbn_get_recording_data_row_text($recording, $metaname, $source, $payload);
1658
}
1659
1660
/**
1661
 * Helper function renders the name for recording used in row for the data used by the recording table.
1662
 *
1663
 * @param array $recording
1664
 * @param array $bbbsession
1665
 *
1666
 * @return string
1667
 */
1668
function bigbluebuttonbn_get_recording_data_row_meta_activity($recording, $bbbsession) {
1669
    $payload = array();
1670 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...
1671
        $payload = array('recordingid' => $recording['recordID'], 'meetingid' => $recording['meetingID'],
1672
            'action' => 'edit', 'tag' => 'edit',
1673
            'target' => 'name');
1674
    }
1675
    $oldsource = 'meta_contextactivity';
1676
    if (isset($recording[$oldsource])) {
1677
        $metaname = trim($recording[$oldsource]);
1678
        return bigbluebuttonbn_get_recording_data_row_text($recording, $metaname, $oldsource, $payload);
1679
    }
1680
    $newsource = 'meta_bbb-recording-name';
1681 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...
1682
        $metaname = trim($recording[$newsource]);
1683
        return bigbluebuttonbn_get_recording_data_row_text($recording, $metaname, $newsource, $payload);
1684
    }
1685
    $metaname = trim($recording['meetingName']);
1686
    return bigbluebuttonbn_get_recording_data_row_text($recording, $metaname, $newsource, $payload);
1687
}
1688
1689
/**
1690
 * Helper function renders the description for recording used in row for the data used by the recording table.
1691
 *
1692
 * @param array $recording
1693
 * @param array $bbbsession
1694
 *
1695
 * @return string
1696
 */
1697
function bigbluebuttonbn_get_recording_data_row_meta_description($recording, $bbbsession) {
1698
    $payload = array();
1699 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...
1700
        $payload = array('recordingid' => $recording['recordID'], 'meetingid' => $recording['meetingID'],
1701
            'action' => 'edit', 'tag' => 'edit',
1702
            'target' => 'description');
1703
    }
1704
    $oldsource = 'meta_contextactivitydescription';
1705 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...
1706
        $metadescription = trim($recording[$oldsource]);
1707
        return bigbluebuttonbn_get_recording_data_row_text($recording, $metadescription, $oldsource, $payload);
1708
    }
1709
    $newsource = 'meta_bbb-recording-description';
1710 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...
1711
        $metadescription = trim($recording[$newsource]);
1712
        return bigbluebuttonbn_get_recording_data_row_text($recording, $metadescription, $newsource, $payload);
1713
    }
1714
    return bigbluebuttonbn_get_recording_data_row_text($recording, '', $newsource, $payload);
1715
}
1716
1717
/**
1718
 * Helper function renders text element for recording used in row for the data used by the recording table.
1719
 *
1720
 * @param array $recording
1721
 * @param string $text
1722
 * @param string $source
1723
 * @param array $data
1724
 *
1725
 * @return string
1726
 */
1727
function bigbluebuttonbn_get_recording_data_row_text($recording, $text, $source, $data) {
1728
    $htmltext = '<span>' . htmlentities($text) . '</span>';
1729
    if (empty($data)) {
1730
        return $htmltext;
1731
    }
1732
    $target = $data['action'] . '-' . $data['target'];
1733
    $id = 'recording-' . $target . '-' . $data['recordingid'];
1734
    $attributes = array('id' => $id, 'class' => 'quickeditlink col-md-20',
1735
        'data-recordingid' => $data['recordingid'], 'data-meetingid' => $data['meetingid'],
1736
        'data-target' => $data['target'], 'data-source' => $source);
1737
    $head = html_writer::start_tag('div', $attributes);
1738
    $tail = html_writer::end_tag('div');
1739
    $payload = array('action' => $data['action'], 'tag' => $data['tag'], 'target' => $data['target']);
1740
    $htmllink = bigbluebuttonbn_actionbar_render_button($recording, $payload);
1741
    return $head . $htmltext . $htmllink . $tail;
1742
}
1743
1744
/**
1745
 * Helper function render a button for the recording action bar
1746
 *
1747
 * @param array $recording
1748
 * @param array $data
1749
 *
1750
 * @return string
1751
 */
1752
function bigbluebuttonbn_actionbar_render_button($recording, $data) {
1753
    global $OUTPUT;
1754
    if (empty($data)) {
1755
        return '';
1756
    }
1757
    $target = $data['action'];
1758
    if (isset($data['target'])) {
1759
        $target .= '-' . $data['target'];
1760
    }
1761
    $id = 'recording-' . $target . '-' . $recording['recordID'];
1762
    $onclick = 'M.mod_bigbluebuttonbn.recordings.recording' . ucfirst($data['action']) . '(this);';
1763
    if ((boolean)\mod_bigbluebuttonbn\locallib\config::get('recording_icons_enabled')) {
1764
        // With icon for $manageaction.
1765
        $iconattributes = array('id' => $id, 'class' => 'iconsmall');
1766
        $linkattributes = array(
1767
            'id' => $id,
1768
            'onclick' => $onclick,
1769
            'data-action' => $data['action']
1770
          );
1771
        if (!isset($recording['imported'])) {
1772
            $linkattributes['data-links'] = bigbluebuttonbn_count_recording_imported_instances(
1773
              $recording['recordID']);
1774
        }
1775
        if (isset($data['disabled'])) {
1776
            $iconattributes['class'] .= ' fa-' . $data['disabled'];
1777
            $linkattributes['class'] = 'disabled';
1778
            unset($linkattributes['onclick']);
1779
        }
1780
        $icon = new pix_icon('i/'.$data['tag'],
1781
            get_string('view_recording_list_actionbar_' . $data['action'], 'bigbluebuttonbn'),
1782
            'moodle', $iconattributes);
1783
        return $OUTPUT->action_icon('#', $icon, null, $linkattributes, false);
1784
    }
1785
    // With text for $manageaction.
1786
    $linkattributes = array('title' => get_string($data['tag']), 'class' => 'btn btn-xs btn-danger',
1787
        'onclick' => $onclick);
1788
    return $OUTPUT->action_link('#', get_string($data['action']), null, $linkattributes);
1789
}
1790
1791
/**
1792
 * Helper function builds the data used for headers by the recording table.
1793
 *
1794
 * @param array $bbbsession
1795
 *
1796
 * @return array
1797
 */
1798
function bigbluebuttonbn_get_recording_columns($bbbsession) {
1799
    $columns = array();
1800
    // Initialize table headers.
1801
    $columns[] = array('key' => 'recording', 'label' => get_string('view_recording_recording', 'bigbluebuttonbn'),
1802
        'width' => '125px', 'allowHTML' => true);
1803
    $columns[] = array('key' => 'meeting', 'label' => get_string('view_recording_meeting', 'bigbluebuttonbn'),
1804
        'sortable' => true, 'width' => '175px', 'allowHTML' => true);
1805
    $columns[] = array('key' => 'activity', 'label' => get_string('view_recording_activity', 'bigbluebuttonbn'),
1806
        'sortable' => true, 'width' => '175px', 'allowHTML' => true);
1807
    $columns[] = array('key' => 'description', 'label' => get_string('view_recording_description', 'bigbluebuttonbn'),
1808
        'sortable' => true, 'width' => '250px', 'allowHTML' => true);
1809
    if (bigbluebuttonbn_get_recording_data_preview_enabled($bbbsession)) {
1810
        $columns[] = array('key' => 'preview', 'label' => get_string('view_recording_preview', 'bigbluebuttonbn'),
1811
            'width' => '250px', 'allowHTML' => true);
1812
    }
1813
    $columns[] = array('key' => 'date', 'label' => get_string('view_recording_date', 'bigbluebuttonbn'),
1814
        'sortable' => true, 'width' => '225px', 'allowHTML' => true);
1815
    $columns[] = array('key' => 'duration', 'label' => get_string('view_recording_duration', 'bigbluebuttonbn'),
1816
        'width' => '50px');
1817
    if ($bbbsession['managerecordings']) {
1818
        $columns[] = array('key' => 'actionbar', 'label' => get_string('view_recording_actionbar', 'bigbluebuttonbn'),
1819
            'width' => '120px', 'allowHTML' => true);
1820
    }
1821
    return $columns;
1822
}
1823
1824
/**
1825
 * Helper function builds the data used by the recording table.
1826
 *
1827
 * @param array $bbbsession
1828
 * @param array $recordings
1829
 * @param array $tools
1830
 *
1831
 * @return array
1832
 */
1833
function bigbluebuttonbn_get_recording_data($bbbsession, $recordings, $tools = ['protect', 'publish', 'delete']) {
1834
    $tabledata = array();
1835
    // Build table content.
1836
    if (isset($recordings) && !array_key_exists('messageKey', $recordings)) {
1837
        // There are recordings for this meeting.
1838
        foreach ($recordings as $recording) {
1839
            $rowdata = bigbluebuttonbn_get_recording_data_row($bbbsession, $recording, $tools);
1840
            if (!empty($rowdata)) {
1841
                array_push($tabledata, $rowdata);
1842
            }
1843
        }
1844
    }
1845
    return $tabledata;
1846
}
1847
1848
/**
1849
 * Helper function builds the recording table.
1850
 *
1851
 * @param array $bbbsession
1852
 * @param array $recordings
1853
 * @param array $tools
1854
 *
1855
 * @return object
1856
 */
1857
function bigbluebuttonbn_get_recording_table($bbbsession, $recordings, $tools = ['protect', 'publish', 'delete']) {
1858
    global $DB;
1859
    // Declare the table.
1860
    $table = new html_table();
1861
    $table->data = array();
1862
    // Initialize table headers.
1863
    $table->head[] = get_string('view_recording_playback', 'bigbluebuttonbn');
1864
    $table->head[] = get_string('view_recording_meeting', 'bigbluebuttonbn');
1865
    $table->head[] = get_string('view_recording_recording', 'bigbluebuttonbn');
1866
    $table->head[] = get_string('view_recording_description', 'bigbluebuttonbn');
1867
    if (bigbluebuttonbn_get_recording_data_preview_enabled($bbbsession)) {
1868
        $table->head[] = get_string('view_recording_preview', 'bigbluebuttonbn');
1869
    }
1870
    $table->head[] = get_string('view_recording_date', 'bigbluebuttonbn');
1871
    $table->head[] = get_string('view_recording_duration', 'bigbluebuttonbn');
1872
    $table->align = array('left', 'left', 'left', 'left', 'left', 'center');
1873
    $table->size = array('', '', '', '', '', '');
1874
    if ($bbbsession['managerecordings']) {
1875
        $table->head[] = get_string('view_recording_actionbar', 'bigbluebuttonbn');
1876
        $table->align[] = 'left';
1877
        $table->size[] = (count($tools) * 40) . 'px';
1878
    }
1879
    // Get the groups of the user.
1880
    $usergroups = groups_get_all_groups($bbbsession['course']->id, $bbbsession['userID']);
1881
1882
    // Build table content.
1883
    foreach ($recordings as $recording) {
1884
1885
        $meetingid = $recording['meetingID'];
1886
        $shortmeetingid = explode('-', $recording['meetingID']);
1887
        if (isset($shortmeetingid[0])) {
1888
            $meetingid = $shortmeetingid[0];
1889
        }
1890
        // Check if the record belongs to a Visible Group type.
1891
        $sql = "SELECT bigbluebuttonbn.id, cm.id, cm.groupmode
1892
                 FROM {bigbluebuttonbn} bigbluebuttonbn
1893
                 JOIN {modules} m
1894
                   ON m.name = :bigbluebuttonbn
1895
                 JOIN {course_modules} cm
1896
                   ON cm.instance = bigbluebuttonbn.id
1897
                  AND cm.module = m.id
1898
                WHERE bigbluebuttonbn.meetingid = :meetingid";
1899
        $params = array('bigbluebuttonbn' => 'bigbluebuttonbn', 'meetingid' => $meetingid);
1900
1901
        $groupmode = $DB->get_record_sql($sql, $params, IGNORE_MULTIPLE);
1902
1903
        $displayrow = true;
1904
        if ((isset($groupmode->groupmode) && (int)$groupmode->groupmode != VISIBLEGROUPS)
1905
            && !$bbbsession['administrator'] && !$bbbsession['moderator']) {
1906
            $groupid = explode('[', $recording['meetingID']);
1907
            if (isset($groupid[1])) {
1908
                // It is a group recording and the user is not moderator/administrator. Recording should not be included by default.
1909
                $displayrow = false;
1910
                $groupid = explode(']', $groupid[1]);
1911
                if (isset($groupid[0])) {
1912
                    foreach ($usergroups as $usergroup) {
1913
                        if ($usergroup->id == $groupid[0]) {
1914
                            // Include recording if the user is in the same group.
1915
                            $displayrow = true;
1916
                        }
1917
                    }
1918
                }
1919
            }
1920
        }
1921
        if ($displayrow) {
1922
            $rowdata = bigbluebuttonbn_get_recording_data_row($bbbsession, $recording, $tools);
1923
            if (!empty($rowdata)) {
1924
                $row = bigbluebuttonbn_get_recording_table_row($bbbsession, $recording, $rowdata);
1925
                array_push($table->data, $row);
1926
            }
1927
        }
1928
    }
1929
    return $table;
1930
}
1931
1932
/**
1933
 * Helper function builds the recording table row and insert into table.
1934
 *
1935
 * @param array $bbbsession
1936
 * @param array $recording
1937
 * @param object $rowdata
1938
 *
1939
 * @return object
1940
 */
1941
function bigbluebuttonbn_get_recording_table_row($bbbsession, $recording, $rowdata) {
1942
    $row = new html_table_row();
1943
    $row->id = 'recording-tr-'.$recording['recordID'];
1944
    $row->attributes['data-imported'] = 'false';
1945
    $texthead = '';
1946
    $texttail = '';
1947
    if (isset($recording['imported'])) {
1948
        $row->attributes['title'] = get_string('view_recording_link_warning', 'bigbluebuttonbn');
1949
        $row->attributes['data-imported'] = 'true';
1950
        $texthead = '<em>';
1951
        $texttail = '</em>';
1952
    }
1953
    $rowdata->date_formatted = str_replace(' ', '&nbsp;', $rowdata->date_formatted);
1954
    $row->cells = array();
1955
    $row->cells[] = $texthead . $rowdata->recording . $texttail;
1956
    $row->cells[] = $texthead . $rowdata->meeting . $texttail;;
1957
    $row->cells[] = $texthead . $rowdata->activity . $texttail;
1958
    $row->cells[] = $texthead . $rowdata->description . $texttail;
1959
    if (bigbluebuttonbn_get_recording_data_preview_enabled($bbbsession)) {
1960
        $row->cells[] = $rowdata->preview;
1961
    }
1962
    $row->cells[] = $texthead . $rowdata->date_formatted . $texttail;
1963
    $row->cells[] = $rowdata->duration_formatted;
1964
    if ($bbbsession['managerecordings']) {
1965
        $row->cells[] = $rowdata->actionbar;
1966
    }
1967
    return $row;
1968
}
1969
1970
/**
1971
 * Helper function evaluates if recording row should be included in the table.
1972
 *
1973
 * @param array $bbbsession
1974
 * @param array $recording
1975
 *
1976
 * @return boolean
1977
 */
1978
function bigbluebuttonbn_include_recording_table_row($bbbsession, $recording) {
1979
    // Exclude unpublished recordings, only if user has no rights to manage them.
1980
    if ($recording['published'] != 'true' && !$bbbsession['managerecordings']) {
1981
        return false;
1982
    }
1983
    // Imported recordings are always shown as long as they are published.
1984
    if (isset($recording['imported'])) {
1985
        return true;
1986
    }
1987
    // When groups are enabled, exclude those to which the user doesn't have access to.
1988
    if (isset($bbbsession['group']) && $recording['meetingID'] != $bbbsession['meetingid']) {
1989
        return false;
1990
    }
1991
    return true;
1992
}
1993
1994
/**
1995
 * Helper function triggers a send notification when the recording is ready.
1996
 *
1997
 * @param object $bigbluebuttonbn
1998
 *
1999
 * @return void
2000
 */
2001
function bigbluebuttonbn_send_notification_recording_ready($bigbluebuttonbn) {
2002
    $sender = get_admin();
2003
    // Prepare message.
2004
    $messagetext = '<p>'.get_string('email_body_recording_ready_for', 'bigbluebuttonbn').
2005
        ' &quot;' . $bigbluebuttonbn->name . '&quot; '.
2006
        get_string('email_body_recording_ready_is_ready', 'bigbluebuttonbn').'.</p>';
2007
    \mod_bigbluebuttonbn\locallib\notifier::notification_send($sender, $bigbluebuttonbn, $messagetext);
2008
}
2009
2010
/**
2011
 * Helper function enqueues list of meeting events to be stored and processed as for completion.
2012
 *
2013
 * @param object $bigbluebuttonbn
2014
 * @param object $jsonobj
2015
 *
2016
 * @return void
2017
 */
2018
function bigbluebuttonbn_process_meeting_events($bigbluebuttonbn, $jsonobj) {
2019
    $meetingid = $jsonobj->{'meeting_id'};
2020
    $recordid = $jsonobj->{'internal_meeting_id'};
2021
    $attendees = $jsonobj->{'data'}->{'attendees'};
2022
    foreach ($attendees as $attendee) {
2023
        $userid = $attendee->{'ext_user_id'};
2024
        $overrides['meetingid'] = $meetingid;
0 ignored issues
show
Coding Style Comprehensibility introduced by
$overrides was never initialized. Although not strictly required by PHP, it is generally a good practice to add $overrides = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
2025
        $overrides['userid'] = $userid;
0 ignored issues
show
Bug introduced by
The variable $overrides does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
2026
        $meta['recordid'] = $recordid;
0 ignored issues
show
Coding Style Comprehensibility introduced by
$meta was never initialized. Although not strictly required by PHP, it is generally a good practice to add $meta = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
2027
        $meta['data'] = $attendee;
0 ignored issues
show
Bug introduced by
The variable $meta does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
2028
        // Stores the log.
2029
        bigbluebuttonbn_log($bigbluebuttonbn, BIGBLUEBUTTON_LOG_EVENT_SUMMARY, $overrides, json_encode($meta));
2030
        // Enqueue a task for processing the completion.
2031
        try {
2032
            // Create the instance of completion_update_state task.
2033
            $task = new \mod_bigbluebuttonbn\task\completion_update_state();
2034
            // Add custom data.
2035
            $data = array(
2036
                'bigbluebuttonbn' => $bigbluebuttonbn,
2037
                'userid' => $userid
2038
            );
2039
            $task->set_custom_data($data);
2040
            // CONTRIB-7457: Task should be executed by a user, maybe Teacher as Student won't have rights for everriding.
2041
            // $ task -> set_userid ( $ user -> id );.
2042
            // Queue it.
2043
            \core\task\manager::queue_adhoc_task($task);
2044
        } catch (Exception $e) {
2045
            mtrace("Error while enqueuing completion_uopdate_state task. " . (string)$e);
2046
        }
2047
    }
2048
}
2049
2050
/**
2051
 * Helper function enqueues completion trigger.
2052
 *
2053
 * @param object $bigbluebuttonbn
2054
 * @param string $userid
2055
 *
2056
 * @return void
2057
 */
2058
function bigbluebuttonbn_completion_update_state($bigbluebuttonbn, $userid) {
2059
    if (!$bigbluebuttonbn->completionattendance) {
2060
        return;
2061
    }
2062
    list($course, $cm) = get_course_and_cm_from_instance($bigbluebuttonbn, 'bigbluebuttonbn');
2063
    $completion = new completion_info($course);
2064
    if (!$completion->is_enabled($cm)) {
2065
        return;
2066
    }
2067
    if (bigbluebuttonbn_get_completion_state($course, $cm, $userid, COMPLETION_AND)) {
2068
        $completion->update_state($cm, COMPLETION_COMPLETE, $userid, true);
2069
    }
2070
}
2071
2072
/**
2073
 * Helper evaluates if the bigbluebutton server used belongs to blindsidenetworks domain.
2074
 *
2075
 * @return boolean
2076
 */
2077
function bigbluebuttonbn_is_bn_server() {
2078
    if (\mod_bigbluebuttonbn\locallib\config::get('bn_server')) {
2079
        return true;
2080
    }
2081
    $parsedurl = parse_url(\mod_bigbluebuttonbn\locallib\config::get('server_url'));
2082
    if (!isset($parsedurl['host'])) {
2083
        return false;
2084
    }
2085
    $h = $parsedurl['host'];
2086
    $hends = explode('.', $h);
2087
    $hendslength = count($hends);
2088
    return ($hends[$hendslength - 1] == 'com' && $hends[$hendslength - 2] == 'blindsidenetworks');
2089
}
2090
2091
/**
2092
 * Helper function returns a list of courses a user has access to, wrapped in an array that can be used
2093
 * by a html select.
2094
 *
2095
 * @param array $bbbsession
2096
 *
2097
 * @return array
2098
 */
2099
function bigbluebuttonbn_import_get_courses_for_select(array $bbbsession) {
2100
    if ($bbbsession['administrator']) {
2101
        $courses = get_courses('all', 'c.fullname ASC');
2102
        // It includes the name of the site as a course (category 0), so remove the first one.
2103
        unset($courses['1']);
2104
    } else {
2105
        $courses = enrol_get_users_courses($bbbsession['userID'], false, 'id,shortname,fullname');
2106
    }
2107
    $coursesforselect = [];
2108
    foreach ($courses as $course) {
2109
        $coursesforselect[$course->id] = $course->fullname;
2110
    }
2111
    return $coursesforselect;
2112
}
2113
2114
/**
2115
 * Helper function renders recording table.
2116
 *
2117
 * @param array $bbbsession
2118
 * @param array $recordings
2119
 * @param array $tools
2120
 *
2121
 * @return array
2122
 */
2123
function bigbluebuttonbn_output_recording_table($bbbsession, $recordings, $tools = ['protect', 'publish', 'delete']) {
2124
    if (isset($recordings) && !empty($recordings)) {
2125
        // There are recordings for this meeting.
2126
        $table = bigbluebuttonbn_get_recording_table($bbbsession, $recordings, $tools);
2127
    }
2128
    if (!isset($table) || !isset($table->data)) {
2129
        // Render a table with "No recordings".
2130
        return html_writer::div(get_string('view_message_norecordings', 'bigbluebuttonbn'), '',
2131
            array('id' => 'bigbluebuttonbn_recordings_table'));
2132
    }
2133
    // Render the table.
2134
    return html_writer::div(html_writer::table($table), '', array('id' => 'bigbluebuttonbn_recordings_table'));
2135
}
2136
2137
/**
2138
 * Helper function to convert an html string to plain text.
2139
 *
2140
 * @param string $html
2141
 * @param integer $len
2142
 *
2143
 * @return string
2144
 */
2145
function bigbluebuttonbn_html2text($html, $len = 0) {
2146
    $text = strip_tags($html);
2147
    $text = str_replace('&nbsp;', ' ', $text);
2148
    $textlen = strlen($text);
2149
    $text = substr($text, 0, $len);
2150
    if ($textlen > $len) {
2151
        $text .= '...';
2152
    }
2153
    return $text;
2154
}
2155
2156
/**
2157
 * Helper function to obtain the tags linked to a bigbluebuttonbn activity
2158
 *
2159
 * @param string $id
2160
 *
2161
 * @return string containing the tags separated by commas
2162
 */
2163
function bigbluebuttonbn_get_tags($id) {
2164
    if (class_exists('core_tag_tag')) {
2165
        return implode(',', core_tag_tag::get_item_tags_array('core', 'course_modules', $id));
2166
    }
2167
    return implode(',', tag_get_tags('bigbluebuttonbn', $id));
2168
}
2169
2170
/**
2171
 * Helper function to define the sql used for gattering the bigbluebuttonbnids whose meetingids should be included
2172
 * in the getRecordings request
2173
 *
2174
 * @param string $courseid
2175
 * @param string $bigbluebuttonbnid
2176
 * @param bool   $subset
2177
 *
2178
 * @return string containing the sql used for getting the target bigbluebuttonbn instances
2179
 */
2180
function bigbluebuttonbn_get_recordings_sql_select($courseid, $bigbluebuttonbnid = null, $subset = true) {
2181
    if (empty($courseid)) {
2182
        $courseid = 0;
2183
    }
2184
    if (empty($bigbluebuttonbnid)) {
2185
        return "course = '{$courseid}'";
2186
    }
2187
    if ($subset) {
2188
        return "id = '{$bigbluebuttonbnid}'";
2189
    }
2190
    return "id <> '{$bigbluebuttonbnid}' AND course = '{$courseid}'";
2191
}
2192
2193
/**
2194
 * Helper function to define the sql used for gattering the bigbluebuttonbnids whose meetingids should be included
2195
 * in the getRecordings request considering only those that belong to deleted activities.
2196
 *
2197
 * @param string $courseid
2198
 * @param string $bigbluebuttonbnid
2199
 * @param bool   $subset
2200
 *
2201
 * @return string containing the sql used for getting the target bigbluebuttonbn instances
2202
 */
2203 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...
2204
    $sql = "log = '" . BIGBLUEBUTTONBN_LOG_EVENT_DELETE . "' AND meta like '%has_recordings%' AND meta like '%true%'";
2205
    if (empty($courseid)) {
2206
        $courseid = 0;
2207
    }
2208
    if (empty($bigbluebuttonbnid)) {
2209
        return $sql . " AND courseid = {$courseid}";
2210
    }
2211
    if ($subset) {
2212
        return $sql . " AND bigbluebuttonbnid = '{$bigbluebuttonbnid}'";
2213
    }
2214
    return $sql . " AND courseid = {$courseid} AND bigbluebuttonbnid <> '{$bigbluebuttonbnid}'";
2215
}
2216
2217
/**
2218
 * Helper function to define the sql used for gattering the bigbluebuttonbnids whose meetingids should be included
2219
 * in the getRecordings request considering only those that belong to imported recordings.
2220
 *
2221
 * @param string $courseid
2222
 * @param string $bigbluebuttonbnid
2223
 * @param bool   $subset
2224
 *
2225
 * @return string containing the sql used for getting the target bigbluebuttonbn instances
2226
 */
2227 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...
2228
    $sql = "log = '" . BIGBLUEBUTTONBN_LOG_EVENT_IMPORT . "'";
2229
    if (empty($courseid)) {
2230
        $courseid = 0;
2231
    }
2232
    if (empty($bigbluebuttonbnid)) {
2233
        return $sql . " AND courseid = '{$courseid}'";
2234
    }
2235
    if ($subset) {
2236
        return $sql . " AND bigbluebuttonbnid = '{$bigbluebuttonbnid}'";
2237
    }
2238
    return $sql . " AND courseid = '{$courseid}' AND bigbluebuttonbnid <> '{$bigbluebuttonbnid}'";
2239
}
2240
2241
/**
2242
 * Helper function to get recordings and imported recordings together.
2243
 *
2244
 * @param string $courseid
2245
 * @param string $bigbluebuttonbnid
2246
 * @param bool   $subset
2247
 * @param bool   $includedeleted
2248
 *
2249
 * @return associative array containing the recordings indexed by recordID, each recording is also a
2250
 * non sequential associative array itself that corresponds to the actual recording in BBB
2251
 */
2252
function bigbluebuttonbn_get_allrecordings($courseid = 0, $bigbluebuttonbnid = null, $subset = true, $includedeleted = false) {
2253
    $recordings = bigbluebuttonbn_get_recordings($courseid, $bigbluebuttonbnid, $subset, $includedeleted);
2254
    $recordingsimported = bigbluebuttonbn_get_recordings_imported_array($courseid, $bigbluebuttonbnid, $subset);
2255
    return ($recordings + $recordingsimported);
2256
}
2257
2258
/**
2259
 * Helper function to retrieve recordings from the BigBlueButton. The references are stored as events
2260
 * in bigbluebuttonbn_logs.
2261
 *
2262
 * @param string $courseid
2263
 * @param string $bigbluebuttonbnid
2264
 * @param bool   $subset
2265
 * @param bool   $includedeleted
2266
 *
2267
 * @return associative array containing the recordings indexed by recordID, each recording is also a
2268
 * non sequential associative array itself that corresponds to the actual recording in BBB
2269
 */
2270
function bigbluebuttonbn_get_recordings($courseid = 0, $bigbluebuttonbnid = null, $subset = true, $includedeleted = false) {
2271
    global $DB;
2272
    $select = bigbluebuttonbn_get_recordings_sql_select($courseid, $bigbluebuttonbnid, $subset);
2273
    $bigbluebuttonbns = $DB->get_records_select_menu('bigbluebuttonbn', $select, null, 'id', 'id, meetingid');
2274
    /* Consider logs from deleted bigbluebuttonbn instances whose meetingids should be included in
2275
     * the getRecordings request. */
2276
    if ($includedeleted) {
2277
        $selectdeleted = bigbluebuttonbn_get_recordings_deleted_sql_select($courseid, $bigbluebuttonbnid, $subset);
2278
        $bigbluebuttonbnsdel = $DB->get_records_select_menu('bigbluebuttonbn_logs', $selectdeleted, null,
2279
            'bigbluebuttonbnid', 'bigbluebuttonbnid, meetingid');
2280
        if (!empty($bigbluebuttonbnsdel)) {
2281
            // Merge bigbluebuttonbnis from deleted instances, only keys are relevant.
2282
            // Artimetic merge is used in order to keep the keys.
2283
            $bigbluebuttonbns += $bigbluebuttonbnsdel;
2284
        }
2285
    }
2286
    // Gather the meetingids from bigbluebuttonbn logs that include a create with record=true.
2287
    if (empty($bigbluebuttonbns)) {
2288
        return array();
2289
    }
2290
    // Prepare select for loading records based on existent bigbluebuttonbns.
2291
    $sql = 'SELECT DISTINCT meetingid, bigbluebuttonbnid FROM {bigbluebuttonbn_logs} WHERE ';
2292
    $sql .= '(bigbluebuttonbnid='.implode(' OR bigbluebuttonbnid=', array_keys($bigbluebuttonbns)).')';
2293
    // Include only Create events and exclude those with record not true.
2294
    $sql .= ' AND log = ? AND meta LIKE ? AND meta LIKE ?';
2295
    // Execute select for loading records based on existent bigbluebuttonbns.
2296
    $records = $DB->get_records_sql_menu($sql, array(BIGBLUEBUTTONBN_LOG_EVENT_CREATE, '%record%', '%true%'));
2297
    // Get actual recordings.
2298
    return bigbluebuttonbn_get_recordings_array(array_keys($records));
2299
}
2300
2301
/**
2302
 * Helper function iterates an array with recordings and unset those already imported.
2303
 *
2304
 * @param array $recordings
2305
 * @param integer $courseid
2306
 * @param integer $bigbluebuttonbnid
2307
 *
2308
 * @return array
2309
 */
2310
function bigbluebuttonbn_unset_existent_recordings_already_imported($recordings, $courseid, $bigbluebuttonbnid) {
2311
    $recordingsimported = bigbluebuttonbn_get_recordings_imported_array($courseid, $bigbluebuttonbnid, true);
2312
    foreach ($recordings as $key => $recording) {
2313
        if (isset($recordingsimported[$recording['recordID']])) {
2314
            unset($recordings[$key]);
2315
        }
2316
    }
2317
    return $recordings;
2318
}
2319
2320
/**
2321
 * Helper function to count the imported recordings for a recordingid.
2322
 *
2323
 * @param string $recordid
2324
 *
2325
 * @return integer
2326
 */
2327
function bigbluebuttonbn_count_recording_imported_instances($recordid) {
2328
    global $DB;
2329
    $sql = 'SELECT COUNT(DISTINCT id) FROM {bigbluebuttonbn_logs} WHERE log = ? AND meta LIKE ? AND meta LIKE ?';
2330
    return $DB->count_records_sql($sql, array(BIGBLUEBUTTONBN_LOG_EVENT_IMPORT, '%recordID%', "%{$recordid}%"));
2331
}
2332
2333
/**
2334
 * Helper function returns an array with all the instances of imported recordings for a recordingid.
2335
 *
2336
 * @param string $recordid
2337
 *
2338
 * @return array
2339
 */
2340
function bigbluebuttonbn_get_recording_imported_instances($recordid) {
2341
    global $DB;
2342
    $sql = 'SELECT * FROM {bigbluebuttonbn_logs} WHERE log = ? AND meta LIKE ? AND meta LIKE ?';
2343
    $recordingsimported = $DB->get_records_sql($sql, array(BIGBLUEBUTTONBN_LOG_EVENT_IMPORT, '%recordID%',
2344
        "%{$recordid}%"));
2345
    return $recordingsimported;
2346
}
2347
2348
/**
2349
 * Helper function to get how much callback events are logged.
2350
 *
2351
 * @param string $recordid
2352
 * @param string $callbacktype
2353
 *
2354
 * @return integer
2355
 */
2356
function bigbluebuttonbn_get_count_callback_event_log($recordid, $callbacktype = 'recording_ready') {
2357
    global $DB;
2358
    $sql = 'SELECT count(DISTINCT id) FROM {bigbluebuttonbn_logs} WHERE log = ? AND meta LIKE ? AND meta LIKE ?';
2359
    // Callback type added on version 2.4, validate recording_ready first or assume it on records with no callback.
2360
    if ($callbacktype == 'recording_ready') {
2361
        $sql .= ' AND (meta LIKE ? OR meta NOT LIKE ? )';
2362
        $count = $DB->count_records_sql($sql, array(BIGBLUEBUTTON_LOG_EVENT_CALLBACK, '%recordid%', "%$recordid%",
2363
            $callbacktype, 'callback'));
2364
        return $count;
2365
    }
2366
    $sql .= ' AND meta LIKE ?;';
2367
    $count = $DB->count_records_sql($sql, array(BIGBLUEBUTTON_LOG_EVENT_CALLBACK, '%recordid%', "%$recordid%", "%$callbacktype%"));
2368
    return $count;
2369
}
2370
2371
/**
2372
 * Helper function returns an array with the profiles (with features per profile) for the different types
2373
 * of bigbluebuttonbn instances.
2374
 *
2375
 * @return array
2376
 */
2377
function bigbluebuttonbn_get_instance_type_profiles() {
2378
    $instanceprofiles = array(
2379
        BIGBLUEBUTTONBN_TYPE_ALL => array('id' => BIGBLUEBUTTONBN_TYPE_ALL,
2380
                  'name' => get_string('instance_type_default', 'bigbluebuttonbn'),
2381
                  'features' => array('all')),
2382
        BIGBLUEBUTTONBN_TYPE_ROOM_ONLY => array('id' => BIGBLUEBUTTONBN_TYPE_ROOM_ONLY,
2383
                  'name' => get_string('instance_type_room_only', 'bigbluebuttonbn'),
2384
                  'features' => array('showroom', 'welcomemessage', 'voicebridge', 'waitformoderator', 'userlimit',
2385
                      'recording', 'sendnotifications', 'preuploadpresentation', 'permissions', 'schedule', 'groups',
2386
                      'modstandardelshdr', 'availabilityconditionsheader', 'tagshdr', 'competenciessection',
2387
                      'clienttype', 'completionattendance')),
2388
        BIGBLUEBUTTONBN_TYPE_RECORDING_ONLY => array('id' => BIGBLUEBUTTONBN_TYPE_RECORDING_ONLY,
2389
                  'name' => get_string('instance_type_recording_only', 'bigbluebuttonbn'),
2390
                  'features' => array('showrecordings', 'importrecordings'))
2391
    );
2392
    return $instanceprofiles;
2393
}
2394
2395
2396
/**
2397
 * Helper function returns an array with enabled features for an specific profile type.
2398
 *
2399
 * @param array $typeprofiles
2400
 * @param string $type
2401
 *
2402
 * @return array
2403
 */
2404
function bigbluebuttonbn_get_enabled_features($typeprofiles, $type = null) {
2405
    $enabledfeatures = array();
2406
    $features = $typeprofiles[BIGBLUEBUTTONBN_TYPE_ALL]['features'];
2407
    if (!is_null($type) && key_exists($type, $typeprofiles)) {
2408
        $features = $typeprofiles[$type]['features'];
2409
    }
2410
    $enabledfeatures['showroom'] = (in_array('all', $features) || in_array('showroom', $features));
2411
    // Evaluates if recordings are enabled for the Moodle site.
2412
    $enabledfeatures['showrecordings'] = false;
2413
    if (\mod_bigbluebuttonbn\locallib\config::recordings_enabled()) {
2414
        $enabledfeatures['showrecordings'] = (in_array('all', $features) || in_array('showrecordings', $features));
2415
    }
2416
    $enabledfeatures['importrecordings'] = false;
2417
    if (\mod_bigbluebuttonbn\locallib\config::importrecordings_enabled()) {
2418
        $enabledfeatures['importrecordings'] = (in_array('all', $features) || in_array('importrecordings', $features));
2419
    }
2420
    // Evaluates if clienttype is enabled for the Moodle site.
2421
    $enabledfeatures['clienttype'] = false;
2422
    if (\mod_bigbluebuttonbn\locallib\config::clienttype_enabled()) {
2423
        $enabledfeatures['clienttype'] = (in_array('all', $features) || in_array('clienttype', $features));
2424
    }
2425
    return $enabledfeatures;
2426
}
2427
2428
/**
2429
 * Helper function returns an array with the profiles (with features per profile) for the different types
2430
 * of bigbluebuttonbn instances that the user is allowed to create.
2431
 *
2432
 * @param boolean $room
2433
 * @param boolean $recording
2434
 *
2435
 * @return array
2436
 */
2437
function bigbluebuttonbn_get_instance_type_profiles_create_allowed($room, $recording) {
2438
    $profiles = bigbluebuttonbn_get_instance_type_profiles();
2439
    if (!$room) {
2440
        unset($profiles[BIGBLUEBUTTONBN_TYPE_ROOM_ONLY]);
2441
        unset($profiles[BIGBLUEBUTTONBN_TYPE_ALL]);
2442
    }
2443
    if (!$recording) {
2444
        unset($profiles[BIGBLUEBUTTONBN_TYPE_RECORDING_ONLY]);
2445
        unset($profiles[BIGBLUEBUTTONBN_TYPE_ALL]);
2446
    }
2447
    return $profiles;
2448
}
2449
2450
/**
2451
 * Helper function returns an array with the profiles (with features per profile) for the different types
2452
 * of bigbluebuttonbn instances.
2453
 *
2454
 * @param array $profiles
2455
 *
2456
 * @return array
2457
 */
2458
function bigbluebuttonbn_get_instance_profiles_array($profiles = []) {
2459
    $profilesarray = array();
2460
    foreach ($profiles as $key => $profile) {
2461
        $profilesarray[$profile['id']] = $profile['name'];
2462
    }
2463
    return $profilesarray;
2464
}
2465
2466
/**
2467
 * Helper function returns time in a formatted string.
2468
 *
2469
 * @param integer $time
2470
 *
2471
 * @return string
2472
 */
2473
function bigbluebuttonbn_format_activity_time($time) {
2474
    $activitytime = '';
2475
    if ($time) {
2476
        $activitytime = calendar_day_representation($time).' '.
2477
          get_string('mod_form_field_notification_msg_at', 'bigbluebuttonbn').' '.
2478
          calendar_time_representation($time);
2479
    }
2480
    return $activitytime;
2481
}
2482
2483
/**
2484
 * Helper function returns array with all the strings to be used in javascript.
2485
 *
2486
 * @return array
2487
 */
2488
function bigbluebuttonbn_get_strings_for_js() {
2489
    $locale = bigbluebuttonbn_get_locale();
2490
    $stringman = get_string_manager();
2491
    $strings = $stringman->load_component_strings('bigbluebuttonbn', $locale);
2492
    return $strings;
2493
}
2494
2495
/**
2496
 * Helper function returns the locale set by moodle.
2497
 *
2498
 * @return string
2499
 */
2500
function bigbluebuttonbn_get_locale() {
2501
    $lang = get_string('locale', 'core_langconfig');
2502
    return substr($lang, 0, strpos($lang, '.'));
2503
}
2504
2505
/**
2506
 * Helper function returns the locale code based on the locale set by moodle.
2507
 *
2508
 * @return string
2509
 */
2510
function bigbluebuttonbn_get_localcode() {
2511
    $locale = bigbluebuttonbn_get_locale();
2512
    return substr($locale, 0, strpos($locale, '_'));
2513
}
2514
2515
/**
2516
 * Helper function returns array with the instance settings used in views.
2517
 *
2518
 * @param string $id
2519
 * @param object $bigbluebuttonbnid
2520
 *
2521
 * @return array
2522
 */
2523
function bigbluebuttonbn_view_validator($id, $bigbluebuttonbnid) {
2524
    $result = null;
2525
    if ($id) {
2526
        $result = bigbluebuttonbn_view_instance_id($id);
2527
    } else if ($bigbluebuttonbnid) {
2528
        $result = bigbluebuttonbn_view_instance_bigbluebuttonbn($bigbluebuttonbnid);
2529
    }
2530
    return $result;
2531
}
2532
2533
/**
2534
 * Helper function returns array with the instance settings used in views based on id.
2535
 *
2536
 * @param string $id
2537
 *
2538
 * @return array
2539
 */
2540 View Code Duplication
function bigbluebuttonbn_view_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...
2541
    global $DB;
2542
    $cm = get_coursemodule_from_id('bigbluebuttonbn', $id, 0, false, MUST_EXIST);
2543
    $course = $DB->get_record('course', array('id' => $cm->course), '*', MUST_EXIST);
2544
    $bigbluebuttonbn = $DB->get_record('bigbluebuttonbn', array('id' => $cm->instance), '*', MUST_EXIST);
2545
    return array('cm' => $cm, 'course' => $course, 'bigbluebuttonbn' => $bigbluebuttonbn);
2546
}
2547
2548
/**
2549
 * Helper function returns array with the instance settings used in views based on bigbluebuttonbnid.
2550
 *
2551
 * @param object $bigbluebuttonbnid
2552
 *
2553
 * @return array
2554
 */
2555 View Code Duplication
function bigbluebuttonbn_view_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...
2556
    global $DB;
2557
    $bigbluebuttonbn = $DB->get_record('bigbluebuttonbn', array('id' => $bigbluebuttonbnid), '*', MUST_EXIST);
2558
    $course = $DB->get_record('course', array('id' => $bigbluebuttonbn->course), '*', MUST_EXIST);
2559
    $cm = get_coursemodule_from_instance('bigbluebuttonbn', $bigbluebuttonbn->id, $course->id, false, MUST_EXIST);
2560
    return array('cm' => $cm, 'course' => $course, 'bigbluebuttonbn' => $bigbluebuttonbn);
2561
}
2562
2563
/**
2564
 * Helper function renders general settings if the feature is enabled.
2565
 *
2566
 * @param object $renderer
2567
 *
2568
 * @return void
2569
 */
2570
function bigbluebuttonbn_settings_general(&$renderer) {
2571
    // Configuration for BigBlueButton.
2572
    if ((boolean)\mod_bigbluebuttonbn\settings\validator::section_general_shown()) {
2573
        $renderer->render_group_header('general');
2574
        $renderer->render_group_element('server_url',
2575
            $renderer->render_group_element_text('server_url', BIGBLUEBUTTONBN_DEFAULT_SERVER_URL));
2576
        $renderer->render_group_element('shared_secret',
2577
            $renderer->render_group_element_text('shared_secret', BIGBLUEBUTTONBN_DEFAULT_SHARED_SECRET));
2578
    }
2579
}
2580
2581
/**
2582
 * Helper function renders record settings if the feature is enabled.
2583
 *
2584
 * @param object $renderer
2585
 *
2586
 * @return void
2587
 */
2588
function bigbluebuttonbn_settings_record(&$renderer) {
2589
    // Configuration for 'recording' feature.
2590
    if ((boolean)\mod_bigbluebuttonbn\settings\validator::section_record_meeting_shown()) {
2591
        $renderer->render_group_header('recording');
2592
        $renderer->render_group_element('recording_default',
2593
            $renderer->render_group_element_checkbox('recording_default', 1));
2594
        $renderer->render_group_element('recording_editable',
2595
            $renderer->render_group_element_checkbox('recording_editable', 1));
2596
        $renderer->render_group_element('recording_icons_enabled',
2597
            $renderer->render_group_element_checkbox('recording_icons_enabled', 1));
2598
2599
        // Add recording start to load and allow/hide stop/pause.
2600
        $renderer->render_group_element('recording_all_from_start_default',
2601
            $renderer->render_group_element_checkbox('recording_all_from_start_default', 0));
2602
        $renderer->render_group_element('recording_all_from_start_editable',
2603
            $renderer->render_group_element_checkbox('recording_all_from_start_editable', 0));
2604
        $renderer->render_group_element('recording_hide_button_default',
2605
            $renderer->render_group_element_checkbox('recording_hide_button_default', 0));
2606
        $renderer->render_group_element('recording_hide_button_editable',
2607
            $renderer->render_group_element_checkbox('recording_hide_button_editable', 0));
2608
    }
2609
}
2610
2611
/**
2612
 * Helper function renders import recording settings if the feature is enabled.
2613
 *
2614
 * @param object $renderer
2615
 *
2616
 * @return void
2617
 */
2618 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...
2619
    // Configuration for 'import recordings' feature.
2620
    if ((boolean)\mod_bigbluebuttonbn\settings\validator::section_import_recordings_shown()) {
2621
        $renderer->render_group_header('importrecordings');
2622
        $renderer->render_group_element('importrecordings_enabled',
2623
            $renderer->render_group_element_checkbox('importrecordings_enabled', 0));
2624
        $renderer->render_group_element('importrecordings_from_deleted_enabled',
2625
            $renderer->render_group_element_checkbox('importrecordings_from_deleted_enabled', 0));
2626
    }
2627
}
2628
2629
/**
2630
 * Helper function renders show recording settings if the feature is enabled.
2631
 *
2632
 * @param object $renderer
2633
 *
2634
 * @return void
2635
 */
2636
function bigbluebuttonbn_settings_showrecordings(&$renderer) {
2637
    // Configuration for 'show recordings' feature.
2638
    if ((boolean)\mod_bigbluebuttonbn\settings\validator::section_show_recordings_shown()) {
2639
        $renderer->render_group_header('recordings');
2640
        $renderer->render_group_element('recordings_html_default',
2641
            $renderer->render_group_element_checkbox('recordings_html_default', 1));
2642
        $renderer->render_group_element('recordings_html_editable',
2643
            $renderer->render_group_element_checkbox('recordings_html_editable', 0));
2644
        $renderer->render_group_element('recordings_deleted_default',
2645
            $renderer->render_group_element_checkbox('recordings_deleted_default', 1));
2646
        $renderer->render_group_element('recordings_deleted_editable',
2647
            $renderer->render_group_element_checkbox('recordings_deleted_editable', 0));
2648
        $renderer->render_group_element('recordings_imported_default',
2649
            $renderer->render_group_element_checkbox('recordings_imported_default', 0));
2650
        $renderer->render_group_element('recordings_imported_editable',
2651
            $renderer->render_group_element_checkbox('recordings_imported_editable', 1));
2652
        $renderer->render_group_element('recordings_preview_default',
2653
            $renderer->render_group_element_checkbox('recordings_preview_default', 1));
2654
        $renderer->render_group_element('recordings_preview_editable',
2655
            $renderer->render_group_element_checkbox('recordings_preview_editable', 0));
2656
        $renderer->render_group_element('recordings_sortorder',
2657
            $renderer->render_group_element_checkbox('recordings_sortorder', 0));
2658
    }
2659
}
2660
2661
/**
2662
 * Helper function renders wait for moderator settings if the feature is enabled.
2663
 *
2664
 * @param object $renderer
2665
 *
2666
 * @return void
2667
 */
2668
function bigbluebuttonbn_settings_waitmoderator(&$renderer) {
2669
    // Configuration for wait for moderator feature.
2670
    if ((boolean)\mod_bigbluebuttonbn\settings\validator::section_wait_moderator_shown()) {
2671
        $renderer->render_group_header('waitformoderator');
2672
        $renderer->render_group_element('waitformoderator_default',
2673
            $renderer->render_group_element_checkbox('waitformoderator_default', 0));
2674
        $renderer->render_group_element('waitformoderator_editable',
2675
            $renderer->render_group_element_checkbox('waitformoderator_editable', 1));
2676
        $renderer->render_group_element('waitformoderator_ping_interval',
2677
            $renderer->render_group_element_text('waitformoderator_ping_interval', 10, PARAM_INT));
2678
        $renderer->render_group_element('waitformoderator_cache_ttl',
2679
            $renderer->render_group_element_text('waitformoderator_cache_ttl', 60, PARAM_INT));
2680
    }
2681
}
2682
2683
/**
2684
 * Helper function renders static voice bridge settings if the feature is enabled.
2685
 *
2686
 * @param object $renderer
2687
 *
2688
 * @return void
2689
 */
2690
function bigbluebuttonbn_settings_voicebridge(&$renderer) {
2691
    // Configuration for "static voice bridge" feature.
2692
    if ((boolean)\mod_bigbluebuttonbn\settings\validator::section_static_voice_bridge_shown()) {
2693
        $renderer->render_group_header('voicebridge');
2694
        $renderer->render_group_element('voicebridge_editable',
2695
            $renderer->render_group_element_checkbox('voicebridge_editable', 0));
2696
    }
2697
}
2698
2699
/**
2700
 * Helper function renders preuploaded presentation settings if the feature is enabled.
2701
 *
2702
 * @param object $renderer
2703
 *
2704
 * @return void
2705
 */
2706
function bigbluebuttonbn_settings_preupload(&$renderer) {
2707
    // Configuration for "preupload presentation" feature.
2708
    if ((boolean)\mod_bigbluebuttonbn\settings\validator::section_preupload_presentation_shown()) {
2709
        // This feature only works if curl is installed.
2710
        $preuploaddescripion = get_string('config_preuploadpresentation_description', 'bigbluebuttonbn');
2711
        if (!extension_loaded('curl')) {
2712
            $preuploaddescripion .= '<div class="form-defaultinfo">';
2713
            $preuploaddescripion .= get_string('config_warning_curl_not_installed', 'bigbluebuttonbn');
2714
            $preuploaddescripion .= '</div><br>';
2715
        }
2716
        $renderer->render_group_header('preuploadpresentation', null, $preuploaddescripion);
2717
        if (extension_loaded('curl')) {
2718
            $renderer->render_group_element('preuploadpresentation_enabled',
2719
                $renderer->render_group_element_checkbox('preuploadpresentation_enabled', 0));
2720
        }
2721
    }
2722
}
2723
2724
/**
2725
 * Helper function renders preuploaded presentation manage file if the feature is enabled.
2726
 * This allow to select a file for use as default in all BBB instances if preuploaded presetantion is enable.
2727
 *
2728
 * @param object $renderer
2729
 *
2730
 * @return void
2731
 */
2732
function bigbluebuttonbn_settings_preupload_manage_default_file(&$renderer) {
2733
    // Configuration for "preupload presentation" feature.
2734
    if ((boolean)\mod_bigbluebuttonbn\settings\validator::section_preupload_presentation_shown()) {
2735
        if (extension_loaded('curl')) {
2736
            // This feature only works if curl is installed.
2737
            $renderer->render_filemanager_default_file_presentation("presentation_default");
2738
        }
2739
    }
2740
}
2741
2742
/**
2743
 * Helper function renders userlimit settings if the feature is enabled.
2744
 *
2745
 * @param object $renderer
2746
 *
2747
 * @return void
2748
 */
2749
function bigbluebuttonbn_settings_userlimit(&$renderer) {
2750
    // Configuration for "user limit" feature.
2751
    if ((boolean)\mod_bigbluebuttonbn\settings\validator::section_user_limit_shown()) {
2752
        $renderer->render_group_header('userlimit');
2753
        $renderer->render_group_element('userlimit_default',
2754
            $renderer->render_group_element_text('userlimit_default', 0, PARAM_INT));
2755
        $renderer->render_group_element('userlimit_editable',
2756
            $renderer->render_group_element_checkbox('userlimit_editable', 0));
2757
    }
2758
}
2759
2760
/**
2761
 * Helper function renders duration settings if the feature is enabled.
2762
 *
2763
 * @param object $renderer
2764
 *
2765
 * @return void
2766
 */
2767
function bigbluebuttonbn_settings_duration(&$renderer) {
2768
    // Configuration for "scheduled duration" feature.
2769
    if ((boolean)\mod_bigbluebuttonbn\settings\validator::section_scheduled_duration_shown()) {
2770
        $renderer->render_group_header('scheduled');
2771
        $renderer->render_group_element('scheduled_duration_enabled',
2772
            $renderer->render_group_element_checkbox('scheduled_duration_enabled', 1));
2773
        $renderer->render_group_element('scheduled_duration_compensation',
2774
            $renderer->render_group_element_text('scheduled_duration_compensation', 10, PARAM_INT));
2775
        $renderer->render_group_element('scheduled_pre_opening',
2776
            $renderer->render_group_element_text('scheduled_pre_opening', 10, PARAM_INT));
2777
    }
2778
}
2779
2780
/**
2781
 * Helper function renders participant settings if the feature is enabled.
2782
 *
2783
 * @param object $renderer
2784
 *
2785
 * @return void
2786
 */
2787
function bigbluebuttonbn_settings_participants(&$renderer) {
2788
    // Configuration for defining the default role/user that will be moderator on new activities.
2789
    if ((boolean)\mod_bigbluebuttonbn\settings\validator::section_moderator_default_shown()) {
2790
        $renderer->render_group_header('participant');
2791
        // UI for 'participants' feature.
2792
        $roles = bigbluebuttonbn_get_roles();
2793
        $owner = array('0' => get_string('mod_form_field_participant_list_type_owner', 'bigbluebuttonbn'));
2794
        $renderer->render_group_element('participant_moderator_default',
2795
            $renderer->render_group_element_configmultiselect('participant_moderator_default',
2796
                array_keys($owner), array_merge($owner, $roles))
2797
          );
2798
    }
2799
}
2800
2801
/**
2802
 * Helper function renders notification settings if the feature is enabled.
2803
 *
2804
 * @param object $renderer
2805
 *
2806
 * @return void
2807
 */
2808
function bigbluebuttonbn_settings_notifications(&$renderer) {
2809
    // Configuration for "send notifications" feature.
2810
    if ((boolean)\mod_bigbluebuttonbn\settings\validator::section_send_notifications_shown()) {
2811
        $renderer->render_group_header('sendnotifications');
2812
        $renderer->render_group_element('sendnotifications_enabled',
2813
            $renderer->render_group_element_checkbox('sendnotifications_enabled', 1));
2814
    }
2815
}
2816
2817
/**
2818
 * Helper function renders client type settings if the feature is enabled.
2819
 *
2820
 * @param object $renderer
2821
 *
2822
 * @return void
2823
 */
2824
function bigbluebuttonbn_settings_clienttype(&$renderer) {
2825
    // Configuration for "clienttype" feature.
2826
    if ((boolean)\mod_bigbluebuttonbn\settings\validator::section_clienttype_shown()) {
2827
        $renderer->render_group_header('clienttype');
2828
        $renderer->render_group_element('clienttype_editable',
2829
            $renderer->render_group_element_checkbox('clienttype_editable', 0));
2830
        // Web Client default.
2831
        $default = intval((int)\mod_bigbluebuttonbn\locallib\config::get('clienttype_default'));
2832
        $choices = array(BIGBLUEBUTTON_CLIENTTYPE_FLASH => get_string('mod_form_block_clienttype_flash', 'bigbluebuttonbn'),
2833
                         BIGBLUEBUTTON_CLIENTTYPE_HTML5 => get_string('mod_form_block_clienttype_html5', 'bigbluebuttonbn'));
2834
        $renderer->render_group_element('clienttype_default',
2835
            $renderer->render_group_element_configselect('clienttype_default',
2836
                $default, $choices));
2837
    }
2838
}
2839
2840
/**
2841
 * Helper function renders general settings if the feature is enabled.
2842
 *
2843
 * @param object $renderer
2844
 *
2845
 * @return void
2846
 */
2847 View Code Duplication
function bigbluebuttonbn_settings_muteonstart(&$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...
2848
    // Configuration for BigBlueButton.
2849
    if ((boolean)\mod_bigbluebuttonbn\settings\validator::section_muteonstart_shown()) {
2850
        $renderer->render_group_header('muteonstart');
2851
        $renderer->render_group_element('muteonstart_default',
2852
            $renderer->render_group_element_checkbox('muteonstart_default', 0));
2853
        $renderer->render_group_element('muteonstart_editable',
2854
            $renderer->render_group_element_checkbox('muteonstart_editable', 0));
2855
    }
2856
}
2857
2858
/**
2859
 * Helper function renders extended settings if any of the features there is enabled.
2860
 *
2861
 * @param object $renderer
2862
 *
2863
 * @return void
2864
 */
2865 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...
2866
    // Configuration for 'notify users when recording ready' feature.
2867
    if (!(boolean)\mod_bigbluebuttonbn\settings\validator::section_settings_extended_shown()) {
2868
        return;
2869
    }
2870
    $renderer->render_group_header('extended_capabilities');
2871
    // UI for 'notify users when recording ready' feature.
2872
    $renderer->render_group_element('recordingready_enabled',
2873
        $renderer->render_group_element_checkbox('recordingready_enabled', 0));
2874
    // Configuration for extended BN capabilities.
2875
    if (bigbluebuttonbn_is_bn_server()) {
2876
        // UI for 'register meeting events' feature.
2877
        $renderer->render_group_element('meetingevents_enabled',
2878
            $renderer->render_group_element_checkbox('meetingevents_enabled', 0));
2879
    }
2880
}
2881
2882
/**
2883
 * Helper function returns a sha1 encoded string that is unique and will be used as a seed for meetingid.
2884
 *
2885
 * @return string
2886
 */
2887
function bigbluebuttonbn_unique_meetingid_seed() {
2888
    global $DB;
2889
    do {
2890
        $encodedseed = sha1(bigbluebuttonbn_random_password(12));
2891
        $meetingid = (string)$DB->get_field('bigbluebuttonbn', 'meetingid', array('meetingid' => $encodedseed));
2892
    } while ($meetingid == $encodedseed);
2893
    return $encodedseed;
2894
}
2895
2896
/**
2897
 * Helper function renders the link used for recording type in row for the data used by the recording table.
2898
 *
2899
 * @param array $recording
2900
 * @param array $bbbsession
2901
 * @param array $playback
2902
 *
2903
 * @return boolean
2904
 */
2905
function bigbluebuttonbn_include_recording_data_row_type($recording, $bbbsession, $playback) {
2906
    // All types that are not restricted are included.
2907
    if (array_key_exists('restricted', $playback) && strtolower($playback['restricted']) == 'false') {
2908
        return true;
2909
    }
2910
    // All types that are not statistics are included.
2911
    if ($playback['type'] != 'statistics') {
2912
        return true;
2913
    }
2914
    // Exclude imported recordings.
2915
    if (isset($recording['imported'])) {
2916
        return false;
2917
    }
2918
    // Exclude non moderators.
2919
    if (!$bbbsession['administrator'] && !$bbbsession['moderator']) {
2920
        return false;
2921
    }
2922
    return true;
2923
}
2924
2925
/**
2926
 * Renders the general warning message.
2927
 *
2928
 * @param string $message
2929
 * @param string $type
2930
 * @param string $href
2931
 * @param string $text
2932
 * @param string $class
2933
 *
2934
 * @return string
2935
 */
2936
function bigbluebuttonbn_render_warning($message, $type='info', $href='', $text='', $class='') {
2937
    global $OUTPUT;
2938
    $output = "\n";
2939
    // Evaluates if config_warning is enabled.
2940
    if (empty($message)) {
2941
        return $output;
2942
    }
2943
    $output .= $OUTPUT->box_start('box boxalignleft adminerror alert alert-' . $type . ' alert-block fade in',
2944
      'bigbluebuttonbn_view_general_warning') . "\n";
2945
    $output .= '    ' . $message . "\n";
2946
    $output .= '  <div class="singlebutton pull-right">' . "\n";
2947
    if (!empty($href)) {
2948
        $output .= bigbluebuttonbn_render_warning_button($href, $text, $class);
2949
    }
2950
    $output .= '  </div>' . "\n";
2951
    $output .= $OUTPUT->box_end() . "\n";
2952
    return $output;
2953
}
2954
2955
/**
2956
 * Renders the general warning button.
2957
 *
2958
 * @param string $href
2959
 * @param string $text
2960
 * @param string $class
2961
 * @param string $title
2962
 *
2963
 * @return string
2964
 */
2965
function bigbluebuttonbn_render_warning_button($href, $text = '', $class = '', $title = '') {
2966
    if ($text == '') {
2967
        $text = get_string('ok', 'moodle');
2968
    }
2969
    if ($title == '') {
2970
        $title = $text;
2971
    }
2972
    if ($class == '') {
2973
        $class = 'btn btn-secondary';
2974
    }
2975
    $output  = '  <form method="post" action="' . $href . '" class="form-inline">'."\n";
2976
    $output .= '      <button type="submit" class="' . $class . '"'."\n";
2977
    $output .= '          title="' . $title . '"'."\n";
2978
    $output .= '          >' . $text . '</button>'."\n";
2979
    $output .= '  </form>'."\n";
2980
    return $output;
2981
}
2982
2983
/**
2984
 * Check if a BigBlueButtonBN is available to be used by the current user.
2985
 *
2986
 * @param  stdClass  $bigbluebuttonbn  BigBlueButtonBN instance
2987
 *
2988
 * @return boolean                     status if room available and current user allowed to join
2989
 */
2990
function bigbluebuttonbn_get_availability_status($bigbluebuttonbn) {
2991
    list($roomavailable) = bigbluebuttonbn_room_is_available($bigbluebuttonbn);
2992
    list($usercanjoin) = bigbluebuttonbn_user_can_join_meeting($bigbluebuttonbn);
2993
2994
    return ($roomavailable && $usercanjoin);
2995
}
2996
2997
/**
2998
 * Helper for evaluating if scheduled activity is avaiable.
2999
 *
3000
 * @param  stdClass  $bigbluebuttonbn  BigBlueButtonBN instance
3001
 *
3002
 * @return array                       status (room available or not and possible warnings)
3003
 */
3004
function bigbluebuttonbn_room_is_available($bigbluebuttonbn) {
3005
    $open = true;
3006
    $closed = false;
3007
    $warnings = array();
3008
3009
    $timenow = time();
3010
    $timeopen = $bigbluebuttonbn->openingtime;
3011
    $timeclose = $bigbluebuttonbn->closingtime;
3012
    if (!empty($timeopen) && $timeopen > $timenow) {
3013
        $open = false;
3014
    }
3015
    if (!empty($timeclose) && $timenow > $timeclose) {
3016
        $closed = true;
3017
    }
3018
3019
    if (!$open || $closed) {
3020
        if (!$open) {
3021
            $warnings['notopenyet'] = userdate($timeopen);
3022
        }
3023
        if ($closed) {
3024
            $warnings['expired'] = userdate($timeclose);
3025
        }
3026
        return array(false, $warnings);
3027
    }
3028
3029
    return array(true, $warnings);
3030
}
3031
3032
/**
3033
 * Helper for evaluating if meeting can be joined.
3034
 *
3035
 * @param  stdClass $bigbluebuttonbn  BigBlueButtonBN instance
3036
 * @param  string   $mid
3037
 * @param  integer  $userid
3038
 *
3039
 * @return array    status (user allowed to join or not and possible message)
3040
 */
3041
function bigbluebuttonbn_user_can_join_meeting($bigbluebuttonbn, $mid = null, $userid = null) {
3042
3043
    // By default, use a meetingid without groups.
3044
    if (empty($mid)) {
3045
        $mid = $bigbluebuttonbn->meetingid . '-' . $bigbluebuttonbn->course . '-' . $bigbluebuttonbn->id;
3046
    }
3047
3048
    // When meeting is running, all authorized users can join right in.
3049
    if (bigbluebuttonbn_is_meeting_running($mid)) {
3050
        return array(true, get_string('view_message_conference_in_progress', 'bigbluebuttonbn'));
3051
    }
3052
3053
    // When meeting is not running, see if the user can join.
3054
    $context = context_course::instance($bigbluebuttonbn->course);
3055
    $participantlist = bigbluebuttonbn_get_participant_list($bigbluebuttonbn, $context);
3056
    $isadmin = is_siteadmin($userid);
3057
    $ismoderator = bigbluebuttonbn_is_moderator($context, $participantlist, $userid);
3058
    // If user is administrator, moderator or if is viewer and no waiting is required, join allowed.
3059
    if ($isadmin || $ismoderator || !$bigbluebuttonbn->wait) {
3060
        return array(true, get_string('view_message_conference_room_ready', 'bigbluebuttonbn'));
3061
    }
3062
    // Otherwise, no join allowed.
3063
    return array(false, get_string('view_message_conference_wait_for_moderator', 'bigbluebuttonbn'));
3064
}
3065
3066
/**
3067
 * Helper for getting a value from a bigbluebuttonbn cache.
3068
 *
3069
 * @param  string   $name       BigBlueButtonBN cache
3070
 * @param  string   $key        Key to be retrieved
3071
 * @param  integer  $default    Default value in case key is not found or it is empty
3072
 *
3073
 * @return variable key value
3074
 */
3075
function bigbluebuttonbn_cache_get($name, $key, $default = null) {
3076
    $cache = cache::make_from_params(cache_store::MODE_APPLICATION, 'mod_bigbluebuttonbn', $name);
3077
    $result = $cache->get($key);
3078
    if (!empty($result)) {
3079
        return $result;
3080
    }
3081
    return $default;
3082
}
3083
3084
/**
3085
 * Helper for setting a value in a bigbluebuttonbn cache.
3086
 *
3087
 * @param  string   $name       BigBlueButtonBN cache
3088
 * @param  string   $key        Key to be created/updated
3089
 * @param  variable $value      Default value to be set
3090
 */
3091
function bigbluebuttonbn_cache_set($name, $key, $value) {
3092
    $cache = cache::make_from_params(cache_store::MODE_APPLICATION, 'mod_bigbluebuttonbn', $name);
3093
    $cache->set($key, $value);
3094
}
3095
3096
/**
3097
 * Helper for getting the owner userid of a bigbluebuttonbn instance.
3098
 *
3099
 * @param  stdClass $bigbluebuttonbn  BigBlueButtonBN instance
3100
 *
3101
 * @return integer ownerid (a valid user id or null if not registered/found)
3102
 */
3103
function bigbluebuttonbn_instance_ownerid($bigbluebuttonbn) {
3104
    global $DB;
3105
    $filters = array('bigbluebuttonbnid' => $bigbluebuttonbn->id, 'log' => 'Add');
3106
    $ownerid = (integer)$DB->get_field('bigbluebuttonbn_logs', 'userid', $filters);
3107
    return $ownerid;
3108
}
3109
3110
/**
3111
 * Helper evaluates if the bigbluebutton server used belongs to blindsidenetworks domain.
3112
 *
3113
 * @return boolean
3114
 */
3115
function bigbluebuttonbn_has_html5_client() {
3116
    $checkurl = \mod_bigbluebuttonbn\locallib\bigbluebutton::root() . "html5client/check";
3117
    $curlinfo = bigbluebuttonbn_wrap_xml_load_file_curl_request($checkurl, 'HEAD');
3118
    return (isset($curlinfo['http_code']) && $curlinfo['http_code'] == 200);
3119
}
3120
3121
/**
3122
 * Setup the bbbsession variable that is used all accross the plugin.
3123
 *
3124
 * @param object $context
3125
 * @param array $bbbsession
3126
 * @return void
3127
 */
3128 View Code Duplication
function bigbluebuttonbn_view_bbbsession_set($context, &$bbbsession) {
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...
3129
    global $CFG, $USER;
3130
    // User data.
3131
    $bbbsession['username'] = fullname($USER);
3132
    $bbbsession['userID'] = $USER->id;
3133
    // User roles.
3134
    $bbbsession['administrator'] = is_siteadmin($bbbsession['userID']);
3135
    $participantlist = bigbluebuttonbn_get_participant_list($bbbsession['bigbluebuttonbn'], $context);
3136
    $bbbsession['moderator'] = bigbluebuttonbn_is_moderator($context, $participantlist);
3137
    $bbbsession['managerecordings'] = ($bbbsession['administrator']
3138
        || has_capability('mod/bigbluebuttonbn:managerecordings', $context));
3139
    $bbbsession['importrecordings'] = ($bbbsession['managerecordings']);
3140
    // Server data.
3141
    $bbbsession['modPW'] = $bbbsession['bigbluebuttonbn']->moderatorpass;
3142
    $bbbsession['viewerPW'] = $bbbsession['bigbluebuttonbn']->viewerpass;
3143
    // Database info related to the activity.
3144
    $bbbsession['meetingid'] = $bbbsession['bigbluebuttonbn']->meetingid.'-'.$bbbsession['course']->id.'-'.
3145
        $bbbsession['bigbluebuttonbn']->id;
3146
    $bbbsession['meetingname'] = $bbbsession['bigbluebuttonbn']->name;
3147
    $bbbsession['meetingdescription'] = $bbbsession['bigbluebuttonbn']->intro;
3148
    // Extra data for setting up the Meeting.
3149
    $bbbsession['userlimit'] = intval((int)\mod_bigbluebuttonbn\locallib\config::get('userlimit_default'));
3150
    if ((boolean)\mod_bigbluebuttonbn\locallib\config::get('userlimit_editable')) {
3151
        $bbbsession['userlimit'] = intval($bbbsession['bigbluebuttonbn']->userlimit);
3152
    }
3153
    $bbbsession['voicebridge'] = $bbbsession['bigbluebuttonbn']->voicebridge;
3154
    if ($bbbsession['bigbluebuttonbn']->voicebridge > 0) {
3155
        $bbbsession['voicebridge'] = 70000 + $bbbsession['bigbluebuttonbn']->voicebridge;
3156
    }
3157
    $bbbsession['wait'] = $bbbsession['bigbluebuttonbn']->wait;
3158
    $bbbsession['record'] = $bbbsession['bigbluebuttonbn']->record;
3159
    $bbbsession['recordallfromstart'] = $CFG->bigbluebuttonbn_recording_all_from_start_default;
3160
    if ($CFG->bigbluebuttonbn_recording_all_from_start_editable) {
3161
        $bbbsession['recordallfromstart'] = $bbbsession['bigbluebuttonbn']->recordallfromstart;
3162
    }
3163
3164
    $bbbsession['recordhidebutton'] = $CFG->bigbluebuttonbn_recording_hide_button_default;
3165
    if ($CFG->bigbluebuttonbn_recording_hide_button_editable) {
3166
        $bbbsession['recordhidebutton'] = $bbbsession['bigbluebuttonbn']->recordhidebutton;
3167
    }
3168
3169
    $bbbsession['welcome'] = $bbbsession['bigbluebuttonbn']->welcome;
3170
    if (!isset($bbbsession['welcome']) || $bbbsession['welcome'] == '') {
3171
        $bbbsession['welcome'] = get_string('mod_form_field_welcome_default', 'bigbluebuttonbn');
3172
    }
3173
    if ($bbbsession['bigbluebuttonbn']->record) {
3174
        // Check if is enable record all from start.
3175
        if ($bbbsession['recordallfromstart']) {
3176
            $bbbsession['welcome'] .= '<br><br>'.get_string('bbbrecordallfromstartwarning',
3177
                    'bigbluebuttonbn');
3178
        } else {
3179
            $bbbsession['welcome'] .= '<br><br>'.get_string('bbbrecordwarning', 'bigbluebuttonbn');
3180
        }
3181
    }
3182
    $bbbsession['openingtime'] = $bbbsession['bigbluebuttonbn']->openingtime;
3183
    $bbbsession['closingtime'] = $bbbsession['bigbluebuttonbn']->closingtime;
3184
    $bbbsession['muteonstart'] = $bbbsession['bigbluebuttonbn']->muteonstart;
3185
    // Additional info related to the course.
3186
    $bbbsession['context'] = $context;
3187
    // Metadata (origin).
3188
    $bbbsession['origin'] = 'Moodle';
3189
    $bbbsession['originVersion'] = $CFG->release;
3190
    $parsedurl = parse_url($CFG->wwwroot);
3191
    $bbbsession['originServerName'] = $parsedurl['host'];
3192
    $bbbsession['originServerUrl'] = $CFG->wwwroot;
3193
    $bbbsession['originServerCommonName'] = '';
3194
    $bbbsession['originTag'] = 'moodle-mod_bigbluebuttonbn ('.get_config('mod_bigbluebuttonbn', 'version').')';
3195
    $bbbsession['bnserver'] = bigbluebuttonbn_is_bn_server();
3196
    // Setting for clienttype, assign flash if not enabled, or default if not editable.
3197
    $bbbsession['clienttype'] = BIGBLUEBUTTON_CLIENTTYPE_FLASH;
3198
    if (\mod_bigbluebuttonbn\locallib\config::clienttype_enabled()) {
3199
        $bbbsession['clienttype'] = \mod_bigbluebuttonbn\locallib\config::get('clienttype_default');
3200
    }
3201
    if (\mod_bigbluebuttonbn\locallib\config::get('clienttype_editable') && isset($bbbsession['bigbluebuttonbn']->clienttype)) {
3202
        $bbbsession['clienttype'] = $bbbsession['bigbluebuttonbn']->clienttype;
3203
    }
3204
}
3205
3206
/**
3207
 * Return the status of an activity [open|not_started|ended].
3208
 *
3209
 * @param array $bbbsession
3210
 * @return string
3211
 */
3212 View Code Duplication
function bigbluebuttonbn_view_get_activity_status(&$bbbsession) {
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...
3213
    $now = time();
3214
    if (!empty($bbbsession['bigbluebuttonbn']->openingtime) && $now < $bbbsession['bigbluebuttonbn']->openingtime) {
3215
        // The activity has not been opened.
3216
        return 'not_started';
3217
    }
3218
    if (!empty($bbbsession['bigbluebuttonbn']->closingtime) && $now > $bbbsession['bigbluebuttonbn']->closingtime) {
3219
        // The activity has been closed.
3220
        return 'ended';
3221
    }
3222
    // The activity is open.
3223
    return 'open';
3224
}
3225
3226
/**
3227
 * Set session URLs.
3228
 *
3229
 * @param array $bbbsession
3230
 * @param int $id
3231
 * @return string
3232
 */
3233
function bigbluebuttonbn_view_session_config(&$bbbsession, $id) {
3234
    // Operation URLs.
3235
    $bbbsession['bigbluebuttonbnURL'] = plugin::necurl(
3236
        '/mod/bigbluebuttonbn/view.php', ['id' => $bbbsession['cm']->id]
3237
    );
3238
    $bbbsession['logoutURL'] = plugin::necurl(
3239
        '/mod/bigbluebuttonbn/bbb_view.php',
3240
        ['action' => 'logout', 'id' => $id, 'bn' => $bbbsession['bigbluebuttonbn']->id]
3241
    );
3242
    $bbbsession['recordingReadyURL'] = plugin::necurl(
3243
        '/mod/bigbluebuttonbn/bbb_broker.php',
3244
        ['action' => 'recording_ready', 'bigbluebuttonbn' => $bbbsession['bigbluebuttonbn']->id]
3245
    );
3246
    $bbbsession['meetingEventsURL'] = plugin::necurl(
3247
        '/mod/bigbluebuttonbn/bbb_broker.php',
3248
        ['action' => 'meeting_events', 'bigbluebuttonbn' => $bbbsession['bigbluebuttonbn']->id]
3249
    );
3250
    $bbbsession['joinURL'] = plugin::necurl(
3251
        '/mod/bigbluebuttonbn/bbb_view.php',
3252
        ['action' => 'join', 'id' => $id, 'bn' => $bbbsession['bigbluebuttonbn']->id]
3253
    );
3254
3255
    // Check status and set extra values.
3256
    $activitystatus = bigbluebuttonbn_view_get_activity_status($bbbsession);  // In locallib.
3257 View Code Duplication
    if ($activitystatus == 'ended') {
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...
3258
        $bbbsession['presentation'] = bigbluebuttonbn_get_presentation_array(
3259
            $bbbsession['context'], $bbbsession['bigbluebuttonbn']->presentation);
3260
    } else if ($activitystatus == 'open') {
3261
        $bbbsession['presentation'] = bigbluebuttonbn_get_presentation_array(
3262
            $bbbsession['context'], $bbbsession['bigbluebuttonbn']->presentation, $bbbsession['bigbluebuttonbn']->id);
3263
    }
3264
3265
    return $activitystatus;
3266
}
3267
3268
/**
3269
 * Helper for preparing metadata used while creating the meeting.
3270
 *
3271
 * @param  array    $bbbsession
3272
 * @return array
3273
 */
3274
function bigbluebuttonbn_create_meeting_metadata(&$bbbsession) {
3275
    global $USER;
3276
    // Create standard metadata.
3277
    $metadata = [
3278
        'bbb-origin' => $bbbsession['origin'],
3279
        'bbb-origin-version' => $bbbsession['originVersion'],
3280
        'bbb-origin-server-name' => $bbbsession['originServerName'],
3281
        'bbb-origin-server-common-name' => $bbbsession['originServerCommonName'],
3282
        'bbb-origin-tag' => $bbbsession['originTag'],
3283
        'bbb-context' => $bbbsession['course']->fullname,
3284
        'bbb-context-id' => $bbbsession['course']->id,
3285
        'bbb-context-name' => trim(html_to_text($bbbsession['course']->fullname, 0)),
3286
        'bbb-context-label' => trim(html_to_text($bbbsession['course']->shortname, 0)),
3287
        'bbb-recording-name' => bigbluebuttonbn_html2text($bbbsession['meetingname'], 64),
3288
        'bbb-recording-description' => bigbluebuttonbn_html2text($bbbsession['meetingdescription'], 64),
3289
        'bbb-recording-tags' => bigbluebuttonbn_get_tags($bbbsession['cm']->id), // Same as $id.
3290
    ];
3291
    // Special metadata for recording processing.
3292
    if ((boolean)\mod_bigbluebuttonbn\locallib\config::get('recordingstatus_enabled')) {
3293
        $metadata["bn-recording-status"] = json_encode(
3294
            array(
3295
                'email' => array('"' . fullname($USER) . '" <' . $USER->email . '>'),
3296
                'context' => $bbbsession['bigbluebuttonbnURL']
3297
              )
3298
          );
3299
    }
3300
    if ((boolean)\mod_bigbluebuttonbn\locallib\config::get('recordingready_enabled')) {
3301
        $metadata['bn-recording-ready-url'] = $bbbsession['recordingReadyURL'];
3302
    }
3303
    if ((boolean)\mod_bigbluebuttonbn\locallib\config::get('meetingevents_enabled')) {
3304
        $metadata['analytics-callback-url'] = $bbbsession['meetingEventsURL'];
3305
    }
3306
    return $metadata;
3307
}
3308