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

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

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

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

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

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

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

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

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

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

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

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

Loading history...
2555
        $renderer->render_group_header('scheduled');
2556
        $renderer->render_group_element('scheduled_duration_enabled',
2557
            $renderer->render_group_element_checkbox('scheduled_duration_enabled', 1));
2558
        $renderer->render_group_element('scheduled_duration_compensation',
2559
            $renderer->render_group_element_text('scheduled_duration_compensation', 10, PARAM_INT));
2560
        $renderer->render_group_element('scheduled_pre_opening',
2561
            $renderer->render_group_element_text('scheduled_pre_opening', 10, PARAM_INT));
2562
    }
2563
}
2564
2565
/**
2566
 * Helper function renders participant settings if the feature is enabled.
2567
 *
2568
 * @param object $renderer
2569
 *
2570
 * @return void
2571
 */
2572
function bigbluebuttonbn_settings_participants(&$renderer) {
2573
    // Configuration for defining the default role/user that will be moderator on new activities.
2574
    if ((boolean)\mod_bigbluebuttonbn\settings\renderer::section_moderator_default_shown()) {
2575
        $renderer->render_group_header('participant');
2576
        // UI for 'participants' feature.
2577
        $roles = bigbluebuttonbn_get_roles();
2578
        $owner = array('0' => get_string('mod_form_field_participant_list_type_owner', 'bigbluebuttonbn'));
2579
        $renderer->render_group_element('participant_moderator_default',
2580
            $renderer->render_group_element_configmultiselect('participant_moderator_default',
2581
                array_keys($owner), array_merge($owner, $roles))
2582
          );
2583
    }
2584
}
2585
2586
/**
2587
 * Helper function renders notification settings if the feature is enabled.
2588
 *
2589
 * @param object $renderer
2590
 *
2591
 * @return void
2592
 */
2593
function bigbluebuttonbn_settings_notifications(&$renderer) {
2594
    // Configuration for "send notifications" feature.
2595
    if ((boolean)\mod_bigbluebuttonbn\settings\renderer::section_send_notifications_shown()) {
2596
        $renderer->render_group_header('sendnotifications');
2597
        $renderer->render_group_element('sendnotifications_enabled',
2598
            $renderer->render_group_element_checkbox('sendnotifications_enabled', 1));
2599
    }
2600
}
2601
2602
/**
2603
 * Helper function renders extended settings if any of the features there is enabled.
2604
 *
2605
 * @param object $renderer
2606
 *
2607
 * @return void
2608
 */
2609 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...
2610
    // Configuration for extended BN capabilities.
2611
    if (!bigbluebuttonbn_is_bn_server()) {
2612
        return;
2613
    }
2614
    // Configuration for 'notify users when recording ready' feature.
2615
    if ((boolean)\mod_bigbluebuttonbn\settings\renderer::section_settings_extended_shown()) {
2616
        $renderer->render_group_header('extended_capabilities');
2617
        // UI for 'notify users when recording ready' feature.
2618
        $renderer->render_group_element('recordingready_enabled',
2619
            $renderer->render_group_element_checkbox('recordingready_enabled', 0));
2620
        // UI for 'register meeting events' feature.
2621
        $renderer->render_group_element('meetingevents_enabled',
2622
            $renderer->render_group_element_checkbox('meetingevents_enabled', 0));
2623
    }
2624
}
2625
2626
/**
2627
 * Helper function returns an encoded meetingid.
2628
 *
2629
 * @param string $seed
2630
 *
2631
 * @return string
2632
 */
2633
function bigbluebuttonbn_encode_meetingid($seed) {
2634
    global $CFG;
2635
    return sha1($CFG->wwwroot . $seed . \mod_bigbluebuttonbn\locallib\config::get('shared_secret'));
2636
}
2637
2638
/**
2639
 * Helper function renders the link used for recording type in row for the data used by the recording table.
2640
 *
2641
 * @param array $recording
2642
 * @param array $bbbsession
2643
 * @param array $playback
2644
 *
2645
 * @return boolean
2646
 */
2647
function bigbluebuttonbn_include_recording_data_row_type($recording, $bbbsession, $playback) {
2648
    // All types that are not restricted are included.
2649
    if (array_key_exists('restricted', $playback) && strtolower($playback['restricted']) == 'false') {
2650
        return true;
2651
    }
2652
    // All types that are not statistics are included.
2653
    if ($playback['type'] != 'statistics') {
2654
        return true;
2655
    }
2656
    // Exclude imported recordings.
2657
    if (isset($recording['imported'])) {
2658
        return false;
2659
    }
2660
    // Exclude non moderators.
2661
    if (!$bbbsession['administrator'] && !$bbbsession['moderator']) {
2662
        return false;
2663
    }
2664
    return true;
2665
}
2666
2667
/**
2668
 * Renders the general warning message.
2669
 *
2670
 * @param string $message
2671
 * @param string $type
2672
 * @param string $href
2673
 * @param string $text
2674
 * @param string $class
2675
 *
2676
 * @return string
2677
 */
2678
function bigbluebuttonbn_render_warning($message, $type='info', $href='', $text='', $class='') {
2679
    global $OUTPUT;
2680
    $output = "\n";
2681
    // Evaluates if config_warning is enabled.
2682
    if (empty($message)) {
2683
        return $output;
2684
    }
2685
    $output .= $OUTPUT->box_start('box boxalignleft adminerror alert alert-' . $type . ' alert-block fade in',
2686
      'bigbluebuttonbn_view_general_warning') . "\n";
2687
    $output .= '    ' . $message . "\n";
2688
    $output .= '  <div class="singlebutton pull-right">' . "\n";
2689
    if (!empty($href)) {
2690
        $output .= bigbluebuttonbn_render_warning_button($href, $text, $class);
2691
    }
2692
    $output .= '  </div>' . "\n";
2693
    $output .= $OUTPUT->box_end() . "\n";
2694
    return $output;
2695
}
2696
2697
/**
2698
 * Renders the general warning button.
2699
 *
2700
 * @param string $href
2701
 * @param string $text
2702
 * @param string $class
2703
 * @param string $title
2704
 *
2705
 * @return string
2706
 */
2707
function bigbluebuttonbn_render_warning_button($href, $text = '', $class = '', $title = '') {
2708
    if ($text == '') {
2709
        $text = get_string('ok', 'moodle');
2710
    }
2711
    if ($title == '') {
2712
        $title = $text;
2713
    }
2714
    if ($class == '') {
2715
        $class = 'btn btn-secondary';
2716
    }
2717
    $output  = '  <form method="post" action="' . $href . '" class="form-inline">'."\n";
2718
    $output .= '      <button type="submit" class="' . $class . '"'."\n";
2719
    $output .= '          title="' . $title . '"'."\n";
2720
    $output .= '          >' . $text . '</button>'."\n";
2721
    $output .= '  </form>'."\n";
2722
    return $output;
2723
}
2724
2725
/**
2726
 * Check if a BigBlueButtonBN is available to be used by the current user.
2727
 *
2728
 * @param  stdClass  $bigbluebuttonbn  BigBlueButtonBN instance
2729
 *
2730
 * @return boolean                     status if room available and current user allowed to join
2731
 */
2732
function bigbluebuttonbn_get_availability_status($bigbluebuttonbn) {
2733
    list($roomavailable, $warnings) = bigbluebuttonbn_room_is_available($bigbluebuttonbn);
0 ignored issues
show
Unused Code introduced by
The assignment to $warnings is unused. Consider omitting it like so list($first,,$third).

This checks looks for assignemnts to variables using the list(...) function, where not all assigned variables are subsequently used.

Consider the following code example.

<?php

function returnThreeValues() {
    return array('a', 'b', 'c');
}

list($a, $b, $c) = returnThreeValues();

print $a . " - " . $c;

Only the variables $a and $c are used. There was no need to assign $b.

Instead, the list call could have been.

list($a,, $c) = returnThreeValues();
Loading history...
2734
    list($usercanjoin, $message) = bigbluebuttonbn_user_can_join_meeting($bigbluebuttonbn);
0 ignored issues
show
Unused Code introduced by
The assignment to $message is unused. Consider omitting it like so list($first,,$third).

This checks looks for assignemnts to variables using the list(...) function, where not all assigned variables are subsequently used.

Consider the following code example.

<?php

function returnThreeValues() {
    return array('a', 'b', 'c');
}

list($a, $b, $c) = returnThreeValues();

print $a . " - " . $c;

Only the variables $a and $c are used. There was no need to assign $b.

Instead, the list call could have been.

list($a,, $c) = returnThreeValues();
Loading history...
2735
2736
    return ($roomavailable && $usercanjoin);
2737
}
2738
2739
/**
2740
 * Helper for evaluating if scheduled activity is avaiable.
2741
 *
2742
 * @param  stdClass  $bigbluebuttonbn  BigBlueButtonBN instance
2743
 *
2744
 * @return array                       status (room available or not and possible warnings)
2745
 */
2746
function bigbluebuttonbn_room_is_available($bigbluebuttonbn) {
2747
    $open = true;
2748
    $closed = false;
2749
    $warnings = array();
2750
2751
    $timenow = time();
2752
    $timeopen = $bigbluebuttonbn->openingtime;
2753
    $timeclose = $bigbluebuttonbn->closingtime;
2754
    if (!empty($timeopen) && $timeopen > $timenow) {
2755
        $open = false;
2756
    }
2757
    if (!empty($timeclose) && $timenow > $timeclose) {
2758
        $closed = true;
2759
    }
2760
2761
    if (!$open || $closed) {
2762
        if (!$open) {
2763
            $warnings['notopenyet'] = userdate($timeopen);
2764
        }
2765
        if ($closed) {
2766
            $warnings['expired'] = userdate($timeclose);
2767
        }
2768
        return array(false, $warnings);
2769
    }
2770
2771
    return array(true, $warnings);
2772
}
2773
2774
2775
/**
2776
 * Helper for evaluating if meeting can be joined.
2777
 *
2778
 * @param  stdClass  $bigbluebuttonbn  BigBlueButtonBN instance
2779
 * @param  integer   $userid
2780
 *
2781
 * @return array     status (user allowed to join or not and possible message)
2782
 */
2783
function bigbluebuttonbn_user_can_join_meeting($bigbluebuttonbn, $meetingid = null, $userid = null) {
2784
2785
    // By default, use a meetingid without groups.
2786
    if (empty($meetingid)) {
2787
        $meetingid = $bigbluebuttonbn->meetingid . '-' . $bigbluebuttonbn->courseid . '-' . $bigbluebuttonbn->id;
2788
    }
2789
2790
    // When meeting is running, all authorized users can join right in.
2791
    if (bigbluebuttonbn_is_meeting_running($meetingid)) {
2792
        return array(true, get_string('view_message_conference_in_progress', 'bigbluebuttonbn'));
2793
    }
2794
2795
    // When meeting is not running, see if the user can join.
2796
    $context = context_course::instance($bigbluebuttonbn->course);
2797
    $participantlist = bigbluebuttonbn_get_participant_list($bigbluebuttonbn, $context);
2798
    $isadmin = is_siteadmin($userid);
2799
    $ismoderator = bigbluebuttonbn_is_moderator($context, json_encode($participantlist), $userid);
2800
    // If user is administrator, moderator or if is viewer and no waiting is required, join allowed.
2801
    if ($isadmin || $ismoderator || !$bigbluebuttonbn->wait) {
2802
        return array(true, get_string('view_message_conference_room_ready', 'bigbluebuttonbn'));
2803
    }
2804
    // Otherwise, no join allowed.
2805
    return array(false, get_string('view_message_conference_wait_for_moderator', 'bigbluebuttonbn'));
2806
}
2807