Completed
Pull Request — master (#57)
by Jesus
02:24
created

locallib.php ➔ bigbluebuttonbn_user_can_join_meeting()   B

Complexity

Conditions 6
Paths 6

Size

Total Lines 24

Duplication

Lines 0
Ratio 0 %

Importance

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