Completed
Pull Request — master (#92)
by Jesus
02:32
created

locallib.php ➔ bigbluebuttonbn_settings_muteonstart()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 10

Duplication

Lines 10
Ratio 100 %

Importance

Changes 0
Metric Value
cc 2
nc 2
nop 1
dl 10
loc 10
rs 9.9332
c 0
b 0
f 0
1
<?php
2
// This file is part of Moodle - http://moodle.org/
3
//
4
// Moodle is free software: you can redistribute it and/or modify
5
// it under the terms of the GNU General Public License as published by
6
// the Free Software Foundation, either version 3 of the License, or
7
// (at your option) any later version.
8
//
9
// Moodle is distributed in the hope that it will be useful,
10
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
// GNU General Public License for more details.
13
//
14
// You should have received a copy of the GNU General Public License
15
// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
16
17
/**
18
 * Internal library of functions for module BigBlueButtonBN.
19
 *
20
 * @package   mod_bigbluebuttonbn
21
 * @copyright 2010 onwards, Blindside Networks Inc
22
 * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
23
 * @author    Jesus Federico  (jesus [at] blindsidenetworks [dt] com)
24
 * @author    Fred Dixon  (ffdixon [at] blindsidenetworks [dt] com)
25
 */
26
27
defined('MOODLE_INTERNAL') || die;
28
29
global $CFG;
30
31
require_once(dirname(__FILE__).'/lib.php');
32
33
/** @var BIGBLUEBUTTONBN_UPDATE_CACHE boolean set to true indicates that cache has to be updated */
34
const BIGBLUEBUTTONBN_UPDATE_CACHE = true;
35
/** @var BIGBLUEBUTTONBN_TYPE_ALL integer set to 0 defines an instance type that inclueds room and recordings */
36
const BIGBLUEBUTTONBN_TYPE_ALL = 0;
37
/** @var BIGBLUEBUTTONBN_TYPE_ROOM_ONLY integer set to 1 defines an instance type that inclueds only room */
38
const BIGBLUEBUTTONBN_TYPE_ROOM_ONLY = 1;
39
/** @var BIGBLUEBUTTONBN_TYPE_RECORDING_ONLY integer set to 2 defines an instance type that inclueds only recordings */
40
const BIGBLUEBUTTONBN_TYPE_RECORDING_ONLY = 2;
41
/** @var BIGBLUEBUTTONBN_ROLE_VIEWER string defines the bigbluebutton viewer role */
42
const BIGBLUEBUTTONBN_ROLE_VIEWER = 'viewer';
43
/** @var BIGBLUEBUTTONBN_ROLE_MODERATOR string defines the bigbluebutton moderator role */
44
const BIGBLUEBUTTONBN_ROLE_MODERATOR = 'moderator';
45
/** @var BIGBLUEBUTTON_EVENT_ACTIVITY_VIEWED string defines the bigbluebuttonbn activity_viewed event */
46
const BIGBLUEBUTTON_EVENT_ACTIVITY_VIEWED = 'activity_viewed';
47
/** @var BIGBLUEBUTTON_EVENT_ACTIVITY_MANAGEMENT_VIEWED string defines the bigbluebuttonbn activity_management_viewed event */
48
const BIGBLUEBUTTON_EVENT_ACTIVITY_MANAGEMENT_VIEWED = 'activity_management_viewed';
49
/** @var BIGBLUEBUTTON_EVENT_LIVE_SESSION string defines the bigbluebuttonbn live_session event */
50
const BIGBLUEBUTTON_EVENT_LIVE_SESSION = 'live_session';
51
/** @var BIGBLUEBUTTON_EVENT_MEETING_CREATED string defines the bigbluebuttonbn meeting_created event */
52
const BIGBLUEBUTTON_EVENT_MEETING_CREATED = 'meeting_created';
53
/** @var BIGBLUEBUTTON_EVENT_MEETING_ENDED string defines the bigbluebuttonbn meeting_ended event */
54
const BIGBLUEBUTTON_EVENT_MEETING_ENDED = 'meeting_ended';
55
/** @var BIGBLUEBUTTON_EVENT_MEETING_JOINED string defines the bigbluebuttonbn meeting_joined event */
56
const BIGBLUEBUTTON_EVENT_MEETING_JOINED = 'meeting_joined';
57
/** @var BIGBLUEBUTTON_EVENT_MEETING_LEFT string defines the bigbluebuttonbn meeting_left event */
58
const BIGBLUEBUTTON_EVENT_MEETING_LEFT = 'meeting_left';
59
/** @var BIGBLUEBUTTON_EVENT_RECORDING_DELETED string defines the bigbluebuttonbn recording_deleted event */
60
const BIGBLUEBUTTON_EVENT_RECORDING_DELETED = 'recording_deleted';
61
/** @var BIGBLUEBUTTON_EVENT_RECORDING_IMPORTED string defines the bigbluebuttonbn recording_imported event */
62
const BIGBLUEBUTTON_EVENT_RECORDING_IMPORTED = 'recording_imported';
63
/** @var BIGBLUEBUTTON_EVENT_RECORDING_PROTECTED string defines the bigbluebuttonbn recording_protected event */
64
const BIGBLUEBUTTON_EVENT_RECORDING_PROTECTED = 'recording_protected';
65
/** @var BIGBLUEBUTTON_EVENT_RECORDING_PUBLISHED string defines the bigbluebuttonbn recording_published event */
66
const BIGBLUEBUTTON_EVENT_RECORDING_PUBLISHED = 'recording_published';
67
/** @var BIGBLUEBUTTON_EVENT_RECORDING_UNPROTECTED string defines the bigbluebuttonbn recording_unprotected event */
68
const BIGBLUEBUTTON_EVENT_RECORDING_UNPROTECTED = 'recording_unprotected';
69
/** @var BIGBLUEBUTTON_EVENT_RECORDING_UNPUBLISHED string defines the bigbluebuttonbn recording_unpublished event */
70
const BIGBLUEBUTTON_EVENT_RECORDING_UNPUBLISHED = 'recording_unpublished';
71
/** @var BIGBLUEBUTTON_EVENT_RECORDING_EDITED string defines the bigbluebuttonbn recording_edited event */
72
const BIGBLUEBUTTON_EVENT_RECORDING_EDITED = 'recording_edited';
73
/** @var BIGBLUEBUTTON_EVENT_RECORDING_VIEWED string defines the bigbluebuttonbn recording_viewed event */
74
const BIGBLUEBUTTON_EVENT_RECORDING_VIEWED = 'recording_viewed';
75
/** @var BIGBLUEBUTTON_EVENT_MEETING_START string defines the bigbluebuttonbn meeting_start event */
76
const BIGBLUEBUTTON_EVENT_MEETING_START = 'meeting_start';
77
/** @var BIGBLUEBUTTON_CLIENTTYPE_FLASH integer that defines the bigbluebuttonbn default web client based on Adobe FLASH */
78
const BIGBLUEBUTTON_CLIENTTYPE_FLASH = 0;
79
/** @var BIGBLUEBUTTON_CLIENTTYPE_HTML5 integer that defines the bigbluebuttonbn default web client based on HTML5 */
80
const BIGBLUEBUTTON_CLIENTTYPE_HTML5 = 1;
81
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
 * @param string $clienttype
92
 *
93
 * @return string
94
 */
95
function bigbluebuttonbn_get_join_url($meetingid, $username, $pw, $logouturl, $configtoken = null,
96
        $userid = null, $clienttype = BIGBLUEBUTTON_CLIENTTYPE_FLASH) {
97
    $data = ['meetingID' => $meetingid,
98
              'fullName' => $username,
99
              'password' => $pw,
100
              'logoutURL' => $logouturl,
101
            ];
102
    // Choose between Adobe Flash or HTML5 Client.
103
    if ( $clienttype == BIGBLUEBUTTON_CLIENTTYPE_HTML5 ) {
104
        $data['joinViaHtml5'] = 'true';
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 register a bigbluebuttonbn event.
1009
 *
1010
 * @param string $type
1011
 * @param object $bigbluebuttonbn
1012
 * @param array $options [timecreated, userid, other]
1013
 *
1014
 * @return void
1015
 */
1016
function bigbluebuttonbn_event_log($type, $bigbluebuttonbn, $options = []) {
1017
    global $DB;
1018
    if (!in_array($type, \mod_bigbluebuttonbn\event\events::$events)) {
1019
        // No log will be created.
1020
        return;
1021
    }
1022
    $course = $DB->get_record('course', array('id' => $bigbluebuttonbn->course), '*', MUST_EXIST);
1023
    $cm = get_coursemodule_from_instance('bigbluebuttonbn', $bigbluebuttonbn->id, $course->id, false, MUST_EXIST);
1024
    $context = context_module::instance($cm->id);
1025
    $params = array('context' => $context, 'objectid' => $bigbluebuttonbn->id);
1026
    if (array_key_exists('timecreated', $options)) {
1027
        $params['timecreated'] = $options['timecreated'];
1028
    }
1029
    if (array_key_exists('userid', $options)) {
1030
        $params['userid'] = $options['userid'];
1031
    }
1032
    if (array_key_exists('other', $options)) {
1033
        $params['other'] = $options['other'];
1034
    }
1035
    $event = call_user_func_array('\mod_bigbluebuttonbn\event\\' . $type . '::create',
1036
        array($params));
1037
    $event->add_record_snapshot('course_modules', $cm);
1038
    $event->add_record_snapshot('course', $course);
1039
    $event->add_record_snapshot('bigbluebuttonbn', $bigbluebuttonbn);
1040
    $event->trigger();
1041
}
1042
1043
/**
1044
 * Updates the meeting info cached object when a participant has joined.
1045
 *
1046
 * @param string $meetingid
1047
 * @param bool $ismoderator
1048
 *
1049
 * @return void
1050
 */
1051
function bigbluebuttonbn_participant_joined($meetingid, $ismoderator) {
1052
    $cache = cache::make_from_params(cache_store::MODE_APPLICATION, 'mod_bigbluebuttonbn', 'meetings_cache');
1053
    $result = $cache->get($meetingid);
1054
    $meetinginfo = json_decode($result['meeting_info']);
1055
    $meetinginfo->participantCount += 1;
1056
    if ($ismoderator) {
1057
        $meetinginfo->moderatorCount += 1;
1058
    }
1059
    $cache->set($meetingid, array('creation_time' => $result['creation_time'],
1060
        'meeting_info' => json_encode($meetinginfo)));
1061
}
1062
1063
/**
1064
 * Gets a meeting info object cached or fetched from the live session.
1065
 *
1066
 * @param string $meetingid
1067
 * @param boolean $updatecache
1068
 *
1069
 * @return array
1070
 */
1071
function bigbluebuttonbn_get_meeting_info($meetingid, $updatecache = false) {
1072
    $cachettl = (int)\mod_bigbluebuttonbn\locallib\config::get('waitformoderator_cache_ttl');
1073
    $cache = cache::make_from_params(cache_store::MODE_APPLICATION, 'mod_bigbluebuttonbn', 'meetings_cache');
1074
    $result = $cache->get($meetingid);
1075
    $now = time();
1076
    if (!$updatecache && isset($result) && $now < ($result['creation_time'] + $cachettl)) {
1077
        // Use the value in the cache.
1078
        return (array) json_decode($result['meeting_info']);
1079
    }
1080
    // Ping again and refresh the cache.
1081
    $meetinginfo = (array) bigbluebuttonbn_wrap_xml_load_file(
1082
        \mod_bigbluebuttonbn\locallib\bigbluebutton::action_url('getMeetingInfo', ['meetingID' => $meetingid])
1083
      );
1084
    $cache->set($meetingid, array('creation_time' => time(), 'meeting_info' => json_encode($meetinginfo)));
1085
    return $meetinginfo;
1086
}
1087
1088
/**
1089
 * Perform isMeetingRunning on BBB.
1090
 *
1091
 * @param string $meetingid
1092
 * @param boolean $updatecache
1093
 *
1094
 * @return boolean
1095
 */
1096
function bigbluebuttonbn_is_meeting_running($meetingid, $updatecache = false) {
1097
    /* As a workaround to isMeetingRunning that always return SUCCESS but only returns true
1098
     * when at least one user is in the session, we use getMeetingInfo instead.
1099
     */
1100
    $meetinginfo = bigbluebuttonbn_get_meeting_info($meetingid, $updatecache);
1101
    return ($meetinginfo['returncode'] === 'SUCCESS');
1102
}
1103
1104
/**
1105
 * Publish an imported recording.
1106
 *
1107
 * @param string $id
1108
 * @param boolean $publish
1109
 *
1110
 * @return boolean
1111
 */
1112 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...
1113
    global $DB;
1114
    // Locate the record to be updated.
1115
    $record = $DB->get_record('bigbluebuttonbn_logs', array('id' => $id));
1116
    $meta = json_decode($record->meta, true);
1117
    // Prepare data for the update.
1118
    $meta['recording']['published'] = ($publish) ? 'true' : 'false';
1119
    $record->meta = json_encode($meta);
1120
    // Proceed with the update.
1121
    $DB->update_record('bigbluebuttonbn_logs', $record);
1122
    return true;
1123
}
1124
1125
/**
1126
 * Delete an imported recording.
1127
 *
1128
 * @param string $id
1129
 *
1130
 * @return boolean
1131
 */
1132
function bigbluebuttonbn_delete_recording_imported($id) {
1133
    global $DB;
1134
    // Execute delete.
1135
    $DB->delete_records('bigbluebuttonbn_logs', array('id' => $id));
1136
    return true;
1137
}
1138
1139
/**
1140
 * Update an imported recording.
1141
 *
1142
 * @param string $id
1143
 * @param array $params ['key'=>param_key, 'value']
1144
 *
1145
 * @return boolean
1146
 */
1147
function bigbluebuttonbn_update_recording_imported($id, $params) {
1148
    global $DB;
1149
    // Locate the record to be updated.
1150
    $record = $DB->get_record('bigbluebuttonbn_logs', array('id' => $id));
1151
    $meta = json_decode($record->meta, true);
1152
    // Prepare data for the update.
1153
    $meta['recording'] = $params + $meta['recording'];
1154
    $record->meta = json_encode($meta);
1155
    // Proceed with the update.
1156
    if (!$DB->update_record('bigbluebuttonbn_logs', $record)) {
1157
        return false;
1158
    }
1159
    return true;
1160
}
1161
1162
/**
1163
 * Protect/Unprotect an imported recording.
1164
 *
1165
 * @param string $id
1166
 * @param boolean $protect
1167
 *
1168
 * @return boolean
1169
 */
1170 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...
1171
    global $DB;
1172
    // Locate the record to be updated.
1173
    $record = $DB->get_record('bigbluebuttonbn_logs', array('id' => $id));
1174
    $meta = json_decode($record->meta, true);
1175
    // Prepare data for the update.
1176
    $meta['recording']['protected'] = ($protect) ? 'true' : 'false';
1177
    $record->meta = json_encode($meta);
1178
    // Proceed with the update.
1179
    $DB->update_record('bigbluebuttonbn_logs', $record);
1180
    return true;
1181
}
1182
1183
/**
1184
 * Sets a custom config.xml file for being used on create.
1185
 *
1186
 * @param string $meetingid
1187
 * @param string $configxml
1188
 *
1189
 * @return object
1190
 */
1191
function bigbluebuttonbn_set_config_xml($meetingid, $configxml) {
1192
    $urldefaultconfig = \mod_bigbluebuttonbn\locallib\config::get('server_url').'api/setConfigXML?';
1193
    $configxmlparams = bigbluebuttonbn_set_config_xml_params($meetingid, $configxml);
1194
    $xml = bigbluebuttonbn_wrap_xml_load_file($urldefaultconfig, 'POST',
1195
        $configxmlparams, 'application/x-www-form-urlencoded');
1196
    return $xml;
1197
}
1198
1199
/**
1200
 * Sets qs used with a custom config.xml file request.
1201
 *
1202
 * @param string $meetingid
1203
 * @param string $configxml
1204
 *
1205
 * @return string
1206
 */
1207
function bigbluebuttonbn_set_config_xml_params($meetingid, $configxml) {
1208
    $params = 'configXML='.urlencode($configxml).'&meetingID='.urlencode($meetingid);
1209
    $configxmlparams = $params.'&checksum='.sha1('setConfigXML'.$params.\mod_bigbluebuttonbn\locallib\config::get('shared_secret'));
1210
    return $configxmlparams;
1211
}
1212
1213
/**
1214
 * Sets a custom config.xml file for being used on create.
1215
 *
1216
 * @param string $meetingid
1217
 * @param string $configxml
1218
 *
1219
 * @return array
1220
 */
1221
function bigbluebuttonbn_set_config_xml_array($meetingid, $configxml) {
1222
    $configxml = bigbluebuttonbn_setConfigXML($meetingid, $configxml);
1223
    $configxmlarray = (array) $configxml;
1224
    if ($configxmlarray['returncode'] != 'SUCCESS') {
1225
        debugging('BigBlueButton was not able to set the custom config.xml file', DEBUG_DEVELOPER);
1226
        return '';
1227
    }
1228
    return $configxmlarray['configToken'];
1229
}
1230
1231
/**
1232
 * Helper function builds a row for the data used by the recording table.
1233
 *
1234
 * @param array $bbbsession
1235
 * @param array $recording
1236
 * @param array $tools
1237
 *
1238
 * @return array
1239
 */
1240
function bigbluebuttonbn_get_recording_data_row($bbbsession, $recording, $tools = ['protect', 'publish', 'delete']) {
1241
    if (!bigbluebuttonbn_include_recording_table_row($bbbsession, $recording)) {
1242
        return;
1243
    }
1244
    $rowdata = new stdClass();
1245
    // Set recording_types.
1246
    $rowdata->recording = bigbluebuttonbn_get_recording_data_row_types($recording, $bbbsession);
1247
    // Set activity name.
1248
    $rowdata->activity = bigbluebuttonbn_get_recording_data_row_meta_activity($recording, $bbbsession);
1249
    // Set activity description.
1250
    $rowdata->description = bigbluebuttonbn_get_recording_data_row_meta_description($recording, $bbbsession);
1251
    if (bigbluebuttonbn_get_recording_data_preview_enabled($bbbsession)) {
1252
        // Set recording_preview.
1253
        $rowdata->preview = bigbluebuttonbn_get_recording_data_row_preview($recording);
1254
    }
1255
    // Set date.
1256
    $rowdata->date = bigbluebuttonbn_get_recording_data_row_date($recording);
1257
    // Set formatted date.
1258
    $rowdata->date_formatted = bigbluebuttonbn_get_recording_data_row_date_formatted($rowdata->date);
1259
    // Set formatted duration.
1260
    $rowdata->duration_formatted = $rowdata->duration = bigbluebuttonbn_get_recording_data_row_duration($recording);
1261
    // Set actionbar, if user is allowed to manage recordings.
1262
    if ($bbbsession['managerecordings']) {
1263
        $rowdata->actionbar = bigbluebuttonbn_get_recording_data_row_actionbar($recording, $tools);
1264
    }
1265
    return $rowdata;
1266
}
1267
1268
/**
1269
 * Helper function evaluates if a row for the data used by the recording table is editable.
1270
 *
1271
 * @param array $bbbsession
1272
 *
1273
 * @return boolean
1274
 */
1275
function bigbluebuttonbn_get_recording_data_row_editable($bbbsession) {
1276
    return ($bbbsession['managerecordings'] && ((double)$bbbsession['serverversion'] >= 1.0 || $bbbsession['bnserver']));
1277
}
1278
1279
/**
1280
 * Helper function evaluates if recording preview should be included.
1281
 *
1282
 * @param array $bbbsession
1283
 *
1284
 * @return boolean
1285
 */
1286
function bigbluebuttonbn_get_recording_data_preview_enabled($bbbsession) {
1287
    return ((double)$bbbsession['serverversion'] >= 1.0 && $bbbsession['bigbluebuttonbn']->recordings_preview == '1');
1288
}
1289
1290
/**
1291
 * Helper function converts recording date used in row for the data used by the recording table.
1292
 *
1293
 * @param array $recording
1294
 *
1295
 * @return integer
1296
 */
1297
function bigbluebuttonbn_get_recording_data_row_date($recording) {
1298
    if (!isset($recording['startTime'])) {
1299
        return 0;
1300
    }
1301
    return floatval($recording['startTime']);
1302
}
1303
1304
/**
1305
 * Helper function format recording date used in row for the data used by the recording table.
1306
 *
1307
 * @param integer $starttime
1308
 *
1309
 * @return string
1310
 */
1311
function bigbluebuttonbn_get_recording_data_row_date_formatted($starttime) {
1312
    global $USER;
1313
    $starttime = $starttime - ($starttime % 1000);
1314
    // Set formatted date.
1315
    $dateformat = get_string('strftimerecentfull', 'langconfig').' %Z';
1316
    return userdate($starttime / 1000, $dateformat, usertimezone($USER->timezone));
1317
}
1318
1319
/**
1320
 * Helper function converts recording duration used in row for the data used by the recording table.
1321
 *
1322
 * @param array $recording
1323
 *
1324
 * @return integer
1325
 */
1326
function bigbluebuttonbn_get_recording_data_row_duration($recording) {
1327
    foreach (array_values($recording['playbacks']) as $playback) {
1328
        // Ignore restricted playbacks.
1329
        if (array_key_exists('restricted', $playback) && strtolower($playback['restricted']) == 'true') {
1330
            continue;
1331
        }
1332
        // Take the lenght form the fist playback with an actual value.
1333
        if (!empty($playback['length'])) {
1334
            return intval($playback['length']);
1335
        }
1336
    }
1337
    return 0;
1338
}
1339
1340
/**
1341
 * Helper function builds recording actionbar used in row for the data used by the recording table.
1342
 *
1343
 * @param array $recording
1344
 * @param array $tools
1345
 *
1346
 * @return string
1347
 */
1348
function bigbluebuttonbn_get_recording_data_row_actionbar($recording, $tools) {
1349
    $actionbar = '';
1350
    foreach ($tools as $tool) {
1351
        $buttonpayload = bigbluebuttonbn_get_recording_data_row_actionbar_payload($recording, $tool);
1352
        if ($tool == 'protect') {
1353
            if (isset($recording['imported'])) {
1354
                $buttonpayload['disabled'] = 'disabled';
1355
            }
1356
            if (!isset($recording['protected'])) {
1357
                $buttonpayload['disabled'] = 'invisible';
1358
            }
1359
        }
1360
        $actionbar .= bigbluebuttonbn_actionbar_render_button($recording, $buttonpayload);
1361
    }
1362
    $head = html_writer::start_tag('div', array(
1363
        'id' => 'recording-actionbar-' . $recording['recordID'],
1364
        'data-recordingid' => $recording['recordID'],
1365
        'data-meetingid' => $recording['meetingID']));
1366
    $tail = html_writer::end_tag('div');
1367
    return $head . $actionbar . $tail;
1368
}
1369
1370
/**
1371
 * Helper function returns the corresponding payload for an actionbar button used in row
1372
 * for the data used by the recording table.
1373
 *
1374
 * @param array $recording
1375
 * @param array $tool
1376
 *
1377
 * @return array
1378
 */
1379
function bigbluebuttonbn_get_recording_data_row_actionbar_payload($recording, $tool) {
1380
    if ($tool == 'protect') {
1381
        $protected = 'false';
1382
        if (isset($recording['protected'])) {
1383
            $protected = $recording['protected'];
1384
        }
1385
        return bigbluebuttonbn_get_recording_data_row_action_protect($protected);
1386
    }
1387
    if ($tool == 'publish') {
1388
        return bigbluebuttonbn_get_recording_data_row_action_publish($recording['published']);
1389
    }
1390
    return array('action' => $tool, 'tag' => $tool);
1391
}
1392
1393
/**
1394
 * Helper function returns the payload for protect action button used in row
1395
 * for the data used by the recording table.
1396
 *
1397
 * @param string $protected
1398
 *
1399
 * @return array
1400
 */
1401
function bigbluebuttonbn_get_recording_data_row_action_protect($protected) {
1402
    if ($protected == 'true') {
1403
        return array('action' => 'unprotect', 'tag' => 'lock');
1404
    }
1405
    return array('action' => 'protect', 'tag' => 'unlock');
1406
}
1407
1408
/**
1409
 * Helper function returns the payload for publish action button used in row
1410
 * for the data used by the recording table.
1411
 *
1412
 * @param string $published
1413
 *
1414
 * @return array
1415
 */
1416
function bigbluebuttonbn_get_recording_data_row_action_publish($published) {
1417
    if ($published == 'true') {
1418
        return array('action' => 'unpublish', 'tag' => 'hide');
1419
    }
1420
    return array('action' => 'publish', 'tag' => 'show');
1421
}
1422
1423
/**
1424
 * Helper function builds recording preview used in row for the data used by the recording table.
1425
 *
1426
 * @param array $recording
1427
 *
1428
 * @return string
1429
 */
1430
function bigbluebuttonbn_get_recording_data_row_preview($recording) {
1431
    $options = array('id' => 'preview-'.$recording['recordID']);
1432
    if ($recording['published'] === 'false') {
1433
        $options['hidden'] = 'hidden';
1434
    }
1435
    $recordingpreview = html_writer::start_tag('div', $options);
1436
    foreach ($recording['playbacks'] as $playback) {
1437
        if (isset($playback['preview'])) {
1438
            $recordingpreview .= bigbluebuttonbn_get_recording_data_row_preview_images($playback);
1439
            break;
1440
        }
1441
    }
1442
    $recordingpreview .= html_writer::end_tag('div');
1443
    return $recordingpreview;
1444
}
1445
1446
/**
1447
 * Helper function builds element with actual images used in recording preview row based on a selected playback.
1448
 *
1449
 * @param array $playback
1450
 *
1451
 * @return string
1452
 */
1453
function bigbluebuttonbn_get_recording_data_row_preview_images($playback) {
1454
    $recordingpreview  = html_writer::start_tag('div', array('class' => 'container-fluid'));
1455
    $recordingpreview .= html_writer::start_tag('div', array('class' => 'row'));
1456
    foreach ($playback['preview'] as $image) {
1457
        if (!bigbluebuttonbn_is_valid_resource(trim($image['url']))) {
1458
            return '';
1459
        }
1460
        $recordingpreview .= html_writer::start_tag('div', array('class' => ''));
1461
        $recordingpreview .= html_writer::empty_tag('img',
1462
            array('src' => trim($image['url']) . '?' . time(), 'class' => 'recording-thumbnail pull-left'));
1463
        $recordingpreview .= html_writer::end_tag('div');
1464
    }
1465
    $recordingpreview .= html_writer::end_tag('div');
1466
    $recordingpreview .= html_writer::start_tag('div', array('class' => 'row'));
1467
    $recordingpreview .= html_writer::tag('div', get_string('view_recording_preview_help', 'bigbluebuttonbn'),
1468
        array('class' => 'text-center text-muted small'));
1469
    $recordingpreview .= html_writer::end_tag('div');
1470
    $recordingpreview .= html_writer::end_tag('div');
1471
    return $recordingpreview;
1472
}
1473
1474
/**
1475
 * Helper function renders recording types to be used in row for the data used by the recording table.
1476
 *
1477
 * @param array $recording
1478
 * @param array $bbbsession
1479
 *
1480
 * @return string
1481
 */
1482
function bigbluebuttonbn_get_recording_data_row_types($recording, $bbbsession) {
1483
    $dataimported = 'false';
1484
    $title = '';
1485
    if (isset($recording['imported'])) {
1486
        $dataimported = 'true';
1487
        $title = get_string('view_recording_link_warning', 'bigbluebuttonbn');
1488
    }
1489
    $visibility = '';
1490
    if ($recording['published'] === 'false') {
1491
        $visibility = 'hidden ';
1492
    }
1493
    $id = 'playbacks-'.$recording['recordID'];
1494
    $recordingtypes = html_writer::start_tag('div', array('id' => $id, 'data-imported' => $dataimported,
1495
          'data-meetingid' => $recording['meetingID'], 'data-recordingid' => $recording['recordID'],
1496
          'title' => $title, $visibility => $visibility));
1497
    foreach ($recording['playbacks'] as $playback) {
1498
        $recordingtypes .= bigbluebuttonbn_get_recording_data_row_type($recording, $bbbsession, $playback);
1499
    }
1500
    $recordingtypes .= html_writer::end_tag('div');
1501
    return $recordingtypes;
1502
}
1503
1504
/**
1505
 * Helper function renders the link used for recording type in row for the data used by the recording table.
1506
 *
1507
 * @param array $recording
1508
 * @param array $bbbsession
1509
 * @param array $playback
1510
 *
1511
 * @return string
1512
 */
1513
function bigbluebuttonbn_get_recording_data_row_type($recording, $bbbsession, $playback) {
1514
    global $CFG, $OUTPUT;
1515
    if (!bigbluebuttonbn_include_recording_data_row_type($recording, $bbbsession, $playback)) {
1516
        return '';
1517
    }
1518
    $text = get_string('view_recording_format_'.$playback['type'], 'bigbluebuttonbn');
1519
    $href = $CFG->wwwroot . '/mod/bigbluebuttonbn/bbb_view.php?action=play&bn=' . $bbbsession['bigbluebuttonbn']->id .
1520
      '&mid='.$recording['meetingID'] . '&rid=' . $recording['recordID'] . '&rtype=' . $playback['type'];
1521
    if (!isset($recording['imported']) || !isset($recording['protected']) || $recording['protected'] === 'false') {
1522
        $href .= '&href='.urlencode(trim($playback['url']));
1523
    }
1524
    $linkattributes = array(
1525
        'id' => 'recording-play-' . $playback['type'] . '-' . $recording['recordID'],
1526
        'class' => 'btn btn-sm btn-default',
1527
        'onclick' => 'M.mod_bigbluebuttonbn.recordings.recordingPlay(this);',
1528
        'data-action' => 'play',
1529
        'data-target' => $playback['type'],
1530
        'data-href' => $href,
1531
      );
1532
    if (!bigbluebuttonbn_is_bn_server() && !bigbluebuttonbn_is_valid_resource(trim($playback['url']))) {
1533
        $linkattributes['class'] = 'btn btn-sm btn-warning';
1534
        $linkattributes['title'] = get_string('view_recording_format_errror_unreachable', 'bigbluebuttonbn');
1535
        unset($linkattributes['data-href']);
1536
    }
1537
    return $OUTPUT->action_link('#', $text, null, $linkattributes) . '&#32;';
1538
}
1539
1540
/**
1541
 * Helper function validates a remote resource.
1542
 *
1543
 * @param string $url
1544
 *
1545
 * @return boolean
1546
 */
1547
function bigbluebuttonbn_is_valid_resource($url) {
1548
    $urlhost = parse_url($url, PHP_URL_HOST);
1549
    $serverurlhost = parse_url(\mod_bigbluebuttonbn\locallib\config::get('server_url'), PHP_URL_HOST);
1550
    // Skip validation when the recording URL host is the same as the configured BBB server.
1551
    if ($urlhost == $serverurlhost) {
1552
        return true;
1553
    }
1554
    // Skip validation when the recording URL was already validated.
1555
    $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...
1556
    if (array_key_exists($urlhost, $validatedurls)) {
1557
        return $validatedurls[$urlhost];
1558
    }
1559
    // Validate the recording URL.
1560
    $validatedurls[$urlhost] = true;
1561
    $curlinfo = bigbluebuttonbn_wrap_xml_load_file_curl_request($url, 'HEAD');
1562
    if (!isset($curlinfo['http_code']) || $curlinfo['http_code'] != 200) {
1563
        $error = "Resources hosted by " . $urlhost . " are unreachable. Server responded with code " . $curlinfo['http_code'];
1564
        debugging($error, DEBUG_DEVELOPER);
1565
        $validatedurls[$urlhost] = false;
1566
    }
1567
    bigbluebuttonbn_cache_set('recordings_cache', 'validated_urls', $validatedurls);
1568
    return $validatedurls[$urlhost];
1569
}
1570
1571
/**
1572
 * Helper function renders the name for recording used in row for the data used by the recording table.
1573
 *
1574
 * @param array $recording
1575
 * @param array $bbbsession
1576
 *
1577
 * @return string
1578
 */
1579
function bigbluebuttonbn_get_recording_data_row_meta_activity($recording, $bbbsession) {
1580
    $payload = array();
1581 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...
1582
        $payload = array('recordingid' => $recording['recordID'], 'meetingid' => $recording['meetingID'],
1583
            'action' => 'edit', 'tag' => 'edit',
1584
            'target' => 'name');
1585
    }
1586
    $oldsource = 'meta_contextactivity';
1587
    if (isset($recording[$oldsource])) {
1588
        $metaname = trim($recording[$oldsource]);
1589
        return bigbluebuttonbn_get_recording_data_row_text($recording, $metaname, $oldsource, $payload);
1590
    }
1591
    $newsource = 'meta_bbb-recording-name';
1592 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...
1593
        $metaname = trim($recording[$newsource]);
1594
        return bigbluebuttonbn_get_recording_data_row_text($recording, $metaname, $newsource, $payload);
1595
    }
1596
    $metaname = trim($recording['meetingName']);
1597
    return bigbluebuttonbn_get_recording_data_row_text($recording, $metaname, $newsource, $payload);
1598
}
1599
1600
/**
1601
 * Helper function renders the description for recording used in row for the data used by the recording table.
1602
 *
1603
 * @param array $recording
1604
 * @param array $bbbsession
1605
 *
1606
 * @return string
1607
 */
1608
function bigbluebuttonbn_get_recording_data_row_meta_description($recording, $bbbsession) {
1609
    $payload = array();
1610 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...
1611
        $payload = array('recordingid' => $recording['recordID'], 'meetingid' => $recording['meetingID'],
1612
            'action' => 'edit', 'tag' => 'edit',
1613
            'target' => 'description');
1614
    }
1615
    $oldsource = 'meta_contextactivitydescription';
1616 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...
1617
        $metadescription = trim($recording[$oldsource]);
1618
        return bigbluebuttonbn_get_recording_data_row_text($recording, $metadescription, $oldsource, $payload);
1619
    }
1620
    $newsource = 'meta_bbb-recording-description';
1621 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...
1622
        $metadescription = trim($recording[$newsource]);
1623
        return bigbluebuttonbn_get_recording_data_row_text($recording, $metadescription, $newsource, $payload);
1624
    }
1625
    return bigbluebuttonbn_get_recording_data_row_text($recording, '', $newsource, $payload);
1626
}
1627
1628
/**
1629
 * Helper function renders text element for recording used in row for the data used by the recording table.
1630
 *
1631
 * @param array $recording
1632
 * @param string $text
1633
 * @param string $source
1634
 * @param array $data
1635
 *
1636
 * @return string
1637
 */
1638
function bigbluebuttonbn_get_recording_data_row_text($recording, $text, $source, $data) {
1639
    $htmltext = '<span>' . htmlentities($text) . '</span>';
1640
    if (empty($data)) {
1641
        return $htmltext;
1642
    }
1643
    $target = $data['action'] . '-' . $data['target'];
1644
    $id = 'recording-' . $target . '-' . $data['recordingid'];
1645
    $attributes = array('id' => $id, 'class' => 'quickeditlink col-md-20',
1646
        'data-recordingid' => $data['recordingid'], 'data-meetingid' => $data['meetingid'],
1647
        'data-target' => $data['target'], 'data-source' => $source);
1648
    $head = html_writer::start_tag('div', $attributes);
1649
    $tail = html_writer::end_tag('div');
1650
    $payload = array('action' => $data['action'], 'tag' => $data['tag'], 'target' => $data['target']);
1651
    $htmllink = bigbluebuttonbn_actionbar_render_button($recording, $payload);
1652
    return $head . $htmltext . $htmllink . $tail;
1653
}
1654
1655
/**
1656
 * Helper function render a button for the recording action bar
1657
 *
1658
 * @param array $recording
1659
 * @param array $data
1660
 *
1661
 * @return string
1662
 */
1663
function bigbluebuttonbn_actionbar_render_button($recording, $data) {
1664
    global $OUTPUT;
1665
    if (empty($data)) {
1666
        return '';
1667
    }
1668
    $target = $data['action'];
1669
    if (isset($data['target'])) {
1670
        $target .= '-' . $data['target'];
1671
    }
1672
    $id = 'recording-' . $target . '-' . $recording['recordID'];
1673
    $onclick = 'M.mod_bigbluebuttonbn.recordings.recording' . ucfirst($data['action']) . '(this);';
1674
    if ((boolean)\mod_bigbluebuttonbn\locallib\config::get('recording_icons_enabled')) {
1675
        // With icon for $manageaction.
1676
        $iconattributes = array('id' => $id, 'class' => 'iconsmall');
1677
        $linkattributes = array(
1678
            'id' => $id,
1679
            'onclick' => $onclick,
1680
            'data-action' => $data['action']
1681
          );
1682
        if (!isset($recording['imported'])) {
1683
            $linkattributes['data-links'] = bigbluebuttonbn_count_recording_imported_instances(
1684
              $recording['recordID']);
1685
        }
1686
        if (isset($data['disabled'])) {
1687
            $iconattributes['class'] .= ' fa-' . $data['disabled'];
1688
            $linkattributes['class'] = 'disabled';
1689
            unset($linkattributes['onclick']);
1690
        }
1691
        $icon = new pix_icon('i/'.$data['tag'],
1692
            get_string('view_recording_list_actionbar_' . $data['action'], 'bigbluebuttonbn'),
1693
            'moodle', $iconattributes);
1694
        return $OUTPUT->action_icon('#', $icon, null, $linkattributes, false);
1695
    }
1696
    // With text for $manageaction.
1697
    $linkattributes = array('title' => get_string($data['tag']), 'class' => 'btn btn-xs btn-danger',
1698
        'onclick' => $onclick);
1699
    return $OUTPUT->action_link('#', get_string($data['action']), null, $linkattributes);
1700
}
1701
1702
/**
1703
 * Helper function builds the data used for headers by the recording table.
1704
 *
1705
 * @param array $bbbsession
1706
 *
1707
 * @return array
1708
 */
1709
function bigbluebuttonbn_get_recording_columns($bbbsession) {
1710
    $columns = array();
1711
    // Initialize table headers.
1712
    $columns[] = array('key' => 'recording', 'label' => get_string('view_recording_recording', 'bigbluebuttonbn'),
1713
        'width' => '125px', 'allowHTML' => true);
1714
    $columns[] = array('key' => 'activity', 'label' => get_string('view_recording_activity', 'bigbluebuttonbn'),
1715
        'sortable' => true, 'width' => '175px', 'allowHTML' => true);
1716
    $columns[] = array('key' => 'description', 'label' => get_string('view_recording_description', 'bigbluebuttonbn'),
1717
        'sortable' => true, 'width' => '250px', 'allowHTML' => true);
1718
    if (bigbluebuttonbn_get_recording_data_preview_enabled($bbbsession)) {
1719
        $columns[] = array('key' => 'preview', 'label' => get_string('view_recording_preview', 'bigbluebuttonbn'),
1720
            'width' => '250px', 'allowHTML' => true);
1721
    }
1722
    $columns[] = array('key' => 'date', 'label' => get_string('view_recording_date', 'bigbluebuttonbn'),
1723
        'sortable' => true, 'width' => '225px', 'allowHTML' => true);
1724
    $columns[] = array('key' => 'duration', 'label' => get_string('view_recording_duration', 'bigbluebuttonbn'),
1725
        'width' => '50px');
1726
    if ($bbbsession['managerecordings']) {
1727
        $columns[] = array('key' => 'actionbar', 'label' => get_string('view_recording_actionbar', 'bigbluebuttonbn'),
1728
            'width' => '120px', 'allowHTML' => true);
1729
    }
1730
    return $columns;
1731
}
1732
1733
/**
1734
 * Helper function builds the data used by the recording table.
1735
 *
1736
 * @param array $bbbsession
1737
 * @param array $recordings
1738
 * @param array $tools
1739
 *
1740
 * @return array
1741
 */
1742
function bigbluebuttonbn_get_recording_data($bbbsession, $recordings, $tools = ['protect', 'publish', 'delete']) {
1743
    $tabledata = array();
1744
    // Build table content.
1745
    if (isset($recordings) && !array_key_exists('messageKey', $recordings)) {
1746
        // There are recordings for this meeting.
1747
        foreach ($recordings as $recording) {
1748
            $rowdata = bigbluebuttonbn_get_recording_data_row($bbbsession, $recording, $tools);
1749
            if (!empty($rowdata)) {
1750
                array_push($tabledata, $rowdata);
1751
            }
1752
        }
1753
    }
1754
    return $tabledata;
1755
}
1756
1757
/**
1758
 * Helper function builds the recording table.
1759
 *
1760
 * @param array $bbbsession
1761
 * @param array $recordings
1762
 * @param array $tools
1763
 *
1764
 * @return object
1765
 */
1766
function bigbluebuttonbn_get_recording_table($bbbsession, $recordings, $tools = ['protect', 'publish', 'delete']) {
1767
    // Declare the table.
1768
    $table = new html_table();
1769
    $table->data = array();
1770
    // Initialize table headers.
1771
    $table->head[] = get_string('view_recording_playback', 'bigbluebuttonbn');
1772
    $table->head[] = get_string('view_recording_recording', 'bigbluebuttonbn');
1773
    $table->head[] = get_string('view_recording_description', 'bigbluebuttonbn');
1774
    if (bigbluebuttonbn_get_recording_data_preview_enabled($bbbsession)) {
1775
        $table->head[] = get_string('view_recording_preview', 'bigbluebuttonbn');
1776
    }
1777
    $table->head[] = get_string('view_recording_date', 'bigbluebuttonbn');
1778
    $table->head[] = get_string('view_recording_duration', 'bigbluebuttonbn');
1779
    $table->align = array('left', 'left', 'left', 'left', 'left', 'center');
1780
    $table->size = array('', '', '', '', '', '');
1781
    if ($bbbsession['managerecordings']) {
1782
        $table->head[] = get_string('view_recording_actionbar', 'bigbluebuttonbn');
1783
        $table->align[] = 'left';
1784
        $table->size[] = (count($tools) * 40) . 'px';
1785
    }
1786
    // Build table content.
1787
    foreach ($recordings as $recording) {
1788
        $rowdata = bigbluebuttonbn_get_recording_data_row($bbbsession, $recording, $tools);
1789
        if (!empty($rowdata)) {
1790
            $row = bigbluebuttonbn_get_recording_table_row($bbbsession, $recording, $rowdata);
1791
            array_push($table->data, $row);
1792
        }
1793
    }
1794
    return $table;
1795
}
1796
1797
/**
1798
 * Helper function builds the recording table row and insert into table.
1799
 *
1800
 * @param array $bbbsession
1801
 * @param array $recording
1802
 * @param object $rowdata
1803
 *
1804
 * @return object
1805
 */
1806
function bigbluebuttonbn_get_recording_table_row($bbbsession, $recording, $rowdata) {
1807
    $row = new html_table_row();
1808
    $row->id = 'recording-tr-'.$recording['recordID'];
1809
    $row->attributes['data-imported'] = 'false';
1810
    $texthead = '';
1811
    $texttail = '';
1812
    if (isset($recording['imported'])) {
1813
        $row->attributes['title'] = get_string('view_recording_link_warning', 'bigbluebuttonbn');
1814
        $row->attributes['data-imported'] = 'true';
1815
        $texthead = '<em>';
1816
        $texttail = '</em>';
1817
    }
1818
    $rowdata->date_formatted = str_replace(' ', '&nbsp;', $rowdata->date_formatted);
1819
    $row->cells = array();
1820
    $row->cells[] = $texthead . $rowdata->recording . $texttail;
1821
    $row->cells[] = $texthead . $rowdata->activity . $texttail;
1822
    $row->cells[] = $texthead . $rowdata->description . $texttail;
1823
    if (bigbluebuttonbn_get_recording_data_preview_enabled($bbbsession)) {
1824
        $row->cells[] = $rowdata->preview;
1825
    }
1826
    $row->cells[] = $texthead . $rowdata->date_formatted . $texttail;
1827
    $row->cells[] = $rowdata->duration_formatted;
1828
    if ($bbbsession['managerecordings']) {
1829
        $row->cells[] = $rowdata->actionbar;
1830
    }
1831
    return $row;
1832
}
1833
1834
/**
1835
 * Helper function evaluates if recording row should be included in the table.
1836
 *
1837
 * @param array $bbbsession
1838
 * @param array $recording
1839
 *
1840
 * @return boolean
1841
 */
1842
function bigbluebuttonbn_include_recording_table_row($bbbsession, $recording) {
1843
    // Exclude unpublished recordings, only if user has no rights to manage them.
1844
    if ($recording['published'] != 'true' && !$bbbsession['managerecordings']) {
1845
        return false;
1846
    }
1847
    // Imported recordings are always shown as long as they are published.
1848
    if (isset($recording['imported'])) {
1849
        return true;
1850
    }
1851
    // When groups are enabled, exclude those to which the user doesn't have access to.
1852
    if (isset($bbbsession['group']) && $recording['meetingID'] != $bbbsession['meetingid']) {
1853
        return false;
1854
    }
1855
    return true;
1856
}
1857
1858
/**
1859
 * Helper function triggers a send notification when the recording is ready.
1860
 *
1861
 * @param object $bigbluebuttonbn
1862
 *
1863
 * @return void
1864
 */
1865
function bigbluebuttonbn_send_notification_recording_ready($bigbluebuttonbn) {
1866
    $sender = get_admin();
1867
    // Prepare message.
1868
    $messagetext = '<p>'.get_string('email_body_recording_ready_for', 'bigbluebuttonbn').
1869
        ' &quot;' . $bigbluebuttonbn->name . '&quot; '.
1870
        get_string('email_body_recording_ready_is_ready', 'bigbluebuttonbn').'.</p>';
1871
    $context = context_course::instance($bigbluebuttonbn->course);
1872
    \mod_bigbluebuttonbn\locallib\notifier::notification_send($context, $sender, $bigbluebuttonbn, $messagetext);
1873
}
1874
1875
/**
1876
 * Helper evaluates if the bigbluebutton server used belongs to blindsidenetworks domain.
1877
 *
1878
 * @return boolean
1879
 */
1880
function bigbluebuttonbn_is_bn_server() {
1881
    $parsedurl = parse_url(\mod_bigbluebuttonbn\locallib\config::get('server_url'));
1882
    if (!isset($parsedurl['host'])) {
1883
        return false;
1884
    }
1885
    $h = $parsedurl['host'];
1886
    $hends = explode('.', $h);
1887
    $hendslength = count($hends);
1888
    return ($hends[$hendslength - 1] == 'com' && $hends[$hendslength - 2] == 'blindsidenetworks');
1889
}
1890
1891
/**
1892
 * Helper function returns a list of courses a user has access to, wrapped in an array that can be used
1893
 * by a html select.
1894
 *
1895
 * @param array $bbbsession
1896
 *
1897
 * @return array
1898
 */
1899
function bigbluebuttonbn_import_get_courses_for_select(array $bbbsession) {
1900
    if ($bbbsession['administrator']) {
1901
        $courses = get_courses('all', 'c.fullname ASC', 'c.id,c.shortname,c.fullname');
1902
        // It includes the name of the site as a course (category 0), so remove the first one.
1903
        unset($courses['1']);
1904
    } else {
1905
        $courses = enrol_get_users_courses($bbbsession['userID'], false, 'id,shortname,fullname');
1906
    }
1907
    $coursesforselect = [];
1908
    foreach ($courses as $course) {
1909
        $coursesforselect[$course->id] = $course->fullname;
1910
    }
1911
    return $coursesforselect;
1912
}
1913
1914
/**
1915
 * Helper function renders recording table.
1916
 *
1917
 * @param array $bbbsession
1918
 * @param array $recordings
1919
 * @param array $tools
1920
 *
1921
 * @return array
1922
 */
1923
function bigbluebuttonbn_output_recording_table($bbbsession, $recordings, $tools = ['protect', 'publish', 'delete']) {
1924
    if (isset($recordings) && !empty($recordings)) {
1925
        // There are recordings for this meeting.
1926
        $table = bigbluebuttonbn_get_recording_table($bbbsession, $recordings, $tools);
1927
    }
1928
    if (!isset($table) || !isset($table->data)) {
1929
        // Render a table with "No recordings".
1930
        return html_writer::div(get_string('view_message_norecordings', 'bigbluebuttonbn'), '',
1931
            array('id' => 'bigbluebuttonbn_recordings_table'));
1932
    }
1933
    // Render the table.
1934
    return html_writer::div(html_writer::table($table), '', array('id' => 'bigbluebuttonbn_recordings_table'));
1935
}
1936
1937
/**
1938
 * Helper function to convert an html string to plain text.
1939
 *
1940
 * @param string $html
1941
 * @param integer $len
1942
 *
1943
 * @return string
1944
 */
1945
function bigbluebuttonbn_html2text($html, $len = 0) {
1946
    $text = strip_tags($html);
1947
    $text = str_replace('&nbsp;', ' ', $text);
1948
    $textlen = strlen($text);
1949
    $text = substr($text, 0, $len);
1950
    if ($textlen > $len) {
1951
        $text .= '...';
1952
    }
1953
    return $text;
1954
}
1955
1956
/**
1957
 * Helper function to obtain the tags linked to a bigbluebuttonbn activity
1958
 *
1959
 * @param string $id
1960
 *
1961
 * @return string containing the tags separated by commas
1962
 */
1963
function bigbluebuttonbn_get_tags($id) {
1964
    if (class_exists('core_tag_tag')) {
1965
        return implode(',', core_tag_tag::get_item_tags_array('core', 'course_modules', $id));
1966
    }
1967
    return implode(',', tag_get_tags('bigbluebuttonbn', $id));
1968
}
1969
1970
/**
1971
 * Helper function to define the sql used for gattering the bigbluebuttonbnids whose meetingids should be included
1972
 * in the getRecordings request
1973
 *
1974
 * @param string $courseid
1975
 * @param string $bigbluebuttonbnid
1976
 * @param bool   $subset
1977
 *
1978
 * @return string containing the sql used for getting the target bigbluebuttonbn instances
1979
 */
1980
function bigbluebuttonbn_get_recordings_sql_select($courseid, $bigbluebuttonbnid = null, $subset = true) {
1981
    if (empty($courseid)) {
1982
        $courseid = 0;
1983
    }
1984
    if (empty($bigbluebuttonbnid)) {
1985
        return "course = '{$courseid}'";
1986
    }
1987
    if ($subset) {
1988
        return "id = '{$bigbluebuttonbnid}'";
1989
    }
1990
    return "id <> '{$bigbluebuttonbnid}' AND course = '{$courseid}'";
1991
}
1992
1993
/**
1994
 * Helper function to define the sql used for gattering the bigbluebuttonbnids whose meetingids should be included
1995
 * in the getRecordings request considering only those that belong to deleted activities.
1996
 *
1997
 * @param string $courseid
1998
 * @param string $bigbluebuttonbnid
1999
 * @param bool   $subset
2000
 *
2001
 * @return string containing the sql used for getting the target bigbluebuttonbn instances
2002
 */
2003 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...
2004
    $sql = "log = '" . BIGBLUEBUTTONBN_LOG_EVENT_DELETE . "' AND meta like '%has_recordings%' AND meta like '%true%'";
2005
    if (empty($courseid)) {
2006
        $courseid = 0;
2007
    }
2008
    if (empty($bigbluebuttonbnid)) {
2009
        return $sql . " AND courseid = {$courseid}";
2010
    }
2011
    if ($subset) {
2012
        return $sql . " AND bigbluebuttonbnid = '{$bigbluebuttonbnid}'";
2013
    }
2014
    return $sql . " AND courseid = {$courseid} AND bigbluebuttonbnid <> '{$bigbluebuttonbnid}'";
2015
}
2016
2017
/**
2018
 * Helper function to define the sql used for gattering the bigbluebuttonbnids whose meetingids should be included
2019
 * in the getRecordings request considering only those that belong to imported recordings.
2020
 *
2021
 * @param string $courseid
2022
 * @param string $bigbluebuttonbnid
2023
 * @param bool   $subset
2024
 *
2025
 * @return string containing the sql used for getting the target bigbluebuttonbn instances
2026
 */
2027 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...
2028
    $sql = "log = '" . BIGBLUEBUTTONBN_LOG_EVENT_IMPORT . "'";
2029
    if (empty($courseid)) {
2030
        $courseid = 0;
2031
    }
2032
    if (empty($bigbluebuttonbnid)) {
2033
        return $sql . " AND courseid = '{$courseid}'";
2034
    }
2035
    if ($subset) {
2036
        return $sql . " AND bigbluebuttonbnid = '{$bigbluebuttonbnid}'";
2037
    }
2038
    return $sql . " AND courseid = '{$courseid}' AND bigbluebuttonbnid <> '{$bigbluebuttonbnid}'";
2039
}
2040
2041
/**
2042
 * Helper function to get recordings  and imported recordings together.
2043
 *
2044
 * @param string $courseid
2045
 * @param string $bigbluebuttonbnid
2046
 * @param bool   $subset
2047
 * @param bool   $includedeleted
2048
 *
2049
 * @return associative array containing the recordings indexed by recordID, each recording is also a
2050
 * non sequential associative array itself that corresponds to the actual recording in BBB
2051
 */
2052
function bigbluebuttonbn_get_allrecordings($courseid = 0, $bigbluebuttonbnid = null, $subset = true, $includedeleted = false) {
2053
    $recordings = bigbluebuttonbn_get_recordings($courseid, $bigbluebuttonbnid, $subset, $includedeleted);
2054
    $recordingsimported = bigbluebuttonbn_get_recordings_imported_array($courseid, $bigbluebuttonbnid, $subset);
2055
    return ($recordings + $recordingsimported);
2056
}
2057
2058
/**
2059
 * Helper function to retrieve recordings from the BigBlueButton. The references are stored as events
2060
 * in bigbluebuttonbn_logs.
2061
 *
2062
 * @param string $courseid
2063
 * @param string $bigbluebuttonbnid
2064
 * @param bool   $subset
2065
 * @param bool   $includedeleted
2066
 *
2067
 * @return associative array containing the recordings indexed by recordID, each recording is also a
2068
 * non sequential associative array itself that corresponds to the actual recording in BBB
2069
 */
2070
function bigbluebuttonbn_get_recordings($courseid = 0, $bigbluebuttonbnid = null, $subset = true, $includedeleted = false) {
2071
    global $DB;
2072
    $select = bigbluebuttonbn_get_recordings_sql_select($courseid, $bigbluebuttonbnid, $subset);
2073
    $bigbluebuttonbns = $DB->get_records_select_menu('bigbluebuttonbn', $select, null, 'id', 'id, meetingid');
2074
    /* Consider logs from deleted bigbluebuttonbn instances whose meetingids should be included in
2075
     * the getRecordings request. */
2076
    if ($includedeleted) {
2077
        $selectdeleted = bigbluebuttonbn_get_recordings_deleted_sql_select($courseid, $bigbluebuttonbnid, $subset);
2078
        $bigbluebuttonbnsdel = $DB->get_records_select_menu('bigbluebuttonbn_logs', $selectdeleted, null,
2079
            'bigbluebuttonbnid', 'bigbluebuttonbnid, meetingid');
2080
        if (!empty($bigbluebuttonbnsdel)) {
2081
            // Merge bigbluebuttonbnis from deleted instances, only keys are relevant.
2082
            // Artimetic merge is used in order to keep the keys.
2083
            $bigbluebuttonbns += $bigbluebuttonbnsdel;
2084
        }
2085
    }
2086
    // Gather the meetingids from bigbluebuttonbn logs that include a create with record=true.
2087
    if (empty($bigbluebuttonbns)) {
2088
        return array();
2089
    }
2090
    // Prepare select for loading records based on existent bigbluebuttonbns.
2091
    $sql = 'SELECT DISTINCT meetingid, bigbluebuttonbnid FROM {bigbluebuttonbn_logs} WHERE ';
2092
    $sql .= '(bigbluebuttonbnid='.implode(' OR bigbluebuttonbnid=', array_keys($bigbluebuttonbns)).')';
2093
    // Include only Create events and exclude those with record not true.
2094
    $sql .= ' AND log = ? AND meta LIKE ? AND meta LIKE ?';
2095
    // Execute select for loading records based on existent bigbluebuttonbns.
2096
    $records = $DB->get_records_sql_menu($sql, array(BIGBLUEBUTTONBN_LOG_EVENT_CREATE, '%record%', '%true%'));
2097
    // Get actual recordings.
2098
    return bigbluebuttonbn_get_recordings_array(array_keys($records));
2099
}
2100
2101
/**
2102
 * Helper function iterates an array with recordings and unset those already imported.
2103
 *
2104
 * @param array $recordings
2105
 * @param integer $courseid
2106
 * @param integer $bigbluebuttonbnid
2107
 *
2108
 * @return array
2109
 */
2110
function bigbluebuttonbn_unset_existent_recordings_already_imported($recordings, $courseid, $bigbluebuttonbnid) {
2111
    $recordingsimported = bigbluebuttonbn_get_recordings_imported_array($courseid, $bigbluebuttonbnid, true);
2112
    foreach ($recordings as $key => $recording) {
2113
        if (isset($recordingsimported[$recording['recordID']])) {
2114
            unset($recordings[$key]);
2115
        }
2116
    }
2117
    return $recordings;
2118
}
2119
2120
/**
2121
 * Helper function to count the imported recordings for a recordingid.
2122
 *
2123
 * @param string $recordid
2124
 *
2125
 * @return integer
2126
 */
2127
function bigbluebuttonbn_count_recording_imported_instances($recordid) {
2128
    global $DB;
2129
    $sql = 'SELECT COUNT(DISTINCT id) FROM {bigbluebuttonbn_logs} WHERE log = ? AND meta LIKE ? AND meta LIKE ?';
2130
    return $DB->count_records_sql($sql, array(BIGBLUEBUTTONBN_LOG_EVENT_IMPORT, '%recordID%', "%{$recordid}%"));
2131
}
2132
2133
/**
2134
 * Helper function returns an array with all the instances of imported recordings for a recordingid.
2135
 *
2136
 * @param string $recordid
2137
 *
2138
 * @return array
2139
 */
2140
function bigbluebuttonbn_get_recording_imported_instances($recordid) {
2141
    global $DB;
2142
    $sql = 'SELECT * FROM {bigbluebuttonbn_logs} WHERE log = ? AND meta LIKE ? AND meta LIKE ?';
2143
    $recordingsimported = $DB->get_records_sql($sql, array(BIGBLUEBUTTONBN_LOG_EVENT_IMPORT, '%recordID%',
2144
        "%{$recordid}%"));
2145
    return $recordingsimported;
2146
}
2147
2148
/**
2149
 * Helper function to get how much callback events are logged.
2150
 *
2151
 * @param string $recordid
2152
 *
2153
 * @return integer
2154
 */
2155
function bigbluebuttonbn_get_count_callback_event_log($recordid) {
2156
    global $DB;
2157
    $sql = 'SELECT count(DISTINCT id) FROM {bigbluebuttonbn_logs} WHERE log = ? AND meta LIKE ? AND meta LIKE ?';
2158
    return $DB->count_records_sql($sql, array(BIGBLUEBUTTON_LOG_EVENT_CALLBACK, '%recordid%', "%{$recordid}%"));
2159
}
2160
2161
/**
2162
 * Helper function returns an array with the profiles (with features per profile) for the different types
2163
 * of bigbluebuttonbn instances.
2164
 *
2165
 * @return array
2166
 */
2167
function bigbluebuttonbn_get_instance_type_profiles() {
2168
    $instanceprofiles = array(
2169
        BIGBLUEBUTTONBN_TYPE_ALL => array('id' => BIGBLUEBUTTONBN_TYPE_ALL,
2170
                  'name' => get_string('instance_type_default', 'bigbluebuttonbn'),
2171
                  'features' => array('all')),
2172
        BIGBLUEBUTTONBN_TYPE_ROOM_ONLY => array('id' => BIGBLUEBUTTONBN_TYPE_ROOM_ONLY,
2173
                  'name' => get_string('instance_type_room_only', 'bigbluebuttonbn'),
2174
                  'features' => array('showroom', 'welcomemessage', 'voicebridge', 'waitformoderator', 'userlimit',
2175
                      'recording', 'sendnotifications', 'preuploadpresentation', 'permissions', 'schedule', 'groups',
2176
                      'modstandardelshdr', 'availabilityconditionsheader', 'tagshdr', 'competenciessection',
2177
                      'clienttype')),
2178
        BIGBLUEBUTTONBN_TYPE_RECORDING_ONLY => array('id' => BIGBLUEBUTTONBN_TYPE_RECORDING_ONLY,
2179
                  'name' => get_string('instance_type_recording_only', 'bigbluebuttonbn'),
2180
                  'features' => array('showrecordings', 'importrecordings'))
2181
    );
2182
    return $instanceprofiles;
2183
}
2184
2185
/**
2186
 * Helper function returns an array with enabled features for an specific profile type.
2187
 *
2188
 * @param array $typeprofiles
2189
 * @param string $type
2190
 *
2191
 * @return array
2192
 */
2193
function bigbluebuttonbn_get_enabled_features($typeprofiles, $type = null) {
2194
    $enabledfeatures = array();
2195
    $features = $typeprofiles[BIGBLUEBUTTONBN_TYPE_ALL]['features'];
2196
    if (!is_null($type) && key_exists($type, $typeprofiles)) {
2197
        $features = $typeprofiles[$type]['features'];
2198
    }
2199
    $enabledfeatures['showroom'] = (in_array('all', $features) || in_array('showroom', $features));
2200
    // Evaluates if recordings are enabled for the Moodle site.
2201
    $enabledfeatures['showrecordings'] = false;
2202
    if (\mod_bigbluebuttonbn\locallib\config::recordings_enabled()) {
2203
        $enabledfeatures['showrecordings'] = (in_array('all', $features) || in_array('showrecordings', $features));
2204
    }
2205
    $enabledfeatures['importrecordings'] = false;
2206
    if (\mod_bigbluebuttonbn\locallib\config::importrecordings_enabled()) {
2207
        $enabledfeatures['importrecordings'] = (in_array('all', $features) || in_array('importrecordings', $features));
2208
    }
2209
    // Evaluates if clienttype is enabled for the Moodle site.
2210
    $enabledfeatures['clienttype'] = false;
2211
    if (\mod_bigbluebuttonbn\locallib\config::clienttype_enabled()) {
2212
        $enabledfeatures['clienttype'] = (in_array('all', $features) || in_array('clienttype', $features));
2213
    }
2214
    return $enabledfeatures;
2215
}
2216
2217
/**
2218
 * Helper function returns an array with the profiles (with features per profile) for the different types
2219
 * of bigbluebuttonbn instances.
2220
 *
2221
 * @param array $profiles
2222
 *
2223
 * @return array
2224
 */
2225
function bigbluebuttonbn_get_instance_profiles_array($profiles = null) {
2226
    if (is_null($profiles) || empty($profiles)) {
2227
        $profiles = bigbluebuttonbn_get_instance_type_profiles();
2228
    }
2229
    $profilesarray = array();
2230
    foreach ($profiles as $key => $profile) {
2231
        $profilesarray += array("{$key}" => $profile['name']);
2232
    }
2233
    return $profilesarray;
2234
}
2235
2236
/**
2237
 * Helper function returns time in a formatted string.
2238
 *
2239
 * @param integer $time
2240
 *
2241
 * @return string
2242
 */
2243
function bigbluebuttonbn_format_activity_time($time) {
2244
    $activitytime = '';
2245
    if ($time) {
2246
        $activitytime = calendar_day_representation($time).' '.
2247
          get_string('mod_form_field_notification_msg_at', 'bigbluebuttonbn').' '.
2248
          calendar_time_representation($time);
2249
    }
2250
    return $activitytime;
2251
}
2252
2253
/**
2254
 * Helper function returns array with all the strings to be used in javascript.
2255
 *
2256
 * @return array
2257
 */
2258
function bigbluebuttonbn_get_strings_for_js() {
2259
    $locale = bigbluebuttonbn_get_locale();
2260
    $stringman = get_string_manager();
2261
    $strings = $stringman->load_component_strings('bigbluebuttonbn', $locale);
2262
    return $strings;
2263
}
2264
2265
/**
2266
 * Helper function returns the locale set by moodle.
2267
 *
2268
 * @return string
2269
 */
2270
function bigbluebuttonbn_get_locale() {
2271
    $lang = get_string('locale', 'core_langconfig');
2272
    return substr($lang, 0, strpos($lang, '.'));
2273
}
2274
2275
/**
2276
 * Helper function returns the locale code based on the locale set by moodle.
2277
 *
2278
 * @return string
2279
 */
2280
function bigbluebuttonbn_get_localcode() {
2281
    $locale = bigbluebuttonbn_get_locale();
2282
    return substr($locale, 0, strpos($locale, '_'));
2283
}
2284
2285
/**
2286
 * Helper function returns array with the instance settings used in views.
2287
 *
2288
 * @param string $id
2289
 * @param object $bigbluebuttonbnid
2290
 *
2291
 * @return array
2292
 */
2293
function bigbluebuttonbn_view_validator($id, $bigbluebuttonbnid) {
2294
    if ($id) {
2295
        return bigbluebuttonbn_view_instance_id($id);
2296
    }
2297
    if ($bigbluebuttonbnid) {
2298
        return bigbluebuttonbn_view_instance_bigbluebuttonbn($bigbluebuttonbnid);
2299
    }
2300
    return;
2301
}
2302
2303
/**
2304
 * Helper function returns array with the instance settings used in views based on id.
2305
 *
2306
 * @param string $id
2307
 *
2308
 * @return array
2309
 */
2310 View Code Duplication
function bigbluebuttonbn_view_instance_id($id) {
0 ignored issues
show
Duplication introduced by
This function seems to be duplicated in your project.

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

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

Loading history...
2311
    global $DB;
2312
    $cm = get_coursemodule_from_id('bigbluebuttonbn', $id, 0, false, MUST_EXIST);
2313
    $course = $DB->get_record('course', array('id' => $cm->course), '*', MUST_EXIST);
2314
    $bigbluebuttonbn = $DB->get_record('bigbluebuttonbn', array('id' => $cm->instance), '*', MUST_EXIST);
2315
    return array('cm' => $cm, 'course' => $course, 'bigbluebuttonbn' => $bigbluebuttonbn);
2316
}
2317
2318
/**
2319
 * Helper function returns array with the instance settings used in views based on bigbluebuttonbnid.
2320
 *
2321
 * @param object $bigbluebuttonbnid
2322
 *
2323
 * @return array
2324
 */
2325 View Code Duplication
function bigbluebuttonbn_view_instance_bigbluebuttonbn($bigbluebuttonbnid) {
0 ignored issues
show
Duplication introduced by
This function seems to be duplicated in your project.

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

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

Loading history...
2326
    global $DB;
2327
    $bigbluebuttonbn = $DB->get_record('bigbluebuttonbn', array('id' => $bigbluebuttonbnid), '*', MUST_EXIST);
2328
    $course = $DB->get_record('course', array('id' => $bigbluebuttonbn->course), '*', MUST_EXIST);
2329
    $cm = get_coursemodule_from_instance('bigbluebuttonbn', $bigbluebuttonbn->id, $course->id, false, MUST_EXIST);
2330
    return array('cm' => $cm, 'course' => $course, 'bigbluebuttonbn' => $bigbluebuttonbn);
2331
}
2332
2333
/**
2334
 * Helper function renders general warning message for settings (if any).
2335
 *
2336
 * @param object $renderer
2337
 *
2338
 * @return void
2339
 */
2340
function bigbluebuttonbn_settings_general_warning(&$renderer) {
0 ignored issues
show
Unused Code introduced by
The parameter $renderer is not used and could be removed.

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

Loading history...
2341
    return;
2342
}
2343
2344
/**
2345
 * Helper function renders general settings if the feature is enabled.
2346
 *
2347
 * @param object $renderer
2348
 *
2349
 * @return void
2350
 */
2351
function bigbluebuttonbn_settings_general(&$renderer) {
2352
    // Configuration for BigBlueButton.
2353
    if ((boolean)\mod_bigbluebuttonbn\settings\validator::section_general_shown()) {
2354
        $renderer->render_group_header('general');
2355
        $renderer->render_group_element('server_url',
2356
            $renderer->render_group_element_text('server_url', BIGBLUEBUTTONBN_DEFAULT_SERVER_URL));
2357
        $renderer->render_group_element('shared_secret',
2358
            $renderer->render_group_element_text('shared_secret', BIGBLUEBUTTONBN_DEFAULT_SHARED_SECRET));
2359
    }
2360
}
2361
2362
/**
2363
 * Helper function renders record settings if the feature is enabled.
2364
 *
2365
 * @param object $renderer
2366
 *
2367
 * @return void
2368
 */
2369
function bigbluebuttonbn_settings_record(&$renderer) {
2370
    // Configuration for 'recording' feature.
2371 View Code Duplication
    if ((boolean)\mod_bigbluebuttonbn\settings\validator::section_record_meeting_shown()) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
2372
        $renderer->render_group_header('recording');
2373
        $renderer->render_group_element('recording_default',
2374
            $renderer->render_group_element_checkbox('recording_default', 1));
2375
        $renderer->render_group_element('recording_editable',
2376
            $renderer->render_group_element_checkbox('recording_editable', 1));
2377
        $renderer->render_group_element('recording_icons_enabled',
2378
            $renderer->render_group_element_checkbox('recording_icons_enabled', 1));
2379
    }
2380
}
2381
2382
/**
2383
 * Helper function renders import recording settings if the feature is enabled.
2384
 *
2385
 * @param object $renderer
2386
 *
2387
 * @return void
2388
 */
2389 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...
2390
    // Configuration for 'import recordings' feature.
2391
    if ((boolean)\mod_bigbluebuttonbn\settings\validator::section_import_recordings_shown()) {
2392
        $renderer->render_group_header('importrecordings');
2393
        $renderer->render_group_element('importrecordings_enabled',
2394
            $renderer->render_group_element_checkbox('importrecordings_enabled', 0));
2395
        $renderer->render_group_element('importrecordings_from_deleted_enabled',
2396
            $renderer->render_group_element_checkbox('importrecordings_from_deleted_enabled', 0));
2397
    }
2398
}
2399
2400
/**
2401
 * Helper function renders show recording settings if the feature is enabled.
2402
 *
2403
 * @param object $renderer
2404
 *
2405
 * @return void
2406
 */
2407
function bigbluebuttonbn_settings_showrecordings(&$renderer) {
2408
    // Configuration for 'show recordings' feature.
2409
    if ((boolean)\mod_bigbluebuttonbn\settings\validator::section_show_recordings_shown()) {
2410
        $renderer->render_group_header('recordings');
2411
        $renderer->render_group_element('recordings_html_default',
2412
            $renderer->render_group_element_checkbox('recordings_html_default', 1));
2413
        $renderer->render_group_element('recordings_html_editable',
2414
            $renderer->render_group_element_checkbox('recordings_html_editable', 0));
2415
        $renderer->render_group_element('recordings_deleted_default',
2416
            $renderer->render_group_element_checkbox('recordings_deleted_default', 1));
2417
        $renderer->render_group_element('recordings_deleted_editable',
2418
            $renderer->render_group_element_checkbox('recordings_deleted_editable', 0));
2419
        $renderer->render_group_element('recordings_imported_default',
2420
            $renderer->render_group_element_checkbox('recordings_imported_default', 0));
2421
        $renderer->render_group_element('recordings_imported_editable',
2422
            $renderer->render_group_element_checkbox('recordings_imported_editable', 1));
2423
        $renderer->render_group_element('recordings_preview_default',
2424
            $renderer->render_group_element_checkbox('recordings_preview_default', 1));
2425
        $renderer->render_group_element('recordings_preview_editable',
2426
            $renderer->render_group_element_checkbox('recordings_preview_editable', 0));
2427
    }
2428
}
2429
2430
/**
2431
 * Helper function renders wait for moderator settings if the feature is enabled.
2432
 *
2433
 * @param object $renderer
2434
 *
2435
 * @return void
2436
 */
2437
function bigbluebuttonbn_settings_waitmoderator(&$renderer) {
2438
    // Configuration for wait for moderator feature.
2439
    if ((boolean)\mod_bigbluebuttonbn\settings\validator::section_wait_moderator_shown()) {
2440
        $renderer->render_group_header('waitformoderator');
2441
        $renderer->render_group_element('waitformoderator_default',
2442
            $renderer->render_group_element_checkbox('waitformoderator_default', 0));
2443
        $renderer->render_group_element('waitformoderator_editable',
2444
            $renderer->render_group_element_checkbox('waitformoderator_editable', 1));
2445
        $renderer->render_group_element('waitformoderator_ping_interval',
2446
            $renderer->render_group_element_text('waitformoderator_ping_interval', 10, PARAM_INT));
2447
        $renderer->render_group_element('waitformoderator_cache_ttl',
2448
            $renderer->render_group_element_text('waitformoderator_cache_ttl', 60, PARAM_INT));
2449
    }
2450
}
2451
2452
/**
2453
 * Helper function renders static voice bridge settings if the feature is enabled.
2454
 *
2455
 * @param object $renderer
2456
 *
2457
 * @return void
2458
 */
2459
function bigbluebuttonbn_settings_voicebridge(&$renderer) {
2460
    // Configuration for "static voice bridge" feature.
2461
    if ((boolean)\mod_bigbluebuttonbn\settings\validator::section_static_voice_bridge_shown()) {
2462
        $renderer->render_group_header('voicebridge');
2463
        $renderer->render_group_element('voicebridge_editable',
2464
            $renderer->render_group_element_checkbox('voicebridge_editable', 0));
2465
    }
2466
}
2467
2468
/**
2469
 * Helper function renders preuploaded presentation settings if the feature is enabled.
2470
 *
2471
 * @param object $renderer
2472
 *
2473
 * @return void
2474
 */
2475
function bigbluebuttonbn_settings_preupload(&$renderer) {
2476
    // Configuration for "preupload presentation" feature.
2477
    if ((boolean)\mod_bigbluebuttonbn\settings\validator::section_preupload_presentation_shown()) {
2478
        // This feature only works if curl is installed.
2479
        $preuploaddescripion = get_string('config_preuploadpresentation_description', 'bigbluebuttonbn');
2480
        if (!extension_loaded('curl')) {
2481
            $preuploaddescripion .= '<div class="form-defaultinfo">';
2482
            $preuploaddescripion .= get_string('config_warning_curl_not_installed', 'bigbluebuttonbn');
2483
            $preuploaddescripion .= '</div><br>';
2484
        }
2485
        $renderer->render_group_header('preuploadpresentation', null, $preuploaddescripion);
2486
        if (extension_loaded('curl')) {
2487
            $renderer->render_group_element('preuploadpresentation_enabled',
2488
                $renderer->render_group_element_checkbox('preuploadpresentation_enabled', 0));
2489
        }
2490
    }
2491
}
2492
2493
/**
2494
 * Helper function renders userlimit settings if the feature is enabled.
2495
 *
2496
 * @param object $renderer
2497
 *
2498
 * @return void
2499
 */
2500
function bigbluebuttonbn_settings_userlimit(&$renderer) {
2501
    // Configuration for "user limit" feature.
2502
    if ((boolean)\mod_bigbluebuttonbn\settings\validator::section_user_limit_shown()) {
2503
        $renderer->render_group_header('userlimit');
2504
        $renderer->render_group_element('userlimit_default',
2505
            $renderer->render_group_element_text('userlimit_default', 0, PARAM_INT));
2506
        $renderer->render_group_element('userlimit_editable',
2507
            $renderer->render_group_element_checkbox('userlimit_editable', 0));
2508
    }
2509
}
2510
2511
/**
2512
 * Helper function renders duration settings if the feature is enabled.
2513
 *
2514
 * @param object $renderer
2515
 *
2516
 * @return void
2517
 */
2518
function bigbluebuttonbn_settings_duration(&$renderer) {
2519
    // Configuration for "scheduled duration" feature.
2520 View Code Duplication
    if ((boolean)\mod_bigbluebuttonbn\settings\validator::section_scheduled_duration_shown()) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
2521
        $renderer->render_group_header('scheduled');
2522
        $renderer->render_group_element('scheduled_duration_enabled',
2523
            $renderer->render_group_element_checkbox('scheduled_duration_enabled', 1));
2524
        $renderer->render_group_element('scheduled_duration_compensation',
2525
            $renderer->render_group_element_text('scheduled_duration_compensation', 10, PARAM_INT));
2526
        $renderer->render_group_element('scheduled_pre_opening',
2527
            $renderer->render_group_element_text('scheduled_pre_opening', 10, PARAM_INT));
2528
    }
2529
}
2530
2531
/**
2532
 * Helper function renders participant settings if the feature is enabled.
2533
 *
2534
 * @param object $renderer
2535
 *
2536
 * @return void
2537
 */
2538
function bigbluebuttonbn_settings_participants(&$renderer) {
2539
    // Configuration for defining the default role/user that will be moderator on new activities.
2540
    if ((boolean)\mod_bigbluebuttonbn\settings\validator::section_moderator_default_shown()) {
2541
        $renderer->render_group_header('participant');
2542
        // UI for 'participants' feature.
2543
        $roles = bigbluebuttonbn_get_roles();
2544
        $owner = array('0' => get_string('mod_form_field_participant_list_type_owner', 'bigbluebuttonbn'));
2545
        $renderer->render_group_element('participant_moderator_default',
2546
            $renderer->render_group_element_configmultiselect('participant_moderator_default',
2547
                array_keys($owner), array_merge($owner, $roles))
2548
          );
2549
    }
2550
}
2551
2552
/**
2553
 * Helper function renders notification settings if the feature is enabled.
2554
 *
2555
 * @param object $renderer
2556
 *
2557
 * @return void
2558
 */
2559
function bigbluebuttonbn_settings_notifications(&$renderer) {
2560
    // Configuration for "send notifications" feature.
2561
    if ((boolean)\mod_bigbluebuttonbn\settings\validator::section_send_notifications_shown()) {
2562
        $renderer->render_group_header('sendnotifications');
2563
        $renderer->render_group_element('sendnotifications_enabled',
2564
            $renderer->render_group_element_checkbox('sendnotifications_enabled', 1));
2565
    }
2566
}
2567
2568
/**
2569
 * Helper function renders client type settings if the feature is enabled.
2570
 *
2571
 * @param object $renderer
2572
 *
2573
 * @return void
2574
 */
2575
function bigbluebuttonbn_settings_clienttype(&$renderer) {
2576
    // Configuration for "clienttype" feature.
2577
    if ((boolean)\mod_bigbluebuttonbn\settings\validator::section_clienttype_shown()) {
2578
        $renderer->render_group_header('clienttype');
2579
        $renderer->render_group_element('clienttype_editable',
2580
            $renderer->render_group_element_checkbox('clienttype_editable', 0));
2581
        // Web Client default.
2582
        $default = intval((int)\mod_bigbluebuttonbn\locallib\config::get('clienttype_default'));
2583
        $choices = array(BIGBLUEBUTTON_CLIENTTYPE_FLASH => get_string('mod_form_block_clienttype_flash', 'bigbluebuttonbn'),
2584
                         BIGBLUEBUTTON_CLIENTTYPE_HTML5 => get_string('mod_form_block_clienttype_html5', 'bigbluebuttonbn'));
2585
        $renderer->render_group_element('clienttype_default',
2586
            $renderer->render_group_element_configselect('clienttype_default',
2587
                $default, $choices));
2588
    }
2589
}
2590
2591
/**
2592
 * Helper function renders general settings if the feature is enabled.
2593
 *
2594
 * @param object $renderer
2595
 *
2596
 * @return void
2597
 */
2598 View Code Duplication
function bigbluebuttonbn_settings_muteonstart(&$renderer) {
0 ignored issues
show
Duplication introduced by
This function seems to be duplicated in your project.

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

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

Loading history...
2599
    // Configuration for BigBlueButton.
2600
    if ((boolean)\mod_bigbluebuttonbn\settings\validator::section_muteonstart_shown()) {
2601
        $renderer->render_group_header('muteonstart');
2602
        $renderer->render_group_element('muteonstart_default',
2603
            $renderer->render_group_element_checkbox('muteonstart_default', 0));
2604
        $renderer->render_group_element('muteonstart_editable',
2605
            $renderer->render_group_element_checkbox('muteonstart_editable', 0));
2606
    }
2607
}
2608
2609
/**
2610
 * Helper function renders extended settings if any of the features there is enabled.
2611
 *
2612
 * @param object $renderer
2613
 *
2614
 * @return void
2615
 */
2616 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...
2617
    // Configuration for extended BN capabilities.
2618
    if (!bigbluebuttonbn_is_bn_server()) {
2619
        return;
2620
    }
2621
    // Configuration for 'notify users when recording ready' feature.
2622
    if ((boolean)\mod_bigbluebuttonbn\settings\validator::section_settings_extended_shown()) {
2623
        $renderer->render_group_header('extended_capabilities');
2624
        // UI for 'notify users when recording ready' feature.
2625
        $renderer->render_group_element('recordingready_enabled',
2626
            $renderer->render_group_element_checkbox('recordingready_enabled', 0));
2627
        // UI for 'register meeting events' feature.
2628
        $renderer->render_group_element('meetingevents_enabled',
2629
            $renderer->render_group_element_checkbox('meetingevents_enabled', 0));
2630
    }
2631
}
2632
2633
/**
2634
 * Helper function returns a sha1 encoded string that is unique and will be used as a seed for meetingid.
2635
 *
2636
 * @return string
2637
 */
2638
function bigbluebuttonbn_unique_meetingid_seed() {
2639
    global $DB;
2640
    do {
2641
        $encodedseed = sha1(bigbluebuttonbn_random_password(12));
2642
        $meetingid = (string)$DB->get_field('bigbluebuttonbn', 'meetingid', array('meetingid' => $encodedseed));
2643
    } while ($meetingid == $encodedseed);
2644
    return $encodedseed;
2645
}
2646
2647
/**
2648
 * Helper function renders the link used for recording type in row for the data used by the recording table.
2649
 *
2650
 * @param array $recording
2651
 * @param array $bbbsession
2652
 * @param array $playback
2653
 *
2654
 * @return boolean
2655
 */
2656
function bigbluebuttonbn_include_recording_data_row_type($recording, $bbbsession, $playback) {
2657
    // All types that are not restricted are included.
2658
    if (array_key_exists('restricted', $playback) && strtolower($playback['restricted']) == 'false') {
2659
        return true;
2660
    }
2661
    // All types that are not statistics are included.
2662
    if ($playback['type'] != 'statistics') {
2663
        return true;
2664
    }
2665
    // Exclude imported recordings.
2666
    if (isset($recording['imported'])) {
2667
        return false;
2668
    }
2669
    // Exclude non moderators.
2670
    if (!$bbbsession['administrator'] && !$bbbsession['moderator']) {
2671
        return false;
2672
    }
2673
    return true;
2674
}
2675
2676
/**
2677
 * Renders the general warning message.
2678
 *
2679
 * @param string $message
2680
 * @param string $type
2681
 * @param string $href
2682
 * @param string $text
2683
 * @param string $class
2684
 *
2685
 * @return string
2686
 */
2687
function bigbluebuttonbn_render_warning($message, $type='info', $href='', $text='', $class='') {
2688
    global $OUTPUT;
2689
    $output = "\n";
2690
    // Evaluates if config_warning is enabled.
2691
    if (empty($message)) {
2692
        return $output;
2693
    }
2694
    $output .= $OUTPUT->box_start('box boxalignleft adminerror alert alert-' . $type . ' alert-block fade in',
2695
      'bigbluebuttonbn_view_general_warning') . "\n";
2696
    $output .= '    ' . $message . "\n";
2697
    $output .= '  <div class="singlebutton pull-right">' . "\n";
2698
    if (!empty($href)) {
2699
        $output .= bigbluebuttonbn_render_warning_button($href, $text, $class);
2700
    }
2701
    $output .= '  </div>' . "\n";
2702
    $output .= $OUTPUT->box_end() . "\n";
2703
    return $output;
2704
}
2705
2706
/**
2707
 * Renders the general warning button.
2708
 *
2709
 * @param string $href
2710
 * @param string $text
2711
 * @param string $class
2712
 * @param string $title
2713
 *
2714
 * @return string
2715
 */
2716
function bigbluebuttonbn_render_warning_button($href, $text = '', $class = '', $title = '') {
2717
    if ($text == '') {
2718
        $text = get_string('ok', 'moodle');
2719
    }
2720
    if ($title == '') {
2721
        $title = $text;
2722
    }
2723
    if ($class == '') {
2724
        $class = 'btn btn-secondary';
2725
    }
2726
    $output  = '  <form method="post" action="' . $href . '" class="form-inline">'."\n";
2727
    $output .= '      <button type="submit" class="' . $class . '"'."\n";
2728
    $output .= '          title="' . $title . '"'."\n";
2729
    $output .= '          >' . $text . '</button>'."\n";
2730
    $output .= '  </form>'."\n";
2731
    return $output;
2732
}
2733
2734
/**
2735
 * Check if a BigBlueButtonBN is available to be used by the current user.
2736
 *
2737
 * @param  stdClass  $bigbluebuttonbn  BigBlueButtonBN instance
2738
 *
2739
 * @return boolean                     status if room available and current user allowed to join
2740
 */
2741
function bigbluebuttonbn_get_availability_status($bigbluebuttonbn) {
2742
    list($roomavailable) = bigbluebuttonbn_room_is_available($bigbluebuttonbn);
2743
    list($usercanjoin) = bigbluebuttonbn_user_can_join_meeting($bigbluebuttonbn);
2744
2745
    return ($roomavailable && $usercanjoin);
2746
}
2747
2748
/**
2749
 * Helper for evaluating if scheduled activity is avaiable.
2750
 *
2751
 * @param  stdClass  $bigbluebuttonbn  BigBlueButtonBN instance
2752
 *
2753
 * @return array                       status (room available or not and possible warnings)
2754
 */
2755
function bigbluebuttonbn_room_is_available($bigbluebuttonbn) {
2756
    $open = true;
2757
    $closed = false;
2758
    $warnings = array();
2759
2760
    $timenow = time();
2761
    $timeopen = $bigbluebuttonbn->openingtime;
2762
    $timeclose = $bigbluebuttonbn->closingtime;
2763
    if (!empty($timeopen) && $timeopen > $timenow) {
2764
        $open = false;
2765
    }
2766
    if (!empty($timeclose) && $timenow > $timeclose) {
2767
        $closed = true;
2768
    }
2769
2770
    if (!$open || $closed) {
2771
        if (!$open) {
2772
            $warnings['notopenyet'] = userdate($timeopen);
2773
        }
2774
        if ($closed) {
2775
            $warnings['expired'] = userdate($timeclose);
2776
        }
2777
        return array(false, $warnings);
2778
    }
2779
2780
    return array(true, $warnings);
2781
}
2782
2783
/**
2784
 * Helper for evaluating if meeting can be joined.
2785
 *
2786
 * @param  stdClass $bigbluebuttonbn  BigBlueButtonBN instance
2787
 * @param  string   $mid
2788
 * @param  integer  $userid
2789
 *
2790
 * @return array    status (user allowed to join or not and possible message)
2791
 */
2792
function bigbluebuttonbn_user_can_join_meeting($bigbluebuttonbn, $mid = null, $userid = null) {
2793
2794
    // By default, use a meetingid without groups.
2795
    if (empty($mid)) {
2796
        $mid = $bigbluebuttonbn->meetingid . '-' . $bigbluebuttonbn->course . '-' . $bigbluebuttonbn->id;
2797
    }
2798
2799
    // When meeting is running, all authorized users can join right in.
2800
    if (bigbluebuttonbn_is_meeting_running($mid)) {
2801
        return array(true, get_string('view_message_conference_in_progress', 'bigbluebuttonbn'));
2802
    }
2803
2804
    // When meeting is not running, see if the user can join.
2805
    $context = context_course::instance($bigbluebuttonbn->course);
2806
    $participantlist = bigbluebuttonbn_get_participant_list($bigbluebuttonbn, $context);
2807
    $isadmin = is_siteadmin($userid);
2808
    $ismoderator = bigbluebuttonbn_is_moderator($context, $participantlist, $userid);
2809
    // If user is administrator, moderator or if is viewer and no waiting is required, join allowed.
2810
    if ($isadmin || $ismoderator || !$bigbluebuttonbn->wait) {
2811
        return array(true, get_string('view_message_conference_room_ready', 'bigbluebuttonbn'));
2812
    }
2813
    // Otherwise, no join allowed.
2814
    return array(false, get_string('view_message_conference_wait_for_moderator', 'bigbluebuttonbn'));
2815
}
2816
2817
/**
2818
 * Helper for getting a value from a bigbluebuttonbn cache.
2819
 *
2820
 * @param  string   $name       BigBlueButtonBN cache
2821
 * @param  string   $key        Key to be retrieved
2822
 * @param  integer  $default    Default value in case key is not found or it is empty
2823
 *
2824
 * @return variable key value
2825
 */
2826
function bigbluebuttonbn_cache_get($name, $key, $default = null) {
2827
    $cache = cache::make_from_params(cache_store::MODE_APPLICATION, 'mod_bigbluebuttonbn', $name);
2828
    $result = $cache->get($key);
2829
    if (!empty($result)) {
2830
        return $result;
2831
    }
2832
    return $default;
2833
}
2834
2835
/**
2836
 * Helper for setting a value in a bigbluebuttonbn cache.
2837
 *
2838
 * @param  string   $name       BigBlueButtonBN cache
2839
 * @param  string   $key        Key to be created/updated
2840
 * @param  variable $value      Default value to be set
2841
 */
2842
function bigbluebuttonbn_cache_set($name, $key, $value) {
2843
    $cache = cache::make_from_params(cache_store::MODE_APPLICATION, 'mod_bigbluebuttonbn', $name);
2844
    $cache->set($key, $value);
2845
}
2846
2847
/**
2848
 * Helper for getting the owner userid of a bigbluebuttonbn instance.
2849
 *
2850
 * @param  stdClass $bigbluebuttonbn  BigBlueButtonBN instance
2851
 *
2852
 * @return integer ownerid (a valid user id or null if not registered/found)
2853
 */
2854
function bigbluebuttonbn_instance_ownerid($bigbluebuttonbn) {
2855
    global $DB;
2856
    $filters = array('bigbluebuttonbnid' => $bigbluebuttonbn->id, 'log' => 'Add');
2857
    $ownerid = (integer)$DB->get_field('bigbluebuttonbn_logs', 'userid', $filters);
2858
    return $ownerid;
2859
}
2860
2861
/**
2862
 * Helper evaluates if the bigbluebutton server used belongs to blindsidenetworks domain.
2863
 *
2864
 * @return boolean
2865
 */
2866
function bigbluebuttonbn_has_html5_client() {
2867
    $checkurl = \mod_bigbluebuttonbn\locallib\bigbluebutton::root() . "html5client/check";
2868
    $curlinfo = bigbluebuttonbn_wrap_xml_load_file_curl_request($checkurl, 'HEAD');
2869
    return (isset($curlinfo['http_code']) && $curlinfo['http_code'] == 200);
2870
}
2871