Completed
Pull Request — master (#110)
by
unknown
03:01
created

locallib.php ➔ bigbluebuttonbn_get_presentation_array()   B

Complexity

Conditions 7
Paths 7

Size

Total Lines 69

Duplication

Lines 28
Ratio 40.58 %

Importance

Changes 0
Metric Value
cc 7
nc 7
nop 3
dl 28
loc 69
rs 7.743
c 0
b 0
f 0

How to fix   Long Method   

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
86
/**
87
 * Builds and retunrs a url for joining a bigbluebutton meeting.
88
 *
89
 * @param string $meetingid
90
 * @param string $username
91
 * @param string $pw
92
 * @param string $logouturl
93
 * @param string $configtoken
94
 * @param string $userid
95
 * @param string $clienttype
96
 *
97
 * @return string
98
 */
99
function bigbluebuttonbn_get_join_url($meetingid, $username, $pw, $logouturl, $configtoken = null,
100
        $userid = null, $clienttype = BIGBLUEBUTTON_CLIENTTYPE_FLASH) {
101
    $data = ['meetingID' => $meetingid,
102
              'fullName' => $username,
103
              'password' => $pw,
104
              'logoutURL' => $logouturl,
105
            ];
106
    // Choose between Adobe Flash or HTML5 Client.
107
    if ( $clienttype == BIGBLUEBUTTON_CLIENTTYPE_HTML5 ) {
108
        $data['joinViaHtml5'] = 'true';
109
    }
110
    if (!is_null($configtoken)) {
111
        $data['configToken'] = $configtoken;
112
    }
113
    if (!is_null($userid)) {
114
        $data['userID'] = $userid;
115
    }
116
    return \mod_bigbluebuttonbn\locallib\bigbluebutton::action_url('join', $data);
117
}
118
119
/**
120
 * Creates a bigbluebutton meeting and returns the response in an array.
121
 *
122
 * @param array  $data
123
 * @param array  $metadata
124
 * @param string $pname
125
 * @param string $purl
126
 *
127
 * @return array
128
 */
129
function bigbluebuttonbn_get_create_meeting_array($data, $metadata = array(), $pname = null, $purl = null) {
130
    $createmeetingurl = \mod_bigbluebuttonbn\locallib\bigbluebutton::action_url('create', $data, $metadata);
131
    $method = 'GET';
132
    $data = null;
133
    if (!is_null($pname) && !is_null($purl)) {
134
        $method = 'POST';
135
        $data = "<?xml version='1.0' encoding='UTF-8'?><modules><module name='presentation'><document url='".
136
            $purl."' /></module></modules>";
137
    }
138
    $xml = bigbluebuttonbn_wrap_xml_load_file($createmeetingurl, $method, $data);
139
    if ($xml) {
140
        $response = array('returncode' => $xml->returncode, 'message' => $xml->message, 'messageKey' => $xml->messageKey);
141
        if ($xml->meetingID) {
142
            $response += array('meetingID' => $xml->meetingID, 'attendeePW' => $xml->attendeePW,
143
                'moderatorPW' => $xml->moderatorPW, 'hasBeenForciblyEnded' => $xml->hasBeenForciblyEnded);
144
        }
145
        return $response;
146
    }
147
    return array('returncode' => 'FAILED', 'message' => 'unreachable', 'messageKey' => 'Server is unreachable');
148
}
149
150
/**
151
 * Fetch meeting info and wrap response in array.
152
 *
153
 * @param string $meetingid
154
 *
155
 * @return array
156
 */
157
function bigbluebuttonbn_get_meeting_info_array($meetingid) {
158
    $xml = bigbluebuttonbn_wrap_xml_load_file(
159
        \mod_bigbluebuttonbn\locallib\bigbluebutton::action_url('getMeetingInfo', ['meetingID' => $meetingid])
160
      );
161
    if ($xml && $xml->returncode == 'SUCCESS' && empty($xml->messageKey)) {
162
        // Meeting info was returned.
163
        return array('returncode' => $xml->returncode,
164
                     'meetingID' => $xml->meetingID,
165
                     'moderatorPW' => $xml->moderatorPW,
166
                     'attendeePW' => $xml->attendeePW,
167
                     'hasBeenForciblyEnded' => $xml->hasBeenForciblyEnded,
168
                     'running' => $xml->running,
169
                     'recording' => $xml->recording,
170
                     'startTime' => $xml->startTime,
171
                     'endTime' => $xml->endTime,
172
                     'participantCount' => $xml->participantCount,
173
                     'moderatorCount' => $xml->moderatorCount,
174
                     'attendees' => $xml->attendees,
175
                     'metadata' => $xml->metadata,
176
                   );
177
    }
178
    if ($xml) {
179
        // Either failure or success without meeting info.
180
        return (array)$xml;
181
    }
182
    // If the server is unreachable, then prompts the user of the necessary action.
183
    return array('returncode' => 'FAILED', 'message' => 'unreachable', 'messageKey' => 'Server is unreachable');
184
}
185
186
/**
187
 * Helper function to retrieve recordings from a BigBlueButton server.
188
 *
189
 * @param string|array $meetingids   list of meetingIDs "mid1,mid2,mid3" or array("mid1","mid2","mid3")
190
 * @param string|array $recordingids list of $recordingids "rid1,rid2,rid3" or array("rid1","rid2","rid3") for filtering
191
 *
192
 * @return associative array with recordings indexed by recordID, each recording is a non sequential associative array
193
 */
194
function bigbluebuttonbn_get_recordings_array($meetingids, $recordingids = []) {
195
    $meetingidsarray = $meetingids;
196
    if (!is_array($meetingids)) {
197
        $meetingidsarray = explode(',', $meetingids);
198
    }
199
    // If $meetingidsarray is empty there is no need to go further.
200
    if (empty($meetingidsarray)) {
201
        return array();
202
    }
203
    $recordings = bigbluebuttonbn_get_recordings_array_fetch($meetingidsarray);
0 ignored issues
show
Bug introduced by
It seems like $meetingidsarray defined by $meetingids on line 195 can also be of type string; however, bigbluebuttonbn_get_recordings_array_fetch() does only seem to accept array, maybe add an additional type check?

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

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

    return array();
}

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

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

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

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

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

    return array();
}

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

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

Loading history...
216
}
217
218
/**
219
 * Helper function to fetch recordings from a BigBlueButton server.
220
 *
221
 * @param array $meetingidsarray   array with meeting ids in the form array("mid1","mid2","mid3")
222
 *
223
 * @return associative array with recordings indexed by recordID, each recording is a non sequential associative array
224
 */
225
function bigbluebuttonbn_get_recordings_array_fetch($meetingidsarray) {
226
    $recordings = array();
227
    // Execute a paginated getRecordings request.
228
    $pages = floor(count($meetingidsarray) / 25) + 1;
229
    for ($page = 1; $page <= $pages; ++$page) {
230
        $mids = array_slice($meetingidsarray, ($page - 1) * 25, 25);
231
        $recordings += bigbluebuttonbn_get_recordings_array_fetch_page($mids);
232
    }
233
    return $recordings;
234
}
235
236
/**
237
 * Helper function to fetch one page of upto 25 recordings from a BigBlueButton server.
238
 *
239
 * @param array  $mids
240
 *
241
 * @return array
242
 */
243
function bigbluebuttonbn_get_recordings_array_fetch_page($mids) {
244
    $recordings = array();
245
    // Do getRecordings is executed using a method GET (supported by all versions of BBB).
246
    $url = \mod_bigbluebuttonbn\locallib\bigbluebutton::action_url('getRecordings', ['meetingID' => implode(',', $mids)]);
247
    $xml = bigbluebuttonbn_wrap_xml_load_file($url);
248
    if ($xml && $xml->returncode == 'SUCCESS' && isset($xml->recordings)) {
249
        // If there were meetings already created.
250
        foreach ($xml->recordings->recording as $recordingxml) {
251
            $recording = bigbluebuttonbn_get_recording_array_value($recordingxml);
252
            $recordings[$recording['recordID']] = $recording;
253
        }
254
    }
255
    return $recordings;
256
}
257
258
/**
259
 * Helper function to remove a set of recordings from an array.
260
 *
261
 * @param array  $rids
262
 * @param array  $recordings
263
 *
264
 * @return array
265
 */
266
function bigbluebuttonbn_get_recordings_array_filter($rids, &$recordings) {
267
    foreach ($recordings as $key => $recording) {
268
        if (!in_array($recording['recordID'], $rids)) {
269
            unset($recordings[$key]);
270
        }
271
    }
272
    return $recordings;
273
}
274
275
/**
276
 * Helper function to retrieve imported recordings from the Moodle database.
277
 * The references are stored as events in bigbluebuttonbn_logs.
278
 *
279
 * @param string $courseid
280
 * @param string $bigbluebuttonbnid
281
 * @param bool   $subset
282
 *
283
 * @return associative array with imported recordings indexed by recordID, each recording
284
 * is a non sequential associative array that corresponds to the actual recording in BBB
285
 */
286
function bigbluebuttonbn_get_recordings_imported_array($courseid = 0, $bigbluebuttonbnid = null, $subset = true) {
287
    global $DB;
288
    $select = bigbluebuttonbn_get_recordings_imported_sql_select($courseid, $bigbluebuttonbnid, $subset);
289
    $recordsimported = $DB->get_records_select('bigbluebuttonbn_logs', $select);
290
    $recordsimportedarray = array();
291
    foreach ($recordsimported as $recordimported) {
292
        $meta = json_decode($recordimported->meta, true);
293
        $recording = $meta['recording'];
294
        // Override imported flag with actual ID.
295
        $recording['imported'] = $recordimported->id;
296
        if (isset($recordimported->protected)) {
297
            $recording['protected'] = (string) $recordimported->protected;
298
        }
299
        $recordsimportedarray[$recording['recordID']] = $recording;
300
    }
301
    return $recordsimportedarray;
302
}
303
304
/**
305
 * Helper function to retrive the default config.xml file.
306
 *
307
 * @return string
308
 */
309
function bigbluebuttonbn_get_default_config_xml() {
310
    $xml = bigbluebuttonbn_wrap_xml_load_file(
311
        \mod_bigbluebuttonbn\locallib\bigbluebutton::action_url('getDefaultConfigXML')
312
      );
313
    return $xml;
314
}
315
316
/**
317
 * Helper function to convert an xml recording object to an array in the format used by the plugin.
318
 *
319
 * @param object $recording
320
 *
321
 * @return array
322
 */
323
function bigbluebuttonbn_get_recording_array_value($recording) {
324
    // Add formats.
325
    $playbackarray = array();
326
    foreach ($recording->playback->format as $format) {
327
        $playbackarray[(string) $format->type] = array('type' => (string) $format->type,
328
            'url' => trim((string) $format->url), 'length' => (string) $format->length);
329
        // Add preview per format when existing.
330
        if ($format->preview) {
331
            $playbackarray[(string) $format->type]['preview'] = bigbluebuttonbn_get_recording_preview_images($format->preview);
332
        }
333
    }
334
    // Add the metadata to the recordings array.
335
    $metadataarray = bigbluebuttonbn_get_recording_array_meta(get_object_vars($recording->metadata));
336
    $recordingarray = array('recordID' => (string) $recording->recordID,
337
        'meetingID' => (string) $recording->meetingID, 'meetingName' => (string) $recording->name,
338
        'published' => (string) $recording->published, 'startTime' => (string) $recording->startTime,
339
        'endTime' => (string) $recording->endTime, 'playbacks' => $playbackarray);
340
    if (isset($recording->protected)) {
341
        $recordingarray['protected'] = (string) $recording->protected;
342
    }
343
    return $recordingarray + $metadataarray;
344
}
345
346
/**
347
 * Helper function to convert an xml recording preview images to an array in the format used by the plugin.
348
 *
349
 * @param object $preview
350
 *
351
 * @return array
352
 */
353
function bigbluebuttonbn_get_recording_preview_images($preview) {
354
    $imagesarray = array();
355
    foreach ($preview->images->image as $image) {
356
        $imagearray = array('url' => trim((string) $image));
357
        foreach ($image->attributes() as $attkey => $attvalue) {
358
            $imagearray[$attkey] = (string) $attvalue;
359
        }
360
        array_push($imagesarray, $imagearray);
361
    }
362
    return $imagesarray;
363
}
364
365
/**
366
 * Helper function to convert an xml recording metadata object to an array in the format used by the plugin.
367
 *
368
 * @param array $metadata
369
 *
370
 * @return array
371
 */
372
function bigbluebuttonbn_get_recording_array_meta($metadata) {
373
    $metadataarray = array();
374
    foreach ($metadata as $key => $value) {
375
        if (is_object($value)) {
376
            $value = '';
377
        }
378
        $metadataarray['meta_'.$key] = $value;
379
    }
380
    return $metadataarray;
381
}
382
383
/**
384
 * Helper function to sort an array of recordings. It compares the startTime in two recording objecs.
385
 *
386
 * @param object $a
387
 * @param object $b
388
 *
389
 * @return array
390
 */
391
function bigbluebuttonbn_recording_build_sorter($a, $b) {
392
    if ($a['startTime'] < $b['startTime']) {
393
        return -1;
394
    }
395
    if ($a['startTime'] == $b['startTime']) {
396
        return 0;
397
    }
398
    return 1;
399
}
400
401
/**
402
 * Perform deleteRecordings on BBB.
403
 *
404
 * @param string $recordids
405
 *
406
 * @return boolean
407
 */
408 View Code Duplication
function bigbluebuttonbn_delete_recordings($recordids) {
0 ignored issues
show
Duplication introduced by
This function seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
409
    $ids = explode(',', $recordids);
410
    foreach ($ids as $id) {
411
        $xml = bigbluebuttonbn_wrap_xml_load_file(
412
            \mod_bigbluebuttonbn\locallib\bigbluebutton::action_url('deleteRecordings', ['recordID' => $id])
413
          );
414
        if ($xml && $xml->returncode != 'SUCCESS') {
415
            return false;
416
        }
417
    }
418
    return true;
419
}
420
421
/**
422
 * Perform publishRecordings on BBB.
423
 *
424
 * @param string $recordids
425
 * @param string $publish
426
 */
427 View Code Duplication
function bigbluebuttonbn_publish_recordings($recordids, $publish = 'true') {
0 ignored issues
show
Duplication introduced by
This function seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
428
    $ids = explode(',', $recordids);
429
    foreach ($ids as $id) {
430
        $xml = bigbluebuttonbn_wrap_xml_load_file(
431
            \mod_bigbluebuttonbn\locallib\bigbluebutton::action_url('publishRecordings', ['recordID' => $id, 'publish' => $publish])
432
          );
433
        if ($xml && $xml->returncode != 'SUCCESS') {
434
            return false;
435
        }
436
    }
437
    return true;
438
}
439
440
/**
441
 * Perform updateRecordings on BBB.
442
 *
443
 * @param string $recordids
444
 * @param array $params ['key'=>param_key, 'value']
445
 */
446 View Code Duplication
function bigbluebuttonbn_update_recordings($recordids, $params) {
0 ignored issues
show
Duplication introduced by
This function seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
447
    $ids = explode(',', $recordids);
448
    foreach ($ids as $id) {
449
        $xml = bigbluebuttonbn_wrap_xml_load_file(
450
            \mod_bigbluebuttonbn\locallib\bigbluebutton::action_url('updateRecordings', ['recordID' => $id] + (array) $params)
451
          );
452
        if ($xml && $xml->returncode != 'SUCCESS') {
453
            return false;
454
        }
455
    }
456
    return true;
457
}
458
459
/**
460
 * Perform end on BBB.
461
 *
462
 * @param string $meetingid
463
 * @param string $modpw
464
 */
465
function bigbluebuttonbn_end_meeting($meetingid, $modpw) {
466
    $xml = bigbluebuttonbn_wrap_xml_load_file(
467
        \mod_bigbluebuttonbn\locallib\bigbluebutton::action_url('end', ['meetingID' => $meetingid, 'password' => $modpw])
468
      );
469
    if ($xml) {
470
        // If the xml packet returned failure it displays the message to the user.
471
        return array('returncode' => $xml->returncode, 'message' => $xml->message, 'messageKey' => $xml->messageKey);
472
    }
473
    // If the server is unreachable, then prompts the user of the necessary action.
474
    return null;
475
}
476
477
/**
478
 * Perform api request on BBB.
479
 *
480
 * @return string
481
 */
482
function bigbluebuttonbn_get_server_version() {
483
    $xml = bigbluebuttonbn_wrap_xml_load_file(
484
        \mod_bigbluebuttonbn\locallib\bigbluebutton::action_url()
485
      );
486
    if ($xml && $xml->returncode == 'SUCCESS') {
487
        return $xml->version;
488
    }
489
    return null;
490
}
491
492
/**
493
 * Perform api request on BBB and wraps the response in an XML object
494
 *
495
 * @param string $url
496
 * @param string $method
497
 * @param string $data
498
 * @param string $contenttype
499
 *
500
 * @return object
501
 */
502
function bigbluebuttonbn_wrap_xml_load_file($url, $method = 'GET', $data = null, $contenttype = 'text/xml') {
503
    if (extension_loaded('curl')) {
504
        $response = bigbluebuttonbn_wrap_xml_load_file_curl_request($url, $method, $data, $contenttype);
505
        if (!$response) {
506
            debugging('No response on wrap_simplexml_load_file', DEBUG_DEVELOPER);
507
            return null;
508
        }
509
        $previous = libxml_use_internal_errors(true);
510
        try {
511
            $xml = simplexml_load_string($response, 'SimpleXMLElement', LIBXML_NOCDATA | LIBXML_NOBLANKS);
512
            return $xml;
513
        } catch (Exception $e) {
514
            libxml_use_internal_errors($previous);
515
            $error = 'Caught exception: '.$e->getMessage();
516
            debugging($error, DEBUG_DEVELOPER);
517
            return null;
518
        }
519
    }
520
    // Alternative request non CURL based.
521
    $previous = libxml_use_internal_errors(true);
522
    try {
523
        $response = simplexml_load_file($url, 'SimpleXMLElement', LIBXML_NOCDATA | LIBXML_NOBLANKS);
524
        return $response;
525
    } catch (Exception $e) {
526
        $error = 'Caught exception: '.$e->getMessage();
527
        debugging($error, DEBUG_DEVELOPER);
528
        libxml_use_internal_errors($previous);
529
        return null;
530
    }
531
}
532
533
/**
534
 * Perform api request on BBB using CURL and wraps the response in an XML object
535
 *
536
 * @param string $url
537
 * @param string $method
538
 * @param string $data
539
 * @param string $contenttype
540
 *
541
 * @return object
542
 */
543
function bigbluebuttonbn_wrap_xml_load_file_curl_request($url, $method = 'GET', $data = null, $contenttype = 'text/xml') {
544
    $c = new curl();
545
    $c->setopt(array('SSL_VERIFYPEER' => true));
546
    if ($method == 'POST') {
547
        if (is_null($data) || is_array($data)) {
548
            return $c->post($url);
549
        }
550
        $options = array();
551
        $options['CURLOPT_HTTPHEADER'] = array(
552
                 'Content-Type: '.$contenttype,
553
                 'Content-Length: '.strlen($data),
554
                 'Content-Language: en-US',
555
               );
556
557
        return $c->post($url, $data, $options);
558
    }
559
    if ($method == 'HEAD') {
560
        $c->head($url, array('followlocation' => true, 'timeout' => 1));
561
        return $c->get_info();
562
    }
563
    return $c->get($url);
564
}
565
566
/**
567
 * End the session associated with this instance (if it's running).
568
 *
569
 * @param object $bigbluebuttonbn
570
 *
571
 * @return void
572
 */
573
function bigbluebuttonbn_end_meeting_if_running($bigbluebuttonbn) {
574
    $meetingid = $bigbluebuttonbn->meetingid.'-'.$bigbluebuttonbn->course.'-'.$bigbluebuttonbn->id;
575
    if (bigbluebuttonbn_is_meeting_running($meetingid)) {
576
        bigbluebuttonbn_end_meeting($meetingid, $bigbluebuttonbn->moderatorpass);
577
    }
578
}
579
580
/**
581
 * Returns user roles in a context.
582
 *
583
 * @param object $context
584
 * @param integer $userid
585
 *
586
 * @return array $userroles
587
 */
588
function bigbluebuttonbn_get_user_roles($context, $userid) {
589
    global $DB;
590
    $userroles = get_user_roles($context, $userid);
591
    if ($userroles) {
592
        $where = '';
593
        foreach ($userroles as $userrole) {
594
            $where .= (empty($where) ? ' WHERE' : ' OR').' id=' . $userrole->roleid;
595
        }
596
        $userroles = $DB->get_records_sql('SELECT * FROM {role}'.$where);
597
    }
598
    return $userroles;
599
}
600
601
/**
602
 * Returns guest role wrapped in an array.
603
 *
604
 * @return array
605
 */
606
function bigbluebuttonbn_get_guest_role() {
607
    $guestrole = get_guest_role();
608
    return array($guestrole->id => $guestrole);
609
}
610
611
/**
612
 * Returns an array containing all the users in a context.
613
 *
614
 * @param context $context
615
 *
616
 * @return array $users
617
 */
618
function bigbluebuttonbn_get_users(context $context = null) {
619
    $users = (array) get_enrolled_users($context, '', 0, 'u.*', null, 0, 0, true);
620
    foreach ($users as $key => $value) {
621
        $users[$key] = fullname($value);
622
    }
623
    return $users;
624
}
625
626
/**
627
 * Returns an array containing all the users in a context wrapped for html select element.
628
 *
629
 * @param context $context
630
 *
631
 * @return array $users
632
 */
633
function bigbluebuttonbn_get_users_select(context $context = null) {
634
    $users = (array) get_enrolled_users($context, '', 0, 'u.*', null, 0, 0, true);
635
    foreach ($users as $key => $value) {
636
        $users[$key] = array('id' => $value->id, 'name' => fullname($value));
637
    }
638
    return $users;
639
}
640
641
/**
642
 * Returns an array containing all the roles in a context.
643
 *
644
 * @param context $context
645
 *
646
 * @return array $roles
647
 */
648
function bigbluebuttonbn_get_roles(context $context = null) {
649
    $roles = (array) role_get_names($context);
650
    foreach ($roles as $key => $value) {
651
        $roles[$key] = $value->localname;
652
    }
653
    return $roles;
654
}
655
656
/**
657
 * Returns an array containing all the roles in a context wrapped for html select element.
658
 *
659
 * @param context $context
660
 *
661
 * @return array $users
662
 */
663
function bigbluebuttonbn_get_roles_select(context $context = null) {
664
    $roles = (array) role_get_names($context);
665
    foreach ($roles as $key => $value) {
666
        $roles[$key] = array('id' => $value->id, 'name' => $value->localname);
667
    }
668
    return $roles;
669
}
670
671
/**
672
 * Returns role that corresponds to an id.
673
 *
674
 * @param string|integer $id
675
 *
676
 * @return object $role
677
 */
678
function bigbluebuttonbn_get_role($id) {
679
    $roles = (array) role_get_names();
680
    if (is_numeric($id) && isset($roles[$id])) {
681
        return (object)$roles[$id];
682
    }
683
    foreach ($roles as $role) {
684
        if ($role->shortname == $id) {
685
            return $role;
686
        }
687
    }
688
}
689
690
/**
691
 * Returns an array to populate a list of participants used in mod_form.js.
692
 *
693
 * @param context $context
694
 *
695
 * @return array $data
696
 */
697
function bigbluebuttonbn_get_participant_data($context) {
698
    $data = array(
699
        'all' => array(
700
            'name' => get_string('mod_form_field_participant_list_type_all', 'bigbluebuttonbn'),
701
            'children' => []
702
          )
703
      );
704
    $data['role'] = array(
705
        'name' => get_string('mod_form_field_participant_list_type_role', 'bigbluebuttonbn'),
706
        'children' => bigbluebuttonbn_get_roles_select($context)
707
      );
708
    $data['user'] = array(
709
        'name' => get_string('mod_form_field_participant_list_type_user', 'bigbluebuttonbn'),
710
        'children' => bigbluebuttonbn_get_users_select($context)
711
      );
712
    return $data;
713
}
714
715
/**
716
 * Returns an array to populate a list of participants used in mod_form.php.
717
 *
718
 * @param object $bigbluebuttonbn
719
 * @param context $context
720
 *
721
 * @return array
722
 */
723
function bigbluebuttonbn_get_participant_list($bigbluebuttonbn, $context) {
724
    global $USER;
725
    if ($bigbluebuttonbn == null) {
726
        return bigbluebuttonbn_get_participant_rules_encoded(
727
            bigbluebuttonbn_get_participant_list_default($context, $USER->id)
728
        );
729
    }
730
    if (empty($bigbluebuttonbn->participants)) {
731
        $bigbluebuttonbn->participants = "[]";
732
    }
733
    $rules = json_decode($bigbluebuttonbn->participants, true);
734
    if (empty($rules)) {
735
        $rules = bigbluebuttonbn_get_participant_list_default($context, bigbluebuttonbn_instance_ownerid($bigbluebuttonbn));
736
    }
737
    return bigbluebuttonbn_get_participant_rules_encoded($rules);
738
}
739
740
/**
741
 * Returns an array to populate a list of participants used in mod_form.php with default values.
742
 *
743
 * @param context $context
744
 * @param integer $ownerid
745
 *
746
 * @return array
747
 */
748
function bigbluebuttonbn_get_participant_list_default($context, $ownerid = null) {
749
    $participantlist = array();
750
    $participantlist[] = array(
751
        'selectiontype' => 'all',
752
        'selectionid' => 'all',
753
        'role' => BIGBLUEBUTTONBN_ROLE_VIEWER
754
      );
755
    $defaultrules = explode(',', \mod_bigbluebuttonbn\locallib\config::get('participant_moderator_default'));
756
    foreach ($defaultrules as $defaultrule) {
757
        if ($defaultrule == '0') {
758
            if (!empty($ownerid) && is_enrolled($context, $ownerid)) {
759
                $participantlist[] = array(
760
                    'selectiontype' => 'user',
761
                    'selectionid' => (string)$ownerid,
762
                    'role' => BIGBLUEBUTTONBN_ROLE_MODERATOR);
763
            }
764
            continue;
765
        }
766
        $participantlist[] = array(
767
              'selectiontype' => 'role',
768
              'selectionid' => $defaultrule,
769
              'role' => BIGBLUEBUTTONBN_ROLE_MODERATOR);
770
    }
771
    return $participantlist;
772
}
773
774
/**
775
 * Returns an array to populate a list of participants used in mod_form.php with bigbluebuttonbn values.
776
 *
777
 * @param array $rules
778
 *
779
 * @return array
780
 */
781
function bigbluebuttonbn_get_participant_rules_encoded($rules) {
782
    foreach ($rules as $key => $rule) {
783
        if ($rule['selectiontype'] !== 'role' || is_numeric($rule['selectionid'])) {
784
            continue;
785
        }
786
        $role = bigbluebuttonbn_get_role($rule['selectionid']);
787
        if ($role == null) {
788
            unset($rules[$key]);
789
            continue;
790
        }
791
        $rule['selectionid'] = $role->id;
792
        $rules[$key] = $rule;
793
    }
794
    return $rules;
795
}
796
797
/**
798
 * Returns an array to populate a list of participant_selection used in mod_form.php.
799
 *
800
 * @return array
801
 */
802
function bigbluebuttonbn_get_participant_selection_data() {
803
    return [
804
        'type_options' => [
805
            'all' => get_string('mod_form_field_participant_list_type_all', 'bigbluebuttonbn'),
806
            'role' => get_string('mod_form_field_participant_list_type_role', 'bigbluebuttonbn'),
807
            'user' => get_string('mod_form_field_participant_list_type_user', 'bigbluebuttonbn'),
808
          ],
809
        'type_selected' => 'all',
810
        'options' => ['all' => '---------------'],
811
        'selected' => 'all',
812
      ];
813
}
814
815
/**
816
 * Evaluate if a user in a context is moderator based on roles and participation rules.
817
 *
818
 * @param context $context
819
 * @param array $participantlist
820
 * @param integer $userid
821
 *
822
 * @return boolean
823
 */
824
function bigbluebuttonbn_is_moderator($context, $participantlist, $userid = null) {
825
    global $USER;
826
    if (!is_array($participantlist)) {
827
        return false;
828
    }
829
    if (empty($userid)) {
830
        $userid = $USER->id;
831
    }
832
    $userroles = bigbluebuttonbn_get_guest_role();
833
    if (!isguestuser()) {
834
        $userroles = bigbluebuttonbn_get_user_roles($context, $userid);
835
    }
836
    return bigbluebuttonbn_is_moderator_validator($participantlist, $userid , $userroles);
837
}
838
839
/**
840
 * Iterates participant list rules to evaluate if a user is moderator.
841
 *
842
 * @param array $participantlist
843
 * @param integer $userid
844
 * @param array $userroles
845
 *
846
 * @return boolean
847
 */
848
function bigbluebuttonbn_is_moderator_validator($participantlist, $userid, $userroles) {
849
    // Iterate participant rules.
850
    foreach ($participantlist as $participant) {
851
        if (bigbluebuttonbn_is_moderator_validate_rule($participant, $userid, $userroles)) {
852
            return true;
853
        }
854
    }
855
    return false;
856
}
857
858
/**
859
 * Evaluate if a user is moderator based on roles and a particular participation rule.
860
 *
861
 * @param object $participant
862
 * @param integer $userid
863
 * @param array $userroles
864
 *
865
 * @return boolean
866
 */
867
function bigbluebuttonbn_is_moderator_validate_rule($participant, $userid, $userroles) {
868
    if ($participant['role'] == BIGBLUEBUTTONBN_ROLE_VIEWER) {
869
        return false;
870
    }
871
    // Looks for all configuration.
872
    if ($participant['selectiontype'] == 'all') {
873
        return true;
874
    }
875
    // Looks for users.
876
    if ($participant['selectiontype'] == 'user' && $participant['selectionid'] == $userid) {
877
        return true;
878
    }
879
    // Looks for roles.
880
    $role = bigbluebuttonbn_get_role($participant['selectionid']);
881
    if ($role != null && array_key_exists($role->id, $userroles)) {
882
        return true;
883
    }
884
    return false;
885
}
886
887
/**
888
 * Helper returns error message key for the language file that corresponds to a bigbluebutton error key.
889
 *
890
 * @param string $messagekey
891
 * @param string $defaultkey
892
 *
893
 * @return string
894
 */
895
function bigbluebuttonbn_get_error_key($messagekey, $defaultkey = null) {
896
    if ($messagekey == 'checksumError') {
897
        return 'index_error_checksum';
898
    }
899
    if ($messagekey == 'maxConcurrent') {
900
        return 'view_error_max_concurrent';
901
    }
902
    return $defaultkey;
903
}
904
905
/**
906
 * Helper evaluates if a voicebridge number is unique.
907
 *
908
 * @param integer $instance
909
 * @param integer $voicebridge
910
 *
911
 * @return string
912
 */
913
function bigbluebuttonbn_voicebridge_unique($instance, $voicebridge) {
914
    global $DB;
915
    if ($voicebridge == 0) {
916
        return true;
917
    }
918
    $select = 'voicebridge = ' . $voicebridge;
919
    if ($instance != 0) {
920
        $select .= ' AND id <>' . $instance;
921
    }
922
    if (!$DB->get_records_select('bigbluebuttonbn', $select)) {
923
        return true;
924
    }
925
    return false;
926
}
927
928
/**
929
 * Helper estimate a duration for the meeting based on the closingtime.
930
 *
931
 * @param integer $closingtime
932
 *
933
 * @return integer
934
 */
935
function bigbluebuttonbn_get_duration($closingtime) {
936
    $duration = 0;
937
    $now = time();
938
    if ($closingtime > 0 && $now < $closingtime) {
939
        $duration = ceil(($closingtime - $now) / 60);
940
        $compensationtime = intval((int)\mod_bigbluebuttonbn\locallib\config::get('scheduled_duration_compensation'));
941
        $duration = intval($duration) + $compensationtime;
942
    }
943
    return $duration;
944
}
945
946
/**
947
 * Helper return array containing the file descriptor for a preuploaded presentation.
948
 *
949
 * @param context $context
950
 * @param string $presentation
951
 * @param integer $id
952
 *
953
 * @return array
954
 */
955
function bigbluebuttonbn_get_presentation_array($context, $presentation, $id = null) {
956
    global $CFG;
957
    if (empty($presentation)) {
958
        if ($CFG->bigbluebuttonbn_preuploadpresentation_enabled) {
959
960
            // Item has not presentation but presentation is enabled..
961
            // Check if exist some file by default in general mod setting ("presentationdefault").
962
            $fs = get_file_storage();
963
            $files = $fs->get_area_files(context_system::instance()->id,
964
                'mod_bigbluebuttonbn',
965
                'presentationdefault',
966
                0,
967
                "filename",
968
                false
969
            );
970
971 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...
972
                // Not exist file by default in "presentationbydefault" setting.
973
                return array('url' => null, 'name' => null, 'icon' => null, 'mimetype_description' => null);
974
            }
975
976
            // Exists file in general setting to use as default for presentation. Cache image for temp public access.
977
            $file = reset($files);
978
            unset($files);
979
            $pnoncevalue = null;
980 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...
981
                // Create the nonce component for granting a temporary public access.
982
                $cache = cache::make_from_params(cache_store::MODE_APPLICATION,
983
                    'mod_bigbluebuttonbn',
984
                    'presentationdefault_cache');
985
                $pnoncekey = sha1(context_system::instance()->id);
986
                /* The item id was adapted for granting public access to the presentation once in order
987
                 * to allow BigBlueButton to gather the file. */
988
                $pnoncevalue = bigbluebuttonbn_generate_nonce();
989
                $cache->set($pnoncekey, array('value' => $pnoncevalue, 'counter' => 0));
990
            }
991
992
            $url = moodle_url::make_pluginfile_url($file->get_contextid(), $file->get_component(),
993
                $file->get_filearea(), $pnoncevalue, $file->get_filepath(), $file->get_filename());
994
            return(array('name' => $file->get_filename(), 'icon' => file_file_icon($file, 24),
995
                'url' => $url->out(false), 'mimetype_description' => get_mimetype_description($file)));
996
        }
997
998
        return array('url' => null, 'name' => null, 'icon' => null, 'mimetype_description' => null);
999
    }
1000
    $fs = get_file_storage();
1001
    $files = $fs->get_area_files($context->id, 'mod_bigbluebuttonbn', 'presentation', 0,
1002
        'itemid, filepath, filename', false);
1003 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...
1004
        return array('url' => null, 'name' => null, 'icon' => null, 'mimetype_description' => null);
1005
    }
1006
    $file = reset($files);
1007
    unset($files);
1008
    $pnoncevalue = null;
1009 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...
1010
        // Create the nonce component for granting a temporary public access.
1011
        $cache = cache::make_from_params(cache_store::MODE_APPLICATION, 'mod_bigbluebuttonbn',
1012
            'presentation_cache');
1013
        $pnoncekey = sha1($id);
1014
        /* The item id was adapted for granting public access to the presentation once in order
1015
         * to allow BigBlueButton to gather the file. */
1016
        $pnoncevalue = bigbluebuttonbn_generate_nonce();
1017
        $cache->set($pnoncekey, array('value' => $pnoncevalue, 'counter' => 0));
1018
    }
1019
    $url = moodle_url::make_pluginfile_url($file->get_contextid(), $file->get_component(),
1020
        $file->get_filearea(), $pnoncevalue, $file->get_filepath(), $file->get_filename());
1021
    return array('name' => $file->get_filename(), 'icon' => file_file_icon($file, 24),
1022
        'url' => $url->out(false), 'mimetype_description' => get_mimetype_description($file));
1023
}
1024
1025
/**
1026
 * Helper generates a nonce used for the preuploaded presentation callback url.
1027
 *
1028
 * @return string
1029
 */
1030
function bigbluebuttonbn_generate_nonce() {
1031
    $mt = microtime();
1032
    $rand = mt_rand();
1033
    return md5($mt.$rand);
1034
}
1035
1036
/**
1037
 * Helper generates a random password.
1038
 *
1039
 * @param integer $length
1040
 * @param string $unique
1041
 *
1042
 * @return string
1043
 */
1044
function bigbluebuttonbn_random_password($length = 8, $unique = "") {
1045
    $chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*()_-=+;:,.?';
1046
    do {
1047
        $password = substr(str_shuffle($chars), 0, $length);
1048
    } while ($unique == $password);
1049
    return $password;
1050
}
1051
1052
/**
1053
 * Helper register a bigbluebuttonbn event.
1054
 *
1055
 * @param string $type
1056
 * @param object $bigbluebuttonbn
1057
 * @param array $options [timecreated, userid, other]
1058
 *
1059
 * @return void
1060
 */
1061
function bigbluebuttonbn_event_log($type, $bigbluebuttonbn, $options = []) {
1062
    global $DB;
1063
    if (!in_array($type, \mod_bigbluebuttonbn\event\events::$events)) {
1064
        // No log will be created.
1065
        return;
1066
    }
1067
    $course = $DB->get_record('course', array('id' => $bigbluebuttonbn->course), '*', MUST_EXIST);
1068
    $cm = get_coursemodule_from_instance('bigbluebuttonbn', $bigbluebuttonbn->id, $course->id, false, MUST_EXIST);
1069
    $context = context_module::instance($cm->id);
1070
    $params = array('context' => $context, 'objectid' => $bigbluebuttonbn->id);
1071
    if (array_key_exists('timecreated', $options)) {
1072
        $params['timecreated'] = $options['timecreated'];
1073
    }
1074
    if (array_key_exists('userid', $options)) {
1075
        $params['userid'] = $options['userid'];
1076
    }
1077
    if (array_key_exists('other', $options)) {
1078
        $params['other'] = $options['other'];
1079
    }
1080
    $event = call_user_func_array('\mod_bigbluebuttonbn\event\\' . $type . '::create',
1081
        array($params));
1082
    $event->add_record_snapshot('course_modules', $cm);
1083
    $event->add_record_snapshot('course', $course);
1084
    $event->add_record_snapshot('bigbluebuttonbn', $bigbluebuttonbn);
1085
    $event->trigger();
1086
}
1087
1088
/**
1089
 * Updates the meeting info cached object when a participant has joined.
1090
 *
1091
 * @param string $meetingid
1092
 * @param bool $ismoderator
1093
 *
1094
 * @return void
1095
 */
1096
function bigbluebuttonbn_participant_joined($meetingid, $ismoderator) {
1097
    $cache = cache::make_from_params(cache_store::MODE_APPLICATION, 'mod_bigbluebuttonbn', 'meetings_cache');
1098
    $result = $cache->get($meetingid);
1099
    $meetinginfo = json_decode($result['meeting_info']);
1100
    $meetinginfo->participantCount += 1;
1101
    if ($ismoderator) {
1102
        $meetinginfo->moderatorCount += 1;
1103
    }
1104
    $cache->set($meetingid, array('creation_time' => $result['creation_time'],
1105
        'meeting_info' => json_encode($meetinginfo)));
1106
}
1107
1108
/**
1109
 * Gets a meeting info object cached or fetched from the live session.
1110
 *
1111
 * @param string $meetingid
1112
 * @param boolean $updatecache
1113
 *
1114
 * @return array
1115
 */
1116
function bigbluebuttonbn_get_meeting_info($meetingid, $updatecache = false) {
1117
    $cachettl = (int)\mod_bigbluebuttonbn\locallib\config::get('waitformoderator_cache_ttl');
1118
    $cache = cache::make_from_params(cache_store::MODE_APPLICATION, 'mod_bigbluebuttonbn', 'meetings_cache');
1119
    $result = $cache->get($meetingid);
1120
    $now = time();
1121
    if (!$updatecache && isset($result) && $now < ($result['creation_time'] + $cachettl)) {
1122
        // Use the value in the cache.
1123
        return (array) json_decode($result['meeting_info']);
1124
    }
1125
    // Ping again and refresh the cache.
1126
    $meetinginfo = (array) bigbluebuttonbn_wrap_xml_load_file(
1127
        \mod_bigbluebuttonbn\locallib\bigbluebutton::action_url('getMeetingInfo', ['meetingID' => $meetingid])
1128
      );
1129
    $cache->set($meetingid, array('creation_time' => time(), 'meeting_info' => json_encode($meetinginfo)));
1130
    return $meetinginfo;
1131
}
1132
1133
/**
1134
 * Perform isMeetingRunning on BBB.
1135
 *
1136
 * @param string $meetingid
1137
 * @param boolean $updatecache
1138
 *
1139
 * @return boolean
1140
 */
1141
function bigbluebuttonbn_is_meeting_running($meetingid, $updatecache = false) {
1142
    /* As a workaround to isMeetingRunning that always return SUCCESS but only returns true
1143
     * when at least one user is in the session, we use getMeetingInfo instead.
1144
     */
1145
    $meetinginfo = bigbluebuttonbn_get_meeting_info($meetingid, $updatecache);
1146
    return ($meetinginfo['returncode'] === 'SUCCESS');
1147
}
1148
1149
/**
1150
 * Publish an imported recording.
1151
 *
1152
 * @param string $id
1153
 * @param boolean $publish
1154
 *
1155
 * @return boolean
1156
 */
1157 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...
1158
    global $DB;
1159
    // Locate the record to be updated.
1160
    $record = $DB->get_record('bigbluebuttonbn_logs', array('id' => $id));
1161
    $meta = json_decode($record->meta, true);
1162
    // Prepare data for the update.
1163
    $meta['recording']['published'] = ($publish) ? 'true' : 'false';
1164
    $record->meta = json_encode($meta);
1165
    // Proceed with the update.
1166
    $DB->update_record('bigbluebuttonbn_logs', $record);
1167
    return true;
1168
}
1169
1170
/**
1171
 * Delete an imported recording.
1172
 *
1173
 * @param string $id
1174
 *
1175
 * @return boolean
1176
 */
1177
function bigbluebuttonbn_delete_recording_imported($id) {
1178
    global $DB;
1179
    // Execute delete.
1180
    $DB->delete_records('bigbluebuttonbn_logs', array('id' => $id));
1181
    return true;
1182
}
1183
1184
/**
1185
 * Update an imported recording.
1186
 *
1187
 * @param string $id
1188
 * @param array $params ['key'=>param_key, 'value']
1189
 *
1190
 * @return boolean
1191
 */
1192
function bigbluebuttonbn_update_recording_imported($id, $params) {
1193
    global $DB;
1194
    // Locate the record to be updated.
1195
    $record = $DB->get_record('bigbluebuttonbn_logs', array('id' => $id));
1196
    $meta = json_decode($record->meta, true);
1197
    // Prepare data for the update.
1198
    $meta['recording'] = $params + $meta['recording'];
1199
    $record->meta = json_encode($meta);
1200
    // Proceed with the update.
1201
    if (!$DB->update_record('bigbluebuttonbn_logs', $record)) {
1202
        return false;
1203
    }
1204
    return true;
1205
}
1206
1207
/**
1208
 * Protect/Unprotect an imported recording.
1209
 *
1210
 * @param string $id
1211
 * @param boolean $protect
1212
 *
1213
 * @return boolean
1214
 */
1215 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...
1216
    global $DB;
1217
    // Locate the record to be updated.
1218
    $record = $DB->get_record('bigbluebuttonbn_logs', array('id' => $id));
1219
    $meta = json_decode($record->meta, true);
1220
    // Prepare data for the update.
1221
    $meta['recording']['protected'] = ($protect) ? 'true' : 'false';
1222
    $record->meta = json_encode($meta);
1223
    // Proceed with the update.
1224
    $DB->update_record('bigbluebuttonbn_logs', $record);
1225
    return true;
1226
}
1227
1228
/**
1229
 * Sets a custom config.xml file for being used on create.
1230
 *
1231
 * @param string $meetingid
1232
 * @param string $configxml
1233
 *
1234
 * @return object
1235
 */
1236
function bigbluebuttonbn_set_config_xml($meetingid, $configxml) {
1237
    $urldefaultconfig = \mod_bigbluebuttonbn\locallib\config::get('server_url').'api/setConfigXML?';
1238
    $configxmlparams = bigbluebuttonbn_set_config_xml_params($meetingid, $configxml);
1239
    $xml = bigbluebuttonbn_wrap_xml_load_file($urldefaultconfig, 'POST',
1240
        $configxmlparams, 'application/x-www-form-urlencoded');
1241
    return $xml;
1242
}
1243
1244
/**
1245
 * Sets qs used with a custom config.xml file request.
1246
 *
1247
 * @param string $meetingid
1248
 * @param string $configxml
1249
 *
1250
 * @return string
1251
 */
1252
function bigbluebuttonbn_set_config_xml_params($meetingid, $configxml) {
1253
    $params = 'configXML='.urlencode($configxml).'&meetingID='.urlencode($meetingid);
1254
    $configxmlparams = $params.'&checksum='.sha1('setConfigXML'.$params.\mod_bigbluebuttonbn\locallib\config::get('shared_secret'));
1255
    return $configxmlparams;
1256
}
1257
1258
/**
1259
 * Sets a custom config.xml file for being used on create.
1260
 *
1261
 * @param string $meetingid
1262
 * @param string $configxml
1263
 *
1264
 * @return array
1265
 */
1266
function bigbluebuttonbn_set_config_xml_array($meetingid, $configxml) {
1267
    $configxml = bigbluebuttonbn_setConfigXML($meetingid, $configxml);
1268
    $configxmlarray = (array) $configxml;
1269
    if ($configxmlarray['returncode'] != 'SUCCESS') {
1270
        debugging('BigBlueButton was not able to set the custom config.xml file', DEBUG_DEVELOPER);
1271
        return '';
1272
    }
1273
    return $configxmlarray['configToken'];
1274
}
1275
1276
/**
1277
 * Helper function builds a row for the data used by the recording table.
1278
 *
1279
 * @param array $bbbsession
1280
 * @param array $recording
1281
 * @param array $tools
1282
 *
1283
 * @return array
1284
 */
1285
function bigbluebuttonbn_get_recording_data_row($bbbsession, $recording, $tools = ['protect', 'publish', 'delete']) {
1286
    if (!bigbluebuttonbn_include_recording_table_row($bbbsession, $recording)) {
1287
        return;
1288
    }
1289
    $rowdata = new stdClass();
1290
    // Set recording_types.
1291
    $rowdata->recording = bigbluebuttonbn_get_recording_data_row_types($recording, $bbbsession);
1292
    // Set activity name.
1293
    $rowdata->activity = bigbluebuttonbn_get_recording_data_row_meta_activity($recording, $bbbsession);
1294
    // Set activity description.
1295
    $rowdata->description = bigbluebuttonbn_get_recording_data_row_meta_description($recording, $bbbsession);
1296
    if (bigbluebuttonbn_get_recording_data_preview_enabled($bbbsession)) {
1297
        // Set recording_preview.
1298
        $rowdata->preview = bigbluebuttonbn_get_recording_data_row_preview($recording);
1299
    }
1300
    // Set date.
1301
    $rowdata->date = bigbluebuttonbn_get_recording_data_row_date($recording);
1302
    // Set formatted date.
1303
    $rowdata->date_formatted = bigbluebuttonbn_get_recording_data_row_date_formatted($rowdata->date);
1304
    // Set formatted duration.
1305
    $rowdata->duration_formatted = $rowdata->duration = bigbluebuttonbn_get_recording_data_row_duration($recording);
1306
    // Set actionbar, if user is allowed to manage recordings.
1307
    if ($bbbsession['managerecordings']) {
1308
        $rowdata->actionbar = bigbluebuttonbn_get_recording_data_row_actionbar($recording, $tools);
1309
    }
1310
    return $rowdata;
1311
}
1312
1313
/**
1314
 * Helper function evaluates if a row for the data used by the recording table is editable.
1315
 *
1316
 * @param array $bbbsession
1317
 *
1318
 * @return boolean
1319
 */
1320
function bigbluebuttonbn_get_recording_data_row_editable($bbbsession) {
1321
    return ($bbbsession['managerecordings'] && ((double)$bbbsession['serverversion'] >= 1.0 || $bbbsession['bnserver']));
1322
}
1323
1324
/**
1325
 * Helper function evaluates if recording preview should be included.
1326
 *
1327
 * @param array $bbbsession
1328
 *
1329
 * @return boolean
1330
 */
1331
function bigbluebuttonbn_get_recording_data_preview_enabled($bbbsession) {
1332
    return ((double)$bbbsession['serverversion'] >= 1.0 && $bbbsession['bigbluebuttonbn']->recordings_preview == '1');
1333
}
1334
1335
/**
1336
 * Helper function converts recording date used in row for the data used by the recording table.
1337
 *
1338
 * @param array $recording
1339
 *
1340
 * @return integer
1341
 */
1342
function bigbluebuttonbn_get_recording_data_row_date($recording) {
1343
    if (!isset($recording['startTime'])) {
1344
        return 0;
1345
    }
1346
    return floatval($recording['startTime']);
1347
}
1348
1349
/**
1350
 * Helper function format recording date used in row for the data used by the recording table.
1351
 *
1352
 * @param integer $starttime
1353
 *
1354
 * @return string
1355
 */
1356
function bigbluebuttonbn_get_recording_data_row_date_formatted($starttime) {
1357
    global $USER;
1358
    $starttime = $starttime - ($starttime % 1000);
1359
    // Set formatted date.
1360
    $dateformat = get_string('strftimerecentfull', 'langconfig').' %Z';
1361
    return userdate($starttime / 1000, $dateformat, usertimezone($USER->timezone));
1362
}
1363
1364
/**
1365
 * Helper function converts recording duration used in row for the data used by the recording table.
1366
 *
1367
 * @param array $recording
1368
 *
1369
 * @return integer
1370
 */
1371
function bigbluebuttonbn_get_recording_data_row_duration($recording) {
1372
    foreach (array_values($recording['playbacks']) as $playback) {
1373
        // Ignore restricted playbacks.
1374
        if (array_key_exists('restricted', $playback) && strtolower($playback['restricted']) == 'true') {
1375
            continue;
1376
        }
1377
        // Take the lenght form the fist playback with an actual value.
1378
        if (!empty($playback['length'])) {
1379
            return intval($playback['length']);
1380
        }
1381
    }
1382
    return 0;
1383
}
1384
1385
/**
1386
 * Helper function builds recording actionbar used in row for the data used by the recording table.
1387
 *
1388
 * @param array $recording
1389
 * @param array $tools
1390
 *
1391
 * @return string
1392
 */
1393
function bigbluebuttonbn_get_recording_data_row_actionbar($recording, $tools) {
1394
    $actionbar = '';
1395
    foreach ($tools as $tool) {
1396
        $buttonpayload = bigbluebuttonbn_get_recording_data_row_actionbar_payload($recording, $tool);
1397
        if ($tool == 'protect') {
1398
            if (isset($recording['imported'])) {
1399
                $buttonpayload['disabled'] = 'disabled';
1400
            }
1401
            if (!isset($recording['protected'])) {
1402
                $buttonpayload['disabled'] = 'invisible';
1403
            }
1404
        }
1405
        $actionbar .= bigbluebuttonbn_actionbar_render_button($recording, $buttonpayload);
1406
    }
1407
    $head = html_writer::start_tag('div', array(
1408
        'id' => 'recording-actionbar-' . $recording['recordID'],
1409
        'data-recordingid' => $recording['recordID'],
1410
        'data-meetingid' => $recording['meetingID']));
1411
    $tail = html_writer::end_tag('div');
1412
    return $head . $actionbar . $tail;
1413
}
1414
1415
/**
1416
 * Helper function returns the corresponding payload for an actionbar button used in row
1417
 * for the data used by the recording table.
1418
 *
1419
 * @param array $recording
1420
 * @param array $tool
1421
 *
1422
 * @return array
1423
 */
1424
function bigbluebuttonbn_get_recording_data_row_actionbar_payload($recording, $tool) {
1425
    if ($tool == 'protect') {
1426
        $protected = 'false';
1427
        if (isset($recording['protected'])) {
1428
            $protected = $recording['protected'];
1429
        }
1430
        return bigbluebuttonbn_get_recording_data_row_action_protect($protected);
1431
    }
1432
    if ($tool == 'publish') {
1433
        return bigbluebuttonbn_get_recording_data_row_action_publish($recording['published']);
1434
    }
1435
    return array('action' => $tool, 'tag' => $tool);
1436
}
1437
1438
/**
1439
 * Helper function returns the payload for protect action button used in row
1440
 * for the data used by the recording table.
1441
 *
1442
 * @param string $protected
1443
 *
1444
 * @return array
1445
 */
1446
function bigbluebuttonbn_get_recording_data_row_action_protect($protected) {
1447
    if ($protected == 'true') {
1448
        return array('action' => 'unprotect', 'tag' => 'lock');
1449
    }
1450
    return array('action' => 'protect', 'tag' => 'unlock');
1451
}
1452
1453
/**
1454
 * Helper function returns the payload for publish action button used in row
1455
 * for the data used by the recording table.
1456
 *
1457
 * @param string $published
1458
 *
1459
 * @return array
1460
 */
1461
function bigbluebuttonbn_get_recording_data_row_action_publish($published) {
1462
    if ($published == 'true') {
1463
        return array('action' => 'unpublish', 'tag' => 'hide');
1464
    }
1465
    return array('action' => 'publish', 'tag' => 'show');
1466
}
1467
1468
/**
1469
 * Helper function builds recording preview used in row for the data used by the recording table.
1470
 *
1471
 * @param array $recording
1472
 *
1473
 * @return string
1474
 */
1475
function bigbluebuttonbn_get_recording_data_row_preview($recording) {
1476
    $options = array('id' => 'preview-'.$recording['recordID']);
1477
    if ($recording['published'] === 'false') {
1478
        $options['hidden'] = 'hidden';
1479
    }
1480
    $recordingpreview = html_writer::start_tag('div', $options);
1481
    foreach ($recording['playbacks'] as $playback) {
1482
        if (isset($playback['preview'])) {
1483
            $recordingpreview .= bigbluebuttonbn_get_recording_data_row_preview_images($playback);
1484
            break;
1485
        }
1486
    }
1487
    $recordingpreview .= html_writer::end_tag('div');
1488
    return $recordingpreview;
1489
}
1490
1491
/**
1492
 * Helper function builds element with actual images used in recording preview row based on a selected playback.
1493
 *
1494
 * @param array $playback
1495
 *
1496
 * @return string
1497
 */
1498
function bigbluebuttonbn_get_recording_data_row_preview_images($playback) {
1499
    $recordingpreview  = html_writer::start_tag('div', array('class' => 'container-fluid'));
1500
    $recordingpreview .= html_writer::start_tag('div', array('class' => 'row'));
1501
    foreach ($playback['preview'] as $image) {
1502
        if (!bigbluebuttonbn_is_valid_resource(trim($image['url']))) {
1503
            return '';
1504
        }
1505
        $recordingpreview .= html_writer::start_tag('div', array('class' => ''));
1506
        $recordingpreview .= html_writer::empty_tag('img',
1507
            array('src' => trim($image['url']) . '?' . time(), 'class' => 'recording-thumbnail pull-left'));
1508
        $recordingpreview .= html_writer::end_tag('div');
1509
    }
1510
    $recordingpreview .= html_writer::end_tag('div');
1511
    $recordingpreview .= html_writer::start_tag('div', array('class' => 'row'));
1512
    $recordingpreview .= html_writer::tag('div', get_string('view_recording_preview_help', 'bigbluebuttonbn'),
1513
        array('class' => 'text-center text-muted small'));
1514
    $recordingpreview .= html_writer::end_tag('div');
1515
    $recordingpreview .= html_writer::end_tag('div');
1516
    return $recordingpreview;
1517
}
1518
1519
/**
1520
 * Helper function renders recording types to be used in row for the data used by the recording table.
1521
 *
1522
 * @param array $recording
1523
 * @param array $bbbsession
1524
 *
1525
 * @return string
1526
 */
1527
function bigbluebuttonbn_get_recording_data_row_types($recording, $bbbsession) {
1528
    $dataimported = 'false';
1529
    $title = '';
1530
    if (isset($recording['imported'])) {
1531
        $dataimported = 'true';
1532
        $title = get_string('view_recording_link_warning', 'bigbluebuttonbn');
1533
    }
1534
    $visibility = '';
1535
    if ($recording['published'] === 'false') {
1536
        $visibility = 'hidden ';
1537
    }
1538
    $id = 'playbacks-'.$recording['recordID'];
1539
    $recordingtypes = html_writer::start_tag('div', array('id' => $id, 'data-imported' => $dataimported,
1540
          'data-meetingid' => $recording['meetingID'], 'data-recordingid' => $recording['recordID'],
1541
          'title' => $title, $visibility => $visibility));
1542
    foreach ($recording['playbacks'] as $playback) {
1543
        $recordingtypes .= bigbluebuttonbn_get_recording_data_row_type($recording, $bbbsession, $playback);
1544
    }
1545
    $recordingtypes .= html_writer::end_tag('div');
1546
    return $recordingtypes;
1547
}
1548
1549
/**
1550
 * Helper function renders the link used for recording type in row for the data used by the recording table.
1551
 *
1552
 * @param array $recording
1553
 * @param array $bbbsession
1554
 * @param array $playback
1555
 *
1556
 * @return string
1557
 */
1558
function bigbluebuttonbn_get_recording_data_row_type($recording, $bbbsession, $playback) {
1559
    global $CFG, $OUTPUT;
1560
    if (!bigbluebuttonbn_include_recording_data_row_type($recording, $bbbsession, $playback)) {
1561
        return '';
1562
    }
1563
    $text = get_string('view_recording_format_'.$playback['type'], 'bigbluebuttonbn');
1564
    $href = $CFG->wwwroot . '/mod/bigbluebuttonbn/bbb_view.php?action=play&bn=' . $bbbsession['bigbluebuttonbn']->id .
1565
      '&mid='.$recording['meetingID'] . '&rid=' . $recording['recordID'] . '&rtype=' . $playback['type'];
1566
    if (!isset($recording['imported']) || !isset($recording['protected']) || $recording['protected'] === 'false') {
1567
        $href .= '&href='.urlencode(trim($playback['url']));
1568
    }
1569
    $linkattributes = array(
1570
        'id' => 'recording-play-' . $playback['type'] . '-' . $recording['recordID'],
1571
        'class' => 'btn btn-sm btn-default',
1572
        'onclick' => 'M.mod_bigbluebuttonbn.recordings.recordingPlay(this);',
1573
        'data-action' => 'play',
1574
        'data-target' => $playback['type'],
1575
        'data-href' => $href,
1576
      );
1577
    if (!bigbluebuttonbn_is_bn_server() && !bigbluebuttonbn_is_valid_resource(trim($playback['url']))) {
1578
        $linkattributes['class'] = 'btn btn-sm btn-warning';
1579
        $linkattributes['title'] = get_string('view_recording_format_errror_unreachable', 'bigbluebuttonbn');
1580
        unset($linkattributes['data-href']);
1581
    }
1582
    return $OUTPUT->action_link('#', $text, null, $linkattributes) . '&#32;';
1583
}
1584
1585
/**
1586
 * Helper function validates a remote resource.
1587
 *
1588
 * @param string $url
1589
 *
1590
 * @return boolean
1591
 */
1592
function bigbluebuttonbn_is_valid_resource($url) {
1593
    $urlhost = parse_url($url, PHP_URL_HOST);
1594
    $serverurlhost = parse_url(\mod_bigbluebuttonbn\locallib\config::get('server_url'), PHP_URL_HOST);
1595
    // Skip validation when the recording URL host is the same as the configured BBB server.
1596
    if ($urlhost == $serverurlhost) {
1597
        return true;
1598
    }
1599
    // Skip validation when the recording URL was already validated.
1600
    $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...
1601
    if (array_key_exists($urlhost, $validatedurls)) {
1602
        return $validatedurls[$urlhost];
1603
    }
1604
    // Validate the recording URL.
1605
    $validatedurls[$urlhost] = true;
1606
    $curlinfo = bigbluebuttonbn_wrap_xml_load_file_curl_request($url, 'HEAD');
1607
    if (!isset($curlinfo['http_code']) || $curlinfo['http_code'] != 200) {
1608
        $error = "Resources hosted by " . $urlhost . " are unreachable. Server responded with code " . $curlinfo['http_code'];
1609
        debugging($error, DEBUG_DEVELOPER);
1610
        $validatedurls[$urlhost] = false;
1611
    }
1612
    bigbluebuttonbn_cache_set('recordings_cache', 'validated_urls', $validatedurls);
1613
    return $validatedurls[$urlhost];
1614
}
1615
1616
/**
1617
 * Helper function renders the name for recording used in row for the data used by the recording table.
1618
 *
1619
 * @param array $recording
1620
 * @param array $bbbsession
1621
 *
1622
 * @return string
1623
 */
1624
function bigbluebuttonbn_get_recording_data_row_meta_activity($recording, $bbbsession) {
1625
    $payload = array();
1626 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...
1627
        $payload = array('recordingid' => $recording['recordID'], 'meetingid' => $recording['meetingID'],
1628
            'action' => 'edit', 'tag' => 'edit',
1629
            'target' => 'name');
1630
    }
1631
    $oldsource = 'meta_contextactivity';
1632
    if (isset($recording[$oldsource])) {
1633
        $metaname = trim($recording[$oldsource]);
1634
        return bigbluebuttonbn_get_recording_data_row_text($recording, $metaname, $oldsource, $payload);
1635
    }
1636
    $newsource = 'meta_bbb-recording-name';
1637 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...
1638
        $metaname = trim($recording[$newsource]);
1639
        return bigbluebuttonbn_get_recording_data_row_text($recording, $metaname, $newsource, $payload);
1640
    }
1641
    $metaname = trim($recording['meetingName']);
1642
    return bigbluebuttonbn_get_recording_data_row_text($recording, $metaname, $newsource, $payload);
1643
}
1644
1645
/**
1646
 * Helper function renders the description for recording used in row for the data used by the recording table.
1647
 *
1648
 * @param array $recording
1649
 * @param array $bbbsession
1650
 *
1651
 * @return string
1652
 */
1653
function bigbluebuttonbn_get_recording_data_row_meta_description($recording, $bbbsession) {
1654
    $payload = array();
1655 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...
1656
        $payload = array('recordingid' => $recording['recordID'], 'meetingid' => $recording['meetingID'],
1657
            'action' => 'edit', 'tag' => 'edit',
1658
            'target' => 'description');
1659
    }
1660
    $oldsource = 'meta_contextactivitydescription';
1661 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...
1662
        $metadescription = trim($recording[$oldsource]);
1663
        return bigbluebuttonbn_get_recording_data_row_text($recording, $metadescription, $oldsource, $payload);
1664
    }
1665
    $newsource = 'meta_bbb-recording-description';
1666 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...
1667
        $metadescription = trim($recording[$newsource]);
1668
        return bigbluebuttonbn_get_recording_data_row_text($recording, $metadescription, $newsource, $payload);
1669
    }
1670
    return bigbluebuttonbn_get_recording_data_row_text($recording, '', $newsource, $payload);
1671
}
1672
1673
/**
1674
 * Helper function renders text element for recording used in row for the data used by the recording table.
1675
 *
1676
 * @param array $recording
1677
 * @param string $text
1678
 * @param string $source
1679
 * @param array $data
1680
 *
1681
 * @return string
1682
 */
1683
function bigbluebuttonbn_get_recording_data_row_text($recording, $text, $source, $data) {
1684
    $htmltext = '<span>' . htmlentities($text) . '</span>';
1685
    if (empty($data)) {
1686
        return $htmltext;
1687
    }
1688
    $target = $data['action'] . '-' . $data['target'];
1689
    $id = 'recording-' . $target . '-' . $data['recordingid'];
1690
    $attributes = array('id' => $id, 'class' => 'quickeditlink col-md-20',
1691
        'data-recordingid' => $data['recordingid'], 'data-meetingid' => $data['meetingid'],
1692
        'data-target' => $data['target'], 'data-source' => $source);
1693
    $head = html_writer::start_tag('div', $attributes);
1694
    $tail = html_writer::end_tag('div');
1695
    $payload = array('action' => $data['action'], 'tag' => $data['tag'], 'target' => $data['target']);
1696
    $htmllink = bigbluebuttonbn_actionbar_render_button($recording, $payload);
1697
    return $head . $htmltext . $htmllink . $tail;
1698
}
1699
1700
/**
1701
 * Helper function render a button for the recording action bar
1702
 *
1703
 * @param array $recording
1704
 * @param array $data
1705
 *
1706
 * @return string
1707
 */
1708
function bigbluebuttonbn_actionbar_render_button($recording, $data) {
1709
    global $OUTPUT;
1710
    if (empty($data)) {
1711
        return '';
1712
    }
1713
    $target = $data['action'];
1714
    if (isset($data['target'])) {
1715
        $target .= '-' . $data['target'];
1716
    }
1717
    $id = 'recording-' . $target . '-' . $recording['recordID'];
1718
    $onclick = 'M.mod_bigbluebuttonbn.recordings.recording' . ucfirst($data['action']) . '(this);';
1719
    if ((boolean)\mod_bigbluebuttonbn\locallib\config::get('recording_icons_enabled')) {
1720
        // With icon for $manageaction.
1721
        $iconattributes = array('id' => $id, 'class' => 'iconsmall');
1722
        $linkattributes = array(
1723
            'id' => $id,
1724
            'onclick' => $onclick,
1725
            'data-action' => $data['action']
1726
          );
1727
        if (!isset($recording['imported'])) {
1728
            $linkattributes['data-links'] = bigbluebuttonbn_count_recording_imported_instances(
1729
              $recording['recordID']);
1730
        }
1731
        if (isset($data['disabled'])) {
1732
            $iconattributes['class'] .= ' fa-' . $data['disabled'];
1733
            $linkattributes['class'] = 'disabled';
1734
            unset($linkattributes['onclick']);
1735
        }
1736
        $icon = new pix_icon('i/'.$data['tag'],
1737
            get_string('view_recording_list_actionbar_' . $data['action'], 'bigbluebuttonbn'),
1738
            'moodle', $iconattributes);
1739
        return $OUTPUT->action_icon('#', $icon, null, $linkattributes, false);
1740
    }
1741
    // With text for $manageaction.
1742
    $linkattributes = array('title' => get_string($data['tag']), 'class' => 'btn btn-xs btn-danger',
1743
        'onclick' => $onclick);
1744
    return $OUTPUT->action_link('#', get_string($data['action']), null, $linkattributes);
1745
}
1746
1747
/**
1748
 * Helper function builds the data used for headers by the recording table.
1749
 *
1750
 * @param array $bbbsession
1751
 *
1752
 * @return array
1753
 */
1754
function bigbluebuttonbn_get_recording_columns($bbbsession) {
1755
    $columns = array();
1756
    // Initialize table headers.
1757
    $columns[] = array('key' => 'recording', 'label' => get_string('view_recording_recording', 'bigbluebuttonbn'),
1758
        'width' => '125px', 'allowHTML' => true);
1759
    $columns[] = array('key' => 'activity', 'label' => get_string('view_recording_activity', 'bigbluebuttonbn'),
1760
        'sortable' => true, 'width' => '175px', 'allowHTML' => true);
1761
    $columns[] = array('key' => 'description', 'label' => get_string('view_recording_description', 'bigbluebuttonbn'),
1762
        'sortable' => true, 'width' => '250px', 'allowHTML' => true);
1763
    if (bigbluebuttonbn_get_recording_data_preview_enabled($bbbsession)) {
1764
        $columns[] = array('key' => 'preview', 'label' => get_string('view_recording_preview', 'bigbluebuttonbn'),
1765
            'width' => '250px', 'allowHTML' => true);
1766
    }
1767
    $columns[] = array('key' => 'date', 'label' => get_string('view_recording_date', 'bigbluebuttonbn'),
1768
        'sortable' => true, 'width' => '225px', 'allowHTML' => true);
1769
    $columns[] = array('key' => 'duration', 'label' => get_string('view_recording_duration', 'bigbluebuttonbn'),
1770
        'width' => '50px');
1771
    if ($bbbsession['managerecordings']) {
1772
        $columns[] = array('key' => 'actionbar', 'label' => get_string('view_recording_actionbar', 'bigbluebuttonbn'),
1773
            'width' => '120px', 'allowHTML' => true);
1774
    }
1775
    return $columns;
1776
}
1777
1778
/**
1779
 * Helper function builds the data used by the recording table.
1780
 *
1781
 * @param array $bbbsession
1782
 * @param array $recordings
1783
 * @param array $tools
1784
 *
1785
 * @return array
1786
 */
1787
function bigbluebuttonbn_get_recording_data($bbbsession, $recordings, $tools = ['protect', 'publish', 'delete']) {
1788
    $tabledata = array();
1789
    // Build table content.
1790
    if (isset($recordings) && !array_key_exists('messageKey', $recordings)) {
1791
        // There are recordings for this meeting.
1792
        foreach ($recordings as $recording) {
1793
            $rowdata = bigbluebuttonbn_get_recording_data_row($bbbsession, $recording, $tools);
1794
            if (!empty($rowdata)) {
1795
                array_push($tabledata, $rowdata);
1796
            }
1797
        }
1798
    }
1799
    return $tabledata;
1800
}
1801
1802
/**
1803
 * Helper function builds the recording table.
1804
 *
1805
 * @param array $bbbsession
1806
 * @param array $recordings
1807
 * @param array $tools
1808
 *
1809
 * @return object
1810
 */
1811
function bigbluebuttonbn_get_recording_table($bbbsession, $recordings, $tools = ['protect', 'publish', 'delete']) {
1812
    // Declare the table.
1813
    $table = new html_table();
1814
    $table->data = array();
1815
    // Initialize table headers.
1816
    $table->head[] = get_string('view_recording_playback', 'bigbluebuttonbn');
1817
    $table->head[] = get_string('view_recording_recording', 'bigbluebuttonbn');
1818
    $table->head[] = get_string('view_recording_description', 'bigbluebuttonbn');
1819
    if (bigbluebuttonbn_get_recording_data_preview_enabled($bbbsession)) {
1820
        $table->head[] = get_string('view_recording_preview', 'bigbluebuttonbn');
1821
    }
1822
    $table->head[] = get_string('view_recording_date', 'bigbluebuttonbn');
1823
    $table->head[] = get_string('view_recording_duration', 'bigbluebuttonbn');
1824
    $table->align = array('left', 'left', 'left', 'left', 'left', 'center');
1825
    $table->size = array('', '', '', '', '', '');
1826
    if ($bbbsession['managerecordings']) {
1827
        $table->head[] = get_string('view_recording_actionbar', 'bigbluebuttonbn');
1828
        $table->align[] = 'left';
1829
        $table->size[] = (count($tools) * 40) . 'px';
1830
    }
1831
    // Build table content.
1832
    foreach ($recordings as $recording) {
1833
        $rowdata = bigbluebuttonbn_get_recording_data_row($bbbsession, $recording, $tools);
1834
        if (!empty($rowdata)) {
1835
            $row = bigbluebuttonbn_get_recording_table_row($bbbsession, $recording, $rowdata);
1836
            array_push($table->data, $row);
1837
        }
1838
    }
1839
    return $table;
1840
}
1841
1842
/**
1843
 * Helper function builds the recording table row and insert into table.
1844
 *
1845
 * @param array $bbbsession
1846
 * @param array $recording
1847
 * @param object $rowdata
1848
 *
1849
 * @return object
1850
 */
1851
function bigbluebuttonbn_get_recording_table_row($bbbsession, $recording, $rowdata) {
1852
    $row = new html_table_row();
1853
    $row->id = 'recording-tr-'.$recording['recordID'];
1854
    $row->attributes['data-imported'] = 'false';
1855
    $texthead = '';
1856
    $texttail = '';
1857
    if (isset($recording['imported'])) {
1858
        $row->attributes['title'] = get_string('view_recording_link_warning', 'bigbluebuttonbn');
1859
        $row->attributes['data-imported'] = 'true';
1860
        $texthead = '<em>';
1861
        $texttail = '</em>';
1862
    }
1863
    $rowdata->date_formatted = str_replace(' ', '&nbsp;', $rowdata->date_formatted);
1864
    $row->cells = array();
1865
    $row->cells[] = $texthead . $rowdata->recording . $texttail;
1866
    $row->cells[] = $texthead . $rowdata->activity . $texttail;
1867
    $row->cells[] = $texthead . $rowdata->description . $texttail;
1868
    if (bigbluebuttonbn_get_recording_data_preview_enabled($bbbsession)) {
1869
        $row->cells[] = $rowdata->preview;
1870
    }
1871
    $row->cells[] = $texthead . $rowdata->date_formatted . $texttail;
1872
    $row->cells[] = $rowdata->duration_formatted;
1873
    if ($bbbsession['managerecordings']) {
1874
        $row->cells[] = $rowdata->actionbar;
1875
    }
1876
    return $row;
1877
}
1878
1879
/**
1880
 * Helper function evaluates if recording row should be included in the table.
1881
 *
1882
 * @param array $bbbsession
1883
 * @param array $recording
1884
 *
1885
 * @return boolean
1886
 */
1887
function bigbluebuttonbn_include_recording_table_row($bbbsession, $recording) {
1888
    // Exclude unpublished recordings, only if user has no rights to manage them.
1889
    if ($recording['published'] != 'true' && !$bbbsession['managerecordings']) {
1890
        return false;
1891
    }
1892
    // Imported recordings are always shown as long as they are published.
1893
    if (isset($recording['imported'])) {
1894
        return true;
1895
    }
1896
    // When groups are enabled, exclude those to which the user doesn't have access to.
1897
    if (isset($bbbsession['group']) && $recording['meetingID'] != $bbbsession['meetingid']) {
1898
        return false;
1899
    }
1900
    return true;
1901
}
1902
1903
/**
1904
 * Helper function triggers a send notification when the recording is ready.
1905
 *
1906
 * @param object $bigbluebuttonbn
1907
 *
1908
 * @return void
1909
 */
1910
function bigbluebuttonbn_send_notification_recording_ready($bigbluebuttonbn) {
1911
    $sender = get_admin();
1912
    // Prepare message.
1913
    $messagetext = '<p>'.get_string('email_body_recording_ready_for', 'bigbluebuttonbn').
1914
        ' &quot;' . $bigbluebuttonbn->name . '&quot; '.
1915
        get_string('email_body_recording_ready_is_ready', 'bigbluebuttonbn').'.</p>';
1916
    $context = context_course::instance($bigbluebuttonbn->course);
1917
    \mod_bigbluebuttonbn\locallib\notifier::notification_send($context, $sender, $bigbluebuttonbn, $messagetext);
1918
}
1919
1920
/**
1921
 * Helper evaluates if the bigbluebutton server used belongs to blindsidenetworks domain.
1922
 *
1923
 * @return boolean
1924
 */
1925
function bigbluebuttonbn_is_bn_server() {
1926
    $parsedurl = parse_url(\mod_bigbluebuttonbn\locallib\config::get('server_url'));
1927
    if (!isset($parsedurl['host'])) {
1928
        return false;
1929
    }
1930
    $h = $parsedurl['host'];
1931
    $hends = explode('.', $h);
1932
    $hendslength = count($hends);
1933
    return ($hends[$hendslength - 1] == 'com' && $hends[$hendslength - 2] == 'blindsidenetworks');
1934
}
1935
1936
/**
1937
 * Helper function returns a list of courses a user has access to, wrapped in an array that can be used
1938
 * by a html select.
1939
 *
1940
 * @param array $bbbsession
1941
 *
1942
 * @return array
1943
 */
1944
function bigbluebuttonbn_import_get_courses_for_select(array $bbbsession) {
1945
    if ($bbbsession['administrator']) {
1946
        $courses = get_courses('all', 'c.fullname ASC', 'c.id,c.shortname,c.fullname');
1947
        // It includes the name of the site as a course (category 0), so remove the first one.
1948
        unset($courses['1']);
1949
    } else {
1950
        $courses = enrol_get_users_courses($bbbsession['userID'], false, 'id,shortname,fullname');
1951
    }
1952
    $coursesforselect = [];
1953
    foreach ($courses as $course) {
1954
        $coursesforselect[$course->id] = $course->fullname;
1955
    }
1956
    return $coursesforselect;
1957
}
1958
1959
/**
1960
 * Helper function renders recording table.
1961
 *
1962
 * @param array $bbbsession
1963
 * @param array $recordings
1964
 * @param array $tools
1965
 *
1966
 * @return array
1967
 */
1968
function bigbluebuttonbn_output_recording_table($bbbsession, $recordings, $tools = ['protect', 'publish', 'delete']) {
1969
    if (isset($recordings) && !empty($recordings)) {
1970
        // There are recordings for this meeting.
1971
        $table = bigbluebuttonbn_get_recording_table($bbbsession, $recordings, $tools);
1972
    }
1973
    if (!isset($table) || !isset($table->data)) {
1974
        // Render a table with "No recordings".
1975
        return html_writer::div(get_string('view_message_norecordings', 'bigbluebuttonbn'), '',
1976
            array('id' => 'bigbluebuttonbn_recordings_table'));
1977
    }
1978
    // Render the table.
1979
    return html_writer::div(html_writer::table($table), '', array('id' => 'bigbluebuttonbn_recordings_table'));
1980
}
1981
1982
/**
1983
 * Helper function to convert an html string to plain text.
1984
 *
1985
 * @param string $html
1986
 * @param integer $len
1987
 *
1988
 * @return string
1989
 */
1990
function bigbluebuttonbn_html2text($html, $len = 0) {
1991
    $text = strip_tags($html);
1992
    $text = str_replace('&nbsp;', ' ', $text);
1993
    $textlen = strlen($text);
1994
    $text = substr($text, 0, $len);
1995
    if ($textlen > $len) {
1996
        $text .= '...';
1997
    }
1998
    return $text;
1999
}
2000
2001
/**
2002
 * Helper function to obtain the tags linked to a bigbluebuttonbn activity
2003
 *
2004
 * @param string $id
2005
 *
2006
 * @return string containing the tags separated by commas
2007
 */
2008
function bigbluebuttonbn_get_tags($id) {
2009
    if (class_exists('core_tag_tag')) {
2010
        return implode(',', core_tag_tag::get_item_tags_array('core', 'course_modules', $id));
2011
    }
2012
    return implode(',', tag_get_tags('bigbluebuttonbn', $id));
2013
}
2014
2015
/**
2016
 * Helper function to define the sql used for gattering the bigbluebuttonbnids whose meetingids should be included
2017
 * in the getRecordings request
2018
 *
2019
 * @param string $courseid
2020
 * @param string $bigbluebuttonbnid
2021
 * @param bool   $subset
2022
 *
2023
 * @return string containing the sql used for getting the target bigbluebuttonbn instances
2024
 */
2025
function bigbluebuttonbn_get_recordings_sql_select($courseid, $bigbluebuttonbnid = null, $subset = true) {
2026
    if (empty($courseid)) {
2027
        $courseid = 0;
2028
    }
2029
    if (empty($bigbluebuttonbnid)) {
2030
        return "course = '{$courseid}'";
2031
    }
2032
    if ($subset) {
2033
        return "id = '{$bigbluebuttonbnid}'";
2034
    }
2035
    return "id <> '{$bigbluebuttonbnid}' AND course = '{$courseid}'";
2036
}
2037
2038
/**
2039
 * Helper function to define the sql used for gattering the bigbluebuttonbnids whose meetingids should be included
2040
 * in the getRecordings request considering only those that belong to deleted activities.
2041
 *
2042
 * @param string $courseid
2043
 * @param string $bigbluebuttonbnid
2044
 * @param bool   $subset
2045
 *
2046
 * @return string containing the sql used for getting the target bigbluebuttonbn instances
2047
 */
2048 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...
2049
    $sql = "log = '" . BIGBLUEBUTTONBN_LOG_EVENT_DELETE . "' AND meta like '%has_recordings%' AND meta like '%true%'";
2050
    if (empty($courseid)) {
2051
        $courseid = 0;
2052
    }
2053
    if (empty($bigbluebuttonbnid)) {
2054
        return $sql . " AND courseid = {$courseid}";
2055
    }
2056
    if ($subset) {
2057
        return $sql . " AND bigbluebuttonbnid = '{$bigbluebuttonbnid}'";
2058
    }
2059
    return $sql . " AND courseid = {$courseid} AND bigbluebuttonbnid <> '{$bigbluebuttonbnid}'";
2060
}
2061
2062
/**
2063
 * Helper function to define the sql used for gattering the bigbluebuttonbnids whose meetingids should be included
2064
 * in the getRecordings request considering only those that belong to imported recordings.
2065
 *
2066
 * @param string $courseid
2067
 * @param string $bigbluebuttonbnid
2068
 * @param bool   $subset
2069
 *
2070
 * @return string containing the sql used for getting the target bigbluebuttonbn instances
2071
 */
2072 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...
2073
    $sql = "log = '" . BIGBLUEBUTTONBN_LOG_EVENT_IMPORT . "'";
2074
    if (empty($courseid)) {
2075
        $courseid = 0;
2076
    }
2077
    if (empty($bigbluebuttonbnid)) {
2078
        return $sql . " AND courseid = '{$courseid}'";
2079
    }
2080
    if ($subset) {
2081
        return $sql . " AND bigbluebuttonbnid = '{$bigbluebuttonbnid}'";
2082
    }
2083
    return $sql . " AND courseid = '{$courseid}' AND bigbluebuttonbnid <> '{$bigbluebuttonbnid}'";
2084
}
2085
2086
/**
2087
 * Helper function to get recordings  and imported recordings together.
2088
 *
2089
 * @param string $courseid
2090
 * @param string $bigbluebuttonbnid
2091
 * @param bool   $subset
2092
 * @param bool   $includedeleted
2093
 *
2094
 * @return associative array containing the recordings indexed by recordID, each recording is also a
2095
 * non sequential associative array itself that corresponds to the actual recording in BBB
2096
 */
2097
function bigbluebuttonbn_get_allrecordings($courseid = 0, $bigbluebuttonbnid = null, $subset = true, $includedeleted = false) {
2098
    $recordings = bigbluebuttonbn_get_recordings($courseid, $bigbluebuttonbnid, $subset, $includedeleted);
2099
    $recordingsimported = bigbluebuttonbn_get_recordings_imported_array($courseid, $bigbluebuttonbnid, $subset);
2100
    return ($recordings + $recordingsimported);
2101
}
2102
2103
/**
2104
 * Helper function to retrieve recordings from the BigBlueButton. The references are stored as events
2105
 * in bigbluebuttonbn_logs.
2106
 *
2107
 * @param string $courseid
2108
 * @param string $bigbluebuttonbnid
2109
 * @param bool   $subset
2110
 * @param bool   $includedeleted
2111
 *
2112
 * @return associative array containing the recordings indexed by recordID, each recording is also a
2113
 * non sequential associative array itself that corresponds to the actual recording in BBB
2114
 */
2115
function bigbluebuttonbn_get_recordings($courseid = 0, $bigbluebuttonbnid = null, $subset = true, $includedeleted = false) {
2116
    global $DB;
2117
    $select = bigbluebuttonbn_get_recordings_sql_select($courseid, $bigbluebuttonbnid, $subset);
2118
    $bigbluebuttonbns = $DB->get_records_select_menu('bigbluebuttonbn', $select, null, 'id', 'id, meetingid');
2119
    /* Consider logs from deleted bigbluebuttonbn instances whose meetingids should be included in
2120
     * the getRecordings request. */
2121
    if ($includedeleted) {
2122
        $selectdeleted = bigbluebuttonbn_get_recordings_deleted_sql_select($courseid, $bigbluebuttonbnid, $subset);
2123
        $bigbluebuttonbnsdel = $DB->get_records_select_menu('bigbluebuttonbn_logs', $selectdeleted, null,
2124
            'bigbluebuttonbnid', 'bigbluebuttonbnid, meetingid');
2125
        if (!empty($bigbluebuttonbnsdel)) {
2126
            // Merge bigbluebuttonbnis from deleted instances, only keys are relevant.
2127
            // Artimetic merge is used in order to keep the keys.
2128
            $bigbluebuttonbns += $bigbluebuttonbnsdel;
2129
        }
2130
    }
2131
    // Gather the meetingids from bigbluebuttonbn logs that include a create with record=true.
2132
    if (empty($bigbluebuttonbns)) {
2133
        return array();
2134
    }
2135
    // Prepare select for loading records based on existent bigbluebuttonbns.
2136
    $sql = 'SELECT DISTINCT meetingid, bigbluebuttonbnid FROM {bigbluebuttonbn_logs} WHERE ';
2137
    $sql .= '(bigbluebuttonbnid='.implode(' OR bigbluebuttonbnid=', array_keys($bigbluebuttonbns)).')';
2138
    // Include only Create events and exclude those with record not true.
2139
    $sql .= ' AND log = ? AND meta LIKE ? AND meta LIKE ?';
2140
    // Execute select for loading records based on existent bigbluebuttonbns.
2141
    $records = $DB->get_records_sql_menu($sql, array(BIGBLUEBUTTONBN_LOG_EVENT_CREATE, '%record%', '%true%'));
2142
    // Get actual recordings.
2143
    return bigbluebuttonbn_get_recordings_array(array_keys($records));
2144
}
2145
2146
/**
2147
 * Helper function iterates an array with recordings and unset those already imported.
2148
 *
2149
 * @param array $recordings
2150
 * @param integer $courseid
2151
 * @param integer $bigbluebuttonbnid
2152
 *
2153
 * @return array
2154
 */
2155
function bigbluebuttonbn_unset_existent_recordings_already_imported($recordings, $courseid, $bigbluebuttonbnid) {
2156
    $recordingsimported = bigbluebuttonbn_get_recordings_imported_array($courseid, $bigbluebuttonbnid, true);
2157
    foreach ($recordings as $key => $recording) {
2158
        if (isset($recordingsimported[$recording['recordID']])) {
2159
            unset($recordings[$key]);
2160
        }
2161
    }
2162
    return $recordings;
2163
}
2164
2165
/**
2166
 * Helper function to count the imported recordings for a recordingid.
2167
 *
2168
 * @param string $recordid
2169
 *
2170
 * @return integer
2171
 */
2172
function bigbluebuttonbn_count_recording_imported_instances($recordid) {
2173
    global $DB;
2174
    $sql = 'SELECT COUNT(DISTINCT id) FROM {bigbluebuttonbn_logs} WHERE log = ? AND meta LIKE ? AND meta LIKE ?';
2175
    return $DB->count_records_sql($sql, array(BIGBLUEBUTTONBN_LOG_EVENT_IMPORT, '%recordID%', "%{$recordid}%"));
2176
}
2177
2178
/**
2179
 * Helper function returns an array with all the instances of imported recordings for a recordingid.
2180
 *
2181
 * @param string $recordid
2182
 *
2183
 * @return array
2184
 */
2185
function bigbluebuttonbn_get_recording_imported_instances($recordid) {
2186
    global $DB;
2187
    $sql = 'SELECT * FROM {bigbluebuttonbn_logs} WHERE log = ? AND meta LIKE ? AND meta LIKE ?';
2188
    $recordingsimported = $DB->get_records_sql($sql, array(BIGBLUEBUTTONBN_LOG_EVENT_IMPORT, '%recordID%',
2189
        "%{$recordid}%"));
2190
    return $recordingsimported;
2191
}
2192
2193
/**
2194
 * Helper function to get how much callback events are logged.
2195
 *
2196
 * @param string $recordid
2197
 *
2198
 * @return integer
2199
 */
2200
function bigbluebuttonbn_get_count_callback_event_log($recordid) {
2201
    global $DB;
2202
    $sql = 'SELECT count(DISTINCT id) FROM {bigbluebuttonbn_logs} WHERE log = ? AND meta LIKE ? AND meta LIKE ?';
2203
    return $DB->count_records_sql($sql, array(BIGBLUEBUTTON_LOG_EVENT_CALLBACK, '%recordid%', "%{$recordid}%"));
2204
}
2205
2206
/**
2207
 * Helper function returns an array with the profiles (with features per profile) for the different types
2208
 * of bigbluebuttonbn instances.
2209
 *
2210
 * @return array
2211
 */
2212
function bigbluebuttonbn_get_instance_type_profiles() {
2213
    $instanceprofiles = array(
2214
        BIGBLUEBUTTONBN_TYPE_ALL => array('id' => BIGBLUEBUTTONBN_TYPE_ALL,
2215
                  'name' => get_string('instance_type_default', 'bigbluebuttonbn'),
2216
                  'features' => array('all')),
2217
        BIGBLUEBUTTONBN_TYPE_ROOM_ONLY => array('id' => BIGBLUEBUTTONBN_TYPE_ROOM_ONLY,
2218
                  'name' => get_string('instance_type_room_only', 'bigbluebuttonbn'),
2219
                  'features' => array('showroom', 'welcomemessage', 'voicebridge', 'waitformoderator', 'userlimit',
2220
                      'recording', 'sendnotifications', 'preuploadpresentation', 'permissions', 'schedule', 'groups',
2221
                      'modstandardelshdr', 'availabilityconditionsheader', 'tagshdr', 'competenciessection',
2222
                      'clienttype')),
2223
        BIGBLUEBUTTONBN_TYPE_RECORDING_ONLY => array('id' => BIGBLUEBUTTONBN_TYPE_RECORDING_ONLY,
2224
                  'name' => get_string('instance_type_recording_only', 'bigbluebuttonbn'),
2225
                  'features' => array('showrecordings', 'importrecordings'))
2226
    );
2227
    return $instanceprofiles;
2228
}
2229
2230
2231
/**
2232
 * Helper function returns an array with enabled features for an specific profile type.
2233
 *
2234
 * @param array $typeprofiles
2235
 * @param string $type
2236
 *
2237
 * @return array
2238
 */
2239
function bigbluebuttonbn_get_enabled_features($typeprofiles, $type = null) {
2240
    $enabledfeatures = array();
2241
    $features = $typeprofiles[BIGBLUEBUTTONBN_TYPE_ALL]['features'];
2242
    if (!is_null($type) && key_exists($type, $typeprofiles)) {
2243
        $features = $typeprofiles[$type]['features'];
2244
    }
2245
    $enabledfeatures['showroom'] = (in_array('all', $features) || in_array('showroom', $features));
2246
    // Evaluates if recordings are enabled for the Moodle site.
2247
    $enabledfeatures['showrecordings'] = false;
2248
    if (\mod_bigbluebuttonbn\locallib\config::recordings_enabled()) {
2249
        $enabledfeatures['showrecordings'] = (in_array('all', $features) || in_array('showrecordings', $features));
2250
    }
2251
    $enabledfeatures['importrecordings'] = false;
2252
    if (\mod_bigbluebuttonbn\locallib\config::importrecordings_enabled()) {
2253
        $enabledfeatures['importrecordings'] = (in_array('all', $features) || in_array('importrecordings', $features));
2254
    }
2255
    // Evaluates if clienttype is enabled for the Moodle site.
2256
    $enabledfeatures['clienttype'] = false;
2257
    if (\mod_bigbluebuttonbn\locallib\config::clienttype_enabled()) {
2258
        $enabledfeatures['clienttype'] = (in_array('all', $features) || in_array('clienttype', $features));
2259
    }
2260
    return $enabledfeatures;
2261
}
2262
2263
/**
2264
 * Helper function returns an array with the profiles (with features per profile) for the different types
2265
 * of bigbluebuttonbn instances that the user is allowed to create.
2266
 *
2267
 * @param boolean $room
2268
 * @param boolean $recording
2269
 *
2270
 * @return array
2271
 */
2272
function bigbluebuttonbn_get_instance_type_profiles_create_allowed($room, $recording) {
2273
    $profiles = bigbluebuttonbn_get_instance_type_profiles();
2274
    if (!$room) {
2275
        unset($profiles[BIGBLUEBUTTONBN_TYPE_ROOM_ONLY]);
2276
        unset($profiles[BIGBLUEBUTTONBN_TYPE_ALL]);
2277
    }
2278
    if (!$recording) {
2279
        unset($profiles[BIGBLUEBUTTONBN_TYPE_RECORDING_ONLY]);
2280
        unset($profiles[BIGBLUEBUTTONBN_TYPE_ALL]);
2281
    }
2282
    return $profiles;
2283
}
2284
2285
/**
2286
 * Helper function returns an array with the profiles (with features per profile) for the different types
2287
 * of bigbluebuttonbn instances.
2288
 *
2289
 * @param array $profiles
2290
 *
2291
 * @return array
2292
 */
2293
function bigbluebuttonbn_get_instance_profiles_array($profiles = []) {
2294
    $profilesarray = array();
2295
    foreach ($profiles as $key => $profile) {
2296
        $profilesarray[$profile['id']] = $profile['name'];
2297
    }
2298
    return $profilesarray;
2299
}
2300
2301
/**
2302
 * Helper function returns time in a formatted string.
2303
 *
2304
 * @param integer $time
2305
 *
2306
 * @return string
2307
 */
2308
function bigbluebuttonbn_format_activity_time($time) {
2309
    $activitytime = '';
2310
    if ($time) {
2311
        $activitytime = calendar_day_representation($time).' '.
2312
          get_string('mod_form_field_notification_msg_at', 'bigbluebuttonbn').' '.
2313
          calendar_time_representation($time);
2314
    }
2315
    return $activitytime;
2316
}
2317
2318
/**
2319
 * Helper function returns array with all the strings to be used in javascript.
2320
 *
2321
 * @return array
2322
 */
2323
function bigbluebuttonbn_get_strings_for_js() {
2324
    $locale = bigbluebuttonbn_get_locale();
2325
    $stringman = get_string_manager();
2326
    $strings = $stringman->load_component_strings('bigbluebuttonbn', $locale);
2327
    return $strings;
2328
}
2329
2330
/**
2331
 * Helper function returns the locale set by moodle.
2332
 *
2333
 * @return string
2334
 */
2335
function bigbluebuttonbn_get_locale() {
2336
    $lang = get_string('locale', 'core_langconfig');
2337
    return substr($lang, 0, strpos($lang, '.'));
2338
}
2339
2340
/**
2341
 * Helper function returns the locale code based on the locale set by moodle.
2342
 *
2343
 * @return string
2344
 */
2345
function bigbluebuttonbn_get_localcode() {
2346
    $locale = bigbluebuttonbn_get_locale();
2347
    return substr($locale, 0, strpos($locale, '_'));
2348
}
2349
2350
/**
2351
 * Helper function returns array with the instance settings used in views.
2352
 *
2353
 * @param string $id
2354
 * @param object $bigbluebuttonbnid
2355
 *
2356
 * @return array
2357
 */
2358
function bigbluebuttonbn_view_validator($id, $bigbluebuttonbnid) {
2359
    if ($id) {
2360
        return bigbluebuttonbn_view_instance_id($id);
2361
    }
2362
    if ($bigbluebuttonbnid) {
2363
        return bigbluebuttonbn_view_instance_bigbluebuttonbn($bigbluebuttonbnid);
2364
    }
2365
    return;
2366
}
2367
2368
/**
2369
 * Helper function returns array with the instance settings used in views based on id.
2370
 *
2371
 * @param string $id
2372
 *
2373
 * @return array
2374
 */
2375 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...
2376
    global $DB;
2377
    $cm = get_coursemodule_from_id('bigbluebuttonbn', $id, 0, false, MUST_EXIST);
2378
    $course = $DB->get_record('course', array('id' => $cm->course), '*', MUST_EXIST);
2379
    $bigbluebuttonbn = $DB->get_record('bigbluebuttonbn', array('id' => $cm->instance), '*', MUST_EXIST);
2380
    return array('cm' => $cm, 'course' => $course, 'bigbluebuttonbn' => $bigbluebuttonbn);
2381
}
2382
2383
/**
2384
 * Helper function returns array with the instance settings used in views based on bigbluebuttonbnid.
2385
 *
2386
 * @param object $bigbluebuttonbnid
2387
 *
2388
 * @return array
2389
 */
2390 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...
2391
    global $DB;
2392
    $bigbluebuttonbn = $DB->get_record('bigbluebuttonbn', array('id' => $bigbluebuttonbnid), '*', MUST_EXIST);
2393
    $course = $DB->get_record('course', array('id' => $bigbluebuttonbn->course), '*', MUST_EXIST);
2394
    $cm = get_coursemodule_from_instance('bigbluebuttonbn', $bigbluebuttonbn->id, $course->id, false, MUST_EXIST);
2395
    return array('cm' => $cm, 'course' => $course, 'bigbluebuttonbn' => $bigbluebuttonbn);
2396
}
2397
2398
/**
2399
 * Helper function renders general warning message for settings (if any).
2400
 *
2401
 * @param object $renderer
2402
 *
2403
 * @return void
2404
 */
2405
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...
2406
    return;
2407
}
2408
2409
/**
2410
 * Helper function renders general settings if the feature is enabled.
2411
 *
2412
 * @param object $renderer
2413
 *
2414
 * @return void
2415
 */
2416
function bigbluebuttonbn_settings_general(&$renderer) {
2417
    // Configuration for BigBlueButton.
2418
    if ((boolean)\mod_bigbluebuttonbn\settings\validator::section_general_shown()) {
2419
        $renderer->render_group_header('general');
2420
        $renderer->render_group_element('server_url',
2421
            $renderer->render_group_element_text('server_url', BIGBLUEBUTTONBN_DEFAULT_SERVER_URL));
2422
        $renderer->render_group_element('shared_secret',
2423
            $renderer->render_group_element_text('shared_secret', BIGBLUEBUTTONBN_DEFAULT_SHARED_SECRET));
2424
    }
2425
}
2426
2427
/**
2428
 * Helper function renders record settings if the feature is enabled.
2429
 *
2430
 * @param object $renderer
2431
 *
2432
 * @return void
2433
 */
2434
function bigbluebuttonbn_settings_record(&$renderer) {
2435
    // Configuration for 'recording' feature.
2436 View Code Duplication
    if ((boolean)\mod_bigbluebuttonbn\settings\validator::section_record_meeting_shown()) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
2437
        $renderer->render_group_header('recording');
2438
        $renderer->render_group_element('recording_default',
2439
            $renderer->render_group_element_checkbox('recording_default', 1));
2440
        $renderer->render_group_element('recording_editable',
2441
            $renderer->render_group_element_checkbox('recording_editable', 1));
2442
        $renderer->render_group_element('recording_icons_enabled',
2443
            $renderer->render_group_element_checkbox('recording_icons_enabled', 1));
2444
    }
2445
}
2446
2447
/**
2448
 * Helper function renders import recording settings if the feature is enabled.
2449
 *
2450
 * @param object $renderer
2451
 *
2452
 * @return void
2453
 */
2454 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...
2455
    // Configuration for 'import recordings' feature.
2456
    if ((boolean)\mod_bigbluebuttonbn\settings\validator::section_import_recordings_shown()) {
2457
        $renderer->render_group_header('importrecordings');
2458
        $renderer->render_group_element('importrecordings_enabled',
2459
            $renderer->render_group_element_checkbox('importrecordings_enabled', 0));
2460
        $renderer->render_group_element('importrecordings_from_deleted_enabled',
2461
            $renderer->render_group_element_checkbox('importrecordings_from_deleted_enabled', 0));
2462
    }
2463
}
2464
2465
/**
2466
 * Helper function renders show recording settings if the feature is enabled.
2467
 *
2468
 * @param object $renderer
2469
 *
2470
 * @return void
2471
 */
2472
function bigbluebuttonbn_settings_showrecordings(&$renderer) {
2473
    // Configuration for 'show recordings' feature.
2474
    if ((boolean)\mod_bigbluebuttonbn\settings\validator::section_show_recordings_shown()) {
2475
        $renderer->render_group_header('recordings');
2476
        $renderer->render_group_element('recordings_html_default',
2477
            $renderer->render_group_element_checkbox('recordings_html_default', 1));
2478
        $renderer->render_group_element('recordings_html_editable',
2479
            $renderer->render_group_element_checkbox('recordings_html_editable', 0));
2480
        $renderer->render_group_element('recordings_deleted_default',
2481
            $renderer->render_group_element_checkbox('recordings_deleted_default', 1));
2482
        $renderer->render_group_element('recordings_deleted_editable',
2483
            $renderer->render_group_element_checkbox('recordings_deleted_editable', 0));
2484
        $renderer->render_group_element('recordings_imported_default',
2485
            $renderer->render_group_element_checkbox('recordings_imported_default', 0));
2486
        $renderer->render_group_element('recordings_imported_editable',
2487
            $renderer->render_group_element_checkbox('recordings_imported_editable', 1));
2488
        $renderer->render_group_element('recordings_preview_default',
2489
            $renderer->render_group_element_checkbox('recordings_preview_default', 1));
2490
        $renderer->render_group_element('recordings_preview_editable',
2491
            $renderer->render_group_element_checkbox('recordings_preview_editable', 0));
2492
    }
2493
}
2494
2495
/**
2496
 * Helper function renders wait for moderator settings if the feature is enabled.
2497
 *
2498
 * @param object $renderer
2499
 *
2500
 * @return void
2501
 */
2502
function bigbluebuttonbn_settings_waitmoderator(&$renderer) {
2503
    // Configuration for wait for moderator feature.
2504
    if ((boolean)\mod_bigbluebuttonbn\settings\validator::section_wait_moderator_shown()) {
2505
        $renderer->render_group_header('waitformoderator');
2506
        $renderer->render_group_element('waitformoderator_default',
2507
            $renderer->render_group_element_checkbox('waitformoderator_default', 0));
2508
        $renderer->render_group_element('waitformoderator_editable',
2509
            $renderer->render_group_element_checkbox('waitformoderator_editable', 1));
2510
        $renderer->render_group_element('waitformoderator_ping_interval',
2511
            $renderer->render_group_element_text('waitformoderator_ping_interval', 10, PARAM_INT));
2512
        $renderer->render_group_element('waitformoderator_cache_ttl',
2513
            $renderer->render_group_element_text('waitformoderator_cache_ttl', 60, PARAM_INT));
2514
    }
2515
}
2516
2517
/**
2518
 * Helper function renders static voice bridge settings if the feature is enabled.
2519
 *
2520
 * @param object $renderer
2521
 *
2522
 * @return void
2523
 */
2524
function bigbluebuttonbn_settings_voicebridge(&$renderer) {
2525
    // Configuration for "static voice bridge" feature.
2526
    if ((boolean)\mod_bigbluebuttonbn\settings\validator::section_static_voice_bridge_shown()) {
2527
        $renderer->render_group_header('voicebridge');
2528
        $renderer->render_group_element('voicebridge_editable',
2529
            $renderer->render_group_element_checkbox('voicebridge_editable', 0));
2530
    }
2531
}
2532
2533
/**
2534
 * Helper function renders preuploaded presentation settings if the feature is enabled.
2535
 *
2536
 * @param object $renderer
2537
 *
2538
 * @return void
2539
 */
2540
function bigbluebuttonbn_settings_preupload(&$renderer) {
2541
    // Configuration for "preupload presentation" feature.
2542
    if ((boolean)\mod_bigbluebuttonbn\settings\validator::section_preupload_presentation_shown()) {
2543
        // This feature only works if curl is installed.
2544
        $preuploaddescripion = get_string('config_preuploadpresentation_description', 'bigbluebuttonbn');
2545
        if (!extension_loaded('curl')) {
2546
            $preuploaddescripion .= '<div class="form-defaultinfo">';
2547
            $preuploaddescripion .= get_string('config_warning_curl_not_installed', 'bigbluebuttonbn');
2548
            $preuploaddescripion .= '</div><br>';
2549
        }
2550
        $renderer->render_group_header('preuploadpresentation', null, $preuploaddescripion);
2551
        if (extension_loaded('curl')) {
2552
            $renderer->render_group_element('preuploadpresentation_enabled',
2553
                $renderer->render_group_element_checkbox('preuploadpresentation_enabled', 0));
2554
        }
2555
    }
2556
}
2557
2558
/**
2559
 * Helper function renders preuploaded presentation manage file if the feature is enabled.
2560
 * This allow to select a file for use as default in all BBB instances if preuploaded presetantion is enable.
2561
 *
2562
 * @param object $renderer
2563
 *
2564
 * @return void
2565
 */
2566
function bigbluebuttonbn_settings_preupload_manage_default_file(&$renderer) {
2567
    // Configuration for "preupload presentation" feature.
2568
    if ((boolean)\mod_bigbluebuttonbn\settings\validator::section_preupload_presentation_shown()) {
2569
        if (extension_loaded('curl')) {
2570
            // This feature only works if curl is installed.
2571
            $renderer->render_filemanager_default_file_presentation("presentation_default");
2572
        }
2573
    }
2574
}
2575
2576
/**
2577
 * Helper function renders userlimit settings if the feature is enabled.
2578
 *
2579
 * @param object $renderer
2580
 *
2581
 * @return void
2582
 */
2583
function bigbluebuttonbn_settings_userlimit(&$renderer) {
2584
    // Configuration for "user limit" feature.
2585
    if ((boolean)\mod_bigbluebuttonbn\settings\validator::section_user_limit_shown()) {
2586
        $renderer->render_group_header('userlimit');
2587
        $renderer->render_group_element('userlimit_default',
2588
            $renderer->render_group_element_text('userlimit_default', 0, PARAM_INT));
2589
        $renderer->render_group_element('userlimit_editable',
2590
            $renderer->render_group_element_checkbox('userlimit_editable', 0));
2591
    }
2592
}
2593
2594
/**
2595
 * Helper function renders duration settings if the feature is enabled.
2596
 *
2597
 * @param object $renderer
2598
 *
2599
 * @return void
2600
 */
2601
function bigbluebuttonbn_settings_duration(&$renderer) {
2602
    // Configuration for "scheduled duration" feature.
2603 View Code Duplication
    if ((boolean)\mod_bigbluebuttonbn\settings\validator::section_scheduled_duration_shown()) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
2604
        $renderer->render_group_header('scheduled');
2605
        $renderer->render_group_element('scheduled_duration_enabled',
2606
            $renderer->render_group_element_checkbox('scheduled_duration_enabled', 1));
2607
        $renderer->render_group_element('scheduled_duration_compensation',
2608
            $renderer->render_group_element_text('scheduled_duration_compensation', 10, PARAM_INT));
2609
        $renderer->render_group_element('scheduled_pre_opening',
2610
            $renderer->render_group_element_text('scheduled_pre_opening', 10, PARAM_INT));
2611
    }
2612
}
2613
2614
/**
2615
 * Helper function renders participant settings if the feature is enabled.
2616
 *
2617
 * @param object $renderer
2618
 *
2619
 * @return void
2620
 */
2621
function bigbluebuttonbn_settings_participants(&$renderer) {
2622
    // Configuration for defining the default role/user that will be moderator on new activities.
2623
    if ((boolean)\mod_bigbluebuttonbn\settings\validator::section_moderator_default_shown()) {
2624
        $renderer->render_group_header('participant');
2625
        // UI for 'participants' feature.
2626
        $roles = bigbluebuttonbn_get_roles();
2627
        $owner = array('0' => get_string('mod_form_field_participant_list_type_owner', 'bigbluebuttonbn'));
2628
        $renderer->render_group_element('participant_moderator_default',
2629
            $renderer->render_group_element_configmultiselect('participant_moderator_default',
2630
                array_keys($owner), array_merge($owner, $roles))
2631
          );
2632
    }
2633
}
2634
2635
/**
2636
 * Helper function renders notification settings if the feature is enabled.
2637
 *
2638
 * @param object $renderer
2639
 *
2640
 * @return void
2641
 */
2642
function bigbluebuttonbn_settings_notifications(&$renderer) {
2643
    // Configuration for "send notifications" feature.
2644
    if ((boolean)\mod_bigbluebuttonbn\settings\validator::section_send_notifications_shown()) {
2645
        $renderer->render_group_header('sendnotifications');
2646
        $renderer->render_group_element('sendnotifications_enabled',
2647
            $renderer->render_group_element_checkbox('sendnotifications_enabled', 1));
2648
    }
2649
}
2650
2651
/**
2652
 * Helper function renders client type settings if the feature is enabled.
2653
 *
2654
 * @param object $renderer
2655
 *
2656
 * @return void
2657
 */
2658
function bigbluebuttonbn_settings_clienttype(&$renderer) {
2659
    // Configuration for "clienttype" feature.
2660
    if ((boolean)\mod_bigbluebuttonbn\settings\validator::section_clienttype_shown()) {
2661
        $renderer->render_group_header('clienttype');
2662
        $renderer->render_group_element('clienttype_editable',
2663
            $renderer->render_group_element_checkbox('clienttype_editable', 0));
2664
        // Web Client default.
2665
        $default = intval((int)\mod_bigbluebuttonbn\locallib\config::get('clienttype_default'));
2666
        $choices = array(BIGBLUEBUTTON_CLIENTTYPE_FLASH => get_string('mod_form_block_clienttype_flash', 'bigbluebuttonbn'),
2667
                         BIGBLUEBUTTON_CLIENTTYPE_HTML5 => get_string('mod_form_block_clienttype_html5', 'bigbluebuttonbn'));
2668
        $renderer->render_group_element('clienttype_default',
2669
            $renderer->render_group_element_configselect('clienttype_default',
2670
                $default, $choices));
2671
    }
2672
}
2673
2674
/**
2675
 * Helper function renders general settings if the feature is enabled.
2676
 *
2677
 * @param object $renderer
2678
 *
2679
 * @return void
2680
 */
2681 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...
2682
    // Configuration for BigBlueButton.
2683
    if ((boolean)\mod_bigbluebuttonbn\settings\validator::section_muteonstart_shown()) {
2684
        $renderer->render_group_header('muteonstart');
2685
        $renderer->render_group_element('muteonstart_default',
2686
            $renderer->render_group_element_checkbox('muteonstart_default', 0));
2687
        $renderer->render_group_element('muteonstart_editable',
2688
            $renderer->render_group_element_checkbox('muteonstart_editable', 0));
2689
    }
2690
}
2691
2692
/**
2693
 * Helper function renders extended settings if any of the features there is enabled.
2694
 *
2695
 * @param object $renderer
2696
 *
2697
 * @return void
2698
 */
2699 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...
2700
    // Configuration for extended BN capabilities.
2701
    if (!bigbluebuttonbn_is_bn_server()) {
2702
        return;
2703
    }
2704
    // Configuration for 'notify users when recording ready' feature.
2705
    if ((boolean)\mod_bigbluebuttonbn\settings\validator::section_settings_extended_shown()) {
2706
        $renderer->render_group_header('extended_capabilities');
2707
        // UI for 'notify users when recording ready' feature.
2708
        $renderer->render_group_element('recordingready_enabled',
2709
            $renderer->render_group_element_checkbox('recordingready_enabled', 0));
2710
        // UI for 'register meeting events' feature.
2711
        $renderer->render_group_element('meetingevents_enabled',
2712
            $renderer->render_group_element_checkbox('meetingevents_enabled', 0));
2713
    }
2714
}
2715
2716
/**
2717
 * Helper function returns a sha1 encoded string that is unique and will be used as a seed for meetingid.
2718
 *
2719
 * @return string
2720
 */
2721
function bigbluebuttonbn_unique_meetingid_seed() {
2722
    global $DB;
2723
    do {
2724
        $encodedseed = sha1(bigbluebuttonbn_random_password(12));
2725
        $meetingid = (string)$DB->get_field('bigbluebuttonbn', 'meetingid', array('meetingid' => $encodedseed));
2726
    } while ($meetingid == $encodedseed);
2727
    return $encodedseed;
2728
}
2729
2730
/**
2731
 * Helper function renders the link used for recording type in row for the data used by the recording table.
2732
 *
2733
 * @param array $recording
2734
 * @param array $bbbsession
2735
 * @param array $playback
2736
 *
2737
 * @return boolean
2738
 */
2739
function bigbluebuttonbn_include_recording_data_row_type($recording, $bbbsession, $playback) {
2740
    // All types that are not restricted are included.
2741
    if (array_key_exists('restricted', $playback) && strtolower($playback['restricted']) == 'false') {
2742
        return true;
2743
    }
2744
    // All types that are not statistics are included.
2745
    if ($playback['type'] != 'statistics') {
2746
        return true;
2747
    }
2748
    // Exclude imported recordings.
2749
    if (isset($recording['imported'])) {
2750
        return false;
2751
    }
2752
    // Exclude non moderators.
2753
    if (!$bbbsession['administrator'] && !$bbbsession['moderator']) {
2754
        return false;
2755
    }
2756
    return true;
2757
}
2758
2759
/**
2760
 * Renders the general warning message.
2761
 *
2762
 * @param string $message
2763
 * @param string $type
2764
 * @param string $href
2765
 * @param string $text
2766
 * @param string $class
2767
 *
2768
 * @return string
2769
 */
2770
function bigbluebuttonbn_render_warning($message, $type='info', $href='', $text='', $class='') {
2771
    global $OUTPUT;
2772
    $output = "\n";
2773
    // Evaluates if config_warning is enabled.
2774
    if (empty($message)) {
2775
        return $output;
2776
    }
2777
    $output .= $OUTPUT->box_start('box boxalignleft adminerror alert alert-' . $type . ' alert-block fade in',
2778
      'bigbluebuttonbn_view_general_warning') . "\n";
2779
    $output .= '    ' . $message . "\n";
2780
    $output .= '  <div class="singlebutton pull-right">' . "\n";
2781
    if (!empty($href)) {
2782
        $output .= bigbluebuttonbn_render_warning_button($href, $text, $class);
2783
    }
2784
    $output .= '  </div>' . "\n";
2785
    $output .= $OUTPUT->box_end() . "\n";
2786
    return $output;
2787
}
2788
2789
/**
2790
 * Renders the general warning button.
2791
 *
2792
 * @param string $href
2793
 * @param string $text
2794
 * @param string $class
2795
 * @param string $title
2796
 *
2797
 * @return string
2798
 */
2799
function bigbluebuttonbn_render_warning_button($href, $text = '', $class = '', $title = '') {
2800
    if ($text == '') {
2801
        $text = get_string('ok', 'moodle');
2802
    }
2803
    if ($title == '') {
2804
        $title = $text;
2805
    }
2806
    if ($class == '') {
2807
        $class = 'btn btn-secondary';
2808
    }
2809
    $output  = '  <form method="post" action="' . $href . '" class="form-inline">'."\n";
2810
    $output .= '      <button type="submit" class="' . $class . '"'."\n";
2811
    $output .= '          title="' . $title . '"'."\n";
2812
    $output .= '          >' . $text . '</button>'."\n";
2813
    $output .= '  </form>'."\n";
2814
    return $output;
2815
}
2816
2817
/**
2818
 * Check if a BigBlueButtonBN is available to be used by the current user.
2819
 *
2820
 * @param  stdClass  $bigbluebuttonbn  BigBlueButtonBN instance
2821
 *
2822
 * @return boolean                     status if room available and current user allowed to join
2823
 */
2824
function bigbluebuttonbn_get_availability_status($bigbluebuttonbn) {
2825
    list($roomavailable) = bigbluebuttonbn_room_is_available($bigbluebuttonbn);
2826
    list($usercanjoin) = bigbluebuttonbn_user_can_join_meeting($bigbluebuttonbn);
2827
2828
    return ($roomavailable && $usercanjoin);
2829
}
2830
2831
/**
2832
 * Helper for evaluating if scheduled activity is avaiable.
2833
 *
2834
 * @param  stdClass  $bigbluebuttonbn  BigBlueButtonBN instance
2835
 *
2836
 * @return array                       status (room available or not and possible warnings)
2837
 */
2838
function bigbluebuttonbn_room_is_available($bigbluebuttonbn) {
2839
    $open = true;
2840
    $closed = false;
2841
    $warnings = array();
2842
2843
    $timenow = time();
2844
    $timeopen = $bigbluebuttonbn->openingtime;
2845
    $timeclose = $bigbluebuttonbn->closingtime;
2846
    if (!empty($timeopen) && $timeopen > $timenow) {
2847
        $open = false;
2848
    }
2849
    if (!empty($timeclose) && $timenow > $timeclose) {
2850
        $closed = true;
2851
    }
2852
2853
    if (!$open || $closed) {
2854
        if (!$open) {
2855
            $warnings['notopenyet'] = userdate($timeopen);
2856
        }
2857
        if ($closed) {
2858
            $warnings['expired'] = userdate($timeclose);
2859
        }
2860
        return array(false, $warnings);
2861
    }
2862
2863
    return array(true, $warnings);
2864
}
2865
2866
/**
2867
 * Helper for evaluating if meeting can be joined.
2868
 *
2869
 * @param  stdClass $bigbluebuttonbn  BigBlueButtonBN instance
2870
 * @param  string   $mid
2871
 * @param  integer  $userid
2872
 *
2873
 * @return array    status (user allowed to join or not and possible message)
2874
 */
2875
function bigbluebuttonbn_user_can_join_meeting($bigbluebuttonbn, $mid = null, $userid = null) {
2876
2877
    // By default, use a meetingid without groups.
2878
    if (empty($mid)) {
2879
        $mid = $bigbluebuttonbn->meetingid . '-' . $bigbluebuttonbn->course . '-' . $bigbluebuttonbn->id;
2880
    }
2881
2882
    // When meeting is running, all authorized users can join right in.
2883
    if (bigbluebuttonbn_is_meeting_running($mid)) {
2884
        return array(true, get_string('view_message_conference_in_progress', 'bigbluebuttonbn'));
2885
    }
2886
2887
    // When meeting is not running, see if the user can join.
2888
    $context = context_course::instance($bigbluebuttonbn->course);
2889
    $participantlist = bigbluebuttonbn_get_participant_list($bigbluebuttonbn, $context);
2890
    $isadmin = is_siteadmin($userid);
2891
    $ismoderator = bigbluebuttonbn_is_moderator($context, $participantlist, $userid);
2892
    // If user is administrator, moderator or if is viewer and no waiting is required, join allowed.
2893
    if ($isadmin || $ismoderator || !$bigbluebuttonbn->wait) {
2894
        return array(true, get_string('view_message_conference_room_ready', 'bigbluebuttonbn'));
2895
    }
2896
    // Otherwise, no join allowed.
2897
    return array(false, get_string('view_message_conference_wait_for_moderator', 'bigbluebuttonbn'));
2898
}
2899
2900
/**
2901
 * Helper for getting a value from a bigbluebuttonbn cache.
2902
 *
2903
 * @param  string   $name       BigBlueButtonBN cache
2904
 * @param  string   $key        Key to be retrieved
2905
 * @param  integer  $default    Default value in case key is not found or it is empty
2906
 *
2907
 * @return variable key value
2908
 */
2909
function bigbluebuttonbn_cache_get($name, $key, $default = null) {
2910
    $cache = cache::make_from_params(cache_store::MODE_APPLICATION, 'mod_bigbluebuttonbn', $name);
2911
    $result = $cache->get($key);
2912
    if (!empty($result)) {
2913
        return $result;
2914
    }
2915
    return $default;
2916
}
2917
2918
/**
2919
 * Helper for setting a value in a bigbluebuttonbn cache.
2920
 *
2921
 * @param  string   $name       BigBlueButtonBN cache
2922
 * @param  string   $key        Key to be created/updated
2923
 * @param  variable $value      Default value to be set
2924
 */
2925
function bigbluebuttonbn_cache_set($name, $key, $value) {
2926
    $cache = cache::make_from_params(cache_store::MODE_APPLICATION, 'mod_bigbluebuttonbn', $name);
2927
    $cache->set($key, $value);
2928
}
2929
2930
/**
2931
 * Helper for getting the owner userid of a bigbluebuttonbn instance.
2932
 *
2933
 * @param  stdClass $bigbluebuttonbn  BigBlueButtonBN instance
2934
 *
2935
 * @return integer ownerid (a valid user id or null if not registered/found)
2936
 */
2937
function bigbluebuttonbn_instance_ownerid($bigbluebuttonbn) {
2938
    global $DB;
2939
    $filters = array('bigbluebuttonbnid' => $bigbluebuttonbn->id, 'log' => 'Add');
2940
    $ownerid = (integer)$DB->get_field('bigbluebuttonbn_logs', 'userid', $filters);
2941
    return $ownerid;
2942
}
2943
2944
/**
2945
 * Helper evaluates if the bigbluebutton server used belongs to blindsidenetworks domain.
2946
 *
2947
 * @return boolean
2948
 */
2949
function bigbluebuttonbn_has_html5_client() {
2950
    $checkurl = \mod_bigbluebuttonbn\locallib\bigbluebutton::root() . "html5client/check";
2951
    $curlinfo = bigbluebuttonbn_wrap_xml_load_file_curl_request($checkurl, 'HEAD');
2952
    return (isset($curlinfo['http_code']) && $curlinfo['http_code'] == 200);
2953
}
2954
2955
/**
2956
 * Setup the bbbsession variable that is used all accross the plugin.
2957
 *
2958
 * @param object $context
2959
 * @param array $bbbsession
2960
 * @return void
2961
 */
2962 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...
2963
    global $CFG, $USER;
2964
    // User data.
2965
    $bbbsession['username'] = fullname($USER);
2966
    $bbbsession['userID'] = $USER->id;
2967
    // User roles.
2968
    $bbbsession['administrator'] = is_siteadmin($bbbsession['userID']);
2969
    $participantlist = bigbluebuttonbn_get_participant_list($bbbsession['bigbluebuttonbn'], $context);
2970
    $bbbsession['moderator'] = bigbluebuttonbn_is_moderator($context, $participantlist);
2971
    $bbbsession['managerecordings'] = ($bbbsession['administrator']
2972
        || has_capability('mod/bigbluebuttonbn:managerecordings', $context));
2973
    $bbbsession['importrecordings'] = ($bbbsession['managerecordings']);
2974
    // Server data.
2975
    $bbbsession['modPW'] = $bbbsession['bigbluebuttonbn']->moderatorpass;
2976
    $bbbsession['viewerPW'] = $bbbsession['bigbluebuttonbn']->viewerpass;
2977
    // Database info related to the activity.
2978
    $bbbsession['meetingid'] = $bbbsession['bigbluebuttonbn']->meetingid.'-'.$bbbsession['course']->id.'-'.
2979
        $bbbsession['bigbluebuttonbn']->id;
2980
    $bbbsession['meetingname'] = $bbbsession['bigbluebuttonbn']->name;
2981
    $bbbsession['meetingdescription'] = $bbbsession['bigbluebuttonbn']->intro;
2982
    // Extra data for setting up the Meeting.
2983
    $bbbsession['userlimit'] = intval((int)\mod_bigbluebuttonbn\locallib\config::get('userlimit_default'));
2984
    if ((boolean)\mod_bigbluebuttonbn\locallib\config::get('userlimit_editable')) {
2985
        $bbbsession['userlimit'] = intval($bbbsession['bigbluebuttonbn']->userlimit);
2986
    }
2987
    $bbbsession['voicebridge'] = $bbbsession['bigbluebuttonbn']->voicebridge;
2988
    if ($bbbsession['bigbluebuttonbn']->voicebridge > 0) {
2989
        $bbbsession['voicebridge'] = 70000 + $bbbsession['bigbluebuttonbn']->voicebridge;
2990
    }
2991
    $bbbsession['wait'] = $bbbsession['bigbluebuttonbn']->wait;
2992
    $bbbsession['record'] = $bbbsession['bigbluebuttonbn']->record;
2993
    $bbbsession['welcome'] = $bbbsession['bigbluebuttonbn']->welcome;
2994
    if (!isset($bbbsession['welcome']) || $bbbsession['welcome'] == '') {
2995
        $bbbsession['welcome'] = get_string('mod_form_field_welcome_default', 'bigbluebuttonbn');
2996
    }
2997
    if ($bbbsession['bigbluebuttonbn']->record) {
2998
        $bbbsession['welcome'] .= '<br><br>'.get_string('bbbrecordwarning', 'bigbluebuttonbn');
2999
    }
3000
    $bbbsession['openingtime'] = $bbbsession['bigbluebuttonbn']->openingtime;
3001
    $bbbsession['closingtime'] = $bbbsession['bigbluebuttonbn']->closingtime;
3002
    $bbbsession['muteonstart'] = $bbbsession['bigbluebuttonbn']->muteonstart;
3003
    // Additional info related to the course.
3004
    $bbbsession['context'] = $context;
3005
    // Metadata (origin).
3006
    $bbbsession['origin'] = 'Moodle';
3007
    $bbbsession['originVersion'] = $CFG->release;
3008
    $parsedurl = parse_url($CFG->wwwroot);
3009
    $bbbsession['originServerName'] = $parsedurl['host'];
3010
    $bbbsession['originServerUrl'] = $CFG->wwwroot;
3011
    $bbbsession['originServerCommonName'] = '';
3012
    $bbbsession['originTag'] = 'moodle-mod_bigbluebuttonbn ('.get_config('mod_bigbluebuttonbn', 'version').')';
3013
    $bbbsession['bnserver'] = bigbluebuttonbn_is_bn_server();
3014
    // Setting for clienttype, assign flash if not enabled, or default if not editable.
3015
    $bbbsession['clienttype'] = \mod_bigbluebuttonbn\locallib\config::get('clienttype_default');
3016
    if (\mod_bigbluebuttonbn\locallib\config::get('clienttype_editable')) {
3017
        $bbbsession['clienttype'] = $bbbsession['bigbluebuttonbn']->clienttype;
3018
    }
3019
    if (!\mod_bigbluebuttonbn\locallib\config::clienttype_enabled()) {
3020
        $bbbsession['clienttype'] = BIGBLUEBUTTON_CLIENTTYPE_FLASH;
3021
    }
3022
}
3023
3024
/**
3025
 * Return the status of an activity [open|not_started|ended].
3026
 *
3027
 * @param array $bbbsession
3028
 * @return string
3029
 */
3030 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...
3031
    $now = time();
3032
    if (!empty($bbbsession['bigbluebuttonbn']->openingtime) && $now < $bbbsession['bigbluebuttonbn']->openingtime) {
3033
        // The activity has not been opened.
3034
        return 'not_started';
3035
    }
3036
    if (!empty($bbbsession['bigbluebuttonbn']->closingtime) && $now > $bbbsession['bigbluebuttonbn']->closingtime) {
3037
        // The activity has been closed.
3038
        return 'ended';
3039
    }
3040
    // The activity is open.
3041
    return 'open';
3042
}
3043