Completed
Pull Request — master (#115)
by
unknown
02:00
created

locallib.php ➔ bigbluebuttonbn_view_bbbsession_set()   F

Complexity

Conditions 12
Paths 768

Size

Total Lines 79

Duplication

Lines 79
Ratio 100 %

Importance

Changes 0
Metric Value
cc 12
nc 768
nop 2
dl 79
loc 79
rs 2.9559
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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