Completed
Pull Request — v2.2-stable (#59)
by Jesus
02:03
created

locallib.php ➔ bigbluebuttonbn_cache_get()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
nc 2
nop 3
dl 0
loc 8
rs 10
c 0
b 0
f 0
1
<?php
2
// This file is part of Moodle - http://moodle.org/
3
//
4
// Moodle is free software: you can redistribute it and/or modify
5
// it under the terms of the GNU General Public License as published by
6
// the Free Software Foundation, either version 3 of the License, or
7
// (at your option) any later version.
8
//
9
// Moodle is distributed in the hope that it will be useful,
10
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
// GNU General Public License for more details.
13
//
14
// You should have received a copy of the GNU General Public License
15
// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
16
17
/**
18
 * Internal library of functions for module BigBlueButtonBN.
19
 *
20
 * @package   mod_bigbluebuttonbn
21
 * @copyright 2010-2017 Blindside Networks Inc
22
 * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v2 or later
23
 * @author    Jesus Federico  (jesus [at] blindsidenetworks [dt] com)
24
 * @author    Fred Dixon  (ffdixon [at] blindsidenetworks [dt] com)
25
 */
26
27
defined('MOODLE_INTERNAL') || die;
28
29
global $CFG;
30
31
require_once(dirname(__FILE__).'/lib.php');
32
33
/** @var BIGBLUEBUTTONBN_UPDATE_CACHE boolean set to true indicates that cache has to be updated */
34
const BIGBLUEBUTTONBN_UPDATE_CACHE = true;
35
/** @var BIGBLUEBUTTONBN_TYPE_ALL integer set to 0 defines an instance type that inclueds room and recordings */
36
const BIGBLUEBUTTONBN_TYPE_ALL = 0;
37
/** @var BIGBLUEBUTTONBN_TYPE_ROOM_ONLY integer set to 1 defines an instance type that inclueds only room */
38
const BIGBLUEBUTTONBN_TYPE_ROOM_ONLY = 1;
39
/** @var BIGBLUEBUTTONBN_TYPE_RECORDING_ONLY integer set to 2 defines an instance type that inclueds only recordings */
40
const BIGBLUEBUTTONBN_TYPE_RECORDING_ONLY = 2;
41
/** @var BIGBLUEBUTTONBN_ROLE_VIEWER string defines the bigbluebutton viewer role */
42
const BIGBLUEBUTTONBN_ROLE_VIEWER = 'viewer';
43
/** @var BIGBLUEBUTTONBN_ROLE_MODERATOR string defines the bigbluebutton moderator role */
44
const BIGBLUEBUTTONBN_ROLE_MODERATOR = 'moderator';
45
/** @var BIGBLUEBUTTON_EVENT_ACTIVITY_VIEWED string defines the bigbluebuttonbn activity_viewed event */
46
const BIGBLUEBUTTON_EVENT_ACTIVITY_VIEWED = 'activity_viewed';
47
/** @var BIGBLUEBUTTON_EVENT_ACTIVITY_MANAGEMENT_VIEWED string defines the bigbluebuttonbn activity_management_viewed event */
48
const BIGBLUEBUTTON_EVENT_ACTIVITY_MANAGEMENT_VIEWED = 'activity_management_viewed';
49
/** @var BIGBLUEBUTTON_EVENT_LIVE_SESSION string defines the bigbluebuttonbn live_session event */
50
const BIGBLUEBUTTON_EVENT_LIVE_SESSION = 'live_session';
51
/** @var BIGBLUEBUTTON_EVENT_MEETING_CREATED string defines the bigbluebuttonbn meeting_created event */
52
const BIGBLUEBUTTON_EVENT_MEETING_CREATED = 'meeting_created';
53
/** @var BIGBLUEBUTTON_EVENT_MEETING_ENDED string defines the bigbluebuttonbn meeting_ended event */
54
const BIGBLUEBUTTON_EVENT_MEETING_ENDED = 'meeting_ended';
55
/** @var BIGBLUEBUTTON_EVENT_MEETING_JOINED string defines the bigbluebuttonbn meeting_joined event */
56
const BIGBLUEBUTTON_EVENT_MEETING_JOINED = 'meeting_joined';
57
/** @var BIGBLUEBUTTON_EVENT_MEETING_LEFT string defines the bigbluebuttonbn meeting_left event */
58
const BIGBLUEBUTTON_EVENT_MEETING_LEFT = 'meeting_left';
59
/** @var BIGBLUEBUTTON_EVENT_RECORDING_DELETED string defines the bigbluebuttonbn recording_deleted event */
60
const BIGBLUEBUTTON_EVENT_RECORDING_DELETED = 'recording_deleted';
61
/** @var BIGBLUEBUTTON_EVENT_RECORDING_IMPORTED string defines the bigbluebuttonbn recording_imported event */
62
const BIGBLUEBUTTON_EVENT_RECORDING_IMPORTED = 'recording_imported';
63
/** @var BIGBLUEBUTTON_EVENT_RECORDING_PROTECTED string defines the bigbluebuttonbn recording_protected event */
64
const BIGBLUEBUTTON_EVENT_RECORDING_PROTECTED = 'recording_protected';
65
/** @var BIGBLUEBUTTON_EVENT_RECORDING_PUBLISHED string defines the bigbluebuttonbn recording_published event */
66
const BIGBLUEBUTTON_EVENT_RECORDING_PUBLISHED = 'recording_published';
67
/** @var BIGBLUEBUTTON_EVENT_RECORDING_UNPROTECTED string defines the bigbluebuttonbn recording_unprotected event */
68
const BIGBLUEBUTTON_EVENT_RECORDING_UNPROTECTED = 'recording_unprotected';
69
/** @var BIGBLUEBUTTON_EVENT_RECORDING_UNPUBLISHED string defines the bigbluebuttonbn recording_unpublished event */
70
const BIGBLUEBUTTON_EVENT_RECORDING_UNPUBLISHED = 'recording_unpublished';
71
/** @var BIGBLUEBUTTON_EVENT_RECORDING_EDITED string defines the bigbluebuttonbn recording_edited event */
72
const BIGBLUEBUTTON_EVENT_RECORDING_EDITED = 'recording_edited';
73
/** @var BIGBLUEBUTTON_EVENT_RECORDING_VIEWED string defines the bigbluebuttonbn recording_viewed event */
74
const BIGBLUEBUTTON_EVENT_RECORDING_VIEWED = 'recording_viewed';
75
/** @var BIGBLUEBUTTON_EVENT_MEETING_START string defines the bigbluebuttonbn meeting_start event */
76
const BIGBLUEBUTTON_EVENT_MEETING_START = 'meeting_start';
77
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
    $urlhost = parse_url($url, PHP_URL_HOST);
1615
    $serverurlhost = parse_url(\mod_bigbluebuttonbn\locallib\config::get('server_url'), PHP_URL_HOST);
1616
    // Skip validation when the recording URL host is the same as the configured BBB server.
1617
    if ($urlhost == $serverurlhost) {
1618
        return true;
1619
    }
1620
    // Skip validation when the recording URL was already validated.
1621
    $validatedurls = bigbluebuttonbn_cache_get('recordings_cache', 'validated_urls', array());
0 ignored issues
show
Documentation introduced by
array() is of type array, but the function expects a integer|null.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
1622
    if (array_key_exists($urlhost, $validatedurls)) {
1623
        return $validatedurls[$urlhost];
1624
    }
1625
    // Validate the recording URL.
1626
    $validatedurls[$urlhost] = true;
1627
    $curlinfo = bigbluebuttonbn_wrap_xml_load_file_curl_request($url, 'HEAD');
1628
    if (!isset($curlinfo['http_code']) || $curlinfo['http_code'] != 200) {
1629
        $error = "Resource " . $url . " is unreachable. Server responded with code " . $curlinfo['http_code'];
1630
        debugging($error, DEBUG_DEVELOPER);
1631
        $validatedurls[$urlhost] = false;
1632
    }
1633
    bigbluebuttonbn_cache_set('recordings_cache', 'validated_urls', $validatedurls);
1634
    return $validatedurls[$urlhost];
1635
}
1636
1637
/**
1638
 * Helper function renders the name for recording used in row for the data used by the recording table.
1639
 *
1640
 * @param array $recording
1641
 * @param array $bbbsession
1642
 *
1643
 * @return string
1644
 */
1645
function bigbluebuttonbn_get_recording_data_row_meta_activity($recording, $bbbsession) {
1646
    $payload = array();
1647 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...
1648
        $payload = array('recordingid' => $recording['recordID'], 'meetingid' => $recording['meetingID'],
1649
            'action' => 'edit', 'tag' => 'edit',
1650
            'target' => 'name');
1651
    }
1652
    $oldsource = 'meta_contextactivity';
1653
    if (isset($recording[$oldsource])) {
1654
        $metaname = trim($recording[$oldsource]);
1655
        return bigbluebuttonbn_get_recording_data_row_text($recording, $metaname, $oldsource, $payload);
1656
    }
1657
    $newsource = 'meta_bbb-recording-name';
1658 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...
1659
        $metaname = trim($recording[$newsource]);
1660
        return bigbluebuttonbn_get_recording_data_row_text($recording, $metaname, $newsource, $payload);
1661
    }
1662
    $metaname = trim($recording['meetingName']);
1663
    return bigbluebuttonbn_get_recording_data_row_text($recording, $metaname, $newsource, $payload);
1664
}
1665
1666
/**
1667
 * Helper function renders the description for recording used in row for the data used by the recording table.
1668
 *
1669
 * @param array $recording
1670
 * @param array $bbbsession
1671
 *
1672
 * @return string
1673
 */
1674
function bigbluebuttonbn_get_recording_data_row_meta_description($recording, $bbbsession) {
1675
    $payload = array();
1676 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...
1677
        $payload = array('recordingid' => $recording['recordID'], 'meetingid' => $recording['meetingID'],
1678
            'action' => 'edit', 'tag' => 'edit',
1679
            'target' => 'description');
1680
    }
1681
    $oldsource = 'meta_contextactivitydescription';
1682 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...
1683
        $metadescription = trim($recording[$oldsource]);
1684
        return bigbluebuttonbn_get_recording_data_row_text($recording, $metadescription, $oldsource, $payload);
1685
    }
1686
    $newsource = 'meta_bbb-recording-description';
1687 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...
1688
        $metadescription = trim($recording[$newsource]);
1689
        return bigbluebuttonbn_get_recording_data_row_text($recording, $metadescription, $newsource, $payload);
1690
    }
1691
    return bigbluebuttonbn_get_recording_data_row_text($recording, '', $newsource, $payload);
1692
}
1693
1694
/**
1695
 * Helper function renders text element for recording used in row for the data used by the recording table.
1696
 *
1697
 * @param array $recording
1698
 * @param string $text
1699
 * @param string $source
1700
 * @param array $data
1701
 *
1702
 * @return string
1703
 */
1704
function bigbluebuttonbn_get_recording_data_row_text($recording, $text, $source, $data) {
1705
    $htmltext = '<span>' . htmlentities($text) . '</span>';
1706
    if (empty($data)) {
1707
        return $htmltext;
1708
    }
1709
    $target = $data['action'] . '-' . $data['target'];
1710
    $id = 'recording-' . $target . '-' . $data['recordingid'];
1711
    $attributes = array('id' => $id, 'class' => 'quickeditlink col-md-20',
1712
        'data-recordingid' => $data['recordingid'], 'data-meetingid' => $data['meetingid'],
1713
        'data-target' => $data['target'], 'data-source' => $source);
1714
    $head = html_writer::start_tag('div', $attributes);
1715
    $tail = html_writer::end_tag('div');
1716
    $payload = array('action' => $data['action'], 'tag' => $data['tag'], 'target' => $data['target']);
1717
    $htmllink = bigbluebuttonbn_actionbar_render_button($recording, $payload);
1718
    return $head . $htmltext . $htmllink . $tail;
1719
}
1720
1721
/**
1722
 * Helper function render a button for the recording action bar
1723
 *
1724
 * @param array $recording
1725
 * @param array $data
1726
 *
1727
 * @return string
1728
 */
1729
function bigbluebuttonbn_actionbar_render_button($recording, $data) {
1730
    global $OUTPUT;
1731
    if (empty($data)) {
1732
        return '';
1733
    }
1734
    $target = $data['action'];
1735
    if (isset($data['target'])) {
1736
        $target .= '-' . $data['target'];
1737
    }
1738
    $id = 'recording-' . $target . '-' . $recording['recordID'];
1739
    $onclick = 'M.mod_bigbluebuttonbn.recordings.recording' . ucfirst($data['action']) . '(this);';
1740
    if ((boolean)\mod_bigbluebuttonbn\locallib\config::get('recording_icons_enabled')) {
1741
        // With icon for $manageaction.
1742
        $iconattributes = array('id' => $id, 'class' => 'iconsmall');
1743
        $linkattributes = array(
1744
            'id' => $id,
1745
            'onclick' => $onclick,
1746
            'data-action' => $data['action']
1747
          );
1748
        if (!isset($recording['imported'])) {
1749
            $linkattributes['data-links'] = bigbluebuttonbn_count_recording_imported_instances(
1750
              $recording['recordID']);
1751
        }
1752
        if (isset($data['disabled'])) {
1753
            $iconattributes['class'] .= ' fa-' . $data['disabled'];
1754
            $linkattributes['class'] = 'disabled';
1755
            unset($linkattributes['onclick']);
1756
        }
1757
        $icon = new pix_icon('i/'.$data['tag'],
1758
            get_string('view_recording_list_actionbar_' . $data['action'], 'bigbluebuttonbn'),
1759
            'moodle', $iconattributes);
1760
        return $OUTPUT->action_icon('#', $icon, null, $linkattributes, false);
1761
    }
1762
    // With text for $manageaction.
1763
    $linkattributes = array('title' => get_string($data['tag']), 'class' => 'btn btn-xs btn-danger',
1764
        'onclick' => $onclick);
1765
    return $OUTPUT->action_link('#', get_string($data['action']), null, $linkattributes);
1766
}
1767
1768
/**
1769
 * Helper function builds the data used for headers by the recording table.
1770
 *
1771
 * @param array $bbbsession
1772
 *
1773
 * @return array
1774
 */
1775
function bigbluebuttonbn_get_recording_columns($bbbsession) {
1776
    $columns = array();
1777
    // Initialize table headers.
1778
    $columns[] = array('key' => 'recording', 'label' => get_string('view_recording_recording', 'bigbluebuttonbn'),
1779
        'width' => '125px', 'allowHTML' => true);
1780
    $columns[] = array('key' => 'activity', 'label' => get_string('view_recording_activity', 'bigbluebuttonbn'),
1781
        'sortable' => true, 'width' => '175px', 'allowHTML' => true);
1782
    $columns[] = array('key' => 'description', 'label' => get_string('view_recording_description', 'bigbluebuttonbn'),
1783
        'sortable' => true, 'width' => '250px', 'allowHTML' => true);
1784
    if (bigbluebuttonbn_get_recording_data_preview_enabled($bbbsession)) {
1785
        $columns[] = array('key' => 'preview', 'label' => get_string('view_recording_preview', 'bigbluebuttonbn'),
1786
            'width' => '250px', 'allowHTML' => true);
1787
    }
1788
    $columns[] = array('key' => 'date', 'label' => get_string('view_recording_date', 'bigbluebuttonbn'),
1789
        'sortable' => true, 'width' => '225px', 'allowHTML' => true);
1790
    $columns[] = array('key' => 'duration', 'label' => get_string('view_recording_duration', 'bigbluebuttonbn'),
1791
        'width' => '50px');
1792
    if ($bbbsession['managerecordings']) {
1793
        $columns[] = array('key' => 'actionbar', 'label' => get_string('view_recording_actionbar', 'bigbluebuttonbn'),
1794
            'width' => '120px', 'allowHTML' => true);
1795
    }
1796
    return $columns;
1797
}
1798
1799
/**
1800
 * Helper function builds the data used by the recording table.
1801
 *
1802
 * @param array $bbbsession
1803
 * @param array $recordings
1804
 * @param array $tools
1805
 *
1806
 * @return array
1807
 */
1808
function bigbluebuttonbn_get_recording_data($bbbsession, $recordings, $tools = ['protect', 'publish', 'delete']) {
1809
    $tabledata = array();
1810
    // Build table content.
1811
    if (isset($recordings) && !array_key_exists('messageKey', $recordings)) {
1812
        // There are recordings for this meeting.
1813
        foreach ($recordings as $recording) {
1814
            $rowdata = bigbluebuttonbn_get_recording_data_row($bbbsession, $recording, $tools);
1815
            if (!empty($rowdata)) {
1816
                array_push($tabledata, $rowdata);
1817
            }
1818
        }
1819
    }
1820
    return $tabledata;
1821
}
1822
1823
/**
1824
 * Helper function builds the recording table.
1825
 *
1826
 * @param array $bbbsession
1827
 * @param array $recordings
1828
 * @param array $tools
1829
 *
1830
 * @return object
1831
 */
1832
function bigbluebuttonbn_get_recording_table($bbbsession, $recordings, $tools = ['protect', 'publish', 'delete']) {
1833
    // Declare the table.
1834
    $table = new html_table();
1835
    $table->data = array();
1836
    // Initialize table headers.
1837
    $table->head[] = get_string('view_recording_playback', 'bigbluebuttonbn');
1838
    $table->head[] = get_string('view_recording_recording', 'bigbluebuttonbn');
1839
    $table->head[] = get_string('view_recording_description', 'bigbluebuttonbn');
1840
    if (bigbluebuttonbn_get_recording_data_preview_enabled($bbbsession)) {
1841
        $table->head[] = get_string('view_recording_preview', 'bigbluebuttonbn');
1842
    }
1843
    $table->head[] = get_string('view_recording_date', 'bigbluebuttonbn');
1844
    $table->head[] = get_string('view_recording_duration', 'bigbluebuttonbn');
1845
    $table->align = array('left', 'left', 'left', 'left', 'left', 'center');
1846
    $table->size = array('', '', '', '', '', '');
1847
    if ($bbbsession['managerecordings']) {
1848
        $table->head[] = get_string('view_recording_actionbar', 'bigbluebuttonbn');
1849
        $table->align[] = 'left';
1850
        $table->size[] = (count($tools) * 40) . 'px';
1851
    }
1852
    // Build table content.
1853
    foreach ($recordings as $recording) {
1854
        $rowdata = bigbluebuttonbn_get_recording_data_row($bbbsession, $recording, $tools);
1855
        if (!empty($rowdata)) {
1856
            $row = bigbluebuttonbn_get_recording_table_row($bbbsession, $recording, $rowdata);
1857
            array_push($table->data, $row);
1858
        }
1859
    }
1860
    return $table;
1861
}
1862
1863
/**
1864
 * Helper function builds the recording table row and insert into table.
1865
 *
1866
 * @param array $bbbsession
1867
 * @param array $recording
1868
 * @param object $rowdata
1869
 *
1870
 * @return object
1871
 */
1872
function bigbluebuttonbn_get_recording_table_row($bbbsession, $recording, $rowdata) {
1873
    $row = new html_table_row();
1874
    $row->id = 'recording-tr-'.$recording['recordID'];
1875
    $row->attributes['data-imported'] = 'false';
1876
    $texthead = '';
1877
    $texttail = '';
1878
    if (isset($recording['imported'])) {
1879
        $row->attributes['title'] = get_string('view_recording_link_warning', 'bigbluebuttonbn');
1880
        $row->attributes['data-imported'] = 'true';
1881
        $texthead = '<em>';
1882
        $texttail = '</em>';
1883
    }
1884
    $rowdata->date_formatted = str_replace(' ', '&nbsp;', $rowdata->date_formatted);
1885
    $row->cells = array();
1886
    $row->cells[] = $texthead . $rowdata->recording . $texttail;
1887
    $row->cells[] = $texthead . $rowdata->activity . $texttail;
1888
    $row->cells[] = $texthead . $rowdata->description . $texttail;
1889
    if (bigbluebuttonbn_get_recording_data_preview_enabled($bbbsession)) {
1890
        $row->cells[] = $rowdata->preview;
1891
    }
1892
    $row->cells[] = $texthead . $rowdata->date_formatted . $texttail;
1893
    $row->cells[] = $rowdata->duration_formatted;
1894
    if ($bbbsession['managerecordings']) {
1895
        $row->cells[] = $rowdata->actionbar;
1896
    }
1897
    return $row;
1898
}
1899
1900
/**
1901
 * Helper function evaluates if recording row should be included in the table.
1902
 *
1903
 * @param array $bbbsession
1904
 * @param array $recording
1905
 *
1906
 * @return boolean
1907
 */
1908
function bigbluebuttonbn_include_recording_table_row($bbbsession, $recording) {
1909
    // Exclude unpublished recordings, only if user has no rights to manage them.
1910
    if ($recording['published'] != 'true' && !$bbbsession['managerecordings']) {
1911
        return false;
1912
    }
1913
    // Imported recordings are always shown as long as they are published.
1914
    if (isset($recording['imported'])) {
1915
        return true;
1916
    }
1917
    // When groups are enabled, exclude those to which the user doesn't have access to.
1918
    if (isset($bbbsession['group']) && $recording['meetingID'] != $bbbsession['meetingid']) {
1919
        return false;
1920
    }
1921
    return true;
1922
}
1923
1924
/**
1925
 * Helper function triggers a send notification when the recording is ready.
1926
 *
1927
 * @param object $bigbluebuttonbn
1928
 *
1929
 * @return void
1930
 */
1931
function bigbluebuttonbn_send_notification_recording_ready($bigbluebuttonbn) {
1932
    $sender = get_admin();
1933
    // Prepare message.
1934
    $messagetext = '<p>'.get_string('email_body_recording_ready_for', 'bigbluebuttonbn').
1935
        ' &quot;' . $bigbluebuttonbn->name . '&quot; '.
1936
        get_string('email_body_recording_ready_is_ready', 'bigbluebuttonbn').'.</p>';
1937
    $context = context_course::instance($bigbluebuttonbn->course);
1938
    \mod_bigbluebuttonbn\locallib\notifier::notification_send($context, $sender, $bigbluebuttonbn, $messagetext);
1939
}
1940
1941
/**
1942
 * Helper evaluates if the bigbluebutton server used belongs to blindsidenetworks domain.
1943
 *
1944
 * @return boolean
1945
 */
1946
function bigbluebuttonbn_is_bn_server() {
1947
    $parsedurl = parse_url(\mod_bigbluebuttonbn\locallib\config::get('server_url'));
1948
    if (!isset($parsedurl['host'])) {
1949
        return false;
1950
    }
1951
    $h = $parsedurl['host'];
1952
    $hends = explode('.', $h);
1953
    $hendslength = count($hends);
1954
    return ($hends[$hendslength - 1] == 'com' && $hends[$hendslength - 2] == 'blindsidenetworks');
1955
}
1956
1957
/**
1958
 * Helper function returns a list of courses a user has access to, wrapped in an array that can be used
1959
 * by a html select.
1960
 *
1961
 * @param array $bbbsession
1962
 *
1963
 * @return array
1964
 */
1965
function bigbluebuttonbn_import_get_courses_for_select(array $bbbsession) {
1966
    if ($bbbsession['administrator']) {
1967
        $courses = get_courses('all', 'c.fullname ASC', 'c.id,c.shortname,c.fullname');
1968
        // It includes the name of the site as a course (category 0), so remove the first one.
1969
        unset($courses['1']);
1970
    } else {
1971
        $courses = enrol_get_users_courses($bbbsession['userID'], false, 'id,shortname,fullname');
1972
    }
1973
    $coursesforselect = [];
1974
    foreach ($courses as $course) {
1975
        $coursesforselect[$course->id] = $course->fullname;
1976
    }
1977
    return $coursesforselect;
1978
}
1979
1980
/**
1981
 * Helper function renders recording table.
1982
 *
1983
 * @param array $bbbsession
1984
 * @param array $recordings
1985
 * @param array $tools
1986
 *
1987
 * @return array
1988
 */
1989
function bigbluebuttonbn_output_recording_table($bbbsession, $recordings, $tools = ['protect', 'publish', 'delete']) {
1990
    if (isset($recordings) && !empty($recordings)) {
1991
        // There are recordings for this meeting.
1992
        $table = bigbluebuttonbn_get_recording_table($bbbsession, $recordings, $tools);
1993
    }
1994
    if (!isset($table) || !isset($table->data)) {
1995
        // Render a table with "No recordings".
1996
        return html_writer::div(get_string('view_message_norecordings', 'bigbluebuttonbn'), '',
1997
            array('id' => 'bigbluebuttonbn_recordings_table'));
1998
    }
1999
    // Render the table.
2000
    return html_writer::div(html_writer::table($table), '', array('id' => 'bigbluebuttonbn_recordings_table'));
2001
}
2002
2003
/**
2004
 * Helper function to convert an html string to plain text.
2005
 *
2006
 * @param string $html
2007
 * @param integer $len
2008
 *
2009
 * @return string
2010
 */
2011
function bigbluebuttonbn_html2text($html, $len = 0) {
2012
    $text = strip_tags($html);
2013
    $text = str_replace('&nbsp;', ' ', $text);
2014
    $textlen = strlen($text);
2015
    $text = substr($text, 0, $len);
2016
    if ($textlen > $len) {
2017
        $text .= '...';
2018
    }
2019
    return $text;
2020
}
2021
2022
/**
2023
 * Helper function to obtain the tags linked to a bigbluebuttonbn activity
2024
 *
2025
 * @param string $id
2026
 *
2027
 * @return string containing the tags separated by commas
2028
 */
2029
function bigbluebuttonbn_get_tags($id) {
2030
    if (class_exists('core_tag_tag')) {
2031
        return implode(',', core_tag_tag::get_item_tags_array('core', 'course_modules', $id));
2032
    }
2033
    return implode(',', tag_get_tags('bigbluebuttonbn', $id));
2034
}
2035
2036
/**
2037
 * Helper function to define the sql used for gattering the bigbluebuttonbnids whose meetingids should be included
2038
 * in the getRecordings request
2039
 *
2040
 * @param string $courseid
2041
 * @param string $bigbluebuttonbnid
2042
 * @param bool   $subset
2043
 *
2044
 * @return string containing the sql used for getting the target bigbluebuttonbn instances
2045
 */
2046
function bigbluebuttonbn_get_recordings_sql_select($courseid, $bigbluebuttonbnid = null, $subset = true) {
2047
    if (empty($courseid)) {
2048
        $courseid = 0;
2049
    }
2050
    if (empty($bigbluebuttonbnid)) {
2051
        return "course = '{$courseid}'";
2052
    }
2053
    if ($subset) {
2054
        return "id = '{$bigbluebuttonbnid}'";
2055
    }
2056
    return "id <> '{$bigbluebuttonbnid}' AND course = '{$courseid}'";
2057
}
2058
2059
/**
2060
 * Helper function to define the sql used for gattering the bigbluebuttonbnids whose meetingids should be included
2061
 * in the getRecordings request considering only those that belong to deleted activities.
2062
 *
2063
 * @param string $courseid
2064
 * @param string $bigbluebuttonbnid
2065
 * @param bool   $subset
2066
 *
2067
 * @return string containing the sql used for getting the target bigbluebuttonbn instances
2068
 */
2069 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...
2070
    $sql = "log = '" . BIGBLUEBUTTONBN_LOG_EVENT_DELETE . "' AND meta like '%has_recordings%' AND meta like '%true%'";
2071
    if (empty($courseid)) {
2072
        $courseid = 0;
2073
    }
2074
    if (empty($bigbluebuttonbnid)) {
2075
        return $sql . " AND courseid = {$courseid}";
2076
    }
2077
    if ($subset) {
2078
        return $sql . " AND bigbluebuttonbnid = '{$bigbluebuttonbnid}'";
2079
    }
2080
    return $sql . " AND courseid = {$courseid} AND bigbluebuttonbnid <> '{$bigbluebuttonbnid}'";
2081
}
2082
2083
/**
2084
 * Helper function to define the sql used for gattering the bigbluebuttonbnids whose meetingids should be included
2085
 * in the getRecordings request considering only those that belong to imported recordings.
2086
 *
2087
 * @param string $courseid
2088
 * @param string $bigbluebuttonbnid
2089
 * @param bool   $subset
2090
 *
2091
 * @return string containing the sql used for getting the target bigbluebuttonbn instances
2092
 */
2093 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...
2094
    $sql = "log = '" . BIGBLUEBUTTONBN_LOG_EVENT_IMPORT . "'";
2095
    if (empty($courseid)) {
2096
        $courseid = 0;
2097
    }
2098
    if (empty($bigbluebuttonbnid)) {
2099
        return $sql . " AND courseid = '{$courseid}'";
2100
    }
2101
    if ($subset) {
2102
        return $sql . " AND bigbluebuttonbnid = '{$bigbluebuttonbnid}'";
2103
    }
2104
    return $sql . " AND courseid = '{$courseid}' AND bigbluebuttonbnid <> '{$bigbluebuttonbnid}'";
2105
}
2106
2107
/**
2108
 * Helper function to get recordings  and imported recordings together.
2109
 *
2110
 * @param string $courseid
2111
 * @param string $bigbluebuttonbnid
2112
 * @param bool   $subset
2113
 * @param bool   $includedeleted
2114
 *
2115
 * @return associative array containing the recordings indexed by recordID, each recording is also a
2116
 * non sequential associative array itself that corresponds to the actual recording in BBB
2117
 */
2118
function bigbluebuttonbn_get_allrecordings($courseid = 0, $bigbluebuttonbnid = null, $subset = true, $includedeleted = false) {
2119
    $recordings = bigbluebuttonbn_get_recordings($courseid, $bigbluebuttonbnid, $subset, $includedeleted);
2120
    $recordingsimported = bigbluebuttonbn_get_recordings_imported_array($courseid, $bigbluebuttonbnid, $subset);
2121
    return ($recordings + $recordingsimported);
2122
}
2123
2124
/**
2125
 * Helper function to retrieve recordings from the BigBlueButton. The references are stored as events
2126
 * in bigbluebuttonbn_logs.
2127
 *
2128
 * @param string $courseid
2129
 * @param string $bigbluebuttonbnid
2130
 * @param bool   $subset
2131
 * @param bool   $includedeleted
2132
 *
2133
 * @return associative array containing the recordings indexed by recordID, each recording is also a
2134
 * non sequential associative array itself that corresponds to the actual recording in BBB
2135
 */
2136
function bigbluebuttonbn_get_recordings($courseid = 0, $bigbluebuttonbnid = null, $subset = true, $includedeleted = false) {
2137
    global $DB;
2138
    $select = bigbluebuttonbn_get_recordings_sql_select($courseid, $bigbluebuttonbnid, $subset);
2139
    $bigbluebuttonbns = $DB->get_records_select_menu('bigbluebuttonbn', $select, null, 'id', 'id, meetingid');
2140
    /* Consider logs from deleted bigbluebuttonbn instances whose meetingids should be included in
2141
     * the getRecordings request. */
2142
    if ($includedeleted) {
2143
        $selectdeleted = bigbluebuttonbn_get_recordings_deleted_sql_select($courseid, $bigbluebuttonbnid, $subset);
2144
        $bigbluebuttonbnsdel = $DB->get_records_select_menu('bigbluebuttonbn_logs', $selectdeleted, null,
2145
            'bigbluebuttonbnid', 'bigbluebuttonbnid, meetingid');
2146
        if (!empty($bigbluebuttonbnsdel)) {
2147
            // Merge bigbluebuttonbnis from deleted instances, only keys are relevant.
2148
            // Artimetic merge is used in order to keep the keys.
2149
            $bigbluebuttonbns += $bigbluebuttonbnsdel;
2150
        }
2151
    }
2152
    // Gather the meetingids from bigbluebuttonbn logs that include a create with record=true.
2153
    if (empty($bigbluebuttonbns)) {
2154
        return array();
2155
    }
2156
    // Prepare select for loading records based on existent bigbluebuttonbns.
2157
    $sql = 'SELECT DISTINCT meetingid, bigbluebuttonbnid FROM {bigbluebuttonbn_logs} WHERE ';
2158
    $sql .= '(bigbluebuttonbnid='.implode(' OR bigbluebuttonbnid=', array_keys($bigbluebuttonbns)).')';
2159
    // Include only Create events and exclude those with record not true.
2160
    $sql .= ' AND log = ? AND meta LIKE ? AND meta LIKE ?';
2161
    // Execute select for loading records based on existent bigbluebuttonbns.
2162
    $records = $DB->get_records_sql_menu($sql, array(BIGBLUEBUTTONBN_LOG_EVENT_CREATE, '%record%', '%true%'));
2163
    // Get actual recordings.
2164
    return bigbluebuttonbn_get_recordings_array(array_keys($records));
2165
}
2166
2167
/**
2168
 * Helper function iterates an array with recordings and unset those already imported.
2169
 *
2170
 * @param array $recordings
2171
 * @param integer $courseid
2172
 * @param integer $bigbluebuttonbnid
2173
 *
2174
 * @return array
2175
 */
2176
function bigbluebuttonbn_unset_existent_recordings_already_imported($recordings, $courseid, $bigbluebuttonbnid) {
2177
    $recordingsimported = bigbluebuttonbn_get_recordings_imported_array($courseid, $bigbluebuttonbnid, true);
2178
    foreach ($recordings as $key => $recording) {
2179
        if (isset($recordingsimported[$recording['recordID']])) {
2180
            unset($recordings[$key]);
2181
        }
2182
    }
2183
    return $recordings;
2184
}
2185
2186
/**
2187
 * Helper function to count the imported recordings for a recordingid.
2188
 *
2189
 * @param string $recordid
2190
 *
2191
 * @return integer
2192
 */
2193
function bigbluebuttonbn_count_recording_imported_instances($recordid) {
2194
    global $DB;
2195
    $sql = 'SELECT COUNT(DISTINCT id) FROM {bigbluebuttonbn_logs} WHERE log = ? AND meta LIKE ? AND meta LIKE ?';
2196
    return $DB->count_records_sql($sql, array(BIGBLUEBUTTONBN_LOG_EVENT_IMPORT, '%recordID%', "%{$recordid}%"));
2197
}
2198
2199
/**
2200
 * Helper function returns an array with all the instances of imported recordings for a recordingid.
2201
 *
2202
 * @param string $recordid
2203
 *
2204
 * @return array
2205
 */
2206
function bigbluebuttonbn_get_recording_imported_instances($recordid) {
2207
    global $DB;
2208
    $sql = 'SELECT * FROM {bigbluebuttonbn_logs} WHERE log = ? AND meta LIKE ? AND meta LIKE ?';
2209
    $recordingsimported = $DB->get_records_sql($sql, array(BIGBLUEBUTTONBN_LOG_EVENT_IMPORT, '%recordID%',
2210
        "%{$recordid}%"));
2211
    return $recordingsimported;
2212
}
2213
2214
/**
2215
 * Helper function returns an array with the profiles (with features per profile) for the different types
2216
 * of bigbluebuttonbn instances.
2217
 *
2218
 * @return array
2219
 */
2220
function bigbluebuttonbn_get_instance_type_profiles() {
2221
    $instanceprofiles = array(
2222
            array('id' => BIGBLUEBUTTONBN_TYPE_ALL, 'name' => get_string('instance_type_default', 'bigbluebuttonbn'),
2223
                'features' => array('all')),
2224
            array('id' => BIGBLUEBUTTONBN_TYPE_ROOM_ONLY, 'name' => get_string('instance_type_room_only', 'bigbluebuttonbn'),
2225
                'features' => array('showroom', 'welcomemessage', 'voicebridge', 'waitformoderator', 'userlimit', 'recording',
2226
                    'sendnotifications', 'preuploadpresentation', 'permissions', 'schedule', 'groups',
2227
                    'modstandardelshdr', 'availabilityconditionsheader', 'tagshdr', 'competenciessection')),
2228
            array('id' => BIGBLUEBUTTONBN_TYPE_RECORDING_ONLY, 'name' => get_string('instance_type_recording_only',
2229
                'bigbluebuttonbn'), 'features' => array('showrecordings', 'importrecordings')),
2230
    );
2231
    return $instanceprofiles;
2232
}
2233
2234
/**
2235
 * Helper function returns an array with enabled features for an specific profile type.
2236
 *
2237
 * @param array $typeprofiles
2238
 * @param string $type
2239
 *
2240
 * @return array
2241
 */
2242
function bigbluebuttonbn_get_enabled_features($typeprofiles, $type = null) {
2243
    $enabledfeatures = array();
2244
    $features = $typeprofiles[0]['features'];
2245
    if (!is_null($type)) {
2246
        $features = $typeprofiles[$type]['features'];
2247
    }
2248
    $enabledfeatures['showroom'] = (in_array('all', $features) || in_array('showroom', $features));
2249
    // Evaluates if recordings are enabled for the Moodle site.
2250
    $enabledfeatures['showrecordings'] = false;
2251
    if (\mod_bigbluebuttonbn\locallib\config::recordings_enabled()) {
2252
        $enabledfeatures['showrecordings'] = (in_array('all', $features) || in_array('showrecordings', $features));
2253
    }
2254
    $enabledfeatures['importrecordings'] = false;
2255
    if (\mod_bigbluebuttonbn\locallib\config::importrecordings_enabled()) {
2256
        $enabledfeatures['importrecordings'] = (in_array('all', $features) || in_array('importrecordings', $features));
2257
    }
2258
    return $enabledfeatures;
2259
}
2260
2261
/**
2262
 * Helper function returns an array with the profiles (with features per profile) for the different types
2263
 * of bigbluebuttonbn instances.
2264
 *
2265
 * @param array $profiles
2266
 *
2267
 * @return array
2268
 */
2269
function bigbluebuttonbn_get_instance_profiles_array($profiles = null) {
2270
    if (is_null($profiles) || empty($profiles)) {
2271
        $profiles = bigbluebuttonbn_get_instance_type_profiles();
2272
    }
2273
    $profilesarray = array();
2274
    foreach ($profiles as $profile) {
2275
        $profilesarray += array("{$profile['id']}" => $profile['name']);
2276
    }
2277
    return $profilesarray;
2278
}
2279
2280
/**
2281
 * Helper function returns time in a formatted string.
2282
 *
2283
 * @param integer $time
2284
 *
2285
 * @return string
2286
 */
2287
function bigbluebuttonbn_format_activity_time($time) {
2288
    $activitytime = '';
2289
    if ($time) {
2290
        $activitytime = calendar_day_representation($time).' '.
2291
          get_string('mod_form_field_notification_msg_at', 'bigbluebuttonbn').' '.
2292
          calendar_time_representation($time);
2293
    }
2294
    return $activitytime;
2295
}
2296
2297
/**
2298
 * Helper function returns array with all the strings to be used in javascript.
2299
 *
2300
 * @return array
2301
 */
2302
function bigbluebuttonbn_get_strings_for_js() {
2303
    $locale = bigbluebuttonbn_get_locale();
2304
    $stringman = get_string_manager();
2305
    $strings = $stringman->load_component_strings('bigbluebuttonbn', $locale);
2306
    return $strings;
2307
}
2308
2309
/**
2310
 * Helper function returns the locale set by moodle.
2311
 *
2312
 * @return string
2313
 */
2314
function bigbluebuttonbn_get_locale() {
2315
    $lang = get_string('locale', 'core_langconfig');
2316
    return substr($lang, 0, strpos($lang, '.'));
2317
}
2318
2319
/**
2320
 * Helper function returns the locale code based on the locale set by moodle.
2321
 *
2322
 * @return string
2323
 */
2324
function bigbluebuttonbn_get_localcode() {
2325
    $locale = bigbluebuttonbn_get_locale();
2326
    return substr($locale, 0, strpos($locale, '_'));
2327
}
2328
2329
/**
2330
 * Helper function returns array with the instance settings used in views.
2331
 *
2332
 * @param string $id
2333
 * @param object $bigbluebuttonbnid
2334
 *
2335
 * @return array
2336
 */
2337
function bigbluebuttonbn_views_validator($id, $bigbluebuttonbnid) {
2338
    if ($id) {
2339
        return bigbluebuttonbn_views_instance_id($id);
2340
    }
2341
    if ($bigbluebuttonbnid) {
2342
        return bigbluebuttonbn_views_instance_bigbluebuttonbn($bigbluebuttonbnid);
2343
    }
2344
    return;
2345
}
2346
2347
/**
2348
 * Helper function returns array with the instance settings used in views based on id.
2349
 *
2350
 * @param string $id
2351
 *
2352
 * @return array
2353
 */
2354 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...
2355
    global $DB;
2356
    $cm = get_coursemodule_from_id('bigbluebuttonbn', $id, 0, false, MUST_EXIST);
2357
    $course = $DB->get_record('course', array('id' => $cm->course), '*', MUST_EXIST);
2358
    $bigbluebuttonbn = $DB->get_record('bigbluebuttonbn', array('id' => $cm->instance), '*', MUST_EXIST);
2359
    return array('cm' => $cm, 'course' => $course, 'bigbluebuttonbn' => $bigbluebuttonbn);
2360
}
2361
2362
/**
2363
 * Helper function returns array with the instance settings used in views based on bigbluebuttonbnid.
2364
 *
2365
 * @param object $bigbluebuttonbnid
2366
 *
2367
 * @return array
2368
 */
2369 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...
2370
    global $DB;
2371
    $bigbluebuttonbn = $DB->get_record('bigbluebuttonbn', array('id' => $bigbluebuttonbnid), '*', MUST_EXIST);
2372
    $course = $DB->get_record('course', array('id' => $bigbluebuttonbn->course), '*', MUST_EXIST);
2373
    $cm = get_coursemodule_from_instance('bigbluebuttonbn', $bigbluebuttonbn->id, $course->id, false, MUST_EXIST);
2374
    return array('cm' => $cm, 'course' => $course, 'bigbluebuttonbn' => $bigbluebuttonbn);
2375
}
2376
2377
/**
2378
 * Helper function renders general warning message for settings (if any).
2379
 *
2380
 * @param object $renderer
2381
 *
2382
 * @return void
2383
 */
2384
function bigbluebuttonbn_settings_general_warning(&$renderer) {
2385
    global $BIGBLUEBUTTONBN_CFG;
2386
    if (isset($BIGBLUEBUTTONBN_CFG)) {
2387
        $renderer->render_warning_message('general_warning',
2388
             get_string('config_warning_bigbluebuttonbn_cfg_deprecated', 'bigbluebuttonbn'));
2389
    }
2390
}
2391
2392
/**
2393
 * Helper function renders general settings if the feature is enabled.
2394
 *
2395
 * @param object $renderer
2396
 *
2397
 * @return void
2398
 */
2399
function bigbluebuttonbn_settings_general(&$renderer) {
2400
    // Configuration for BigBlueButton.
2401
    if ((boolean)\mod_bigbluebuttonbn\settings\renderer::section_general_shown()) {
2402
        $renderer->render_group_header('general');
2403
        $renderer->render_group_element('server_url',
2404
            $renderer->render_group_element_text('server_url', BIGBLUEBUTTONBN_DEFAULT_SERVER_URL));
2405
        $renderer->render_group_element('shared_secret',
2406
            $renderer->render_group_element_text('shared_secret', BIGBLUEBUTTONBN_DEFAULT_SHARED_SECRET));
2407
    }
2408
}
2409
2410
/**
2411
 * Helper function renders record settings if the feature is enabled.
2412
 *
2413
 * @param object $renderer
2414
 *
2415
 * @return void
2416
 */
2417
function bigbluebuttonbn_settings_record(&$renderer) {
2418
    // Configuration for 'recording' feature.
2419 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...
2420
        $renderer->render_group_header('recording');
2421
        $renderer->render_group_element('recording_default',
2422
            $renderer->render_group_element_checkbox('recording_default', 1));
2423
        $renderer->render_group_element('recording_editable',
2424
            $renderer->render_group_element_checkbox('recording_editable', 1));
2425
        $renderer->render_group_element('recording_icons_enabled',
2426
            $renderer->render_group_element_checkbox('recording_icons_enabled', 1));
2427
    }
2428
}
2429
2430
/**
2431
 * Helper function renders import recording settings if the feature is enabled.
2432
 *
2433
 * @param object $renderer
2434
 *
2435
 * @return void
2436
 */
2437 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...
2438
    // Configuration for 'import recordings' feature.
2439
    if ((boolean)\mod_bigbluebuttonbn\settings\renderer::section_import_recordings_shown()) {
2440
        $renderer->render_group_header('importrecordings');
2441
        $renderer->render_group_element('importrecordings_enabled',
2442
            $renderer->render_group_element_checkbox('importrecordings_enabled', 0));
2443
        $renderer->render_group_element('importrecordings_from_deleted_enabled',
2444
            $renderer->render_group_element_checkbox('importrecordings_from_deleted_enabled', 0));
2445
    }
2446
}
2447
2448
/**
2449
 * Helper function renders show recording settings if the feature is enabled.
2450
 *
2451
 * @param object $renderer
2452
 *
2453
 * @return void
2454
 */
2455
function bigbluebuttonbn_settings_showrecordings(&$renderer) {
2456
    // Configuration for 'show recordings' feature.
2457
    if ((boolean)\mod_bigbluebuttonbn\settings\renderer::section_show_recordings_shown()) {
2458
        $renderer->render_group_header('recordings');
2459
        $renderer->render_group_element('recordings_html_default',
2460
            $renderer->render_group_element_checkbox('recordings_html_default', 1));
2461
        $renderer->render_group_element('recordings_html_editable',
2462
            $renderer->render_group_element_checkbox('recordings_html_editable', 0));
2463
        $renderer->render_group_element('recordings_deleted_default',
2464
            $renderer->render_group_element_checkbox('recordings_deleted_default', 1));
2465
        $renderer->render_group_element('recordings_deleted_editable',
2466
            $renderer->render_group_element_checkbox('recordings_deleted_editable', 0));
2467
        $renderer->render_group_element('recordings_imported_default',
2468
            $renderer->render_group_element_checkbox('recordings_imported_default', 0));
2469
        $renderer->render_group_element('recordings_imported_editable',
2470
            $renderer->render_group_element_checkbox('recordings_imported_editable', 1));
2471
        $renderer->render_group_element('recordings_preview_default',
2472
            $renderer->render_group_element_checkbox('recordings_preview_default', 1));
2473
        $renderer->render_group_element('recordings_preview_editable',
2474
            $renderer->render_group_element_checkbox('recordings_preview_editable', 0));
2475
    }
2476
}
2477
2478
/**
2479
 * Helper function renders wait for moderator settings if the feature is enabled.
2480
 *
2481
 * @param object $renderer
2482
 *
2483
 * @return void
2484
 */
2485
function bigbluebuttonbn_settings_waitmoderator(&$renderer) {
2486
    // Configuration for wait for moderator feature.
2487
    if ((boolean)\mod_bigbluebuttonbn\settings\renderer::section_wait_moderator_shown()) {
2488
        $renderer->render_group_header('waitformoderator');
2489
        $renderer->render_group_element('waitformoderator_default',
2490
            $renderer->render_group_element_checkbox('waitformoderator_default', 0));
2491
        $renderer->render_group_element('waitformoderator_editable',
2492
            $renderer->render_group_element_checkbox('waitformoderator_editable', 1));
2493
        $renderer->render_group_element('waitformoderator_ping_interval',
2494
            $renderer->render_group_element_text('waitformoderator_ping_interval', 10, PARAM_INT));
2495
        $renderer->render_group_element('waitformoderator_cache_ttl',
2496
            $renderer->render_group_element_text('waitformoderator_cache_ttl', 60, PARAM_INT));
2497
    }
2498
}
2499
2500
/**
2501
 * Helper function renders static voice bridge settings if the feature is enabled.
2502
 *
2503
 * @param object $renderer
2504
 *
2505
 * @return void
2506
 */
2507
function bigbluebuttonbn_settings_voicebridge(&$renderer) {
2508
    // Configuration for "static voice bridge" feature.
2509
    if ((boolean)\mod_bigbluebuttonbn\settings\renderer::section_static_voice_bridge_shown()) {
2510
        $renderer->render_group_header('voicebridge');
2511
        $renderer->render_group_element('voicebridge_editable',
2512
            $renderer->render_group_element_checkbox('voicebridge_editable', 0));
2513
    }
2514
}
2515
2516
/**
2517
 * Helper function renders preuploaded presentation settings if the feature is enabled.
2518
 *
2519
 * @param object $renderer
2520
 *
2521
 * @return void
2522
 */
2523
function bigbluebuttonbn_settings_preupload(&$renderer) {
2524
    // Configuration for "preupload presentation" feature.
2525
    if ((boolean)\mod_bigbluebuttonbn\settings\renderer::section_preupload_presentation_shown()) {
2526
        // This feature only works if curl is installed.
2527
        $preuploaddescripion = get_string('config_preuploadpresentation_description', 'bigbluebuttonbn');
2528
        if (!extension_loaded('curl')) {
2529
            $preuploaddescripion .= '<div class="form-defaultinfo">';
2530
            $preuploaddescripion .= get_string('config_warning_curl_not_installed', 'bigbluebuttonbn');
2531
            $preuploaddescripion .= '</div><br>';
2532
        }
2533
        $renderer->render_group_header('preuploadpresentation', null, $preuploaddescripion);
2534
        if (extension_loaded('curl')) {
2535
            $renderer->render_group_element('preuploadpresentation_enabled',
2536
                $renderer->render_group_element_checkbox('preuploadpresentation_enabled', 0));
2537
        }
2538
    }
2539
}
2540
2541
/**
2542
 * Helper function renders userlimit settings if the feature is enabled.
2543
 *
2544
 * @param object $renderer
2545
 *
2546
 * @return void
2547
 */
2548
function bigbluebuttonbn_settings_userlimit(&$renderer) {
2549
    // Configuration for "user limit" feature.
2550
    if ((boolean)\mod_bigbluebuttonbn\settings\renderer::section_user_limit_shown()) {
2551
        $renderer->render_group_header('userlimit');
2552
        $renderer->render_group_element('userlimit_default',
2553
            $renderer->render_group_element_text('userlimit_default', 0, PARAM_INT));
2554
        $renderer->render_group_element('userlimit_editable',
2555
            $renderer->render_group_element_checkbox('userlimit_editable', 0));
2556
    }
2557
}
2558
2559
/**
2560
 * Helper function renders duration settings if the feature is enabled.
2561
 *
2562
 * @param object $renderer
2563
 *
2564
 * @return void
2565
 */
2566
function bigbluebuttonbn_settings_duration(&$renderer) {
2567
    // Configuration for "scheduled duration" feature.
2568 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...
2569
        $renderer->render_group_header('scheduled');
2570
        $renderer->render_group_element('scheduled_duration_enabled',
2571
            $renderer->render_group_element_checkbox('scheduled_duration_enabled', 1));
2572
        $renderer->render_group_element('scheduled_duration_compensation',
2573
            $renderer->render_group_element_text('scheduled_duration_compensation', 10, PARAM_INT));
2574
        $renderer->render_group_element('scheduled_pre_opening',
2575
            $renderer->render_group_element_text('scheduled_pre_opening', 10, PARAM_INT));
2576
    }
2577
}
2578
2579
/**
2580
 * Helper function renders participant settings if the feature is enabled.
2581
 *
2582
 * @param object $renderer
2583
 *
2584
 * @return void
2585
 */
2586
function bigbluebuttonbn_settings_participants(&$renderer) {
2587
    // Configuration for defining the default role/user that will be moderator on new activities.
2588
    if ((boolean)\mod_bigbluebuttonbn\settings\renderer::section_moderator_default_shown()) {
2589
        $renderer->render_group_header('participant');
2590
        // UI for 'participants' feature.
2591
        $roles = bigbluebuttonbn_get_roles();
2592
        $owner = array('0' => get_string('mod_form_field_participant_list_type_owner', 'bigbluebuttonbn'));
2593
        $renderer->render_group_element('participant_moderator_default',
2594
            $renderer->render_group_element_configmultiselect('participant_moderator_default',
2595
                array_keys($owner), array_merge($owner, $roles))
2596
          );
2597
    }
2598
}
2599
2600
/**
2601
 * Helper function renders notification settings if the feature is enabled.
2602
 *
2603
 * @param object $renderer
2604
 *
2605
 * @return void
2606
 */
2607
function bigbluebuttonbn_settings_notifications(&$renderer) {
2608
    // Configuration for "send notifications" feature.
2609
    if ((boolean)\mod_bigbluebuttonbn\settings\renderer::section_send_notifications_shown()) {
2610
        $renderer->render_group_header('sendnotifications');
2611
        $renderer->render_group_element('sendnotifications_enabled',
2612
            $renderer->render_group_element_checkbox('sendnotifications_enabled', 1));
2613
    }
2614
}
2615
2616
/**
2617
 * Helper function renders extended settings if any of the features there is enabled.
2618
 *
2619
 * @param object $renderer
2620
 *
2621
 * @return void
2622
 */
2623 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...
2624
    // Configuration for extended BN capabilities.
2625
    if (!bigbluebuttonbn_is_bn_server()) {
2626
        return;
2627
    }
2628
    // Configuration for 'notify users when recording ready' feature.
2629
    if ((boolean)\mod_bigbluebuttonbn\settings\renderer::section_settings_extended_shown()) {
2630
        $renderer->render_group_header('extended_capabilities');
2631
        // UI for 'notify users when recording ready' feature.
2632
        $renderer->render_group_element('recordingready_enabled',
2633
            $renderer->render_group_element_checkbox('recordingready_enabled', 0));
2634
        // UI for 'register meeting events' feature.
2635
        $renderer->render_group_element('meetingevents_enabled',
2636
            $renderer->render_group_element_checkbox('meetingevents_enabled', 0));
2637
    }
2638
}
2639
2640
/**
2641
 * Helper function returns an encoded meetingid.
2642
 *
2643
 * @param string $seed
2644
 *
2645
 * @return string
2646
 */
2647
function bigbluebuttonbn_encode_meetingid($seed) {
2648
    global $CFG;
2649
    return sha1($CFG->wwwroot . $seed . \mod_bigbluebuttonbn\locallib\config::get('shared_secret'));
2650
}
2651
2652
/**
2653
 * Helper function renders the link used for recording type in row for the data used by the recording table.
2654
 *
2655
 * @param array $recording
2656
 * @param array $bbbsession
2657
 * @param array $playback
2658
 *
2659
 * @return boolean
2660
 */
2661
function bigbluebuttonbn_include_recording_data_row_type($recording, $bbbsession, $playback) {
2662
    // All types that are not restricted are included.
2663
    if (array_key_exists('restricted', $playback) && strtolower($playback['restricted']) == 'false') {
2664
        return true;
2665
    }
2666
    // All types that are not statistics are included.
2667
    if ($playback['type'] != 'statistics') {
2668
        return true;
2669
    }
2670
    // Exclude imported recordings.
2671
    if (isset($recording['imported'])) {
2672
        return false;
2673
    }
2674
    // Exclude non moderators.
2675
    if (!$bbbsession['administrator'] && !$bbbsession['moderator']) {
2676
        return false;
2677
    }
2678
    return true;
2679
}
2680
2681
/**
2682
 * Renders the general warning message.
2683
 *
2684
 * @param string $message
2685
 * @param string $type
2686
 * @param string $href
2687
 * @param string $text
2688
 * @param string $class
2689
 *
2690
 * @return string
2691
 */
2692
function bigbluebuttonbn_render_warning($message, $type='info', $href='', $text='', $class='') {
2693
    global $OUTPUT;
2694
    $output = "\n";
2695
    // Evaluates if config_warning is enabled.
2696
    if (empty($message)) {
2697
        return $output;
2698
    }
2699
    $output .= $OUTPUT->box_start('box boxalignleft adminerror alert alert-' . $type . ' alert-block fade in',
2700
      'bigbluebuttonbn_view_general_warning') . "\n";
2701
    $output .= '    ' . $message . "\n";
2702
    $output .= '  <div class="singlebutton pull-right">' . "\n";
2703
    if (!empty($href)) {
2704
        $output .= bigbluebuttonbn_render_warning_button($href, $text, $class);
2705
    }
2706
    $output .= '  </div>' . "\n";
2707
    $output .= $OUTPUT->box_end() . "\n";
2708
    return $output;
2709
}
2710
2711
/**
2712
 * Renders the general warning button.
2713
 *
2714
 * @param string $href
2715
 * @param string $text
2716
 * @param string $class
2717
 * @param string $title
2718
 *
2719
 * @return string
2720
 */
2721
function bigbluebuttonbn_render_warning_button($href, $text = '', $class = '', $title = '') {
2722
    if ($text == '') {
2723
        $text = get_string('ok', 'moodle');
2724
    }
2725
    if ($title == '') {
2726
        $title = $text;
2727
    }
2728
    if ($class == '') {
2729
        $class = 'btn btn-secondary';
2730
    }
2731
    $output  = '  <form method="post" action="' . $href . '" class="form-inline">'."\n";
2732
    $output .= '      <button type="submit" class="' . $class . '"'."\n";
2733
    $output .= '          title="' . $title . '"'."\n";
2734
    $output .= '          >' . $text . '</button>'."\n";
2735
    $output .= '  </form>'."\n";
2736
    return $output;
2737
}
2738
2739
/**
2740
 * Check if a BigBlueButtonBN is available to be used by the current user.
2741
 *
2742
 * @param  stdClass  $bigbluebuttonbn  BigBlueButtonBN instance
2743
 *
2744
 * @return boolean                     status if room available and current user allowed to join
2745
 */
2746
function bigbluebuttonbn_get_availability_status($bigbluebuttonbn) {
2747
    list($roomavailable) = bigbluebuttonbn_room_is_available($bigbluebuttonbn);
2748
    list($usercanjoin) = bigbluebuttonbn_user_can_join_meeting($bigbluebuttonbn);
2749
2750
    return ($roomavailable && $usercanjoin);
2751
}
2752
2753
/**
2754
 * Helper for evaluating if scheduled activity is avaiable.
2755
 *
2756
 * @param  stdClass  $bigbluebuttonbn  BigBlueButtonBN instance
2757
 *
2758
 * @return array                       status (room available or not and possible warnings)
2759
 */
2760
function bigbluebuttonbn_room_is_available($bigbluebuttonbn) {
2761
    $open = true;
2762
    $closed = false;
2763
    $warnings = array();
2764
2765
    $timenow = time();
2766
    $timeopen = $bigbluebuttonbn->openingtime;
2767
    $timeclose = $bigbluebuttonbn->closingtime;
2768
    if (!empty($timeopen) && $timeopen > $timenow) {
2769
        $open = false;
2770
    }
2771
    if (!empty($timeclose) && $timenow > $timeclose) {
2772
        $closed = true;
2773
    }
2774
2775
    if (!$open || $closed) {
2776
        if (!$open) {
2777
            $warnings['notopenyet'] = userdate($timeopen);
2778
        }
2779
        if ($closed) {
2780
            $warnings['expired'] = userdate($timeclose);
2781
        }
2782
        return array(false, $warnings);
2783
    }
2784
2785
    return array(true, $warnings);
2786
}
2787
2788
/**
2789
 * Helper for evaluating if meeting can be joined.
2790
 *
2791
 * @param  stdClass $bigbluebuttonbn  BigBlueButtonBN instance
2792
 * @param  string   $meetingid
2793
 * @param  integer  $userid
2794
 *
2795
 * @return array    status (user allowed to join or not and possible message)
2796
 */
2797
function bigbluebuttonbn_user_can_join_meeting($bigbluebuttonbn, $meetingid = null, $userid = null) {
2798
2799
    // By default, use a meetingid without groups.
2800
    if (empty($meetingid)) {
2801
        $meetingid = $bigbluebuttonbn->meetingid . '-' . $bigbluebuttonbn->courseid . '-' . $bigbluebuttonbn->id;
2802
    }
2803
2804
    // When meeting is running, all authorized users can join right in.
2805
    if (bigbluebuttonbn_is_meeting_running($meetingid)) {
2806
        return array(true, get_string('view_message_conference_in_progress', 'bigbluebuttonbn'));
2807
    }
2808
2809
    // When meeting is not running, see if the user can join.
2810
    $context = context_course::instance($bigbluebuttonbn->course);
2811
    $participantlist = bigbluebuttonbn_get_participant_list($bigbluebuttonbn, $context);
2812
    $isadmin = is_siteadmin($userid);
2813
    $ismoderator = bigbluebuttonbn_is_moderator($context, json_encode($participantlist), $userid);
2814
    // If user is administrator, moderator or if is viewer and no waiting is required, join allowed.
2815
    if ($isadmin || $ismoderator || !$bigbluebuttonbn->wait) {
2816
        return array(true, get_string('view_message_conference_room_ready', 'bigbluebuttonbn'));
2817
    }
2818
    // Otherwise, no join allowed.
2819
    return array(false, get_string('view_message_conference_wait_for_moderator', 'bigbluebuttonbn'));
2820
}
2821
2822
/**
2823
 * Helper for getting a value from a bigbluebuttonbn cache.
2824
 *
2825
 * @param  string   $name       BigBlueButtonBN cache
2826
 * @param  string   $key        Key to be retrieved
2827
 * @param  integer  $default    Default value in case key is not found or it is empty
2828
 *
2829
 * @return variable key value
2830
 */
2831
function bigbluebuttonbn_cache_get($name, $key, $default = null) {
2832
    $cache = cache::make_from_params(cache_store::MODE_APPLICATION, 'mod_bigbluebuttonbn', $name);
2833
    $result = $cache->get($key);
2834
    if (!empty($result)) {
2835
        return $result;
2836
    }
2837
    return $default;
2838
}
2839
2840
/**
2841
 * Helper for setting a value in a bigbluebuttonbn cache.
2842
 *
2843
 * @param  string   $name       BigBlueButtonBN cache
2844
 * @param  string   $key        Key to be created/updated
2845
 * @param  variable $value      Default value to be set
2846
 */
2847
function bigbluebuttonbn_cache_set($name, $key, $value) {
2848
    $cache = cache::make_from_params(cache_store::MODE_APPLICATION, 'mod_bigbluebuttonbn', $name);
2849
    $result = $cache->set($key, $value);
0 ignored issues
show
Unused Code introduced by
$result is not used, you could remove the assignment.

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

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

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

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

Loading history...
2850
}
2851