Completed
Push — v2.2-stable ( 20d974...7dc50b )
by Jesus
02:31
created

locallib.php ➔ bigbluebuttonbn_has_html5_client()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
nc 2
nop 0
dl 0
loc 5
rs 10
c 0
b 0
f 0
1
<?php
2
// This file is part of Moodle - http://moodle.org/
3
//
4
// Moodle is free software: you can redistribute it and/or modify
5
// it under the terms of the GNU General Public License as published by
6
// the Free Software Foundation, either version 3 of the License, or
7
// (at your option) any later version.
8
//
9
// Moodle is distributed in the hope that it will be useful,
10
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
// GNU General Public License for more details.
13
//
14
// You should have received a copy of the GNU General Public License
15
// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
16
17
/**
18
 * Internal library of functions for module BigBlueButtonBN.
19
 *
20
 * @package   mod_bigbluebuttonbn
21
 * @copyright 2010-2017 Blindside Networks Inc
22
 * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v2 or later
23
 * @author    Jesus Federico  (jesus [at] blindsidenetworks [dt] com)
24
 * @author    Fred Dixon  (ffdixon [at] blindsidenetworks [dt] com)
25
 */
26
27
defined('MOODLE_INTERNAL') || die;
28
29
global $CFG;
30
31
require_once(dirname(__FILE__).'/lib.php');
32
33
/** @var BIGBLUEBUTTONBN_UPDATE_CACHE boolean set to true indicates that cache has to be updated */
34
const BIGBLUEBUTTONBN_UPDATE_CACHE = true;
35
/** @var BIGBLUEBUTTONBN_TYPE_ALL integer set to 0 defines an instance type that inclueds room and recordings */
36
const BIGBLUEBUTTONBN_TYPE_ALL = 0;
37
/** @var BIGBLUEBUTTONBN_TYPE_ROOM_ONLY integer set to 1 defines an instance type that inclueds only room */
38
const BIGBLUEBUTTONBN_TYPE_ROOM_ONLY = 1;
39
/** @var BIGBLUEBUTTONBN_TYPE_RECORDING_ONLY integer set to 2 defines an instance type that inclueds only recordings */
40
const BIGBLUEBUTTONBN_TYPE_RECORDING_ONLY = 2;
41
/** @var BIGBLUEBUTTONBN_ROLE_VIEWER string defines the bigbluebutton viewer role */
42
const BIGBLUEBUTTONBN_ROLE_VIEWER = 'viewer';
43
/** @var BIGBLUEBUTTONBN_ROLE_MODERATOR string defines the bigbluebutton moderator role */
44
const BIGBLUEBUTTONBN_ROLE_MODERATOR = 'moderator';
45
/** @var BIGBLUEBUTTON_EVENT_ACTIVITY_VIEWED string defines the bigbluebuttonbn activity_viewed event */
46
const BIGBLUEBUTTON_EVENT_ACTIVITY_VIEWED = 'activity_viewed';
47
/** @var BIGBLUEBUTTON_EVENT_ACTIVITY_MANAGEMENT_VIEWED string defines the bigbluebuttonbn activity_management_viewed event */
48
const BIGBLUEBUTTON_EVENT_ACTIVITY_MANAGEMENT_VIEWED = 'activity_management_viewed';
49
/** @var BIGBLUEBUTTON_EVENT_LIVE_SESSION string defines the bigbluebuttonbn live_session event */
50
const BIGBLUEBUTTON_EVENT_LIVE_SESSION = 'live_session';
51
/** @var BIGBLUEBUTTON_EVENT_MEETING_CREATED string defines the bigbluebuttonbn meeting_created event */
52
const BIGBLUEBUTTON_EVENT_MEETING_CREATED = 'meeting_created';
53
/** @var BIGBLUEBUTTON_EVENT_MEETING_ENDED string defines the bigbluebuttonbn meeting_ended event */
54
const BIGBLUEBUTTON_EVENT_MEETING_ENDED = 'meeting_ended';
55
/** @var BIGBLUEBUTTON_EVENT_MEETING_JOINED string defines the bigbluebuttonbn meeting_joined event */
56
const BIGBLUEBUTTON_EVENT_MEETING_JOINED = 'meeting_joined';
57
/** @var BIGBLUEBUTTON_EVENT_MEETING_LEFT string defines the bigbluebuttonbn meeting_left event */
58
const BIGBLUEBUTTON_EVENT_MEETING_LEFT = 'meeting_left';
59
/** @var BIGBLUEBUTTON_EVENT_RECORDING_DELETED string defines the bigbluebuttonbn recording_deleted event */
60
const BIGBLUEBUTTON_EVENT_RECORDING_DELETED = 'recording_deleted';
61
/** @var BIGBLUEBUTTON_EVENT_RECORDING_IMPORTED string defines the bigbluebuttonbn recording_imported event */
62
const BIGBLUEBUTTON_EVENT_RECORDING_IMPORTED = 'recording_imported';
63
/** @var BIGBLUEBUTTON_EVENT_RECORDING_PROTECTED string defines the bigbluebuttonbn recording_protected event */
64
const BIGBLUEBUTTON_EVENT_RECORDING_PROTECTED = 'recording_protected';
65
/** @var BIGBLUEBUTTON_EVENT_RECORDING_PUBLISHED string defines the bigbluebuttonbn recording_published event */
66
const BIGBLUEBUTTON_EVENT_RECORDING_PUBLISHED = 'recording_published';
67
/** @var BIGBLUEBUTTON_EVENT_RECORDING_UNPROTECTED string defines the bigbluebuttonbn recording_unprotected event */
68
const BIGBLUEBUTTON_EVENT_RECORDING_UNPROTECTED = 'recording_unprotected';
69
/** @var BIGBLUEBUTTON_EVENT_RECORDING_UNPUBLISHED string defines the bigbluebuttonbn recording_unpublished event */
70
const BIGBLUEBUTTON_EVENT_RECORDING_UNPUBLISHED = 'recording_unpublished';
71
/** @var BIGBLUEBUTTON_EVENT_RECORDING_EDITED string defines the bigbluebuttonbn recording_edited event */
72
const BIGBLUEBUTTON_EVENT_RECORDING_EDITED = 'recording_edited';
73
/** @var BIGBLUEBUTTON_EVENT_RECORDING_VIEWED string defines the bigbluebuttonbn recording_viewed event */
74
const BIGBLUEBUTTON_EVENT_RECORDING_VIEWED = 'recording_viewed';
75
/** @var BIGBLUEBUTTON_EVENT_MEETING_START string defines the bigbluebuttonbn meeting_start event */
76
const BIGBLUEBUTTON_EVENT_MEETING_START = 'meeting_start';
77
/** @var BIGBLUEBUTTON_CLIENTTYPE_FLASH integer that defines the bigbluebuttonbn default web client based on Adobe FLASH */
78
const BIGBLUEBUTTON_CLIENTTYPE_FLASH = 0;
79
/** @var BIGBLUEBUTTON_CLIENTTYPE_HTML5 integer that defines the bigbluebuttonbn default web client based on Adobe HTML5 */
80
const BIGBLUEBUTTON_CLIENTTYPE_HTML5 = 1;
81
82
/**
83
 * Builds and retunrs a url for joining a bigbluebutton meeting.
84
 *
85
 * @param string $meetingid
86
 * @param string $username
87
 * @param string $pw
88
 * @param string $logouturl
89
 * @param string $configtoken
90
 * @param string $userid
91
 *
92
 * @return string
93
 */
94
function bigbluebuttonbn_get_join_url($meetingid, $username, $pw, $logouturl, $configtoken = null,
95
                                      $userid = null, $clienttype = BIGBLUEBUTTON_CLIENTTYPE_FLASH) {
96
    $data = ['meetingID' => $meetingid,
97
              'fullName' => $username,
98
              'password' => $pw,
99
              'logoutURL' => $logouturl,
100
            ];
101
    // Choose between Adobe Flash or HTML5 Client.
102
    if ( $clienttype == BIGBLUEBUTTON_CLIENTTYPE_HTML5 ) {
103
        $data['joinViaHtml5'] = 'true';
104
    }
105
106
    if (!is_null($configtoken)) {
107
        $data['configToken'] = $configtoken;
108
    }
109
    if (!is_null($userid)) {
110
        $data['userID'] = $userid;
111
    }
112
    return \mod_bigbluebuttonbn\locallib\bigbluebutton::action_url('join', $data);
113
}
114
115
/**
116
 * Creates a bigbluebutton meeting and returns the response in an array.
117
 *
118
 * @param array  $data
119
 * @param array  $metadata
120
 * @param string $pname
121
 * @param string $purl
122
 *
123
 * @return array
124
 */
125
function bigbluebuttonbn_get_create_meeting_array($data, $metadata = array(), $pname = null, $purl = null) {
126
    $createmeetingurl = \mod_bigbluebuttonbn\locallib\bigbluebutton::action_url('create', $data, $metadata);
127
    $method = 'GET';
128
    $data = null;
129
    if (!is_null($pname) && !is_null($purl)) {
130
        $method = 'POST';
131
        $data = "<?xml version='1.0' encoding='UTF-8'?><modules><module name='presentation'><document url='".
132
            $purl."' /></module></modules>";
133
    }
134
    $xml = bigbluebuttonbn_wrap_xml_load_file($createmeetingurl, $method, $data);
135
    if ($xml) {
136
        $response = array('returncode' => $xml->returncode, 'message' => $xml->message, 'messageKey' => $xml->messageKey);
137
        if ($xml->meetingID) {
138
            $response += array('meetingID' => $xml->meetingID, 'attendeePW' => $xml->attendeePW,
139
                'moderatorPW' => $xml->moderatorPW, 'hasBeenForciblyEnded' => $xml->hasBeenForciblyEnded);
140
        }
141
        return $response;
142
    }
143
    return array('returncode' => 'FAILED', 'message' => 'unreachable', 'messageKey' => 'Server is unreachable');
144
}
145
146
/**
147
 * Fetch meeting info and wrap response in array.
148
 *
149
 * @param string $meetingid
150
 *
151
 * @return array
152
 */
153
function bigbluebuttonbn_get_meeting_info_array($meetingid) {
154
    $xml = bigbluebuttonbn_wrap_xml_load_file(
155
        \mod_bigbluebuttonbn\locallib\bigbluebutton::action_url('getMeetingInfo', ['meetingID' => $meetingid])
156
      );
157
    if ($xml && $xml->returncode == 'SUCCESS' && empty($xml->messageKey)) {
158
        // Meeting info was returned.
159
        return array('returncode' => $xml->returncode,
160
                     'meetingID' => $xml->meetingID,
161
                     'moderatorPW' => $xml->moderatorPW,
162
                     'attendeePW' => $xml->attendeePW,
163
                     'hasBeenForciblyEnded' => $xml->hasBeenForciblyEnded,
164
                     'running' => $xml->running,
165
                     'recording' => $xml->recording,
166
                     'startTime' => $xml->startTime,
167
                     'endTime' => $xml->endTime,
168
                     'participantCount' => $xml->participantCount,
169
                     'moderatorCount' => $xml->moderatorCount,
170
                     'attendees' => $xml->attendees,
171
                     'metadata' => $xml->metadata,
172
                   );
173
    }
174
    if ($xml) {
175
        // Either failure or success without meeting info.
176
        return (array)$xml;
177
    }
178
    // If the server is unreachable, then prompts the user of the necessary action.
179
    return array('returncode' => 'FAILED', 'message' => 'unreachable', 'messageKey' => 'Server is unreachable');
180
}
181
182
/**
183
 * Helper function to retrieve recordings from a BigBlueButton server.
184
 *
185
 * @param string|array $meetingids   list of meetingIDs "mid1,mid2,mid3" or array("mid1","mid2","mid3")
186
 * @param string|array $recordingids list of $recordingids "rid1,rid2,rid3" or array("rid1","rid2","rid3") for filtering
187
 *
188
 * @return associative array with recordings indexed by recordID, each recording is a non sequential associative array
189
 */
190
function bigbluebuttonbn_get_recordings_array($meetingids, $recordingids = []) {
191
    $meetingidsarray = $meetingids;
192
    if (!is_array($meetingids)) {
193
        $meetingidsarray = explode(',', $meetingids);
194
    }
195
    // If $meetingidsarray is empty there is no need to go further.
196
    if (empty($meetingidsarray)) {
197
        return array();
198
    }
199
    $recordings = bigbluebuttonbn_get_recordings_array_fetch($meetingidsarray);
0 ignored issues
show
Bug introduced by
It seems like $meetingidsarray defined by $meetingids on line 191 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...
200
    // Sort recordings.
201
    uasort($recordings, 'bigbluebuttonbn_recording_build_sorter');
202
    // Filter recordings based on recordingIDs.
203
    $recordingidsarray = $recordingids;
204
    if (!is_array($recordingids)) {
205
        $recordingidsarray = explode(',', $recordingids);
206
    }
207
    if (empty($recordingidsarray)) {
208
        // No recording ids, no need to filter.
209
        return $recordings;
210
    }
211
    return bigbluebuttonbn_get_recordings_array_filter($recordingidsarray, $recordings);
0 ignored issues
show
Bug introduced by
It seems like $recordingidsarray defined by $recordingids on line 203 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...
212
}
213
214
/**
215
 * Helper function to fetch recordings from a BigBlueButton server.
216
 *
217
 * @param array $meetingidsarray   array with meeting ids in the form array("mid1","mid2","mid3")
218
 *
219
 * @return associative array with recordings indexed by recordID, each recording is a non sequential associative array
220
 */
221
function bigbluebuttonbn_get_recordings_array_fetch($meetingidsarray) {
222
    $recordings = array();
223
    // Execute a paginated getRecordings request.
224
    $pages = floor(count($meetingidsarray) / 25) + 1;
225
    for ($page = 1; $page <= $pages; ++$page) {
226
        $mids = array_slice($meetingidsarray, ($page - 1) * 25, 25);
227
        $recordings += bigbluebuttonbn_get_recordings_array_fetch_page($mids);
228
    }
229
    return $recordings;
230
}
231
232
/**
233
 * Helper function to fetch one page of upto 25 recordings from a BigBlueButton server.
234
 *
235
 * @param array  $mids
236
 *
237
 * @return array
238
 */
239
function bigbluebuttonbn_get_recordings_array_fetch_page($mids) {
240
    $recordings = array();
241
    // Do getRecordings is executed using a method GET (supported by all versions of BBB).
242
    $url = \mod_bigbluebuttonbn\locallib\bigbluebutton::action_url('getRecordings', ['meetingID' => implode(',', $mids)]);
243
    $xml = bigbluebuttonbn_wrap_xml_load_file($url);
244
    if ($xml && $xml->returncode == 'SUCCESS' && isset($xml->recordings)) {
245
        // If there were meetings already created.
246
        foreach ($xml->recordings->recording as $recordingxml) {
247
            $recording = bigbluebuttonbn_get_recording_array_value($recordingxml);
248
            $recordings[$recording['recordID']] = $recording;
249
        }
250
    }
251
    return $recordings;
252
}
253
254
/**
255
 * Helper function to remove a set of recordings from an array.
256
 *
257
 * @param array  $rids
258
 * @param array  $recordings
259
 *
260
 * @return array
261
 */
262
function bigbluebuttonbn_get_recordings_array_filter($rids, &$recordings) {
263
    foreach ($recordings as $key => $recording) {
264
        if (!in_array($recording['recordID'], $rids)) {
265
            unset($recordings[$key]);
266
        }
267
    }
268
    return $recordings;
269
}
270
271
/**
272
 * Helper function to retrieve imported recordings from the Moodle database.
273
 * The references are stored as events in bigbluebuttonbn_logs.
274
 *
275
 * @param string $courseid
276
 * @param string $bigbluebuttonbnid
277
 * @param bool   $subset
278
 *
279
 * @return associative array with imported recordings indexed by recordID, each recording
280
 * is a non sequential associative array that corresponds to the actual recording in BBB
281
 */
282
function bigbluebuttonbn_get_recordings_imported_array($courseid = 0, $bigbluebuttonbnid = null, $subset = true) {
283
    global $DB;
284
    $select = bigbluebuttonbn_get_recordings_imported_sql_select($courseid, $bigbluebuttonbnid, $subset);
285
    $recordsimported = $DB->get_records_select('bigbluebuttonbn_logs', $select);
286
    $recordsimportedarray = array();
287
    foreach ($recordsimported as $recordimported) {
288
        $meta = json_decode($recordimported->meta, true);
289
        $recording = $meta['recording'];
290
        // Override imported flag with actual ID.
291
        $recording['imported'] = $recordimported->id;
292
        if (isset($recordimported->protected)) {
293
            $recording['protected'] = (string) $recordimported->protected;
294
        }
295
        $recordsimportedarray[$recording['recordID']] = $recording;
296
    }
297
    return $recordsimportedarray;
298
}
299
300
/**
301
 * Helper function to retrive the default config.xml file.
302
 *
303
 * @return string
304
 */
305
function bigbluebuttonbn_get_default_config_xml() {
306
    $xml = bigbluebuttonbn_wrap_xml_load_file(
307
        \mod_bigbluebuttonbn\locallib\bigbluebutton::action_url('getDefaultConfigXML')
308
      );
309
    return $xml;
310
}
311
312
/**
313
 * Helper function to convert an xml recording object to an array in the format used by the plugin.
314
 *
315
 * @param object $recording
316
 *
317
 * @return array
318
 */
319
function bigbluebuttonbn_get_recording_array_value($recording) {
320
    // Add formats.
321
    $playbackarray = array();
322
    foreach ($recording->playback->format as $format) {
323
        $playbackarray[(string) $format->type] = array('type' => (string) $format->type,
324
            'url' => trim((string) $format->url), 'length' => (string) $format->length);
325
        // Add preview per format when existing.
326
        if ($format->preview) {
327
            $playbackarray[(string) $format->type]['preview'] = bigbluebuttonbn_get_recording_preview_images($format->preview);
328
        }
329
    }
330
    // Add the metadata to the recordings array.
331
    $metadataarray = bigbluebuttonbn_get_recording_array_meta(get_object_vars($recording->metadata));
332
    $recordingarray = array('recordID' => (string) $recording->recordID,
333
        'meetingID' => (string) $recording->meetingID, 'meetingName' => (string) $recording->name,
334
        'published' => (string) $recording->published, 'startTime' => (string) $recording->startTime,
335
        'endTime' => (string) $recording->endTime, 'playbacks' => $playbackarray);
336
    if (isset($recording->protected)) {
337
        $recordingarray['protected'] = (string) $recording->protected;
338
    }
339
    return $recordingarray + $metadataarray;
340
}
341
342
/**
343
 * Helper function to convert an xml recording preview images to an array in the format used by the plugin.
344
 *
345
 * @param object $preview
346
 *
347
 * @return array
348
 */
349
function bigbluebuttonbn_get_recording_preview_images($preview) {
350
    $imagesarray = array();
351
    foreach ($preview->images->image as $image) {
352
        $imagearray = array('url' => trim((string) $image));
353
        foreach ($image->attributes() as $attkey => $attvalue) {
354
            $imagearray[$attkey] = (string) $attvalue;
355
        }
356
        array_push($imagesarray, $imagearray);
357
    }
358
    return $imagesarray;
359
}
360
361
/**
362
 * Helper function to convert an xml recording metadata object to an array in the format used by the plugin.
363
 *
364
 * @param array $metadata
365
 *
366
 * @return array
367
 */
368
function bigbluebuttonbn_get_recording_array_meta($metadata) {
369
    $metadataarray = array();
370
    foreach ($metadata as $key => $value) {
371
        if (is_object($value)) {
372
            $value = '';
373
        }
374
        $metadataarray['meta_'.$key] = $value;
375
    }
376
    return $metadataarray;
377
}
378
379
/**
380
 * Helper function to sort an array of recordings. It compares the startTime in two recording objecs.
381
 *
382
 * @param object $a
383
 * @param object $b
384
 *
385
 * @return array
386
 */
387
function bigbluebuttonbn_recording_build_sorter($a, $b) {
388
    if ($a['startTime'] < $b['startTime']) {
389
        return -1;
390
    }
391
    if ($a['startTime'] == $b['startTime']) {
392
        return 0;
393
    }
394
    return 1;
395
}
396
397
/**
398
 * Perform deleteRecordings on BBB.
399
 *
400
 * @param string $recordids
401
 *
402
 * @return boolean
403
 */
404 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...
405
    $ids = explode(',', $recordids);
406
    foreach ($ids as $id) {
407
        $xml = bigbluebuttonbn_wrap_xml_load_file(
408
            \mod_bigbluebuttonbn\locallib\bigbluebutton::action_url('deleteRecordings', ['recordID' => $id])
409
          );
410
        if ($xml && $xml->returncode != 'SUCCESS') {
411
            return false;
412
        }
413
    }
414
    return true;
415
}
416
417
/**
418
 * Perform publishRecordings on BBB.
419
 *
420
 * @param string $recordids
421
 * @param string $publish
422
 */
423 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...
424
    $ids = explode(',', $recordids);
425
    foreach ($ids as $id) {
426
        $xml = bigbluebuttonbn_wrap_xml_load_file(
427
            \mod_bigbluebuttonbn\locallib\bigbluebutton::action_url('publishRecordings', ['recordID' => $id, 'publish' => $publish])
428
          );
429
        if ($xml && $xml->returncode != 'SUCCESS') {
430
            return false;
431
        }
432
    }
433
    return true;
434
}
435
436
/**
437
 * Perform updateRecordings on BBB.
438
 *
439
 * @param string $recordids
440
 * @param array $params ['key'=>param_key, 'value']
441
 */
442 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...
443
    $ids = explode(',', $recordids);
444
    foreach ($ids as $id) {
445
        $xml = bigbluebuttonbn_wrap_xml_load_file(
446
            \mod_bigbluebuttonbn\locallib\bigbluebutton::action_url('updateRecordings', ['recordID' => $id] + (array) $params)
447
          );
448
        if ($xml && $xml->returncode != 'SUCCESS') {
449
            return false;
450
        }
451
    }
452
    return true;
453
}
454
455
/**
456
 * Perform end on BBB.
457
 *
458
 * @param string $meetingid
459
 * @param string $modpw
460
 */
461
function bigbluebuttonbn_end_meeting($meetingid, $modpw) {
462
    $xml = bigbluebuttonbn_wrap_xml_load_file(
463
        \mod_bigbluebuttonbn\locallib\bigbluebutton::action_url('end', ['meetingID' => $meetingid, 'password' => $modpw])
464
      );
465
    if ($xml) {
466
        // If the xml packet returned failure it displays the message to the user.
467
        return array('returncode' => $xml->returncode, 'message' => $xml->message, 'messageKey' => $xml->messageKey);
468
    }
469
    // If the server is unreachable, then prompts the user of the necessary action.
470
    return null;
471
}
472
473
/**
474
 * Perform api request on BBB.
475
 *
476
 * @return string
477
 */
478
function bigbluebuttonbn_get_server_version() {
479
    $xml = bigbluebuttonbn_wrap_xml_load_file(
480
        \mod_bigbluebuttonbn\locallib\bigbluebutton::action_url()
481
      );
482
    if ($xml && $xml->returncode == 'SUCCESS') {
483
        return $xml->version;
484
    }
485
    return null;
486
}
487
488
/**
489
 * Perform api request on BBB and wraps the response in an XML object
490
 *
491
 * @param string $url
492
 * @param string $method
493
 * @param string $data
494
 * @param string $contenttype
495
 *
496
 * @return object
497
 */
498
function bigbluebuttonbn_wrap_xml_load_file($url, $method = 'GET', $data = null, $contenttype = 'text/xml') {
499
    if (extension_loaded('curl')) {
500
        $response = bigbluebuttonbn_wrap_xml_load_file_curl_request($url, $method, $data, $contenttype);
501
        if (!$response) {
502
            debugging('No response on wrap_simplexml_load_file', DEBUG_DEVELOPER);
503
            return null;
504
        }
505
        $previous = libxml_use_internal_errors(true);
506
        try {
507
            $xml = simplexml_load_string($response, 'SimpleXMLElement', LIBXML_NOCDATA | LIBXML_NOBLANKS);
508
            return $xml;
509
        } catch (Exception $e) {
510
            libxml_use_internal_errors($previous);
511
            $error = 'Caught exception: '.$e->getMessage();
512
            debugging($error, DEBUG_DEVELOPER);
513
            return null;
514
        }
515
    }
516
    // Alternative request non CURL based.
517
    $previous = libxml_use_internal_errors(true);
518
    try {
519
        $response = simplexml_load_file($url, 'SimpleXMLElement', LIBXML_NOCDATA | LIBXML_NOBLANKS);
520
        return $response;
521
    } catch (Exception $e) {
522
        $error = 'Caught exception: '.$e->getMessage();
523
        debugging($error, DEBUG_DEVELOPER);
524
        libxml_use_internal_errors($previous);
525
        return null;
526
    }
527
}
528
529
/**
530
 * Perform api request on BBB using CURL and wraps the response in an XML object
531
 *
532
 * @param string $url
533
 * @param string $method
534
 * @param string $data
535
 * @param string $contenttype
536
 *
537
 * @return object
538
 */
539
function bigbluebuttonbn_wrap_xml_load_file_curl_request($url, $method = 'GET', $data = null, $contenttype = 'text/xml') {
540
    $c = new curl();
541
    $c->setopt(array('SSL_VERIFYPEER' => true));
542
    if ($method == 'POST') {
543
        if (is_null($data) || is_array($data)) {
544
            return $c->post($url);
545
        }
546
        $options = array();
547
        $options['CURLOPT_HTTPHEADER'] = array(
548
                 'Content-Type: '.$contenttype,
549
                 'Content-Length: '.strlen($data),
550
                 'Content-Language: en-US',
551
               );
552
553
        return $c->post($url, $data, $options);
554
    }
555
    if ($method == 'HEAD') {
556
        $c->head($url, array('followlocation' => true, 'timeout' => 1));
557
        return $c->get_info();
558
    }
559
    return $c->get($url);
560
}
561
562
/**
563
 * End the session associated with this instance (if it's running).
564
 *
565
 * @param object $bigbluebuttonbn
566
 *
567
 * @return void
568
 */
569
function bigbluebuttonbn_end_meeting_if_running($bigbluebuttonbn) {
570
    $meetingid = $bigbluebuttonbn->meetingid.'-'.$bigbluebuttonbn->course.'-'.$bigbluebuttonbn->id;
571
    if (bigbluebuttonbn_is_meeting_running($meetingid)) {
572
        bigbluebuttonbn_end_meeting($meetingid, $bigbluebuttonbn->moderatorpass);
573
    }
574
}
575
576
/**
577
 * Returns user roles in a context.
578
 *
579
 * @param object $context
580
 * @param integer $userid
581
 *
582
 * @return array $userroles
583
 */
584
function bigbluebuttonbn_get_user_roles($context, $userid) {
585
    global $DB;
586
    $userroles = get_user_roles($context, $userid);
587
    if ($userroles) {
588
        $where = '';
589
        foreach ($userroles as $userrole) {
590
            $where .= (empty($where) ? ' WHERE' : ' OR').' id=' . $userrole->roleid;
591
        }
592
        $userroles = $DB->get_records_sql('SELECT * FROM {role}'.$where);
593
    }
594
    return $userroles;
595
}
596
597
/**
598
 * Returns guest role wrapped in an array.
599
 *
600
 * @return array
601
 */
602
function bigbluebuttonbn_get_guest_role() {
603
    $guestrole = get_guest_role();
604
    return array($guestrole->id => $guestrole);
605
}
606
607
/**
608
 * Returns an array containing all the users in a context.
609
 *
610
 * @param context $context
611
 *
612
 * @return array $users
613
 */
614
function bigbluebuttonbn_get_users(context $context = null) {
615
    $users = (array) get_enrolled_users($context, '', 0, 'u.*', null, 0, 0, true);
616
    foreach ($users as $key => $value) {
617
        $users[$key] = fullname($value);
618
    }
619
    return $users;
620
}
621
622
/**
623
 * Returns an array containing all the users in a context wrapped for html select element.
624
 *
625
 * @param context $context
626
 *
627
 * @return array $users
628
 */
629
function bigbluebuttonbn_get_users_select(context $context = null) {
630
    $users = (array) get_enrolled_users($context, '', 0, 'u.*', null, 0, 0, true);
631
    foreach ($users as $key => $value) {
632
        $users[$key] = array('id' => $value->id, 'name' => fullname($value));
633
    }
634
    return $users;
635
}
636
637
/**
638
 * Returns an array containing all the roles in a context.
639
 *
640
 * @param context $context
641
 *
642
 * @return array $roles
643
 */
644
function bigbluebuttonbn_get_roles(context $context = null) {
645
    $roles = (array) role_get_names($context);
646
    foreach ($roles as $key => $value) {
647
        $roles[$key] = $value->localname;
648
    }
649
    return $roles;
650
}
651
652
/**
653
 * Returns an array containing all the roles in a context wrapped for html select element.
654
 *
655
 * @param context $context
656
 *
657
 * @return array $users
658
 */
659
function bigbluebuttonbn_get_roles_select(context $context = null) {
660
    $roles = (array) role_get_names($context);
661
    foreach ($roles as $key => $value) {
662
        $roles[$key] = array('id' => $value->id, 'name' => $value->localname);
663
    }
664
    return $roles;
665
}
666
667
/**
668
 * Returns role that corresponds to an id.
669
 *
670
 * @param string|integer $id
671
 *
672
 * @return object $role
673
 */
674
function bigbluebuttonbn_get_role($id) {
675
    $roles = (array) role_get_names();
676
    if (is_numeric($id) && isset($roles[$id])) {
677
        return (object)$roles[$id];
678
    }
679
    foreach ($roles as $role) {
680
        if ($role->shortname == $id) {
681
            return $role;
682
        }
683
    }
684
}
685
686
/**
687
 * Returns an array to populate a list of participants used in mod_form.js.
688
 *
689
 * @param context $context
690
 *
691
 * @return array $data
692
 */
693
function bigbluebuttonbn_get_participant_data($context) {
694
    $data = array(
695
        'all' => array(
696
            'name' => get_string('mod_form_field_participant_list_type_all', 'bigbluebuttonbn'),
697
            'children' => []
698
          )
699
      );
700
    $data['role'] = array(
701
        'name' => get_string('mod_form_field_participant_list_type_role', 'bigbluebuttonbn'),
702
        'children' => bigbluebuttonbn_get_roles_select($context)
703
      );
704
    $data['user'] = array(
705
        'name' => get_string('mod_form_field_participant_list_type_user', 'bigbluebuttonbn'),
706
        'children' => bigbluebuttonbn_get_users_select($context)
707
      );
708
    return $data;
709
}
710
711
/**
712
 * Returns an array to populate a list of participants used in mod_form.php.
713
 *
714
 * @param object $bigbluebuttonbn
715
 * @param context $context
716
 *
717
 * @return array
718
 */
719
function bigbluebuttonbn_get_participant_list($bigbluebuttonbn, $context) {
720
    global $USER;
721
    if ($bigbluebuttonbn == null) {
722
        return bigbluebuttonbn_get_participant_rules_encoded(
723
            bigbluebuttonbn_get_participant_list_default($context, $USER->id)
724
        );
725
    }
726
    if (empty($bigbluebuttonbn->participants)) {
727
        $bigbluebuttonbn->participants = "[]";
728
    }
729
    $rules = json_decode($bigbluebuttonbn->participants, true);
730
    if (empty($rules)) {
731
        $rules = bigbluebuttonbn_get_participant_list_default($context, bigbluebuttonbn_instance_ownerid($bigbluebuttonbn));
732
    }
733
    return bigbluebuttonbn_get_participant_rules_encoded($rules);
734
}
735
736
/**
737
 * Returns an array to populate a list of participants used in mod_form.php with default values.
738
 *
739
 * @param context $context
740
 * @param integer $ownerid
741
 *
742
 * @return array
743
 */
744
function bigbluebuttonbn_get_participant_list_default($context, $ownerid = null) {
745
    $participantlist = array();
746
    $participantlist[] = array(
747
        'selectiontype' => 'all',
748
        'selectionid' => 'all',
749
        'role' => BIGBLUEBUTTONBN_ROLE_VIEWER
750
      );
751
    $defaultrules = explode(',', \mod_bigbluebuttonbn\locallib\config::get('participant_moderator_default'));
752
    foreach ($defaultrules as $defaultrule) {
753
        if ($defaultrule == '0') {
754
            if (!empty($ownerid) && is_enrolled($context, $ownerid)) {
755
                $participantlist[] = array(
756
                    'selectiontype' => 'user',
757
                    'selectionid' => (string)$ownerid,
758
                    'role' => BIGBLUEBUTTONBN_ROLE_MODERATOR);
759
            }
760
            continue;
761
        }
762
        $participantlist[] = array(
763
              'selectiontype' => 'role',
764
              'selectionid' => $defaultrule,
765
              'role' => BIGBLUEBUTTONBN_ROLE_MODERATOR);
766
    }
767
    return $participantlist;
768
}
769
770
/**
771
 * Returns an array to populate a list of participants used in mod_form.php with bigbluebuttonbn values.
772
 *
773
 * @param array $rules
774
 *
775
 * @return array
776
 */
777
function bigbluebuttonbn_get_participant_rules_encoded($rules) {
778
    foreach ($rules as $key => $rule) {
779
        if ($rule['selectiontype'] !== 'role' || is_numeric($rule['selectionid'])) {
780
            continue;
781
        }
782
        $role = bigbluebuttonbn_get_role($rule['selectionid']);
783
        if ($role == null) {
784
            unset($rules[$key]);
785
            continue;
786
        }
787
        $rule['selectionid'] = $role->id;
788
        $rules[$key] = $rule;
789
    }
790
    return $rules;
791
}
792
793
/**
794
 * Returns an array to populate a list of participant_selection used in mod_form.php.
795
 *
796
 * @return array
797
 */
798
function bigbluebuttonbn_get_participant_selection_data() {
799
    return [
800
        'type_options' => [
801
            'all' => get_string('mod_form_field_participant_list_type_all', 'bigbluebuttonbn'),
802
            'role' => get_string('mod_form_field_participant_list_type_role', 'bigbluebuttonbn'),
803
            'user' => get_string('mod_form_field_participant_list_type_user', 'bigbluebuttonbn'),
804
          ],
805
        'type_selected' => 'all',
806
        'options' => ['all' => '---------------'],
807
        'selected' => 'all',
808
      ];
809
}
810
811
/**
812
 * Evaluate if a user in a context is moderator based on roles and participation rules.
813
 *
814
 * @param context $context
815
 * @param array $participantlist
816
 * @param integer $userid
817
 *
818
 * @return boolean
819
 */
820
function bigbluebuttonbn_is_moderator($context, $participantlist, $userid = null) {
821
    global $USER;
822
    if (!is_array($participantlist)) {
823
        return false;
824
    }
825
    if (empty($userid)) {
826
        $userid = $USER->id;
827
    }
828
    $userroles = bigbluebuttonbn_get_guest_role();
829
    if (!isguestuser()) {
830
        $userroles = bigbluebuttonbn_get_user_roles($context, $userid);
831
    }
832
    return bigbluebuttonbn_is_moderator_validator($participantlist, $userid , $userroles);
833
}
834
835
/**
836
 * Iterates participant list rules to evaluate if a user is moderator.
837
 *
838
 * @param array $participantlist
839
 * @param integer $userid
840
 * @param array $userroles
841
 *
842
 * @return boolean
843
 */
844
function bigbluebuttonbn_is_moderator_validator($participantlist, $userid, $userroles) {
845
    // Iterate participant rules.
846
    foreach ($participantlist as $participant) {
847
        if (bigbluebuttonbn_is_moderator_validate_rule($participant, $userid, $userroles)) {
848
            return true;
849
        }
850
    }
851
    return false;
852
}
853
854
/**
855
 * Evaluate if a user is moderator based on roles and a particular participation rule.
856
 *
857
 * @param object $participant
858
 * @param integer $userid
859
 * @param array $userroles
860
 *
861
 * @return boolean
862
 */
863
function bigbluebuttonbn_is_moderator_validate_rule($participant, $userid, $userroles) {
864
    if ($participant['role'] == BIGBLUEBUTTONBN_ROLE_VIEWER) {
865
        return false;
866
    }
867
    // Looks for all configuration.
868
    if ($participant['selectiontype'] == 'all') {
869
        return true;
870
    }
871
    // Looks for users.
872
    if ($participant['selectiontype'] == 'user' && $participant['selectionid'] == $userid) {
873
        return true;
874
    }
875
    // Looks for roles.
876
    $role = bigbluebuttonbn_get_role($participant['selectionid']);
877
    if ($role != null && array_key_exists($role->id, $userroles)) {
878
        return true;
879
    }
880
    return false;
881
}
882
883
/**
884
 * Helper returns error message key for the language file that corresponds to a bigbluebutton error key.
885
 *
886
 * @param string $messagekey
887
 * @param string $defaultkey
888
 *
889
 * @return string
890
 */
891
function bigbluebuttonbn_get_error_key($messagekey, $defaultkey = null) {
892
    if ($messagekey == 'checksumError') {
893
        return 'index_error_checksum';
894
    }
895
    if ($messagekey == 'maxConcurrent') {
896
        return 'view_error_max_concurrent';
897
    }
898
    return $defaultkey;
899
}
900
901
/**
902
 * Helper evaluates if a voicebridge number is unique.
903
 *
904
 * @param integer $instance
905
 * @param integer $voicebridge
906
 *
907
 * @return string
908
 */
909
function bigbluebuttonbn_voicebridge_unique($instance, $voicebridge) {
910
    global $DB;
911
    if ($voicebridge == 0) {
912
        return true;
913
    }
914
    $select = 'voicebridge = ' . $voicebridge;
915
    if ($instance != 0) {
916
        $select .= ' AND id <>' . $instance;
917
    }
918
    if (!$DB->get_records_select('bigbluebuttonbn', $select)) {
919
        return true;
920
    }
921
    return false;
922
}
923
924
/**
925
 * Helper estimate a duration for the meeting based on the closingtime.
926
 *
927
 * @param integer $closingtime
928
 *
929
 * @return integer
930
 */
931
function bigbluebuttonbn_get_duration($closingtime) {
932
    $duration = 0;
933
    $now = time();
934
    if ($closingtime > 0 && $now < $closingtime) {
935
        $duration = ceil(($closingtime - $now) / 60);
936
        $compensationtime = intval((int)\mod_bigbluebuttonbn\locallib\config::get('scheduled_duration_compensation'));
937
        $duration = intval($duration) + $compensationtime;
938
    }
939
    return $duration;
940
}
941
942
/**
943
 * Helper return array containing the file descriptor for a preuploaded presentation.
944
 *
945
 * @param context $context
946
 * @param string $presentation
947
 * @param integer $id
948
 *
949
 * @return array
950
 */
951
function bigbluebuttonbn_get_presentation_array($context, $presentation, $id = null) {
952
    if (empty($presentation)) {
953
        return array('url' => null, 'name' => null, 'icon' => null, 'mimetype_description' => null);
954
    }
955
    $fs = get_file_storage();
956
    $files = $fs->get_area_files($context->id, 'mod_bigbluebuttonbn', 'presentation', 0,
957
        'itemid, filepath, filename', false);
958
    if (count($files) == 0) {
959
        return array('url' => null, 'name' => null, 'icon' => null, 'mimetype_description' => null);
960
    }
961
    $file = reset($files);
962
    unset($files);
963
    $pnoncevalue = null;
964
    if (!is_null($id)) {
965
        // Create the nonce component for granting a temporary public access.
966
        $cache = cache::make_from_params(cache_store::MODE_APPLICATION, 'mod_bigbluebuttonbn',
967
            'presentation_cache');
968
        $pnoncekey = sha1($id);
969
        /* The item id was adapted for granting public access to the presentation once in order
970
         * to allow BigBlueButton to gather the file. */
971
        $pnoncevalue = bigbluebuttonbn_generate_nonce();
972
        $cache->set($pnoncekey, array('value' => $pnoncevalue, 'counter' => 0));
973
    }
974
    $url = moodle_url::make_pluginfile_url($file->get_contextid(), $file->get_component(),
975
        $file->get_filearea(), $pnoncevalue, $file->get_filepath(), $file->get_filename());
976
    return array('name' => $file->get_filename(), 'icon' => file_file_icon($file, 24),
977
            'url' => $url->out(false), 'mimetype_description' => get_mimetype_description($file));
978
}
979
980
/**
981
 * Helper generates a nonce used for the preuploaded presentation callback url.
982
 *
983
 * @return string
984
 */
985
function bigbluebuttonbn_generate_nonce() {
986
    $mt = microtime();
987
    $rand = mt_rand();
988
    return md5($mt.$rand);
989
}
990
991
/**
992
 * Helper generates a random password.
993
 *
994
 * @param integer $length
995
 * @param string $unique
996
 *
997
 * @return string
998
 */
999
function bigbluebuttonbn_random_password($length = 8, $unique = "") {
1000
    $chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*()_-=+;:,.?';
1001
    do {
1002
        $password = substr(str_shuffle($chars), 0, $length);
1003
    } while ($unique == $password);
1004
    return $password;
1005
}
1006
1007
/**
1008
 * Helper returns an array with all possible bigbluebuttonbn events.
1009
 *
1010
 * @return array
1011
 */
1012
function bigbluebuttonbn_events() {
1013
    return array(
1014
        (string) BIGBLUEBUTTON_EVENT_ACTIVITY_VIEWED,
1015
        (string) BIGBLUEBUTTON_EVENT_ACTIVITY_MANAGEMENT_VIEWED,
1016
        (string) BIGBLUEBUTTON_EVENT_LIVE_SESSION,
1017
        (string) BIGBLUEBUTTON_EVENT_MEETING_CREATED,
1018
        (string) BIGBLUEBUTTON_EVENT_MEETING_ENDED,
1019
        (string) BIGBLUEBUTTON_EVENT_MEETING_JOINED,
1020
        (string) BIGBLUEBUTTON_EVENT_MEETING_LEFT,
1021
        (string) BIGBLUEBUTTON_EVENT_RECORDING_DELETED,
1022
        (string) BIGBLUEBUTTON_EVENT_RECORDING_IMPORTED,
1023
        (string) BIGBLUEBUTTON_EVENT_RECORDING_PROTECTED,
1024
        (string) BIGBLUEBUTTON_EVENT_RECORDING_PUBLISHED,
1025
        (string) BIGBLUEBUTTON_EVENT_RECORDING_UNPROTECTED,
1026
        (string) BIGBLUEBUTTON_EVENT_RECORDING_UNPUBLISHED,
1027
        (string) BIGBLUEBUTTON_EVENT_RECORDING_EDITED,
1028
        (string) BIGBLUEBUTTON_EVENT_RECORDING_VIEWED
1029
    );
1030
}
1031
1032
/**
1033
 * Helper returns an array with the actions and their corresponding bigbluebuttonbn events.
1034
 *
1035
 * @return array
1036
 */
1037
function bigbluebuttonbn_events_action() {
1038
    return array(
1039
        'view' => (string) BIGBLUEBUTTON_EVENT_ACTIVITY_VIEWED,
1040
        'view_management' => (string) BIGBLUEBUTTON_EVENT_ACTIVITY_MANAGEMENT_VIEWED,
1041
        'live_action' => (string) BIGBLUEBUTTON_EVENT_LIVE_SESSION,
1042
        'meeting_create' => (string) BIGBLUEBUTTON_EVENT_MEETING_CREATED,
1043
        'meeting_end' => (string) BIGBLUEBUTTON_EVENT_MEETING_ENDED,
1044
        'meeting_join' => (string) BIGBLUEBUTTON_EVENT_MEETING_JOINED,
1045
        'meeting_left' => (string) BIGBLUEBUTTON_EVENT_MEETING_LEFT,
1046
        'recording_delete' => (string) BIGBLUEBUTTON_EVENT_RECORDING_DELETED,
1047
        'recording_import' => (string) BIGBLUEBUTTON_EVENT_RECORDING_IMPORTED,
1048
        'recording_protect' => (string) BIGBLUEBUTTON_EVENT_RECORDING_PROTECTED,
1049
        'recording_publish' => (string) BIGBLUEBUTTON_EVENT_RECORDING_PUBLISHED,
1050
        'recording_unprotect' => (string) BIGBLUEBUTTON_EVENT_RECORDING_UNPROTECTED,
1051
        'recording_unpublish' => (string) BIGBLUEBUTTON_EVENT_RECORDING_UNPUBLISHED,
1052
        'recording_edit' => (string) BIGBLUEBUTTON_EVENT_RECORDING_EDITED,
1053
        'recording_play' => (string) BIGBLUEBUTTON_EVENT_RECORDING_VIEWED
1054
    );
1055
}
1056
1057
/**
1058
 * Helper register a bigbluebuttonbn event.
1059
 *
1060
 * @param string $eventtype
1061
 * @param object $bigbluebuttonbn
1062
 * @param object $cm
1063
 * @param array $options
1064
 *
1065
 * @return void
1066
 */
1067
function bigbluebuttonbn_event_log($eventtype, $bigbluebuttonbn, $cm, $options = []) {
1068
    $events = bigbluebuttonbn_events();
1069
    if (!in_array($eventtype, $events)) {
1070
        // No log will be created.
1071
        return;
1072
    }
1073
    $context = context_module::instance($cm->id);
1074
    $eventproperties = array('context' => $context, 'objectid' => $bigbluebuttonbn->id);
1075
    if (array_key_exists('timecreated', $options)) {
1076
        $eventproperties['timecreated'] = $options['timecreated'];
1077
    }
1078
    if (array_key_exists('userid', $options)) {
1079
        $eventproperties['userid'] = $options['userid'];
1080
    }
1081
    if (array_key_exists('other', $options)) {
1082
        $eventproperties['other'] = $options['other'];
1083
    }
1084
    $event = call_user_func_array('\mod_bigbluebuttonbn\event\bigbluebuttonbn_'.$eventtype.'::create',
1085
      array($eventproperties));
1086
    $event->trigger();
1087
}
1088
1089
/**
1090
 * Updates the meeting info cached object when a participant has joined.
1091
 *
1092
 * @param string $meetingid
1093
 * @param bool $ismoderator
1094
 *
1095
 * @return void
1096
 */
1097
function bigbluebuttonbn_participant_joined($meetingid, $ismoderator) {
1098
    $cache = cache::make_from_params(cache_store::MODE_APPLICATION, 'mod_bigbluebuttonbn', 'meetings_cache');
1099
    $result = $cache->get($meetingid);
1100
    $meetinginfo = json_decode($result['meeting_info']);
1101
    $meetinginfo->participantCount += 1;
1102
    if ($ismoderator) {
1103
        $meetinginfo->moderatorCount += 1;
1104
    }
1105
    $cache->set($meetingid, array('creation_time' => $result['creation_time'],
1106
        'meeting_info' => json_encode($meetinginfo)));
1107
}
1108
1109
/**
1110
 * Gets a meeting info object cached or fetched from the live session.
1111
 *
1112
 * @param string $meetingid
1113
 * @param boolean $updatecache
1114
 *
1115
 * @return array
1116
 */
1117
function bigbluebuttonbn_get_meeting_info($meetingid, $updatecache = false) {
1118
    $cachettl = (int)\mod_bigbluebuttonbn\locallib\config::get('waitformoderator_cache_ttl');
1119
    $cache = cache::make_from_params(cache_store::MODE_APPLICATION, 'mod_bigbluebuttonbn', 'meetings_cache');
1120
    $result = $cache->get($meetingid);
1121
    $now = time();
1122
    if (!$updatecache && isset($result) && $now < ($result['creation_time'] + $cachettl)) {
1123
        // Use the value in the cache.
1124
        return (array) json_decode($result['meeting_info']);
1125
    }
1126
    // Ping again and refresh the cache.
1127
    $meetinginfo = (array) bigbluebuttonbn_wrap_xml_load_file(
1128
        \mod_bigbluebuttonbn\locallib\bigbluebutton::action_url('getMeetingInfo', ['meetingID' => $meetingid])
1129
      );
1130
    $cache->set($meetingid, array('creation_time' => time(), 'meeting_info' => json_encode($meetinginfo)));
1131
    return $meetinginfo;
1132
}
1133
1134
/**
1135
 * Perform isMeetingRunning on BBB.
1136
 *
1137
 * @param string $meetingid
1138
 * @param boolean $updatecache
1139
 *
1140
 * @return boolean
1141
 */
1142
function bigbluebuttonbn_is_meeting_running($meetingid, $updatecache = false) {
1143
    /* As a workaround to isMeetingRunning that always return SUCCESS but only returns true
1144
     * when at least one user is in the session, we use getMeetingInfo instead.
1145
     */
1146
    $meetinginfo = bigbluebuttonbn_get_meeting_info($meetingid, $updatecache);
1147
    return ($meetinginfo['returncode'] === 'SUCCESS');
1148
}
1149
1150
/**
1151
 * Publish an imported recording.
1152
 *
1153
 * @param string $id
1154
 * @param boolean $publish
1155
 *
1156
 * @return boolean
1157
 */
1158 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...
1159
    global $DB;
1160
    // Locate the record to be updated.
1161
    $record = $DB->get_record('bigbluebuttonbn_logs', array('id' => $id));
1162
    $meta = json_decode($record->meta, true);
1163
    // Prepare data for the update.
1164
    $meta['recording']['published'] = ($publish) ? 'true' : 'false';
1165
    $record->meta = json_encode($meta);
1166
    // Proceed with the update.
1167
    $DB->update_record('bigbluebuttonbn_logs', $record);
1168
    return true;
1169
}
1170
1171
/**
1172
 * Delete an imported recording.
1173
 *
1174
 * @param string $id
1175
 *
1176
 * @return boolean
1177
 */
1178
function bigbluebuttonbn_delete_recording_imported($id) {
1179
    global $DB;
1180
    // Execute delete.
1181
    $DB->delete_records('bigbluebuttonbn_logs', array('id' => $id));
1182
    return true;
1183
}
1184
1185
/**
1186
 * Update an imported recording.
1187
 *
1188
 * @param string $id
1189
 * @param array $params ['key'=>param_key, 'value']
1190
 *
1191
 * @return boolean
1192
 */
1193
function bigbluebuttonbn_update_recording_imported($id, $params) {
1194
    global $DB;
1195
    // Locate the record to be updated.
1196
    $record = $DB->get_record('bigbluebuttonbn_logs', array('id' => $id));
1197
    $meta = json_decode($record->meta, true);
1198
    // Prepare data for the update.
1199
    $meta['recording'] = $params + $meta['recording'];
1200
    $record->meta = json_encode($meta);
1201
    // Proceed with the update.
1202
    if (!$DB->update_record('bigbluebuttonbn_logs', $record)) {
1203
        return false;
1204
    }
1205
    return true;
1206
}
1207
1208
/**
1209
 * Protect/Unprotect an imported recording.
1210
 *
1211
 * @param string $id
1212
 * @param boolean $protect
1213
 *
1214
 * @return boolean
1215
 */
1216 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...
1217
    global $DB;
1218
    // Locate the record to be updated.
1219
    $record = $DB->get_record('bigbluebuttonbn_logs', array('id' => $id));
1220
    $meta = json_decode($record->meta, true);
1221
    // Prepare data for the update.
1222
    $meta['recording']['protected'] = ($protect) ? 'true' : 'false';
1223
    $record->meta = json_encode($meta);
1224
    // Proceed with the update.
1225
    $DB->update_record('bigbluebuttonbn_logs', $record);
1226
    return true;
1227
}
1228
1229
/**
1230
 * Sets a custom config.xml file for being used on create.
1231
 *
1232
 * @param string $meetingid
1233
 * @param string $configxml
1234
 *
1235
 * @return object
1236
 */
1237
function bigbluebuttonbn_set_config_xml($meetingid, $configxml) {
1238
    $urldefaultconfig = \mod_bigbluebuttonbn\locallib\config::get('server_url').'api/setConfigXML?';
1239
    $configxmlparams = bigbluebuttonbn_set_config_xml_params($meetingid, $configxml);
1240
    $xml = bigbluebuttonbn_wrap_xml_load_file($urldefaultconfig, 'POST',
1241
        $configxmlparams, 'application/x-www-form-urlencoded');
1242
    return $xml;
1243
}
1244
1245
/**
1246
 * Sets qs used with a custom config.xml file request.
1247
 *
1248
 * @param string $meetingid
1249
 * @param string $configxml
1250
 *
1251
 * @return string
1252
 */
1253
function bigbluebuttonbn_set_config_xml_params($meetingid, $configxml) {
1254
    $params = 'configXML='.urlencode($configxml).'&meetingID='.urlencode($meetingid);
1255
    $configxmlparams = $params.'&checksum='.sha1('setConfigXML'.$params.\mod_bigbluebuttonbn\locallib\config::get('shared_secret'));
1256
    return $configxmlparams;
1257
}
1258
1259
/**
1260
 * Sets a custom config.xml file for being used on create.
1261
 *
1262
 * @param string $meetingid
1263
 * @param string $configxml
1264
 *
1265
 * @return array
1266
 */
1267
function bigbluebuttonbn_set_config_xml_array($meetingid, $configxml) {
1268
    $configxml = bigbluebuttonbn_setConfigXML($meetingid, $configxml);
1269
    $configxmlarray = (array) $configxml;
1270
    if ($configxmlarray['returncode'] != 'SUCCESS') {
1271
        debugging('BigBlueButton was not able to set the custom config.xml file', DEBUG_DEVELOPER);
1272
        return '';
1273
    }
1274
    return $configxmlarray['configToken'];
1275
}
1276
1277
/**
1278
 * Helper function builds a row for the data used by the recording table.
1279
 *
1280
 * @param array $bbbsession
1281
 * @param array $recording
1282
 * @param array $tools
1283
 *
1284
 * @return array
1285
 */
1286
function bigbluebuttonbn_get_recording_data_row($bbbsession, $recording, $tools = ['protect', 'publish', 'delete']) {
1287
    if (!bigbluebuttonbn_include_recording_table_row($bbbsession, $recording)) {
1288
        return;
1289
    }
1290
    $rowdata = new stdClass();
1291
    // Set recording_types.
1292
    $rowdata->recording = bigbluebuttonbn_get_recording_data_row_types($recording, $bbbsession);
1293
    // Set activity name.
1294
    $rowdata->activity = bigbluebuttonbn_get_recording_data_row_meta_activity($recording, $bbbsession);
1295
    // Set activity description.
1296
    $rowdata->description = bigbluebuttonbn_get_recording_data_row_meta_description($recording, $bbbsession);
1297
    if (bigbluebuttonbn_get_recording_data_preview_enabled($bbbsession)) {
1298
        // Set recording_preview.
1299
        $rowdata->preview = bigbluebuttonbn_get_recording_data_row_preview($recording);
1300
    }
1301
    // Set date.
1302
    $rowdata->date = bigbluebuttonbn_get_recording_data_row_date($recording);
1303
    // Set formatted date.
1304
    $rowdata->date_formatted = bigbluebuttonbn_get_recording_data_row_date_formatted($rowdata->date);
1305
    // Set formatted duration.
1306
    $rowdata->duration_formatted = $rowdata->duration = bigbluebuttonbn_get_recording_data_row_duration($recording);
1307
    // Set actionbar, if user is allowed to manage recordings.
1308
    if ($bbbsession['managerecordings']) {
1309
        $rowdata->actionbar = bigbluebuttonbn_get_recording_data_row_actionbar($recording, $tools);
1310
    }
1311
    return $rowdata;
1312
}
1313
1314
/**
1315
 * Helper function evaluates if a row for the data used by the recording table is editable.
1316
 *
1317
 * @param array $bbbsession
1318
 *
1319
 * @return boolean
1320
 */
1321
function bigbluebuttonbn_get_recording_data_row_editable($bbbsession) {
1322
    return ($bbbsession['managerecordings'] && ((double)$bbbsession['serverversion'] >= 1.0 || $bbbsession['bnserver']));
1323
}
1324
1325
/**
1326
 * Helper function evaluates if recording preview should be included.
1327
 *
1328
 * @param array $bbbsession
1329
 *
1330
 * @return boolean
1331
 */
1332
function bigbluebuttonbn_get_recording_data_preview_enabled($bbbsession) {
1333
    return ((double)$bbbsession['serverversion'] >= 1.0 && $bbbsession['bigbluebuttonbn']->recordings_preview == '1');
1334
}
1335
1336
/**
1337
 * Helper function converts recording date used in row for the data used by the recording table.
1338
 *
1339
 * @param array $recording
1340
 *
1341
 * @return integer
1342
 */
1343
function bigbluebuttonbn_get_recording_data_row_date($recording) {
1344
    if (!isset($recording['startTime'])) {
1345
        return 0;
1346
    }
1347
    return floatval($recording['startTime']);
1348
}
1349
1350
/**
1351
 * Helper function format recording date used in row for the data used by the recording table.
1352
 *
1353
 * @param integer $starttime
1354
 *
1355
 * @return string
1356
 */
1357
function bigbluebuttonbn_get_recording_data_row_date_formatted($starttime) {
1358
    global $USER;
1359
    $starttime = $starttime - ($starttime % 1000);
1360
    // Set formatted date.
1361
    $dateformat = get_string('strftimerecentfull', 'langconfig').' %Z';
1362
    return userdate($starttime / 1000, $dateformat, usertimezone($USER->timezone));
1363
}
1364
1365
/**
1366
 * Helper function converts recording duration used in row for the data used by the recording table.
1367
 *
1368
 * @param array $recording
1369
 *
1370
 * @return integer
1371
 */
1372
function bigbluebuttonbn_get_recording_data_row_duration($recording) {
1373
    foreach (array_values($recording['playbacks']) as $playback) {
1374
        // Ignore restricted playbacks.
1375
        if (array_key_exists('restricted', $playback) && strtolower($playback['restricted']) == 'true') {
1376
            continue;
1377
        }
1378
        // Take the lenght form the fist playback with an actual value.
1379
        if (!empty($playback['length'])) {
1380
            return intval($playback['length']);
1381
        }
1382
    }
1383
    return 0;
1384
}
1385
1386
/**
1387
 * Helper function builds recording actionbar used in row for the data used by the recording table.
1388
 *
1389
 * @param array $recording
1390
 * @param array $tools
1391
 *
1392
 * @return string
1393
 */
1394
function bigbluebuttonbn_get_recording_data_row_actionbar($recording, $tools) {
1395
    $actionbar = '';
1396
    foreach ($tools as $tool) {
1397
        $buttonpayload = bigbluebuttonbn_get_recording_data_row_actionbar_payload($recording, $tool);
1398
        if ($tool == 'protect') {
1399
            if (isset($recording['imported'])) {
1400
                $buttonpayload['disabled'] = 'disabled';
1401
            }
1402
            if (!isset($recording['protected'])) {
1403
                $buttonpayload['disabled'] = 'invisible';
1404
            }
1405
        }
1406
        $actionbar .= bigbluebuttonbn_actionbar_render_button($recording, $buttonpayload);
1407
    }
1408
    $head = html_writer::start_tag('div', array(
1409
        'id' => 'recording-actionbar-' . $recording['recordID'],
1410
        'data-recordingid' => $recording['recordID'],
1411
        'data-meetingid' => $recording['meetingID']));
1412
    $tail = html_writer::end_tag('div');
1413
    return $head . $actionbar . $tail;
1414
}
1415
1416
/**
1417
 * Helper function returns the corresponding payload for an actionbar button used in row
1418
 * for the data used by the recording table.
1419
 *
1420
 * @param array $recording
1421
 * @param array $tool
1422
 *
1423
 * @return array
1424
 */
1425
function bigbluebuttonbn_get_recording_data_row_actionbar_payload($recording, $tool) {
1426
    if ($tool == 'protect') {
1427
        $protected = 'false';
1428
        if (isset($recording['protected'])) {
1429
            $protected = $recording['protected'];
1430
        }
1431
        return bigbluebuttonbn_get_recording_data_row_action_protect($protected);
1432
    }
1433
    if ($tool == 'publish') {
1434
        return bigbluebuttonbn_get_recording_data_row_action_publish($recording['published']);
1435
    }
1436
    return array('action' => $tool, 'tag' => $tool);
1437
}
1438
1439
/**
1440
 * Helper function returns the payload for protect action button used in row
1441
 * for the data used by the recording table.
1442
 *
1443
 * @param string $protected
1444
 *
1445
 * @return array
1446
 */
1447
function bigbluebuttonbn_get_recording_data_row_action_protect($protected) {
1448
    if ($protected == 'true') {
1449
        return array('action' => 'unprotect', 'tag' => 'lock');
1450
    }
1451
    return array('action' => 'protect', 'tag' => 'unlock');
1452
}
1453
1454
/**
1455
 * Helper function returns the payload for publish action button used in row
1456
 * for the data used by the recording table.
1457
 *
1458
 * @param string $published
1459
 *
1460
 * @return array
1461
 */
1462
function bigbluebuttonbn_get_recording_data_row_action_publish($published) {
1463
    if ($published == 'true') {
1464
        return array('action' => 'unpublish', 'tag' => 'hide');
1465
    }
1466
    return array('action' => 'publish', 'tag' => 'show');
1467
}
1468
1469
/**
1470
 * Helper function builds recording preview used in row for the data used by the recording table.
1471
 *
1472
 * @param array $recording
1473
 *
1474
 * @return string
1475
 */
1476
function bigbluebuttonbn_get_recording_data_row_preview($recording) {
1477
    $options = array('id' => 'preview-'.$recording['recordID']);
1478
    if ($recording['published'] === 'false') {
1479
        $options['hidden'] = 'hidden';
1480
    }
1481
    $recordingpreview = html_writer::start_tag('div', $options);
1482
    foreach ($recording['playbacks'] as $playback) {
1483
        if (isset($playback['preview'])) {
1484
            $recordingpreview .= bigbluebuttonbn_get_recording_data_row_preview_images($playback);
1485
            break;
1486
        }
1487
    }
1488
    $recordingpreview .= html_writer::end_tag('div');
1489
    return $recordingpreview;
1490
}
1491
1492
/**
1493
 * Helper function builds element with actual images used in recording preview row based on a selected playback.
1494
 *
1495
 * @param array $playback
1496
 *
1497
 * @return string
1498
 */
1499
function bigbluebuttonbn_get_recording_data_row_preview_images($playback) {
1500
    $recordingpreview  = html_writer::start_tag('div', array('class' => 'container-fluid'));
1501
    $recordingpreview .= html_writer::start_tag('div', array('class' => 'row'));
1502
    foreach ($playback['preview'] as $image) {
1503
        if (!bigbluebuttonbn_is_valid_resource(trim($image['url']))) {
1504
            return '';
1505
        }
1506
        $recordingpreview .= html_writer::start_tag('div', array('class' => ''));
1507
        $recordingpreview .= html_writer::empty_tag('img',
1508
            array('src' => trim($image['url']) . '?' . time(), 'class' => 'recording-thumbnail pull-left'));
1509
        $recordingpreview .= html_writer::end_tag('div');
1510
    }
1511
    $recordingpreview .= html_writer::end_tag('div');
1512
    $recordingpreview .= html_writer::start_tag('div', array('class' => 'row'));
1513
    $recordingpreview .= html_writer::tag('div', get_string('view_recording_preview_help', 'bigbluebuttonbn'),
1514
        array('class' => 'text-center text-muted small'));
1515
    $recordingpreview .= html_writer::end_tag('div');
1516
    $recordingpreview .= html_writer::end_tag('div');
1517
    return $recordingpreview;
1518
}
1519
1520
/**
1521
 * Helper function renders recording types to be used in row for the data used by the recording table.
1522
 *
1523
 * @param array $recording
1524
 * @param array $bbbsession
1525
 *
1526
 * @return string
1527
 */
1528
function bigbluebuttonbn_get_recording_data_row_types($recording, $bbbsession) {
1529
    $dataimported = 'false';
1530
    $title = '';
1531
    if (isset($recording['imported'])) {
1532
        $dataimported = 'true';
1533
        $title = get_string('view_recording_link_warning', 'bigbluebuttonbn');
1534
    }
1535
    $visibility = '';
1536
    if ($recording['published'] === 'false') {
1537
        $visibility = 'hidden ';
1538
    }
1539
    $id = 'playbacks-'.$recording['recordID'];
1540
    $recordingtypes = html_writer::start_tag('div', array('id' => $id, 'data-imported' => $dataimported,
1541
          'data-meetingid' => $recording['meetingID'], 'data-recordingid' => $recording['recordID'],
1542
          'title' => $title, $visibility => $visibility));
1543
    foreach ($recording['playbacks'] as $playback) {
1544
        $recordingtypes .= bigbluebuttonbn_get_recording_data_row_type($recording, $bbbsession, $playback);
1545
    }
1546
    $recordingtypes .= html_writer::end_tag('div');
1547
    return $recordingtypes;
1548
}
1549
1550
/**
1551
 * Helper function renders the link used for recording type in row for the data used by the recording table.
1552
 *
1553
 * @param array $recording
1554
 * @param array $bbbsession
1555
 * @param array $playback
1556
 *
1557
 * @return string
1558
 */
1559
function bigbluebuttonbn_get_recording_data_row_type($recording, $bbbsession, $playback) {
1560
    global $CFG, $OUTPUT;
1561
    if (!bigbluebuttonbn_include_recording_data_row_type($recording, $bbbsession, $playback)) {
1562
        return '';
1563
    }
1564
    $text = get_string('view_recording_format_'.$playback['type'], 'bigbluebuttonbn');
1565
    $href = $CFG->wwwroot . '/mod/bigbluebuttonbn/bbb_view.php?action=play&bn=' . $bbbsession['bigbluebuttonbn']->id .
1566
      '&mid='.$recording['meetingID'] . '&rid=' . $recording['recordID'] . '&rtype=' . $playback['type'];
1567
    if (!isset($recording['imported']) || !isset($recording['protected']) || $recording['protected'] === 'false') {
1568
        $href .= '&href='.urlencode(trim($playback['url']));
1569
    }
1570
    $linkattributes = array(
1571
        'id' => 'recording-play-' . $playback['type'] . '-' . $recording['recordID'],
1572
        'class' => 'btn btn-sm btn-default',
1573
        'onclick' => 'M.mod_bigbluebuttonbn.recordings.recordingPlay(this);',
1574
        'data-action' => 'play',
1575
        'data-target' => $playback['type'],
1576
        'data-href' => $href,
1577
      );
1578
    if (!bigbluebuttonbn_is_bn_server() && !bigbluebuttonbn_is_valid_resource(trim($playback['url']))) {
1579
        $linkattributes['class'] = 'btn btn-sm btn-warning';
1580
        $linkattributes['title'] = get_string('view_recording_format_errror_unreachable', 'bigbluebuttonbn');
1581
        unset($linkattributes['data-href']);
1582
    }
1583
    return $OUTPUT->action_link('#', $text, null, $linkattributes) . '&#32;';
1584
}
1585
1586
/**
1587
 * Helper function validates a remote resource.
1588
 *
1589
 * @param string $url
1590
 *
1591
 * @return boolean
1592
 */
1593
function bigbluebuttonbn_is_valid_resource($url) {
1594
    $urlhost = parse_url($url, PHP_URL_HOST);
1595
    $serverurlhost = parse_url(\mod_bigbluebuttonbn\locallib\config::get('server_url'), PHP_URL_HOST);
1596
    // Skip validation when the recording URL host is the same as the configured BBB server.
1597
    if ($urlhost == $serverurlhost) {
1598
        return true;
1599
    }
1600
    // Skip validation when the recording URL was already validated.
1601
    $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...
1602
    if (array_key_exists($urlhost, $validatedurls)) {
1603
        return $validatedurls[$urlhost];
1604
    }
1605
    // Validate the recording URL.
1606
    $validatedurls[$urlhost] = true;
1607
    $curlinfo = bigbluebuttonbn_wrap_xml_load_file_curl_request($url, 'HEAD');
1608
    if (!isset($curlinfo['http_code']) || $curlinfo['http_code'] != 200) {
1609
        $error = "Resources hosted by " . $urlhost . " are unreachable. Server responded with code " . $curlinfo['http_code'];
1610
        debugging($error, DEBUG_DEVELOPER);
1611
        $validatedurls[$urlhost] = false;
1612
    }
1613
    bigbluebuttonbn_cache_set('recordings_cache', 'validated_urls', $validatedurls);
1614
    return $validatedurls[$urlhost];
1615
}
1616
1617
/**
1618
 * Helper function renders the name for recording used in row for the data used by the recording table.
1619
 *
1620
 * @param array $recording
1621
 * @param array $bbbsession
1622
 *
1623
 * @return string
1624
 */
1625
function bigbluebuttonbn_get_recording_data_row_meta_activity($recording, $bbbsession) {
1626
    $payload = array();
1627 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...
1628
        $payload = array('recordingid' => $recording['recordID'], 'meetingid' => $recording['meetingID'],
1629
            'action' => 'edit', 'tag' => 'edit',
1630
            'target' => 'name');
1631
    }
1632
    $oldsource = 'meta_contextactivity';
1633
    if (isset($recording[$oldsource])) {
1634
        $metaname = trim($recording[$oldsource]);
1635
        return bigbluebuttonbn_get_recording_data_row_text($recording, $metaname, $oldsource, $payload);
1636
    }
1637
    $newsource = 'meta_bbb-recording-name';
1638 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...
1639
        $metaname = trim($recording[$newsource]);
1640
        return bigbluebuttonbn_get_recording_data_row_text($recording, $metaname, $newsource, $payload);
1641
    }
1642
    $metaname = trim($recording['meetingName']);
1643
    return bigbluebuttonbn_get_recording_data_row_text($recording, $metaname, $newsource, $payload);
1644
}
1645
1646
/**
1647
 * Helper function renders the description for recording used in row for the data used by the recording table.
1648
 *
1649
 * @param array $recording
1650
 * @param array $bbbsession
1651
 *
1652
 * @return string
1653
 */
1654
function bigbluebuttonbn_get_recording_data_row_meta_description($recording, $bbbsession) {
1655
    $payload = array();
1656 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...
1657
        $payload = array('recordingid' => $recording['recordID'], 'meetingid' => $recording['meetingID'],
1658
            'action' => 'edit', 'tag' => 'edit',
1659
            'target' => 'description');
1660
    }
1661
    $oldsource = 'meta_contextactivitydescription';
1662 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...
1663
        $metadescription = trim($recording[$oldsource]);
1664
        return bigbluebuttonbn_get_recording_data_row_text($recording, $metadescription, $oldsource, $payload);
1665
    }
1666
    $newsource = 'meta_bbb-recording-description';
1667 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...
1668
        $metadescription = trim($recording[$newsource]);
1669
        return bigbluebuttonbn_get_recording_data_row_text($recording, $metadescription, $newsource, $payload);
1670
    }
1671
    return bigbluebuttonbn_get_recording_data_row_text($recording, '', $newsource, $payload);
1672
}
1673
1674
/**
1675
 * Helper function renders text element for recording used in row for the data used by the recording table.
1676
 *
1677
 * @param array $recording
1678
 * @param string $text
1679
 * @param string $source
1680
 * @param array $data
1681
 *
1682
 * @return string
1683
 */
1684
function bigbluebuttonbn_get_recording_data_row_text($recording, $text, $source, $data) {
1685
    $htmltext = '<span>' . htmlentities($text) . '</span>';
1686
    if (empty($data)) {
1687
        return $htmltext;
1688
    }
1689
    $target = $data['action'] . '-' . $data['target'];
1690
    $id = 'recording-' . $target . '-' . $data['recordingid'];
1691
    $attributes = array('id' => $id, 'class' => 'quickeditlink col-md-20',
1692
        'data-recordingid' => $data['recordingid'], 'data-meetingid' => $data['meetingid'],
1693
        'data-target' => $data['target'], 'data-source' => $source);
1694
    $head = html_writer::start_tag('div', $attributes);
1695
    $tail = html_writer::end_tag('div');
1696
    $payload = array('action' => $data['action'], 'tag' => $data['tag'], 'target' => $data['target']);
1697
    $htmllink = bigbluebuttonbn_actionbar_render_button($recording, $payload);
1698
    return $head . $htmltext . $htmllink . $tail;
1699
}
1700
1701
/**
1702
 * Helper function render a button for the recording action bar
1703
 *
1704
 * @param array $recording
1705
 * @param array $data
1706
 *
1707
 * @return string
1708
 */
1709
function bigbluebuttonbn_actionbar_render_button($recording, $data) {
1710
    global $OUTPUT;
1711
    if (empty($data)) {
1712
        return '';
1713
    }
1714
    $target = $data['action'];
1715
    if (isset($data['target'])) {
1716
        $target .= '-' . $data['target'];
1717
    }
1718
    $id = 'recording-' . $target . '-' . $recording['recordID'];
1719
    $onclick = 'M.mod_bigbluebuttonbn.recordings.recording' . ucfirst($data['action']) . '(this);';
1720
    if ((boolean)\mod_bigbluebuttonbn\locallib\config::get('recording_icons_enabled')) {
1721
        // With icon for $manageaction.
1722
        $iconattributes = array('id' => $id, 'class' => 'iconsmall');
1723
        $linkattributes = array(
1724
            'id' => $id,
1725
            'onclick' => $onclick,
1726
            'data-action' => $data['action']
1727
          );
1728
        if (!isset($recording['imported'])) {
1729
            $linkattributes['data-links'] = bigbluebuttonbn_count_recording_imported_instances(
1730
              $recording['recordID']);
1731
        }
1732
        if (isset($data['disabled'])) {
1733
            $iconattributes['class'] .= ' fa-' . $data['disabled'];
1734
            $linkattributes['class'] = 'disabled';
1735
            unset($linkattributes['onclick']);
1736
        }
1737
        $icon = new pix_icon('i/'.$data['tag'],
1738
            get_string('view_recording_list_actionbar_' . $data['action'], 'bigbluebuttonbn'),
1739
            'moodle', $iconattributes);
1740
        return $OUTPUT->action_icon('#', $icon, null, $linkattributes, false);
1741
    }
1742
    // With text for $manageaction.
1743
    $linkattributes = array('title' => get_string($data['tag']), 'class' => 'btn btn-xs btn-danger',
1744
        'onclick' => $onclick);
1745
    return $OUTPUT->action_link('#', get_string($data['action']), null, $linkattributes);
1746
}
1747
1748
/**
1749
 * Helper function builds the data used for headers by the recording table.
1750
 *
1751
 * @param array $bbbsession
1752
 *
1753
 * @return array
1754
 */
1755
function bigbluebuttonbn_get_recording_columns($bbbsession) {
1756
    $columns = array();
1757
    // Initialize table headers.
1758
    $columns[] = array('key' => 'recording', 'label' => get_string('view_recording_recording', 'bigbluebuttonbn'),
1759
        'width' => '125px', 'allowHTML' => true);
1760
    $columns[] = array('key' => 'activity', 'label' => get_string('view_recording_activity', 'bigbluebuttonbn'),
1761
        'sortable' => true, 'width' => '175px', 'allowHTML' => true);
1762
    $columns[] = array('key' => 'description', 'label' => get_string('view_recording_description', 'bigbluebuttonbn'),
1763
        'sortable' => true, 'width' => '250px', 'allowHTML' => true);
1764
    if (bigbluebuttonbn_get_recording_data_preview_enabled($bbbsession)) {
1765
        $columns[] = array('key' => 'preview', 'label' => get_string('view_recording_preview', 'bigbluebuttonbn'),
1766
            'width' => '250px', 'allowHTML' => true);
1767
    }
1768
    $columns[] = array('key' => 'date', 'label' => get_string('view_recording_date', 'bigbluebuttonbn'),
1769
        'sortable' => true, 'width' => '225px', 'allowHTML' => true);
1770
    $columns[] = array('key' => 'duration', 'label' => get_string('view_recording_duration', 'bigbluebuttonbn'),
1771
        'width' => '50px');
1772
    if ($bbbsession['managerecordings']) {
1773
        $columns[] = array('key' => 'actionbar', 'label' => get_string('view_recording_actionbar', 'bigbluebuttonbn'),
1774
            'width' => '120px', 'allowHTML' => true);
1775
    }
1776
    return $columns;
1777
}
1778
1779
/**
1780
 * Helper function builds the data used by the recording table.
1781
 *
1782
 * @param array $bbbsession
1783
 * @param array $recordings
1784
 * @param array $tools
1785
 *
1786
 * @return array
1787
 */
1788
function bigbluebuttonbn_get_recording_data($bbbsession, $recordings, $tools = ['protect', 'publish', 'delete']) {
1789
    $tabledata = array();
1790
    // Build table content.
1791
    if (isset($recordings) && !array_key_exists('messageKey', $recordings)) {
1792
        // There are recordings for this meeting.
1793
        foreach ($recordings as $recording) {
1794
            $rowdata = bigbluebuttonbn_get_recording_data_row($bbbsession, $recording, $tools);
1795
            if (!empty($rowdata)) {
1796
                array_push($tabledata, $rowdata);
1797
            }
1798
        }
1799
    }
1800
    return $tabledata;
1801
}
1802
1803
/**
1804
 * Helper function builds the recording table.
1805
 *
1806
 * @param array $bbbsession
1807
 * @param array $recordings
1808
 * @param array $tools
1809
 *
1810
 * @return object
1811
 */
1812
function bigbluebuttonbn_get_recording_table($bbbsession, $recordings, $tools = ['protect', 'publish', 'delete']) {
1813
    // Declare the table.
1814
    $table = new html_table();
1815
    $table->data = array();
1816
    // Initialize table headers.
1817
    $table->head[] = get_string('view_recording_playback', 'bigbluebuttonbn');
1818
    $table->head[] = get_string('view_recording_recording', 'bigbluebuttonbn');
1819
    $table->head[] = get_string('view_recording_description', 'bigbluebuttonbn');
1820
    if (bigbluebuttonbn_get_recording_data_preview_enabled($bbbsession)) {
1821
        $table->head[] = get_string('view_recording_preview', 'bigbluebuttonbn');
1822
    }
1823
    $table->head[] = get_string('view_recording_date', 'bigbluebuttonbn');
1824
    $table->head[] = get_string('view_recording_duration', 'bigbluebuttonbn');
1825
    $table->align = array('left', 'left', 'left', 'left', 'left', 'center');
1826
    $table->size = array('', '', '', '', '', '');
1827
    if ($bbbsession['managerecordings']) {
1828
        $table->head[] = get_string('view_recording_actionbar', 'bigbluebuttonbn');
1829
        $table->align[] = 'left';
1830
        $table->size[] = (count($tools) * 40) . 'px';
1831
    }
1832
    // Build table content.
1833
    foreach ($recordings as $recording) {
1834
        $rowdata = bigbluebuttonbn_get_recording_data_row($bbbsession, $recording, $tools);
1835
        if (!empty($rowdata)) {
1836
            $row = bigbluebuttonbn_get_recording_table_row($bbbsession, $recording, $rowdata);
1837
            array_push($table->data, $row);
1838
        }
1839
    }
1840
    return $table;
1841
}
1842
1843
/**
1844
 * Helper function builds the recording table row and insert into table.
1845
 *
1846
 * @param array $bbbsession
1847
 * @param array $recording
1848
 * @param object $rowdata
1849
 *
1850
 * @return object
1851
 */
1852
function bigbluebuttonbn_get_recording_table_row($bbbsession, $recording, $rowdata) {
1853
    $row = new html_table_row();
1854
    $row->id = 'recording-tr-'.$recording['recordID'];
1855
    $row->attributes['data-imported'] = 'false';
1856
    $texthead = '';
1857
    $texttail = '';
1858
    if (isset($recording['imported'])) {
1859
        $row->attributes['title'] = get_string('view_recording_link_warning', 'bigbluebuttonbn');
1860
        $row->attributes['data-imported'] = 'true';
1861
        $texthead = '<em>';
1862
        $texttail = '</em>';
1863
    }
1864
    $rowdata->date_formatted = str_replace(' ', '&nbsp;', $rowdata->date_formatted);
1865
    $row->cells = array();
1866
    $row->cells[] = $texthead . $rowdata->recording . $texttail;
1867
    $row->cells[] = $texthead . $rowdata->activity . $texttail;
1868
    $row->cells[] = $texthead . $rowdata->description . $texttail;
1869
    if (bigbluebuttonbn_get_recording_data_preview_enabled($bbbsession)) {
1870
        $row->cells[] = $rowdata->preview;
1871
    }
1872
    $row->cells[] = $texthead . $rowdata->date_formatted . $texttail;
1873
    $row->cells[] = $rowdata->duration_formatted;
1874
    if ($bbbsession['managerecordings']) {
1875
        $row->cells[] = $rowdata->actionbar;
1876
    }
1877
    return $row;
1878
}
1879
1880
/**
1881
 * Helper function evaluates if recording row should be included in the table.
1882
 *
1883
 * @param array $bbbsession
1884
 * @param array $recording
1885
 *
1886
 * @return boolean
1887
 */
1888
function bigbluebuttonbn_include_recording_table_row($bbbsession, $recording) {
1889
    // Exclude unpublished recordings, only if user has no rights to manage them.
1890
    if ($recording['published'] != 'true' && !$bbbsession['managerecordings']) {
1891
        return false;
1892
    }
1893
    // Imported recordings are always shown as long as they are published.
1894
    if (isset($recording['imported'])) {
1895
        return true;
1896
    }
1897
    // When groups are enabled, exclude those to which the user doesn't have access to.
1898
    if (isset($bbbsession['group']) && $recording['meetingID'] != $bbbsession['meetingid']) {
1899
        return false;
1900
    }
1901
    return true;
1902
}
1903
1904
/**
1905
 * Helper function triggers a send notification when the recording is ready.
1906
 *
1907
 * @param object $bigbluebuttonbn
1908
 *
1909
 * @return void
1910
 */
1911
function bigbluebuttonbn_send_notification_recording_ready($bigbluebuttonbn) {
1912
    $sender = get_admin();
1913
    // Prepare message.
1914
    $messagetext = '<p>'.get_string('email_body_recording_ready_for', 'bigbluebuttonbn').
1915
        ' "' . $bigbluebuttonbn->name . '" '.
1916
        get_string('email_body_recording_ready_is_ready', 'bigbluebuttonbn').'.</p>';
1917
    $context = context_course::instance($bigbluebuttonbn->course);
1918
    \mod_bigbluebuttonbn\locallib\notifier::notification_send($context, $sender, $bigbluebuttonbn, $messagetext);
1919
}
1920
1921
/**
1922
 * Helper evaluates if the bigbluebutton server used belongs to blindsidenetworks domain.
1923
 *
1924
 * @return boolean
1925
 */
1926
function bigbluebuttonbn_is_bn_server() {
1927
    $parsedurl = parse_url(\mod_bigbluebuttonbn\locallib\config::get('server_url'));
1928
    if (!isset($parsedurl['host'])) {
1929
        return false;
1930
    }
1931
    $h = $parsedurl['host'];
1932
    $hends = explode('.', $h);
1933
    $hendslength = count($hends);
1934
    return ($hends[$hendslength - 1] == 'com' && $hends[$hendslength - 2] == 'blindsidenetworks');
1935
}
1936
1937
/**
1938
 * Helper function returns a list of courses a user has access to, wrapped in an array that can be used
1939
 * by a html select.
1940
 *
1941
 * @param array $bbbsession
1942
 *
1943
 * @return array
1944
 */
1945
function bigbluebuttonbn_import_get_courses_for_select(array $bbbsession) {
1946
    if ($bbbsession['administrator']) {
1947
        $courses = get_courses('all', 'c.fullname ASC', 'c.id,c.shortname,c.fullname');
1948
        // It includes the name of the site as a course (category 0), so remove the first one.
1949
        unset($courses['1']);
1950
    } else {
1951
        $courses = enrol_get_users_courses($bbbsession['userID'], false, 'id,shortname,fullname');
1952
    }
1953
    $coursesforselect = [];
1954
    foreach ($courses as $course) {
1955
        $coursesforselect[$course->id] = $course->fullname;
1956
    }
1957
    return $coursesforselect;
1958
}
1959
1960
/**
1961
 * Helper function renders recording table.
1962
 *
1963
 * @param array $bbbsession
1964
 * @param array $recordings
1965
 * @param array $tools
1966
 *
1967
 * @return array
1968
 */
1969
function bigbluebuttonbn_output_recording_table($bbbsession, $recordings, $tools = ['protect', 'publish', 'delete']) {
1970
    if (isset($recordings) && !empty($recordings)) {
1971
        // There are recordings for this meeting.
1972
        $table = bigbluebuttonbn_get_recording_table($bbbsession, $recordings, $tools);
1973
    }
1974
    if (!isset($table) || !isset($table->data)) {
1975
        // Render a table with "No recordings".
1976
        return html_writer::div(get_string('view_message_norecordings', 'bigbluebuttonbn'), '',
1977
            array('id' => 'bigbluebuttonbn_recordings_table'));
1978
    }
1979
    // Render the table.
1980
    return html_writer::div(html_writer::table($table), '', array('id' => 'bigbluebuttonbn_recordings_table'));
1981
}
1982
1983
/**
1984
 * Helper function to convert an html string to plain text.
1985
 *
1986
 * @param string $html
1987
 * @param integer $len
1988
 *
1989
 * @return string
1990
 */
1991
function bigbluebuttonbn_html2text($html, $len = 0) {
1992
    $text = strip_tags($html);
1993
    $text = str_replace('&nbsp;', ' ', $text);
1994
    $textlen = strlen($text);
1995
    $text = substr($text, 0, $len);
1996
    if ($textlen > $len) {
1997
        $text .= '...';
1998
    }
1999
    return $text;
2000
}
2001
2002
/**
2003
 * Helper function to obtain the tags linked to a bigbluebuttonbn activity
2004
 *
2005
 * @param string $id
2006
 *
2007
 * @return string containing the tags separated by commas
2008
 */
2009
function bigbluebuttonbn_get_tags($id) {
2010
    if (class_exists('core_tag_tag')) {
2011
        return implode(',', core_tag_tag::get_item_tags_array('core', 'course_modules', $id));
2012
    }
2013
    return implode(',', tag_get_tags('bigbluebuttonbn', $id));
2014
}
2015
2016
/**
2017
 * Helper function to define the sql used for gattering the bigbluebuttonbnids whose meetingids should be included
2018
 * in the getRecordings request
2019
 *
2020
 * @param string $courseid
2021
 * @param string $bigbluebuttonbnid
2022
 * @param bool   $subset
2023
 *
2024
 * @return string containing the sql used for getting the target bigbluebuttonbn instances
2025
 */
2026
function bigbluebuttonbn_get_recordings_sql_select($courseid, $bigbluebuttonbnid = null, $subset = true) {
2027
    if (empty($courseid)) {
2028
        $courseid = 0;
2029
    }
2030
    if (empty($bigbluebuttonbnid)) {
2031
        return "course = '{$courseid}'";
2032
    }
2033
    if ($subset) {
2034
        return "id = '{$bigbluebuttonbnid}'";
2035
    }
2036
    return "id <> '{$bigbluebuttonbnid}' AND course = '{$courseid}'";
2037
}
2038
2039
/**
2040
 * Helper function to define the sql used for gattering the bigbluebuttonbnids whose meetingids should be included
2041
 * in the getRecordings request considering only those that belong to deleted activities.
2042
 *
2043
 * @param string $courseid
2044
 * @param string $bigbluebuttonbnid
2045
 * @param bool   $subset
2046
 *
2047
 * @return string containing the sql used for getting the target bigbluebuttonbn instances
2048
 */
2049 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...
2050
    $sql = "log = '" . BIGBLUEBUTTONBN_LOG_EVENT_DELETE . "' AND meta like '%has_recordings%' AND meta like '%true%'";
2051
    if (empty($courseid)) {
2052
        $courseid = 0;
2053
    }
2054
    if (empty($bigbluebuttonbnid)) {
2055
        return $sql . " AND courseid = {$courseid}";
2056
    }
2057
    if ($subset) {
2058
        return $sql . " AND bigbluebuttonbnid = '{$bigbluebuttonbnid}'";
2059
    }
2060
    return $sql . " AND courseid = {$courseid} AND bigbluebuttonbnid <> '{$bigbluebuttonbnid}'";
2061
}
2062
2063
/**
2064
 * Helper function to define the sql used for gattering the bigbluebuttonbnids whose meetingids should be included
2065
 * in the getRecordings request considering only those that belong to imported recordings.
2066
 *
2067
 * @param string $courseid
2068
 * @param string $bigbluebuttonbnid
2069
 * @param bool   $subset
2070
 *
2071
 * @return string containing the sql used for getting the target bigbluebuttonbn instances
2072
 */
2073 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...
2074
    $sql = "log = '" . BIGBLUEBUTTONBN_LOG_EVENT_IMPORT . "'";
2075
    if (empty($courseid)) {
2076
        $courseid = 0;
2077
    }
2078
    if (empty($bigbluebuttonbnid)) {
2079
        return $sql . " AND courseid = '{$courseid}'";
2080
    }
2081
    if ($subset) {
2082
        return $sql . " AND bigbluebuttonbnid = '{$bigbluebuttonbnid}'";
2083
    }
2084
    return $sql . " AND courseid = '{$courseid}' AND bigbluebuttonbnid <> '{$bigbluebuttonbnid}'";
2085
}
2086
2087
/**
2088
 * Helper function to get recordings  and imported recordings together.
2089
 *
2090
 * @param string $courseid
2091
 * @param string $bigbluebuttonbnid
2092
 * @param bool   $subset
2093
 * @param bool   $includedeleted
2094
 *
2095
 * @return associative array containing the recordings indexed by recordID, each recording is also a
2096
 * non sequential associative array itself that corresponds to the actual recording in BBB
2097
 */
2098
function bigbluebuttonbn_get_allrecordings($courseid = 0, $bigbluebuttonbnid = null, $subset = true, $includedeleted = false) {
2099
    $recordings = bigbluebuttonbn_get_recordings($courseid, $bigbluebuttonbnid, $subset, $includedeleted);
2100
    $recordingsimported = bigbluebuttonbn_get_recordings_imported_array($courseid, $bigbluebuttonbnid, $subset);
2101
    return ($recordings + $recordingsimported);
2102
}
2103
2104
/**
2105
 * Helper function to retrieve recordings from the BigBlueButton. The references are stored as events
2106
 * in bigbluebuttonbn_logs.
2107
 *
2108
 * @param string $courseid
2109
 * @param string $bigbluebuttonbnid
2110
 * @param bool   $subset
2111
 * @param bool   $includedeleted
2112
 *
2113
 * @return associative array containing the recordings indexed by recordID, each recording is also a
2114
 * non sequential associative array itself that corresponds to the actual recording in BBB
2115
 */
2116
function bigbluebuttonbn_get_recordings($courseid = 0, $bigbluebuttonbnid = null, $subset = true, $includedeleted = false) {
2117
    global $DB;
2118
    $select = bigbluebuttonbn_get_recordings_sql_select($courseid, $bigbluebuttonbnid, $subset);
2119
    $bigbluebuttonbns = $DB->get_records_select_menu('bigbluebuttonbn', $select, null, 'id', 'id, meetingid');
2120
    /* Consider logs from deleted bigbluebuttonbn instances whose meetingids should be included in
2121
     * the getRecordings request. */
2122
    if ($includedeleted) {
2123
        $selectdeleted = bigbluebuttonbn_get_recordings_deleted_sql_select($courseid, $bigbluebuttonbnid, $subset);
2124
        $bigbluebuttonbnsdel = $DB->get_records_select_menu('bigbluebuttonbn_logs', $selectdeleted, null,
2125
            'bigbluebuttonbnid', 'bigbluebuttonbnid, meetingid');
2126
        if (!empty($bigbluebuttonbnsdel)) {
2127
            // Merge bigbluebuttonbnis from deleted instances, only keys are relevant.
2128
            // Artimetic merge is used in order to keep the keys.
2129
            $bigbluebuttonbns += $bigbluebuttonbnsdel;
2130
        }
2131
    }
2132
    // Gather the meetingids from bigbluebuttonbn logs that include a create with record=true.
2133
    if (empty($bigbluebuttonbns)) {
2134
        return array();
2135
    }
2136
    // Prepare select for loading records based on existent bigbluebuttonbns.
2137
    $sql = 'SELECT DISTINCT meetingid, bigbluebuttonbnid FROM {bigbluebuttonbn_logs} WHERE ';
2138
    $sql .= '(bigbluebuttonbnid='.implode(' OR bigbluebuttonbnid=', array_keys($bigbluebuttonbns)).')';
2139
    // Include only Create events and exclude those with record not true.
2140
    $sql .= ' AND log = ? AND meta LIKE ? AND meta LIKE ?';
2141
    // Execute select for loading records based on existent bigbluebuttonbns.
2142
    $records = $DB->get_records_sql_menu($sql, array(BIGBLUEBUTTONBN_LOG_EVENT_CREATE, '%record%', '%true%'));
2143
    // Get actual recordings.
2144
    return bigbluebuttonbn_get_recordings_array(array_keys($records));
2145
}
2146
2147
/**
2148
 * Helper function iterates an array with recordings and unset those already imported.
2149
 *
2150
 * @param array $recordings
2151
 * @param integer $courseid
2152
 * @param integer $bigbluebuttonbnid
2153
 *
2154
 * @return array
2155
 */
2156
function bigbluebuttonbn_unset_existent_recordings_already_imported($recordings, $courseid, $bigbluebuttonbnid) {
2157
    $recordingsimported = bigbluebuttonbn_get_recordings_imported_array($courseid, $bigbluebuttonbnid, true);
2158
    foreach ($recordings as $key => $recording) {
2159
        if (isset($recordingsimported[$recording['recordID']])) {
2160
            unset($recordings[$key]);
2161
        }
2162
    }
2163
    return $recordings;
2164
}
2165
2166
/**
2167
 * Helper function to count the imported recordings for a recordingid.
2168
 *
2169
 * @param string $recordid
2170
 *
2171
 * @return integer
2172
 */
2173
function bigbluebuttonbn_count_recording_imported_instances($recordid) {
2174
    global $DB;
2175
    $sql = 'SELECT COUNT(DISTINCT id) FROM {bigbluebuttonbn_logs} WHERE log = ? AND meta LIKE ? AND meta LIKE ?';
2176
    return $DB->count_records_sql($sql, array(BIGBLUEBUTTONBN_LOG_EVENT_IMPORT, '%recordID%', "%{$recordid}%"));
2177
}
2178
2179
/**
2180
 * Helper function returns an array with all the instances of imported recordings for a recordingid.
2181
 *
2182
 * @param string $recordid
2183
 *
2184
 * @return array
2185
 */
2186
function bigbluebuttonbn_get_recording_imported_instances($recordid) {
2187
    global $DB;
2188
    $sql = 'SELECT * FROM {bigbluebuttonbn_logs} WHERE log = ? AND meta LIKE ? AND meta LIKE ?';
2189
    $recordingsimported = $DB->get_records_sql($sql, array(BIGBLUEBUTTONBN_LOG_EVENT_IMPORT, '%recordID%',
2190
        "%{$recordid}%"));
2191
    return $recordingsimported;
2192
}
2193
2194
/**
2195
 * Helper function returns an array with the profiles (with features per profile) for the different types
2196
 * of bigbluebuttonbn instances.
2197
 *
2198
 * @return array
2199
 */
2200
function bigbluebuttonbn_get_instance_type_profiles() {
2201
    $instanceprofiles = array(
2202
            array('id' => BIGBLUEBUTTONBN_TYPE_ALL, 'name' => get_string('instance_type_default', 'bigbluebuttonbn'),
2203
                'features' => array('all')),
2204
            array('id' => BIGBLUEBUTTONBN_TYPE_ROOM_ONLY, 'name' => get_string('instance_type_room_only', 'bigbluebuttonbn'),
2205
                'features' => array('showroom', 'welcomemessage', 'voicebridge', 'waitformoderator', 'userlimit', 'recording',
2206
                    'sendnotifications', 'preuploadpresentation', 'permissions', 'schedule', 'groups',
2207
                    'modstandardelshdr', 'availabilityconditionsheader', 'tagshdr', 'competenciessection', 'clienttype')),
2208
            array('id' => BIGBLUEBUTTONBN_TYPE_RECORDING_ONLY, 'name' => get_string('instance_type_recording_only',
2209
                'bigbluebuttonbn'), 'features' => array('showrecordings', 'importrecordings')),
2210
    );
2211
    return $instanceprofiles;
2212
}
2213
2214
/**
2215
 * Helper function returns an array with enabled features for an specific profile type.
2216
 *
2217
 * @param array $typeprofiles
2218
 * @param string $type
2219
 *
2220
 * @return array
2221
 */
2222
function bigbluebuttonbn_get_enabled_features($typeprofiles, $type = null) {
2223
    $enabledfeatures = array();
2224
    $features = $typeprofiles[0]['features'];
2225
    if (!is_null($type)) {
2226
        $features = $typeprofiles[$type]['features'];
2227
    }
2228
    $enabledfeatures['showroom'] = (in_array('all', $features) || in_array('showroom', $features));
2229
    // Evaluates if recordings are enabled for the Moodle site.
2230
    $enabledfeatures['showrecordings'] = false;
2231
    if (\mod_bigbluebuttonbn\locallib\config::recordings_enabled()) {
2232
        $enabledfeatures['showrecordings'] = (in_array('all', $features) || in_array('showrecordings', $features));
2233
    }
2234
    $enabledfeatures['importrecordings'] = false;
2235
    if (\mod_bigbluebuttonbn\locallib\config::importrecordings_enabled()) {
2236
        $enabledfeatures['importrecordings'] = (in_array('all', $features) || in_array('importrecordings', $features));
2237
    }
2238
    // Evaluates if clienttype is enabled for the Moodle site.
2239
    $enabledfeatures['clienttype'] = false;
2240
    if (\mod_bigbluebuttonbn\locallib\config::clienttype_enabled()) {
2241
        $enabledfeatures['clienttype'] = (in_array('all', $features) || in_array('clienttype', $features));
2242
    }
2243
    return $enabledfeatures;
2244
}
2245
2246
/**
2247
 * Helper function returns an array with the profiles (with features per profile) for the different types
2248
 * of bigbluebuttonbn instances.
2249
 *
2250
 * @param array $profiles
2251
 *
2252
 * @return array
2253
 */
2254
function bigbluebuttonbn_get_instance_profiles_array($profiles = null) {
2255
    if (is_null($profiles) || empty($profiles)) {
2256
        $profiles = bigbluebuttonbn_get_instance_type_profiles();
2257
    }
2258
    $profilesarray = array();
2259
    foreach ($profiles as $profile) {
2260
        $profilesarray += array("{$profile['id']}" => $profile['name']);
2261
    }
2262
    return $profilesarray;
2263
}
2264
2265
/**
2266
 * Helper function returns time in a formatted string.
2267
 *
2268
 * @param integer $time
2269
 *
2270
 * @return string
2271
 */
2272
function bigbluebuttonbn_format_activity_time($time) {
2273
    $activitytime = '';
2274
    if ($time) {
2275
        $activitytime = calendar_day_representation($time).' '.
2276
          get_string('mod_form_field_notification_msg_at', 'bigbluebuttonbn').' '.
2277
          calendar_time_representation($time);
2278
    }
2279
    return $activitytime;
2280
}
2281
2282
/**
2283
 * Helper function returns array with all the strings to be used in javascript.
2284
 *
2285
 * @return array
2286
 */
2287
function bigbluebuttonbn_get_strings_for_js() {
2288
    $locale = bigbluebuttonbn_get_locale();
2289
    $stringman = get_string_manager();
2290
    $strings = $stringman->load_component_strings('bigbluebuttonbn', $locale);
2291
    return $strings;
2292
}
2293
2294
/**
2295
 * Helper function returns the locale set by moodle.
2296
 *
2297
 * @return string
2298
 */
2299
function bigbluebuttonbn_get_locale() {
2300
    $lang = get_string('locale', 'core_langconfig');
2301
    return substr($lang, 0, strpos($lang, '.'));
2302
}
2303
2304
/**
2305
 * Helper function returns the locale code based on the locale set by moodle.
2306
 *
2307
 * @return string
2308
 */
2309
function bigbluebuttonbn_get_localcode() {
2310
    $locale = bigbluebuttonbn_get_locale();
2311
    return substr($locale, 0, strpos($locale, '_'));
2312
}
2313
2314
/**
2315
 * Helper function returns array with the instance settings used in views.
2316
 *
2317
 * @param string $id
2318
 * @param object $bigbluebuttonbnid
2319
 *
2320
 * @return array
2321
 */
2322
function bigbluebuttonbn_views_validator($id, $bigbluebuttonbnid) {
2323
    if ($id) {
2324
        return bigbluebuttonbn_views_instance_id($id);
2325
    }
2326
    if ($bigbluebuttonbnid) {
2327
        return bigbluebuttonbn_views_instance_bigbluebuttonbn($bigbluebuttonbnid);
2328
    }
2329
    return;
2330
}
2331
2332
/**
2333
 * Helper function returns array with the instance settings used in views based on id.
2334
 *
2335
 * @param string $id
2336
 *
2337
 * @return array
2338
 */
2339 View Code Duplication
function bigbluebuttonbn_views_instance_id($id) {
0 ignored issues
show
Duplication introduced by
This function seems to be duplicated in your project.

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

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

Loading history...
2340
    global $DB;
2341
    $cm = get_coursemodule_from_id('bigbluebuttonbn', $id, 0, false, MUST_EXIST);
2342
    $course = $DB->get_record('course', array('id' => $cm->course), '*', MUST_EXIST);
2343
    $bigbluebuttonbn = $DB->get_record('bigbluebuttonbn', array('id' => $cm->instance), '*', MUST_EXIST);
2344
    return array('cm' => $cm, 'course' => $course, 'bigbluebuttonbn' => $bigbluebuttonbn);
2345
}
2346
2347
/**
2348
 * Helper function returns array with the instance settings used in views based on bigbluebuttonbnid.
2349
 *
2350
 * @param object $bigbluebuttonbnid
2351
 *
2352
 * @return array
2353
 */
2354 View Code Duplication
function bigbluebuttonbn_views_instance_bigbluebuttonbn($bigbluebuttonbnid) {
0 ignored issues
show
Duplication introduced by
This function seems to be duplicated in your project.

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

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

Loading history...
2355
    global $DB;
2356
    $bigbluebuttonbn = $DB->get_record('bigbluebuttonbn', array('id' => $bigbluebuttonbnid), '*', MUST_EXIST);
2357
    $course = $DB->get_record('course', array('id' => $bigbluebuttonbn->course), '*', MUST_EXIST);
2358
    $cm = get_coursemodule_from_instance('bigbluebuttonbn', $bigbluebuttonbn->id, $course->id, false, MUST_EXIST);
2359
    return array('cm' => $cm, 'course' => $course, 'bigbluebuttonbn' => $bigbluebuttonbn);
2360
}
2361
2362
/**
2363
 * Helper function renders general warning message for settings (if any).
2364
 *
2365
 * @param object $renderer
2366
 *
2367
 * @return void
2368
 */
2369
function bigbluebuttonbn_settings_general_warning(&$renderer) {
2370
    global $BIGBLUEBUTTONBN_CFG;
2371
    if (isset($BIGBLUEBUTTONBN_CFG)) {
2372
        $renderer->render_warning_message('general_warning',
2373
             get_string('config_warning_bigbluebuttonbn_cfg_deprecated', 'bigbluebuttonbn'));
2374
    }
2375
}
2376
2377
/**
2378
 * Helper function renders general settings if the feature is enabled.
2379
 *
2380
 * @param object $renderer
2381
 *
2382
 * @return void
2383
 */
2384
function bigbluebuttonbn_settings_general(&$renderer) {
2385
    // Configuration for BigBlueButton.
2386
    if ((boolean)\mod_bigbluebuttonbn\settings\renderer::section_general_shown()) {
2387
        $renderer->render_group_header('general');
2388
        $renderer->render_group_element('server_url',
2389
            $renderer->render_group_element_text('server_url', BIGBLUEBUTTONBN_DEFAULT_SERVER_URL));
2390
        $renderer->render_group_element('shared_secret',
2391
            $renderer->render_group_element_text('shared_secret', BIGBLUEBUTTONBN_DEFAULT_SHARED_SECRET));
2392
    }
2393
}
2394
2395
/**
2396
 * Helper function renders record settings if the feature is enabled.
2397
 *
2398
 * @param object $renderer
2399
 *
2400
 * @return void
2401
 */
2402
function bigbluebuttonbn_settings_record(&$renderer) {
2403
    // Configuration for 'recording' feature.
2404 View Code Duplication
    if ((boolean)\mod_bigbluebuttonbn\settings\renderer::section_record_meeting_shown()) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
2405
        $renderer->render_group_header('recording');
2406
        $renderer->render_group_element('recording_default',
2407
            $renderer->render_group_element_checkbox('recording_default', 1));
2408
        $renderer->render_group_element('recording_editable',
2409
            $renderer->render_group_element_checkbox('recording_editable', 1));
2410
        $renderer->render_group_element('recording_icons_enabled',
2411
            $renderer->render_group_element_checkbox('recording_icons_enabled', 1));
2412
    }
2413
}
2414
2415
/**
2416
 * Helper function renders import recording settings if the feature is enabled.
2417
 *
2418
 * @param object $renderer
2419
 *
2420
 * @return void
2421
 */
2422 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...
2423
    // Configuration for 'import recordings' feature.
2424
    if ((boolean)\mod_bigbluebuttonbn\settings\renderer::section_import_recordings_shown()) {
2425
        $renderer->render_group_header('importrecordings');
2426
        $renderer->render_group_element('importrecordings_enabled',
2427
            $renderer->render_group_element_checkbox('importrecordings_enabled', 0));
2428
        $renderer->render_group_element('importrecordings_from_deleted_enabled',
2429
            $renderer->render_group_element_checkbox('importrecordings_from_deleted_enabled', 0));
2430
    }
2431
}
2432
2433
/**
2434
 * Helper function renders show recording settings if the feature is enabled.
2435
 *
2436
 * @param object $renderer
2437
 *
2438
 * @return void
2439
 */
2440
function bigbluebuttonbn_settings_showrecordings(&$renderer) {
2441
    // Configuration for 'show recordings' feature.
2442
    if ((boolean)\mod_bigbluebuttonbn\settings\renderer::section_show_recordings_shown()) {
2443
        $renderer->render_group_header('recordings');
2444
        $renderer->render_group_element('recordings_html_default',
2445
            $renderer->render_group_element_checkbox('recordings_html_default', 1));
2446
        $renderer->render_group_element('recordings_html_editable',
2447
            $renderer->render_group_element_checkbox('recordings_html_editable', 0));
2448
        $renderer->render_group_element('recordings_deleted_default',
2449
            $renderer->render_group_element_checkbox('recordings_deleted_default', 1));
2450
        $renderer->render_group_element('recordings_deleted_editable',
2451
            $renderer->render_group_element_checkbox('recordings_deleted_editable', 0));
2452
        $renderer->render_group_element('recordings_imported_default',
2453
            $renderer->render_group_element_checkbox('recordings_imported_default', 0));
2454
        $renderer->render_group_element('recordings_imported_editable',
2455
            $renderer->render_group_element_checkbox('recordings_imported_editable', 1));
2456
        $renderer->render_group_element('recordings_preview_default',
2457
            $renderer->render_group_element_checkbox('recordings_preview_default', 1));
2458
        $renderer->render_group_element('recordings_preview_editable',
2459
            $renderer->render_group_element_checkbox('recordings_preview_editable', 0));
2460
    }
2461
}
2462
2463
/**
2464
 * Helper function renders wait for moderator settings if the feature is enabled.
2465
 *
2466
 * @param object $renderer
2467
 *
2468
 * @return void
2469
 */
2470
function bigbluebuttonbn_settings_waitmoderator(&$renderer) {
2471
    // Configuration for wait for moderator feature.
2472
    if ((boolean)\mod_bigbluebuttonbn\settings\renderer::section_wait_moderator_shown()) {
2473
        $renderer->render_group_header('waitformoderator');
2474
        $renderer->render_group_element('waitformoderator_default',
2475
            $renderer->render_group_element_checkbox('waitformoderator_default', 0));
2476
        $renderer->render_group_element('waitformoderator_editable',
2477
            $renderer->render_group_element_checkbox('waitformoderator_editable', 1));
2478
        $renderer->render_group_element('waitformoderator_ping_interval',
2479
            $renderer->render_group_element_text('waitformoderator_ping_interval', 10, PARAM_INT));
2480
        $renderer->render_group_element('waitformoderator_cache_ttl',
2481
            $renderer->render_group_element_text('waitformoderator_cache_ttl', 60, PARAM_INT));
2482
    }
2483
}
2484
2485
/**
2486
 * Helper function renders static voice bridge settings if the feature is enabled.
2487
 *
2488
 * @param object $renderer
2489
 *
2490
 * @return void
2491
 */
2492
function bigbluebuttonbn_settings_voicebridge(&$renderer) {
2493
    // Configuration for "static voice bridge" feature.
2494
    if ((boolean)\mod_bigbluebuttonbn\settings\renderer::section_static_voice_bridge_shown()) {
2495
        $renderer->render_group_header('voicebridge');
2496
        $renderer->render_group_element('voicebridge_editable',
2497
            $renderer->render_group_element_checkbox('voicebridge_editable', 0));
2498
    }
2499
}
2500
2501
/**
2502
 * Helper function renders preuploaded presentation settings if the feature is enabled.
2503
 *
2504
 * @param object $renderer
2505
 *
2506
 * @return void
2507
 */
2508
function bigbluebuttonbn_settings_preupload(&$renderer) {
2509
    // Configuration for "preupload presentation" feature.
2510
    if ((boolean)\mod_bigbluebuttonbn\settings\renderer::section_preupload_presentation_shown()) {
2511
        // This feature only works if curl is installed.
2512
        $preuploaddescripion = get_string('config_preuploadpresentation_description', 'bigbluebuttonbn');
2513
        if (!extension_loaded('curl')) {
2514
            $preuploaddescripion .= '<div class="form-defaultinfo">';
2515
            $preuploaddescripion .= get_string('config_warning_curl_not_installed', 'bigbluebuttonbn');
2516
            $preuploaddescripion .= '</div><br>';
2517
        }
2518
        $renderer->render_group_header('preuploadpresentation', null, $preuploaddescripion);
2519
        if (extension_loaded('curl')) {
2520
            $renderer->render_group_element('preuploadpresentation_enabled',
2521
                $renderer->render_group_element_checkbox('preuploadpresentation_enabled', 0));
2522
        }
2523
    }
2524
}
2525
2526
/**
2527
 * Helper function renders userlimit settings if the feature is enabled.
2528
 *
2529
 * @param object $renderer
2530
 *
2531
 * @return void
2532
 */
2533
function bigbluebuttonbn_settings_userlimit(&$renderer) {
2534
    // Configuration for "user limit" feature.
2535
    if ((boolean)\mod_bigbluebuttonbn\settings\renderer::section_user_limit_shown()) {
2536
        $renderer->render_group_header('userlimit');
2537
        $renderer->render_group_element('userlimit_default',
2538
            $renderer->render_group_element_text('userlimit_default', 0, PARAM_INT));
2539
        $renderer->render_group_element('userlimit_editable',
2540
            $renderer->render_group_element_checkbox('userlimit_editable', 0));
2541
    }
2542
}
2543
2544
/**
2545
 * Helper function renders duration settings if the feature is enabled.
2546
 *
2547
 * @param object $renderer
2548
 *
2549
 * @return void
2550
 */
2551
function bigbluebuttonbn_settings_duration(&$renderer) {
2552
    // Configuration for "scheduled duration" feature.
2553 View Code Duplication
    if ((boolean)\mod_bigbluebuttonbn\settings\renderer::section_scheduled_duration_shown()) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
2554
        $renderer->render_group_header('scheduled');
2555
        $renderer->render_group_element('scheduled_duration_enabled',
2556
            $renderer->render_group_element_checkbox('scheduled_duration_enabled', 1));
2557
        $renderer->render_group_element('scheduled_duration_compensation',
2558
            $renderer->render_group_element_text('scheduled_duration_compensation', 10, PARAM_INT));
2559
        $renderer->render_group_element('scheduled_pre_opening',
2560
            $renderer->render_group_element_text('scheduled_pre_opening', 10, PARAM_INT));
2561
    }
2562
}
2563
2564
/**
2565
 * Helper function renders participant settings if the feature is enabled.
2566
 *
2567
 * @param object $renderer
2568
 *
2569
 * @return void
2570
 */
2571
function bigbluebuttonbn_settings_participants(&$renderer) {
2572
    // Configuration for defining the default role/user that will be moderator on new activities.
2573
    if ((boolean)\mod_bigbluebuttonbn\settings\renderer::section_moderator_default_shown()) {
2574
        $renderer->render_group_header('participant');
2575
        // UI for 'participants' feature.
2576
        $roles = bigbluebuttonbn_get_roles();
2577
        $owner = array('0' => get_string('mod_form_field_participant_list_type_owner', 'bigbluebuttonbn'));
2578
        $renderer->render_group_element('participant_moderator_default',
2579
            $renderer->render_group_element_configmultiselect('participant_moderator_default',
2580
                array_keys($owner), array_merge($owner, $roles))
2581
          );
2582
    }
2583
}
2584
2585
/**
2586
 * Helper function renders notification settings if the feature is enabled.
2587
 *
2588
 * @param object $renderer
2589
 *
2590
 * @return void
2591
 */
2592
function bigbluebuttonbn_settings_notifications(&$renderer) {
2593
    // Configuration for "send notifications" feature.
2594
    if ((boolean)\mod_bigbluebuttonbn\settings\renderer::section_send_notifications_shown()) {
2595
        $renderer->render_group_header('sendnotifications');
2596
        $renderer->render_group_element('sendnotifications_enabled',
2597
            $renderer->render_group_element_checkbox('sendnotifications_enabled', 1));
2598
    }
2599
}
2600
2601
/**
2602
 * Helper function renders client type settings if the feature is enabled.
2603
 *
2604
 * @param object $renderer
2605
 *
2606
 * @return void
2607
 */
2608
function bigbluebuttonbn_settings_clienttype(&$renderer) {
2609
    // Configuration for "clienttype" feature.
2610
    if ((boolean)\mod_bigbluebuttonbn\settings\renderer::section_clienttype_shown()) {
2611
        $renderer->render_group_header('clienttype');
2612
        $renderer->render_group_element('clienttype_editable',
2613
            $renderer->render_group_element_checkbox('clienttype_editable', 0));
2614
2615
        // Web Client default.
2616
        $default = intval((int)\mod_bigbluebuttonbn\locallib\config::get('clienttype_default'));
2617
2618
        $choices = array(BIGBLUEBUTTON_CLIENTTYPE_FLASH => get_string('mod_form_block_clienttype_flash', 'bigbluebuttonbn'),
2619
                         BIGBLUEBUTTON_CLIENTTYPE_HTML5 => get_string('mod_form_block_clienttype_html5', 'bigbluebuttonbn'));
2620
        $renderer->render_group_element('clienttype_default',
2621
            $renderer->render_group_element_configselect('clienttype_default',
2622
                $default, $choices));
2623
    }
2624
}
2625
2626
/**
2627
 * Helper function renders extended settings if any of the features there is enabled.
2628
 *
2629
 * @param object $renderer
2630
 *
2631
 * @return void
2632
 */
2633 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...
2634
    // Configuration for extended BN capabilities.
2635
    if (!bigbluebuttonbn_is_bn_server()) {
2636
        return;
2637
    }
2638
    // Configuration for 'notify users when recording ready' feature.
2639
    if ((boolean)\mod_bigbluebuttonbn\settings\renderer::section_settings_extended_shown()) {
2640
        $renderer->render_group_header('extended_capabilities');
2641
        // UI for 'notify users when recording ready' feature.
2642
        $renderer->render_group_element('recordingready_enabled',
2643
            $renderer->render_group_element_checkbox('recordingready_enabled', 0));
2644
        // UI for 'register meeting events' feature.
2645
        $renderer->render_group_element('meetingevents_enabled',
2646
            $renderer->render_group_element_checkbox('meetingevents_enabled', 0));
2647
    }
2648
}
2649
2650
/**
2651
 * Helper function returns an encoded meetingid.
2652
 *
2653
 * @param string $seed
2654
 *
2655
 * @return string
2656
 */
2657
function bigbluebuttonbn_encode_meetingid($seed) {
2658
    global $CFG;
2659
    return sha1($CFG->wwwroot . $seed . \mod_bigbluebuttonbn\locallib\config::get('shared_secret'));
2660
}
2661
2662
/**
2663
 * Helper function renders the link used for recording type in row for the data used by the recording table.
2664
 *
2665
 * @param array $recording
2666
 * @param array $bbbsession
2667
 * @param array $playback
2668
 *
2669
 * @return boolean
2670
 */
2671
function bigbluebuttonbn_include_recording_data_row_type($recording, $bbbsession, $playback) {
2672
    // All types that are not restricted are included.
2673
    if (array_key_exists('restricted', $playback) && strtolower($playback['restricted']) == 'false') {
2674
        return true;
2675
    }
2676
    // All types that are not statistics are included.
2677
    if ($playback['type'] != 'statistics') {
2678
        return true;
2679
    }
2680
    // Exclude imported recordings.
2681
    if (isset($recording['imported'])) {
2682
        return false;
2683
    }
2684
    // Exclude non moderators.
2685
    if (!$bbbsession['administrator'] && !$bbbsession['moderator']) {
2686
        return false;
2687
    }
2688
    return true;
2689
}
2690
2691
/**
2692
 * Renders the general warning message.
2693
 *
2694
 * @param string $message
2695
 * @param string $type
2696
 * @param string $href
2697
 * @param string $text
2698
 * @param string $class
2699
 *
2700
 * @return string
2701
 */
2702
function bigbluebuttonbn_render_warning($message, $type='info', $href='', $text='', $class='') {
2703
    global $OUTPUT;
2704
    $output = "\n";
2705
    // Evaluates if config_warning is enabled.
2706
    if (empty($message)) {
2707
        return $output;
2708
    }
2709
    $output .= $OUTPUT->box_start('box boxalignleft adminerror alert alert-' . $type . ' alert-block fade in',
2710
      'bigbluebuttonbn_view_general_warning') . "\n";
2711
    $output .= '    ' . $message . "\n";
2712
    $output .= '  <div class="singlebutton pull-right">' . "\n";
2713
    if (!empty($href)) {
2714
        $output .= bigbluebuttonbn_render_warning_button($href, $text, $class);
2715
    }
2716
    $output .= '  </div>' . "\n";
2717
    $output .= $OUTPUT->box_end() . "\n";
2718
    return $output;
2719
}
2720
2721
/**
2722
 * Renders the general warning button.
2723
 *
2724
 * @param string $href
2725
 * @param string $text
2726
 * @param string $class
2727
 * @param string $title
2728
 *
2729
 * @return string
2730
 */
2731
function bigbluebuttonbn_render_warning_button($href, $text = '', $class = '', $title = '') {
2732
    if ($text == '') {
2733
        $text = get_string('ok', 'moodle');
2734
    }
2735
    if ($title == '') {
2736
        $title = $text;
2737
    }
2738
    if ($class == '') {
2739
        $class = 'btn btn-secondary';
2740
    }
2741
    $output  = '  <form method="post" action="' . $href . '" class="form-inline">'."\n";
2742
    $output .= '      <button type="submit" class="' . $class . '"'."\n";
2743
    $output .= '          title="' . $title . '"'."\n";
2744
    $output .= '          >' . $text . '</button>'."\n";
2745
    $output .= '  </form>'."\n";
2746
    return $output;
2747
}
2748
2749
/**
2750
 * Check if a BigBlueButtonBN is available to be used by the current user.
2751
 *
2752
 * @param  stdClass  $bigbluebuttonbn  BigBlueButtonBN instance
2753
 *
2754
 * @return boolean                     status if room available and current user allowed to join
2755
 */
2756
function bigbluebuttonbn_get_availability_status($bigbluebuttonbn) {
2757
    list($roomavailable) = bigbluebuttonbn_room_is_available($bigbluebuttonbn);
2758
    list($usercanjoin) = bigbluebuttonbn_user_can_join_meeting($bigbluebuttonbn);
2759
2760
    return ($roomavailable && $usercanjoin);
2761
}
2762
2763
/**
2764
 * Helper for evaluating if scheduled activity is avaiable.
2765
 *
2766
 * @param  stdClass  $bigbluebuttonbn  BigBlueButtonBN instance
2767
 *
2768
 * @return array                       status (room available or not and possible warnings)
2769
 */
2770
function bigbluebuttonbn_room_is_available($bigbluebuttonbn) {
2771
    $open = true;
2772
    $closed = false;
2773
    $warnings = array();
2774
2775
    $timenow = time();
2776
    $timeopen = $bigbluebuttonbn->openingtime;
2777
    $timeclose = $bigbluebuttonbn->closingtime;
2778
    if (!empty($timeopen) && $timeopen > $timenow) {
2779
        $open = false;
2780
    }
2781
    if (!empty($timeclose) && $timenow > $timeclose) {
2782
        $closed = true;
2783
    }
2784
2785
    if (!$open || $closed) {
2786
        if (!$open) {
2787
            $warnings['notopenyet'] = userdate($timeopen);
2788
        }
2789
        if ($closed) {
2790
            $warnings['expired'] = userdate($timeclose);
2791
        }
2792
        return array(false, $warnings);
2793
    }
2794
2795
    return array(true, $warnings);
2796
}
2797
2798
/**
2799
 * Helper for evaluating if meeting can be joined.
2800
 *
2801
 * @param  stdClass $bigbluebuttonbn  BigBlueButtonBN instance
2802
 * @param  string   $mid
2803
 * @param  integer  $userid
2804
 *
2805
 * @return array    status (user allowed to join or not and possible message)
2806
 */
2807
function bigbluebuttonbn_user_can_join_meeting($bigbluebuttonbn, $mid = null, $userid = null) {
2808
2809
    // By default, use a meetingid without groups.
2810
    if (empty($mid)) {
2811
        $mid = $bigbluebuttonbn->meetingid . '-' . $bigbluebuttonbn->course . '-' . $bigbluebuttonbn->id;
2812
    }
2813
2814
    // When meeting is running, all authorized users can join right in.
2815
    if (bigbluebuttonbn_is_meeting_running($mid)) {
2816
        return array(true, get_string('view_message_conference_in_progress', 'bigbluebuttonbn'));
2817
    }
2818
2819
    // When meeting is not running, see if the user can join.
2820
    $context = context_course::instance($bigbluebuttonbn->course);
2821
    $participantlist = bigbluebuttonbn_get_participant_list($bigbluebuttonbn, $context);
2822
    $isadmin = is_siteadmin($userid);
2823
    $ismoderator = bigbluebuttonbn_is_moderator($context, $participantlist, $userid);
2824
    // If user is administrator, moderator or if is viewer and no waiting is required, join allowed.
2825
    if ($isadmin || $ismoderator || !$bigbluebuttonbn->wait) {
2826
        return array(true, get_string('view_message_conference_room_ready', 'bigbluebuttonbn'));
2827
    }
2828
    // Otherwise, no join allowed.
2829
    return array(false, get_string('view_message_conference_wait_for_moderator', 'bigbluebuttonbn'));
2830
}
2831
2832
/**
2833
 * Helper for getting a value from a bigbluebuttonbn cache.
2834
 *
2835
 * @param  string   $name       BigBlueButtonBN cache
2836
 * @param  string   $key        Key to be retrieved
2837
 * @param  integer  $default    Default value in case key is not found or it is empty
2838
 *
2839
 * @return variable key value
2840
 */
2841
function bigbluebuttonbn_cache_get($name, $key, $default = null) {
2842
    $cache = cache::make_from_params(cache_store::MODE_APPLICATION, 'mod_bigbluebuttonbn', $name);
2843
    $result = $cache->get($key);
2844
    if (!empty($result)) {
2845
        return $result;
2846
    }
2847
    return $default;
2848
}
2849
2850
/**
2851
 * Helper for setting a value in a bigbluebuttonbn cache.
2852
 *
2853
 * @param  string   $name       BigBlueButtonBN cache
2854
 * @param  string   $key        Key to be created/updated
2855
 * @param  variable $value      Default value to be set
2856
 */
2857
function bigbluebuttonbn_cache_set($name, $key, $value) {
2858
    $cache = cache::make_from_params(cache_store::MODE_APPLICATION, 'mod_bigbluebuttonbn', $name);
2859
    $result = $cache->set($key, $value);
0 ignored issues
show
Unused Code introduced by
$result is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
2860
}
2861
2862
/**
2863
 * Helper for getting the owner userid of a bigbluebuttonbn instance.
2864
 *
2865
 * @param  stdClass $bigbluebuttonbn  BigBlueButtonBN instance
2866
 *
2867
 * @return integer ownerid (a valid user id or null if not registered/found)
2868
 */
2869
function bigbluebuttonbn_instance_ownerid($bigbluebuttonbn) {
2870
    global $DB;
2871
    $filters = array('bigbluebuttonbnid' => $bigbluebuttonbn->id, 'log' => 'Add');
2872
    $ownerid = (integer)$DB->get_field('bigbluebuttonbn_logs', 'userid', $filters);
2873
    return $ownerid;
2874
}
2875
2876
/**
2877
 * Helper evaluates if the bigbluebutton server used belongs to blindsidenetworks domain.
2878
 *
2879
 * @return boolean
2880
 */
2881
function bigbluebuttonbn_has_html5_client() {
2882
    $checkurl = \mod_bigbluebuttonbn\locallib\bigbluebutton::root() . "html5client/check";
2883
    $curlinfo = bigbluebuttonbn_wrap_xml_load_file_curl_request($checkurl, 'HEAD');
2884
    return (isset($curlinfo['http_code']) && $curlinfo['http_code'] == 200);
2885
}
2886