Completed
Pull Request — master (#155)
by Jesus
02:17
created

locallib.php ➔ bigbluebuttonbn_process_meeting_events()   A

Complexity

Conditions 3
Paths 5

Size

Total Lines 29

Duplication

Lines 0
Ratio 0 %

Importance

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