Completed
Pull Request — master (#85)
by Jesus
05:06 queued 02:26
created

locallib.php ➔ bigbluebuttonbn_view_get_activity_status()   A

Complexity

Conditions 5
Paths 3

Size

Total Lines 17

Duplication

Lines 4
Ratio 23.53 %

Importance

Changes 0
Metric Value
cc 5
nc 3
nop 1
dl 4
loc 17
rs 9.3888
c 0
b 0
f 0
1
<?php
2
// This file is part of Moodle - http://moodle.org/
3
//
4
// Moodle is free software: you can redistribute it and/or modify
5
// it under the terms of the GNU General Public License as published by
6
// the Free Software Foundation, either version 3 of the License, or
7
// (at your option) any later version.
8
//
9
// Moodle is distributed in the hope that it will be useful,
10
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
// GNU General Public License for more details.
13
//
14
// You should have received a copy of the GNU General Public License
15
// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
16
17
/**
18
 * Internal library of functions for module BigBlueButtonBN.
19
 *
20
 * @package   mod_bigbluebuttonbn
21
 * @copyright 2010 onwards, Blindside Networks Inc
22
 * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
23
 * @author    Jesus Federico  (jesus [at] blindsidenetworks [dt] com)
24
 * @author    Fred Dixon  (ffdixon [at] blindsidenetworks [dt] com)
25
 */
26
27
defined('MOODLE_INTERNAL') || die;
28
29
global $CFG;
30
31
require_once(dirname(__FILE__).'/lib.php');
32
33
/** @var BIGBLUEBUTTONBN_UPDATE_CACHE boolean set to true indicates that cache has to be updated */
34
const BIGBLUEBUTTONBN_UPDATE_CACHE = true;
35
/** @var BIGBLUEBUTTONBN_TYPE_ALL integer set to 0 defines an instance type that inclueds room and recordings */
36
const BIGBLUEBUTTONBN_TYPE_ALL = 0;
37
/** @var BIGBLUEBUTTONBN_TYPE_ROOM_ONLY integer set to 1 defines an instance type that inclueds only room */
38
const BIGBLUEBUTTONBN_TYPE_ROOM_ONLY = 1;
39
/** @var BIGBLUEBUTTONBN_TYPE_RECORDING_ONLY integer set to 2 defines an instance type that inclueds only recordings */
40
const BIGBLUEBUTTONBN_TYPE_RECORDING_ONLY = 2;
41
/** @var BIGBLUEBUTTONBN_ROLE_VIEWER string defines the bigbluebutton viewer role */
42
const BIGBLUEBUTTONBN_ROLE_VIEWER = 'viewer';
43
/** @var BIGBLUEBUTTONBN_ROLE_MODERATOR string defines the bigbluebutton moderator role */
44
const BIGBLUEBUTTONBN_ROLE_MODERATOR = 'moderator';
45
/** @var BIGBLUEBUTTON_EVENT_ACTIVITY_VIEWED string defines the bigbluebuttonbn activity_viewed event */
46
const BIGBLUEBUTTON_EVENT_ACTIVITY_VIEWED = 'activity_viewed';
47
/** @var BIGBLUEBUTTON_EVENT_ACTIVITY_MANAGEMENT_VIEWED string defines the bigbluebuttonbn activity_management_viewed event */
48
const BIGBLUEBUTTON_EVENT_ACTIVITY_MANAGEMENT_VIEWED = 'activity_management_viewed';
49
/** @var BIGBLUEBUTTON_EVENT_LIVE_SESSION string defines the bigbluebuttonbn live_session event */
50
const BIGBLUEBUTTON_EVENT_LIVE_SESSION = 'live_session';
51
/** @var BIGBLUEBUTTON_EVENT_MEETING_CREATED string defines the bigbluebuttonbn meeting_created event */
52
const BIGBLUEBUTTON_EVENT_MEETING_CREATED = 'meeting_created';
53
/** @var BIGBLUEBUTTON_EVENT_MEETING_ENDED string defines the bigbluebuttonbn meeting_ended event */
54
const BIGBLUEBUTTON_EVENT_MEETING_ENDED = 'meeting_ended';
55
/** @var BIGBLUEBUTTON_EVENT_MEETING_JOINED string defines the bigbluebuttonbn meeting_joined event */
56
const BIGBLUEBUTTON_EVENT_MEETING_JOINED = 'meeting_joined';
57
/** @var BIGBLUEBUTTON_EVENT_MEETING_LEFT string defines the bigbluebuttonbn meeting_left event */
58
const BIGBLUEBUTTON_EVENT_MEETING_LEFT = 'meeting_left';
59
/** @var BIGBLUEBUTTON_EVENT_RECORDING_DELETED string defines the bigbluebuttonbn recording_deleted event */
60
const BIGBLUEBUTTON_EVENT_RECORDING_DELETED = 'recording_deleted';
61
/** @var BIGBLUEBUTTON_EVENT_RECORDING_IMPORTED string defines the bigbluebuttonbn recording_imported event */
62
const BIGBLUEBUTTON_EVENT_RECORDING_IMPORTED = 'recording_imported';
63
/** @var BIGBLUEBUTTON_EVENT_RECORDING_PROTECTED string defines the bigbluebuttonbn recording_protected event */
64
const BIGBLUEBUTTON_EVENT_RECORDING_PROTECTED = 'recording_protected';
65
/** @var BIGBLUEBUTTON_EVENT_RECORDING_PUBLISHED string defines the bigbluebuttonbn recording_published event */
66
const BIGBLUEBUTTON_EVENT_RECORDING_PUBLISHED = 'recording_published';
67
/** @var BIGBLUEBUTTON_EVENT_RECORDING_UNPROTECTED string defines the bigbluebuttonbn recording_unprotected event */
68
const BIGBLUEBUTTON_EVENT_RECORDING_UNPROTECTED = 'recording_unprotected';
69
/** @var BIGBLUEBUTTON_EVENT_RECORDING_UNPUBLISHED string defines the bigbluebuttonbn recording_unpublished event */
70
const BIGBLUEBUTTON_EVENT_RECORDING_UNPUBLISHED = 'recording_unpublished';
71
/** @var BIGBLUEBUTTON_EVENT_RECORDING_EDITED string defines the bigbluebuttonbn recording_edited event */
72
const BIGBLUEBUTTON_EVENT_RECORDING_EDITED = 'recording_edited';
73
/** @var BIGBLUEBUTTON_EVENT_RECORDING_VIEWED string defines the bigbluebuttonbn recording_viewed event */
74
const BIGBLUEBUTTON_EVENT_RECORDING_VIEWED = 'recording_viewed';
75
/** @var BIGBLUEBUTTON_EVENT_MEETING_START string defines the bigbluebuttonbn meeting_start event */
76
const BIGBLUEBUTTON_EVENT_MEETING_START = 'meeting_start';
77
/** @var BIGBLUEBUTTON_CLIENTTYPE_FLASH integer that defines the bigbluebuttonbn default web client based on Adobe FLASH */
78
const BIGBLUEBUTTON_CLIENTTYPE_FLASH = 0;
79
/** @var BIGBLUEBUTTON_CLIENTTYPE_HTML5 integer that defines the bigbluebuttonbn default web client based on HTML5 */
80
const BIGBLUEBUTTON_CLIENTTYPE_HTML5 = 1;
81
82
/**
83
 * Builds and retunrs a url for joining a bigbluebutton meeting.
84
 *
85
 * @param string $meetingid
86
 * @param string $username
87
 * @param string $pw
88
 * @param string $logouturl
89
 * @param string $configtoken
90
 * @param string $userid
91
 * @param string $clienttype
92
 *
93
 * @return string
94
 */
95
function bigbluebuttonbn_get_join_url($meetingid, $username, $pw, $logouturl, $configtoken = null,
96
        $userid = null, $clienttype = BIGBLUEBUTTON_CLIENTTYPE_FLASH) {
97
    $data = ['meetingID' => $meetingid,
98
              'fullName' => $username,
99
              'password' => $pw,
100
              'logoutURL' => $logouturl,
101
            ];
102
    // Choose between Adobe Flash or HTML5 Client.
103
    if ( $clienttype == BIGBLUEBUTTON_CLIENTTYPE_HTML5 ) {
104
        $data['joinViaHtml5'] = 'true';
105
    }
106
    if (!is_null($configtoken)) {
107
        $data['configToken'] = $configtoken;
108
    }
109
    if (!is_null($userid)) {
110
        $data['userID'] = $userid;
111
    }
112
    return \mod_bigbluebuttonbn\locallib\bigbluebutton::action_url('join', $data);
113
}
114
115
/**
116
 * Creates a bigbluebutton meeting and returns the response in an array.
117
 *
118
 * @param array  $data
119
 * @param array  $metadata
120
 * @param string $pname
121
 * @param string $purl
122
 *
123
 * @return array
124
 */
125
function bigbluebuttonbn_get_create_meeting_array($data, $metadata = array(), $pname = null, $purl = null) {
126
    $createmeetingurl = \mod_bigbluebuttonbn\locallib\bigbluebutton::action_url('create', $data, $metadata);
127
    $method = 'GET';
128
    $data = null;
129
    if (!is_null($pname) && !is_null($purl)) {
130
        $method = 'POST';
131
        $data = "<?xml version='1.0' encoding='UTF-8'?><modules><module name='presentation'><document url='".
132
            $purl."' /></module></modules>";
133
    }
134
    $xml = bigbluebuttonbn_wrap_xml_load_file($createmeetingurl, $method, $data);
135
    if ($xml) {
136
        $response = array('returncode' => $xml->returncode, 'message' => $xml->message, 'messageKey' => $xml->messageKey);
137
        if ($xml->meetingID) {
138
            $response += array('meetingID' => $xml->meetingID, 'attendeePW' => $xml->attendeePW,
139
                'moderatorPW' => $xml->moderatorPW, 'hasBeenForciblyEnded' => $xml->hasBeenForciblyEnded);
140
        }
141
        return $response;
142
    }
143
    return array('returncode' => 'FAILED', 'message' => 'unreachable', 'messageKey' => 'Server is unreachable');
144
}
145
146
/**
147
 * Fetch meeting info and wrap response in array.
148
 *
149
 * @param string $meetingid
150
 *
151
 * @return array
152
 */
153
function bigbluebuttonbn_get_meeting_info_array($meetingid) {
154
    $xml = bigbluebuttonbn_wrap_xml_load_file(
155
        \mod_bigbluebuttonbn\locallib\bigbluebutton::action_url('getMeetingInfo', ['meetingID' => $meetingid])
156
      );
157
    if ($xml && $xml->returncode == 'SUCCESS' && empty($xml->messageKey)) {
158
        // Meeting info was returned.
159
        return array('returncode' => $xml->returncode,
160
                     'meetingID' => $xml->meetingID,
161
                     'moderatorPW' => $xml->moderatorPW,
162
                     'attendeePW' => $xml->attendeePW,
163
                     'hasBeenForciblyEnded' => $xml->hasBeenForciblyEnded,
164
                     'running' => $xml->running,
165
                     'recording' => $xml->recording,
166
                     'startTime' => $xml->startTime,
167
                     'endTime' => $xml->endTime,
168
                     'participantCount' => $xml->participantCount,
169
                     'moderatorCount' => $xml->moderatorCount,
170
                     'attendees' => $xml->attendees,
171
                     'metadata' => $xml->metadata,
172
                   );
173
    }
174
    if ($xml) {
175
        // Either failure or success without meeting info.
176
        return (array)$xml;
177
    }
178
    // If the server is unreachable, then prompts the user of the necessary action.
179
    return array('returncode' => 'FAILED', 'message' => 'unreachable', 'messageKey' => 'Server is unreachable');
180
}
181
182
/**
183
 * Helper function to retrieve recordings from a BigBlueButton server.
184
 *
185
 * @param string|array $meetingids   list of meetingIDs "mid1,mid2,mid3" or array("mid1","mid2","mid3")
186
 * @param string|array $recordingids list of $recordingids "rid1,rid2,rid3" or array("rid1","rid2","rid3") for filtering
187
 *
188
 * @return associative array with recordings indexed by recordID, each recording is a non sequential associative array
189
 */
190
function bigbluebuttonbn_get_recordings_array($meetingids, $recordingids = []) {
191
    $meetingidsarray = $meetingids;
192
    if (!is_array($meetingids)) {
193
        $meetingidsarray = explode(',', $meetingids);
194
    }
195
    // If $meetingidsarray is empty there is no need to go further.
196
    if (empty($meetingidsarray)) {
197
        return array();
198
    }
199
    $recordings = bigbluebuttonbn_get_recordings_array_fetch($meetingidsarray);
0 ignored issues
show
Bug introduced by
It seems like $meetingidsarray defined by $meetingids on line 191 can also be of type string; however, bigbluebuttonbn_get_recordings_array_fetch() does only seem to accept array, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
200
    // Sort recordings.
201
    uasort($recordings, 'bigbluebuttonbn_recording_build_sorter');
202
    // Filter recordings based on recordingIDs.
203
    $recordingidsarray = $recordingids;
204
    if (!is_array($recordingids)) {
205
        $recordingidsarray = explode(',', $recordingids);
206
    }
207
    if (empty($recordingidsarray)) {
208
        // No recording ids, no need to filter.
209
        return $recordings;
210
    }
211
    return bigbluebuttonbn_get_recordings_array_filter($recordingidsarray, $recordings);
0 ignored issues
show
Bug introduced by
It seems like $recordingidsarray defined by $recordingids on line 203 can also be of type string; however, bigbluebuttonbn_get_recordings_array_filter() does only seem to accept array, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
212
}
213
214
/**
215
 * Helper function to fetch recordings from a BigBlueButton server.
216
 *
217
 * @param array $meetingidsarray   array with meeting ids in the form array("mid1","mid2","mid3")
218
 *
219
 * @return associative array with recordings indexed by recordID, each recording is a non sequential associative array
220
 */
221
function bigbluebuttonbn_get_recordings_array_fetch($meetingidsarray) {
222
    $recordings = array();
223
    // Execute a paginated getRecordings request.
224
    $pages = floor(count($meetingidsarray) / 25) + 1;
225
    for ($page = 1; $page <= $pages; ++$page) {
226
        $mids = array_slice($meetingidsarray, ($page - 1) * 25, 25);
227
        $recordings += bigbluebuttonbn_get_recordings_array_fetch_page($mids);
228
    }
229
    return $recordings;
230
}
231
232
/**
233
 * Helper function to fetch one page of upto 25 recordings from a BigBlueButton server.
234
 *
235
 * @param array  $mids
236
 *
237
 * @return array
238
 */
239
function bigbluebuttonbn_get_recordings_array_fetch_page($mids) {
240
    $recordings = array();
241
    // Do getRecordings is executed using a method GET (supported by all versions of BBB).
242
    $url = \mod_bigbluebuttonbn\locallib\bigbluebutton::action_url('getRecordings', ['meetingID' => implode(',', $mids)]);
243
    $xml = bigbluebuttonbn_wrap_xml_load_file($url);
244
    if ($xml && $xml->returncode == 'SUCCESS' && isset($xml->recordings)) {
245
        // If there were meetings already created.
246
        foreach ($xml->recordings->recording as $recordingxml) {
247
            $recording = bigbluebuttonbn_get_recording_array_value($recordingxml);
248
            $recordings[$recording['recordID']] = $recording;
249
        }
250
    }
251
    return $recordings;
252
}
253
254
/**
255
 * Helper function to remove a set of recordings from an array.
256
 *
257
 * @param array  $rids
258
 * @param array  $recordings
259
 *
260
 * @return array
261
 */
262
function bigbluebuttonbn_get_recordings_array_filter($rids, &$recordings) {
263
    foreach ($recordings as $key => $recording) {
264
        if (!in_array($recording['recordID'], $rids)) {
265
            unset($recordings[$key]);
266
        }
267
    }
268
    return $recordings;
269
}
270
271
/**
272
 * Helper function to retrieve imported recordings from the Moodle database.
273
 * The references are stored as events in bigbluebuttonbn_logs.
274
 *
275
 * @param string $courseid
276
 * @param string $bigbluebuttonbnid
277
 * @param bool   $subset
278
 *
279
 * @return associative array with imported recordings indexed by recordID, each recording
280
 * is a non sequential associative array that corresponds to the actual recording in BBB
281
 */
282
function bigbluebuttonbn_get_recordings_imported_array($courseid = 0, $bigbluebuttonbnid = null, $subset = true) {
283
    global $DB;
284
    $select = bigbluebuttonbn_get_recordings_imported_sql_select($courseid, $bigbluebuttonbnid, $subset);
285
    $recordsimported = $DB->get_records_select('bigbluebuttonbn_logs', $select);
286
    $recordsimportedarray = array();
287
    foreach ($recordsimported as $recordimported) {
288
        $meta = json_decode($recordimported->meta, true);
289
        $recording = $meta['recording'];
290
        // Override imported flag with actual ID.
291
        $recording['imported'] = $recordimported->id;
292
        if (isset($recordimported->protected)) {
293
            $recording['protected'] = (string) $recordimported->protected;
294
        }
295
        $recordsimportedarray[$recording['recordID']] = $recording;
296
    }
297
    return $recordsimportedarray;
298
}
299
300
/**
301
 * Helper function to retrive the default config.xml file.
302
 *
303
 * @return string
304
 */
305
function bigbluebuttonbn_get_default_config_xml() {
306
    $xml = bigbluebuttonbn_wrap_xml_load_file(
307
        \mod_bigbluebuttonbn\locallib\bigbluebutton::action_url('getDefaultConfigXML')
308
      );
309
    return $xml;
310
}
311
312
/**
313
 * Helper function to convert an xml recording object to an array in the format used by the plugin.
314
 *
315
 * @param object $recording
316
 *
317
 * @return array
318
 */
319
function bigbluebuttonbn_get_recording_array_value($recording) {
320
    // Add formats.
321
    $playbackarray = array();
322
    foreach ($recording->playback->format as $format) {
323
        $playbackarray[(string) $format->type] = array('type' => (string) $format->type,
324
            'url' => trim((string) $format->url), 'length' => (string) $format->length);
325
        // Add preview per format when existing.
326
        if ($format->preview) {
327
            $playbackarray[(string) $format->type]['preview'] = bigbluebuttonbn_get_recording_preview_images($format->preview);
328
        }
329
    }
330
    // Add the metadata to the recordings array.
331
    $metadataarray = bigbluebuttonbn_get_recording_array_meta(get_object_vars($recording->metadata));
332
    $recordingarray = array('recordID' => (string) $recording->recordID,
333
        'meetingID' => (string) $recording->meetingID, 'meetingName' => (string) $recording->name,
334
        'published' => (string) $recording->published, 'startTime' => (string) $recording->startTime,
335
        'endTime' => (string) $recording->endTime, 'playbacks' => $playbackarray);
336
    if (isset($recording->protected)) {
337
        $recordingarray['protected'] = (string) $recording->protected;
338
    }
339
    return $recordingarray + $metadataarray;
340
}
341
342
/**
343
 * Helper function to convert an xml recording preview images to an array in the format used by the plugin.
344
 *
345
 * @param object $preview
346
 *
347
 * @return array
348
 */
349
function bigbluebuttonbn_get_recording_preview_images($preview) {
350
    $imagesarray = array();
351
    foreach ($preview->images->image as $image) {
352
        $imagearray = array('url' => trim((string) $image));
353
        foreach ($image->attributes() as $attkey => $attvalue) {
354
            $imagearray[$attkey] = (string) $attvalue;
355
        }
356
        array_push($imagesarray, $imagearray);
357
    }
358
    return $imagesarray;
359
}
360
361
/**
362
 * Helper function to convert an xml recording metadata object to an array in the format used by the plugin.
363
 *
364
 * @param array $metadata
365
 *
366
 * @return array
367
 */
368
function bigbluebuttonbn_get_recording_array_meta($metadata) {
369
    $metadataarray = array();
370
    foreach ($metadata as $key => $value) {
371
        if (is_object($value)) {
372
            $value = '';
373
        }
374
        $metadataarray['meta_'.$key] = $value;
375
    }
376
    return $metadataarray;
377
}
378
379
/**
380
 * Helper function to sort an array of recordings. It compares the startTime in two recording objecs.
381
 *
382
 * @param object $a
383
 * @param object $b
384
 *
385
 * @return array
386
 */
387
function bigbluebuttonbn_recording_build_sorter($a, $b) {
388
    if ($a['startTime'] < $b['startTime']) {
389
        return -1;
390
    }
391
    if ($a['startTime'] == $b['startTime']) {
392
        return 0;
393
    }
394
    return 1;
395
}
396
397
/**
398
 * Perform deleteRecordings on BBB.
399
 *
400
 * @param string $recordids
401
 *
402
 * @return boolean
403
 */
404 View Code Duplication
function bigbluebuttonbn_delete_recordings($recordids) {
0 ignored issues
show
Duplication introduced by
This function seems to be duplicated in your project.

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

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

Loading history...
405
    $ids = explode(',', $recordids);
406
    foreach ($ids as $id) {
407
        $xml = bigbluebuttonbn_wrap_xml_load_file(
408
            \mod_bigbluebuttonbn\locallib\bigbluebutton::action_url('deleteRecordings', ['recordID' => $id])
409
          );
410
        if ($xml && $xml->returncode != 'SUCCESS') {
411
            return false;
412
        }
413
    }
414
    return true;
415
}
416
417
/**
418
 * Perform publishRecordings on BBB.
419
 *
420
 * @param string $recordids
421
 * @param string $publish
422
 */
423 View Code Duplication
function bigbluebuttonbn_publish_recordings($recordids, $publish = 'true') {
0 ignored issues
show
Duplication introduced by
This function seems to be duplicated in your project.

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

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

Loading history...
424
    $ids = explode(',', $recordids);
425
    foreach ($ids as $id) {
426
        $xml = bigbluebuttonbn_wrap_xml_load_file(
427
            \mod_bigbluebuttonbn\locallib\bigbluebutton::action_url('publishRecordings', ['recordID' => $id, 'publish' => $publish])
428
          );
429
        if ($xml && $xml->returncode != 'SUCCESS') {
430
            return false;
431
        }
432
    }
433
    return true;
434
}
435
436
/**
437
 * Perform updateRecordings on BBB.
438
 *
439
 * @param string $recordids
440
 * @param array $params ['key'=>param_key, 'value']
441
 */
442 View Code Duplication
function bigbluebuttonbn_update_recordings($recordids, $params) {
0 ignored issues
show
Duplication introduced by
This function seems to be duplicated in your project.

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

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

Loading history...
443
    $ids = explode(',', $recordids);
444
    foreach ($ids as $id) {
445
        $xml = bigbluebuttonbn_wrap_xml_load_file(
446
            \mod_bigbluebuttonbn\locallib\bigbluebutton::action_url('updateRecordings', ['recordID' => $id] + (array) $params)
447
          );
448
        if ($xml && $xml->returncode != 'SUCCESS') {
449
            return false;
450
        }
451
    }
452
    return true;
453
}
454
455
/**
456
 * Perform end on BBB.
457
 *
458
 * @param string $meetingid
459
 * @param string $modpw
460
 */
461
function bigbluebuttonbn_end_meeting($meetingid, $modpw) {
462
    $xml = bigbluebuttonbn_wrap_xml_load_file(
463
        \mod_bigbluebuttonbn\locallib\bigbluebutton::action_url('end', ['meetingID' => $meetingid, 'password' => $modpw])
464
      );
465
    if ($xml) {
466
        // If the xml packet returned failure it displays the message to the user.
467
        return array('returncode' => $xml->returncode, 'message' => $xml->message, 'messageKey' => $xml->messageKey);
468
    }
469
    // If the server is unreachable, then prompts the user of the necessary action.
470
    return null;
471
}
472
473
/**
474
 * Perform api request on BBB.
475
 *
476
 * @return string
477
 */
478
function bigbluebuttonbn_get_server_version() {
479
    $xml = bigbluebuttonbn_wrap_xml_load_file(
480
        \mod_bigbluebuttonbn\locallib\bigbluebutton::action_url()
481
      );
482
    if ($xml && $xml->returncode == 'SUCCESS') {
483
        return $xml->version;
484
    }
485
    return null;
486
}
487
488
/**
489
 * Perform api request on BBB and wraps the response in an XML object
490
 *
491
 * @param string $url
492
 * @param string $method
493
 * @param string $data
494
 * @param string $contenttype
495
 *
496
 * @return object
497
 */
498
function bigbluebuttonbn_wrap_xml_load_file($url, $method = 'GET', $data = null, $contenttype = 'text/xml') {
499
    if (extension_loaded('curl')) {
500
        $response = bigbluebuttonbn_wrap_xml_load_file_curl_request($url, $method, $data, $contenttype);
501
        if (!$response) {
502
            debugging('No response on wrap_simplexml_load_file', DEBUG_DEVELOPER);
503
            return null;
504
        }
505
        $previous = libxml_use_internal_errors(true);
506
        try {
507
            $xml = simplexml_load_string($response, 'SimpleXMLElement', LIBXML_NOCDATA | LIBXML_NOBLANKS);
508
            return $xml;
509
        } catch (Exception $e) {
510
            libxml_use_internal_errors($previous);
511
            $error = 'Caught exception: '.$e->getMessage();
512
            debugging($error, DEBUG_DEVELOPER);
513
            return null;
514
        }
515
    }
516
    // Alternative request non CURL based.
517
    $previous = libxml_use_internal_errors(true);
518
    try {
519
        $response = simplexml_load_file($url, 'SimpleXMLElement', LIBXML_NOCDATA | LIBXML_NOBLANKS);
520
        return $response;
521
    } catch (Exception $e) {
522
        $error = 'Caught exception: '.$e->getMessage();
523
        debugging($error, DEBUG_DEVELOPER);
524
        libxml_use_internal_errors($previous);
525
        return null;
526
    }
527
}
528
529
/**
530
 * Perform api request on BBB using CURL and wraps the response in an XML object
531
 *
532
 * @param string $url
533
 * @param string $method
534
 * @param string $data
535
 * @param string $contenttype
536
 *
537
 * @return object
538
 */
539
function bigbluebuttonbn_wrap_xml_load_file_curl_request($url, $method = 'GET', $data = null, $contenttype = 'text/xml') {
540
    $c = new curl();
541
    $c->setopt(array('SSL_VERIFYPEER' => true));
542
    if ($method == 'POST') {
543
        if (is_null($data) || is_array($data)) {
544
            return $c->post($url);
545
        }
546
        $options = array();
547
        $options['CURLOPT_HTTPHEADER'] = array(
548
                 'Content-Type: '.$contenttype,
549
                 'Content-Length: '.strlen($data),
550
                 'Content-Language: en-US',
551
               );
552
553
        return $c->post($url, $data, $options);
554
    }
555
    if ($method == 'HEAD') {
556
        $c->head($url, array('followlocation' => true, 'timeout' => 1));
557
        return $c->get_info();
558
    }
559
    return $c->get($url);
560
}
561
562
/**
563
 * End the session associated with this instance (if it's running).
564
 *
565
 * @param object $bigbluebuttonbn
566
 *
567
 * @return void
568
 */
569
function bigbluebuttonbn_end_meeting_if_running($bigbluebuttonbn) {
570
    $meetingid = $bigbluebuttonbn->meetingid.'-'.$bigbluebuttonbn->course.'-'.$bigbluebuttonbn->id;
571
    if (bigbluebuttonbn_is_meeting_running($meetingid)) {
572
        bigbluebuttonbn_end_meeting($meetingid, $bigbluebuttonbn->moderatorpass);
573
    }
574
}
575
576
/**
577
 * Returns user roles in a context.
578
 *
579
 * @param object $context
580
 * @param integer $userid
581
 *
582
 * @return array $userroles
583
 */
584
function bigbluebuttonbn_get_user_roles($context, $userid) {
585
    global $DB;
586
    $userroles = get_user_roles($context, $userid);
587
    if ($userroles) {
588
        $where = '';
589
        foreach ($userroles as $userrole) {
590
            $where .= (empty($where) ? ' WHERE' : ' OR').' id=' . $userrole->roleid;
591
        }
592
        $userroles = $DB->get_records_sql('SELECT * FROM {role}'.$where);
593
    }
594
    return $userroles;
595
}
596
597
/**
598
 * Returns guest role wrapped in an array.
599
 *
600
 * @return array
601
 */
602
function bigbluebuttonbn_get_guest_role() {
603
    $guestrole = get_guest_role();
604
    return array($guestrole->id => $guestrole);
605
}
606
607
/**
608
 * Returns an array containing all the users in a context.
609
 *
610
 * @param context $context
611
 *
612
 * @return array $users
613
 */
614
function bigbluebuttonbn_get_users(context $context = null) {
615
    $users = (array) get_enrolled_users($context, '', 0, 'u.*', null, 0, 0, true);
616
    foreach ($users as $key => $value) {
617
        $users[$key] = fullname($value);
618
    }
619
    return $users;
620
}
621
622
/**
623
 * Returns an array containing all the users in a context wrapped for html select element.
624
 *
625
 * @param context $context
626
 *
627
 * @return array $users
628
 */
629
function bigbluebuttonbn_get_users_select(context $context = null) {
630
    $users = (array) get_enrolled_users($context, '', 0, 'u.*', null, 0, 0, true);
631
    foreach ($users as $key => $value) {
632
        $users[$key] = array('id' => $value->id, 'name' => fullname($value));
633
    }
634
    return $users;
635
}
636
637
/**
638
 * Returns an array containing all the roles in a context.
639
 *
640
 * @param context $context
641
 *
642
 * @return array $roles
643
 */
644
function bigbluebuttonbn_get_roles(context $context = null) {
645
    $roles = (array) role_get_names($context);
646
    foreach ($roles as $key => $value) {
647
        $roles[$key] = $value->localname;
648
    }
649
    return $roles;
650
}
651
652
/**
653
 * Returns an array containing all the roles in a context wrapped for html select element.
654
 *
655
 * @param context $context
656
 *
657
 * @return array $users
658
 */
659
function bigbluebuttonbn_get_roles_select(context $context = null) {
660
    $roles = (array) role_get_names($context);
661
    foreach ($roles as $key => $value) {
662
        $roles[$key] = array('id' => $value->id, 'name' => $value->localname);
663
    }
664
    return $roles;
665
}
666
667
/**
668
 * Returns role that corresponds to an id.
669
 *
670
 * @param string|integer $id
671
 *
672
 * @return object $role
673
 */
674
function bigbluebuttonbn_get_role($id) {
675
    $roles = (array) role_get_names();
676
    if (is_numeric($id) && isset($roles[$id])) {
677
        return (object)$roles[$id];
678
    }
679
    foreach ($roles as $role) {
680
        if ($role->shortname == $id) {
681
            return $role;
682
        }
683
    }
684
}
685
686
/**
687
 * Returns an array to populate a list of participants used in mod_form.js.
688
 *
689
 * @param context $context
690
 *
691
 * @return array $data
692
 */
693
function bigbluebuttonbn_get_participant_data($context) {
694
    $data = array(
695
        'all' => array(
696
            'name' => get_string('mod_form_field_participant_list_type_all', 'bigbluebuttonbn'),
697
            'children' => []
698
          )
699
      );
700
    $data['role'] = array(
701
        'name' => get_string('mod_form_field_participant_list_type_role', 'bigbluebuttonbn'),
702
        'children' => bigbluebuttonbn_get_roles_select($context)
703
      );
704
    $data['user'] = array(
705
        'name' => get_string('mod_form_field_participant_list_type_user', 'bigbluebuttonbn'),
706
        'children' => bigbluebuttonbn_get_users_select($context)
707
      );
708
    return $data;
709
}
710
711
/**
712
 * Returns an array to populate a list of participants used in mod_form.php.
713
 *
714
 * @param object $bigbluebuttonbn
715
 * @param context $context
716
 *
717
 * @return array
718
 */
719
function bigbluebuttonbn_get_participant_list($bigbluebuttonbn, $context) {
720
    global $USER;
721
    if ($bigbluebuttonbn == null) {
722
        return bigbluebuttonbn_get_participant_rules_encoded(
723
            bigbluebuttonbn_get_participant_list_default($context, $USER->id)
724
        );
725
    }
726
    if (empty($bigbluebuttonbn->participants)) {
727
        $bigbluebuttonbn->participants = "[]";
728
    }
729
    $rules = json_decode($bigbluebuttonbn->participants, true);
730
    if (empty($rules)) {
731
        $rules = bigbluebuttonbn_get_participant_list_default($context, bigbluebuttonbn_instance_ownerid($bigbluebuttonbn));
732
    }
733
    return bigbluebuttonbn_get_participant_rules_encoded($rules);
734
}
735
736
/**
737
 * Returns an array to populate a list of participants used in mod_form.php with default values.
738
 *
739
 * @param context $context
740
 * @param integer $ownerid
741
 *
742
 * @return array
743
 */
744
function bigbluebuttonbn_get_participant_list_default($context, $ownerid = null) {
745
    $participantlist = array();
746
    $participantlist[] = array(
747
        'selectiontype' => 'all',
748
        'selectionid' => 'all',
749
        'role' => BIGBLUEBUTTONBN_ROLE_VIEWER
750
      );
751
    $defaultrules = explode(',', \mod_bigbluebuttonbn\locallib\config::get('participant_moderator_default'));
752
    foreach ($defaultrules as $defaultrule) {
753
        if ($defaultrule == '0') {
754
            if (!empty($ownerid) && is_enrolled($context, $ownerid)) {
755
                $participantlist[] = array(
756
                    'selectiontype' => 'user',
757
                    'selectionid' => (string)$ownerid,
758
                    'role' => BIGBLUEBUTTONBN_ROLE_MODERATOR);
759
            }
760
            continue;
761
        }
762
        $participantlist[] = array(
763
              'selectiontype' => 'role',
764
              'selectionid' => $defaultrule,
765
              'role' => BIGBLUEBUTTONBN_ROLE_MODERATOR);
766
    }
767
    return $participantlist;
768
}
769
770
/**
771
 * Returns an array to populate a list of participants used in mod_form.php with bigbluebuttonbn values.
772
 *
773
 * @param array $rules
774
 *
775
 * @return array
776
 */
777
function bigbluebuttonbn_get_participant_rules_encoded($rules) {
778
    foreach ($rules as $key => $rule) {
779
        if ($rule['selectiontype'] !== 'role' || is_numeric($rule['selectionid'])) {
780
            continue;
781
        }
782
        $role = bigbluebuttonbn_get_role($rule['selectionid']);
783
        if ($role == null) {
784
            unset($rules[$key]);
785
            continue;
786
        }
787
        $rule['selectionid'] = $role->id;
788
        $rules[$key] = $rule;
789
    }
790
    return $rules;
791
}
792
793
/**
794
 * Returns an array to populate a list of participant_selection used in mod_form.php.
795
 *
796
 * @return array
797
 */
798
function bigbluebuttonbn_get_participant_selection_data() {
799
    return [
800
        'type_options' => [
801
            'all' => get_string('mod_form_field_participant_list_type_all', 'bigbluebuttonbn'),
802
            'role' => get_string('mod_form_field_participant_list_type_role', 'bigbluebuttonbn'),
803
            'user' => get_string('mod_form_field_participant_list_type_user', 'bigbluebuttonbn'),
804
          ],
805
        'type_selected' => 'all',
806
        'options' => ['all' => '---------------'],
807
        'selected' => 'all',
808
      ];
809
}
810
811
/**
812
 * Evaluate if a user in a context is moderator based on roles and participation rules.
813
 *
814
 * @param context $context
815
 * @param array $participantlist
816
 * @param integer $userid
817
 *
818
 * @return boolean
819
 */
820
function bigbluebuttonbn_is_moderator($context, $participantlist, $userid = null) {
821
    global $USER;
822
    if (!is_array($participantlist)) {
823
        return false;
824
    }
825
    if (empty($userid)) {
826
        $userid = $USER->id;
827
    }
828
    $userroles = bigbluebuttonbn_get_guest_role();
829
    if (!isguestuser()) {
830
        $userroles = bigbluebuttonbn_get_user_roles($context, $userid);
831
    }
832
    return bigbluebuttonbn_is_moderator_validator($participantlist, $userid , $userroles);
833
}
834
835
/**
836
 * Iterates participant list rules to evaluate if a user is moderator.
837
 *
838
 * @param array $participantlist
839
 * @param integer $userid
840
 * @param array $userroles
841
 *
842
 * @return boolean
843
 */
844
function bigbluebuttonbn_is_moderator_validator($participantlist, $userid, $userroles) {
845
    // Iterate participant rules.
846
    foreach ($participantlist as $participant) {
847
        if (bigbluebuttonbn_is_moderator_validate_rule($participant, $userid, $userroles)) {
848
            return true;
849
        }
850
    }
851
    return false;
852
}
853
854
/**
855
 * Evaluate if a user is moderator based on roles and a particular participation rule.
856
 *
857
 * @param object $participant
858
 * @param integer $userid
859
 * @param array $userroles
860
 *
861
 * @return boolean
862
 */
863
function bigbluebuttonbn_is_moderator_validate_rule($participant, $userid, $userroles) {
864
    if ($participant['role'] == BIGBLUEBUTTONBN_ROLE_VIEWER) {
865
        return false;
866
    }
867
    // Looks for all configuration.
868
    if ($participant['selectiontype'] == 'all') {
869
        return true;
870
    }
871
    // Looks for users.
872
    if ($participant['selectiontype'] == 'user' && $participant['selectionid'] == $userid) {
873
        return true;
874
    }
875
    // Looks for roles.
876
    $role = bigbluebuttonbn_get_role($participant['selectionid']);
877
    if ($role != null && array_key_exists($role->id, $userroles)) {
878
        return true;
879
    }
880
    return false;
881
}
882
883
/**
884
 * Helper returns error message key for the language file that corresponds to a bigbluebutton error key.
885
 *
886
 * @param string $messagekey
887
 * @param string $defaultkey
888
 *
889
 * @return string
890
 */
891
function bigbluebuttonbn_get_error_key($messagekey, $defaultkey = null) {
892
    if ($messagekey == 'checksumError') {
893
        return 'index_error_checksum';
894
    }
895
    if ($messagekey == 'maxConcurrent') {
896
        return 'view_error_max_concurrent';
897
    }
898
    return $defaultkey;
899
}
900
901
/**
902
 * Helper evaluates if a voicebridge number is unique.
903
 *
904
 * @param integer $instance
905
 * @param integer $voicebridge
906
 *
907
 * @return string
908
 */
909
function bigbluebuttonbn_voicebridge_unique($instance, $voicebridge) {
910
    global $DB;
911
    if ($voicebridge == 0) {
912
        return true;
913
    }
914
    $select = 'voicebridge = ' . $voicebridge;
915
    if ($instance != 0) {
916
        $select .= ' AND id <>' . $instance;
917
    }
918
    if (!$DB->get_records_select('bigbluebuttonbn', $select)) {
919
        return true;
920
    }
921
    return false;
922
}
923
924
/**
925
 * Helper estimate a duration for the meeting based on the closingtime.
926
 *
927
 * @param integer $closingtime
928
 *
929
 * @return integer
930
 */
931
function bigbluebuttonbn_get_duration($closingtime) {
932
    $duration = 0;
933
    $now = time();
934
    if ($closingtime > 0 && $now < $closingtime) {
935
        $duration = ceil(($closingtime - $now) / 60);
936
        $compensationtime = intval((int)\mod_bigbluebuttonbn\locallib\config::get('scheduled_duration_compensation'));
937
        $duration = intval($duration) + $compensationtime;
938
    }
939
    return $duration;
940
}
941
942
/**
943
 * Helper return array containing the file descriptor for a preuploaded presentation.
944
 *
945
 * @param context $context
946
 * @param string $presentation
947
 * @param integer $id
948
 *
949
 * @return array
950
 */
951
function bigbluebuttonbn_get_presentation_array($context, $presentation, $id = null) {
952
    if (empty($presentation)) {
953
        return array('url' => null, 'name' => null, 'icon' => null, 'mimetype_description' => null);
954
    }
955
    $fs = get_file_storage();
956
    $files = $fs->get_area_files($context->id, 'mod_bigbluebuttonbn', 'presentation', 0,
957
        'itemid, filepath, filename', false);
958
    if (count($files) == 0) {
959
        return array('url' => null, 'name' => null, 'icon' => null, 'mimetype_description' => null);
960
    }
961
    $file = reset($files);
962
    unset($files);
963
    $pnoncevalue = null;
964
    if (!is_null($id)) {
965
        // Create the nonce component for granting a temporary public access.
966
        $cache = cache::make_from_params(cache_store::MODE_APPLICATION, 'mod_bigbluebuttonbn',
967
            'presentation_cache');
968
        $pnoncekey = sha1($id);
969
        /* The item id was adapted for granting public access to the presentation once in order
970
         * to allow BigBlueButton to gather the file. */
971
        $pnoncevalue = bigbluebuttonbn_generate_nonce();
972
        $cache->set($pnoncekey, array('value' => $pnoncevalue, 'counter' => 0));
973
    }
974
    $url = moodle_url::make_pluginfile_url($file->get_contextid(), $file->get_component(),
975
        $file->get_filearea(), $pnoncevalue, $file->get_filepath(), $file->get_filename());
976
    return array('name' => $file->get_filename(), 'icon' => file_file_icon($file, 24),
977
            'url' => $url->out(false), 'mimetype_description' => get_mimetype_description($file));
978
}
979
980
/**
981
 * Helper generates a nonce used for the preuploaded presentation callback url.
982
 *
983
 * @return string
984
 */
985
function bigbluebuttonbn_generate_nonce() {
986
    $mt = microtime();
987
    $rand = mt_rand();
988
    return md5($mt.$rand);
989
}
990
991
/**
992
 * Helper generates a random password.
993
 *
994
 * @param integer $length
995
 * @param string $unique
996
 *
997
 * @return string
998
 */
999
function bigbluebuttonbn_random_password($length = 8, $unique = "") {
1000
    $chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*()_-=+;:,.?';
1001
    do {
1002
        $password = substr(str_shuffle($chars), 0, $length);
1003
    } while ($unique == $password);
1004
    return $password;
1005
}
1006
1007
/**
1008
 * Helper register a bigbluebuttonbn event.
1009
 *
1010
 * @param string $type
1011
 * @param object $bigbluebuttonbn
1012
 * @param array $options [timecreated, userid, other]
1013
 *
1014
 * @return void
1015
 */
1016
function bigbluebuttonbn_event_log($type, $bigbluebuttonbn, $options = []) {
1017
    global $DB;
1018
    if (!in_array($type, \mod_bigbluebuttonbn\event\events::$events)) {
1019
        // No log will be created.
1020
        return;
1021
    }
1022
    $course = $DB->get_record('course', array('id' => $bigbluebuttonbn->course), '*', MUST_EXIST);
1023
    $cm = get_coursemodule_from_instance('bigbluebuttonbn', $bigbluebuttonbn->id, $course->id, false, MUST_EXIST);
1024
    $context = context_module::instance($cm->id);
1025
    $params = array('context' => $context, 'objectid' => $bigbluebuttonbn->id);
1026
    if (array_key_exists('timecreated', $options)) {
1027
        $params['timecreated'] = $options['timecreated'];
1028
    }
1029
    if (array_key_exists('userid', $options)) {
1030
        $params['userid'] = $options['userid'];
1031
    }
1032
    if (array_key_exists('other', $options)) {
1033
        $params['other'] = $options['other'];
1034
    }
1035
    $event = call_user_func_array('\mod_bigbluebuttonbn\event\\' . $type . '::create',
1036
        array($params));
1037
    $event->add_record_snapshot('course_modules', $cm);
1038
    $event->add_record_snapshot('course', $course);
1039
    $event->add_record_snapshot('bigbluebuttonbn', $bigbluebuttonbn);
1040
    $event->trigger();
1041
}
1042
1043
/**
1044
 * Updates the meeting info cached object when a participant has joined.
1045
 *
1046
 * @param string $meetingid
1047
 * @param bool $ismoderator
1048
 *
1049
 * @return void
1050
 */
1051
function bigbluebuttonbn_participant_joined($meetingid, $ismoderator) {
1052
    $cache = cache::make_from_params(cache_store::MODE_APPLICATION, 'mod_bigbluebuttonbn', 'meetings_cache');
1053
    $result = $cache->get($meetingid);
1054
    $meetinginfo = json_decode($result['meeting_info']);
1055
    $meetinginfo->participantCount += 1;
1056
    if ($ismoderator) {
1057
        $meetinginfo->moderatorCount += 1;
1058
    }
1059
    $cache->set($meetingid, array('creation_time' => $result['creation_time'],
1060
        'meeting_info' => json_encode($meetinginfo)));
1061
}
1062
1063
/**
1064
 * Gets a meeting info object cached or fetched from the live session.
1065
 *
1066
 * @param string $meetingid
1067
 * @param boolean $updatecache
1068
 *
1069
 * @return array
1070
 */
1071
function bigbluebuttonbn_get_meeting_info($meetingid, $updatecache = false) {
1072
    $cachettl = (int)\mod_bigbluebuttonbn\locallib\config::get('waitformoderator_cache_ttl');
1073
    $cache = cache::make_from_params(cache_store::MODE_APPLICATION, 'mod_bigbluebuttonbn', 'meetings_cache');
1074
    $result = $cache->get($meetingid);
1075
    $now = time();
1076
    if (!$updatecache && isset($result) && $now < ($result['creation_time'] + $cachettl)) {
1077
        // Use the value in the cache.
1078
        return (array) json_decode($result['meeting_info']);
1079
    }
1080
    // Ping again and refresh the cache.
1081
    $meetinginfo = (array) bigbluebuttonbn_wrap_xml_load_file(
1082
        \mod_bigbluebuttonbn\locallib\bigbluebutton::action_url('getMeetingInfo', ['meetingID' => $meetingid])
1083
      );
1084
    $cache->set($meetingid, array('creation_time' => time(), 'meeting_info' => json_encode($meetinginfo)));
1085
    return $meetinginfo;
1086
}
1087
1088
/**
1089
 * Perform isMeetingRunning on BBB.
1090
 *
1091
 * @param string $meetingid
1092
 * @param boolean $updatecache
1093
 *
1094
 * @return boolean
1095
 */
1096
function bigbluebuttonbn_is_meeting_running($meetingid, $updatecache = false) {
1097
    /* As a workaround to isMeetingRunning that always return SUCCESS but only returns true
1098
     * when at least one user is in the session, we use getMeetingInfo instead.
1099
     */
1100
    $meetinginfo = bigbluebuttonbn_get_meeting_info($meetingid, $updatecache);
1101
    return ($meetinginfo['returncode'] === 'SUCCESS');
1102
}
1103
1104
/**
1105
 * Publish an imported recording.
1106
 *
1107
 * @param string $id
1108
 * @param boolean $publish
1109
 *
1110
 * @return boolean
1111
 */
1112 View Code Duplication
function bigbluebuttonbn_publish_recording_imported($id, $publish = true) {
0 ignored issues
show
Duplication introduced by
This function seems to be duplicated in your project.

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

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

Loading history...
1113
    global $DB;
1114
    // Locate the record to be updated.
1115
    $record = $DB->get_record('bigbluebuttonbn_logs', array('id' => $id));
1116
    $meta = json_decode($record->meta, true);
1117
    // Prepare data for the update.
1118
    $meta['recording']['published'] = ($publish) ? 'true' : 'false';
1119
    $record->meta = json_encode($meta);
1120
    // Proceed with the update.
1121
    $DB->update_record('bigbluebuttonbn_logs', $record);
1122
    return true;
1123
}
1124
1125
/**
1126
 * Delete an imported recording.
1127
 *
1128
 * @param string $id
1129
 *
1130
 * @return boolean
1131
 */
1132
function bigbluebuttonbn_delete_recording_imported($id) {
1133
    global $DB;
1134
    // Execute delete.
1135
    $DB->delete_records('bigbluebuttonbn_logs', array('id' => $id));
1136
    return true;
1137
}
1138
1139
/**
1140
 * Update an imported recording.
1141
 *
1142
 * @param string $id
1143
 * @param array $params ['key'=>param_key, 'value']
1144
 *
1145
 * @return boolean
1146
 */
1147
function bigbluebuttonbn_update_recording_imported($id, $params) {
1148
    global $DB;
1149
    // Locate the record to be updated.
1150
    $record = $DB->get_record('bigbluebuttonbn_logs', array('id' => $id));
1151
    $meta = json_decode($record->meta, true);
1152
    // Prepare data for the update.
1153
    $meta['recording'] = $params + $meta['recording'];
1154
    $record->meta = json_encode($meta);
1155
    // Proceed with the update.
1156
    if (!$DB->update_record('bigbluebuttonbn_logs', $record)) {
1157
        return false;
1158
    }
1159
    return true;
1160
}
1161
1162
/**
1163
 * Protect/Unprotect an imported recording.
1164
 *
1165
 * @param string $id
1166
 * @param boolean $protect
1167
 *
1168
 * @return boolean
1169
 */
1170 View Code Duplication
function bigbluebuttonbn_protect_recording_imported($id, $protect = true) {
0 ignored issues
show
Duplication introduced by
This function seems to be duplicated in your project.

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

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

Loading history...
1171
    global $DB;
1172
    // Locate the record to be updated.
1173
    $record = $DB->get_record('bigbluebuttonbn_logs', array('id' => $id));
1174
    $meta = json_decode($record->meta, true);
1175
    // Prepare data for the update.
1176
    $meta['recording']['protected'] = ($protect) ? 'true' : 'false';
1177
    $record->meta = json_encode($meta);
1178
    // Proceed with the update.
1179
    $DB->update_record('bigbluebuttonbn_logs', $record);
1180
    return true;
1181
}
1182
1183
/**
1184
 * Sets a custom config.xml file for being used on create.
1185
 *
1186
 * @param string $meetingid
1187
 * @param string $configxml
1188
 *
1189
 * @return object
1190
 */
1191
function bigbluebuttonbn_set_config_xml($meetingid, $configxml) {
1192
    $urldefaultconfig = \mod_bigbluebuttonbn\locallib\config::get('server_url').'api/setConfigXML?';
1193
    $configxmlparams = bigbluebuttonbn_set_config_xml_params($meetingid, $configxml);
1194
    $xml = bigbluebuttonbn_wrap_xml_load_file($urldefaultconfig, 'POST',
1195
        $configxmlparams, 'application/x-www-form-urlencoded');
1196
    return $xml;
1197
}
1198
1199
/**
1200
 * Sets qs used with a custom config.xml file request.
1201
 *
1202
 * @param string $meetingid
1203
 * @param string $configxml
1204
 *
1205
 * @return string
1206
 */
1207
function bigbluebuttonbn_set_config_xml_params($meetingid, $configxml) {
1208
    $params = 'configXML='.urlencode($configxml).'&meetingID='.urlencode($meetingid);
1209
    $configxmlparams = $params.'&checksum='.sha1('setConfigXML'.$params.\mod_bigbluebuttonbn\locallib\config::get('shared_secret'));
1210
    return $configxmlparams;
1211
}
1212
1213
/**
1214
 * Sets a custom config.xml file for being used on create.
1215
 *
1216
 * @param string $meetingid
1217
 * @param string $configxml
1218
 *
1219
 * @return array
1220
 */
1221
function bigbluebuttonbn_set_config_xml_array($meetingid, $configxml) {
1222
    $configxml = bigbluebuttonbn_setConfigXML($meetingid, $configxml);
1223
    $configxmlarray = (array) $configxml;
1224
    if ($configxmlarray['returncode'] != 'SUCCESS') {
1225
        debugging('BigBlueButton was not able to set the custom config.xml file', DEBUG_DEVELOPER);
1226
        return '';
1227
    }
1228
    return $configxmlarray['configToken'];
1229
}
1230
1231
/**
1232
 * Helper function builds a row for the data used by the recording table.
1233
 *
1234
 * @param array $bbbsession
1235
 * @param array $recording
1236
 * @param array $tools
1237
 *
1238
 * @return array
1239
 */
1240
function bigbluebuttonbn_get_recording_data_row($bbbsession, $recording, $tools = ['protect', 'publish', 'delete']) {
1241
    if (!bigbluebuttonbn_include_recording_table_row($bbbsession, $recording)) {
1242
        return;
1243
    }
1244
    $rowdata = new stdClass();
1245
    // Set recording_types.
1246
    $rowdata->recording = bigbluebuttonbn_get_recording_data_row_types($recording, $bbbsession);
1247
    // Set activity name.
1248
    $rowdata->activity = bigbluebuttonbn_get_recording_data_row_meta_activity($recording, $bbbsession);
1249
    // Set activity description.
1250
    $rowdata->description = bigbluebuttonbn_get_recording_data_row_meta_description($recording, $bbbsession);
1251
    if (bigbluebuttonbn_get_recording_data_preview_enabled($bbbsession)) {
1252
        // Set recording_preview.
1253
        $rowdata->preview = bigbluebuttonbn_get_recording_data_row_preview($recording);
1254
    }
1255
    // Set date.
1256
    $rowdata->date = bigbluebuttonbn_get_recording_data_row_date($recording);
1257
    // Set formatted date.
1258
    $rowdata->date_formatted = bigbluebuttonbn_get_recording_data_row_date_formatted($rowdata->date);
1259
    // Set formatted duration.
1260
    $rowdata->duration_formatted = $rowdata->duration = bigbluebuttonbn_get_recording_data_row_duration($recording);
1261
    // Set actionbar, if user is allowed to manage recordings.
1262
    if ($bbbsession['managerecordings']) {
1263
        $rowdata->actionbar = bigbluebuttonbn_get_recording_data_row_actionbar($recording, $tools);
1264
    }
1265
    return $rowdata;
1266
}
1267
1268
/**
1269
 * Helper function evaluates if a row for the data used by the recording table is editable.
1270
 *
1271
 * @param array $bbbsession
1272
 *
1273
 * @return boolean
1274
 */
1275
function bigbluebuttonbn_get_recording_data_row_editable($bbbsession) {
1276
    return ($bbbsession['managerecordings'] && ((double)$bbbsession['serverversion'] >= 1.0 || $bbbsession['bnserver']));
1277
}
1278
1279
/**
1280
 * Helper function evaluates if recording preview should be included.
1281
 *
1282
 * @param array $bbbsession
1283
 *
1284
 * @return boolean
1285
 */
1286
function bigbluebuttonbn_get_recording_data_preview_enabled($bbbsession) {
1287
    return ((double)$bbbsession['serverversion'] >= 1.0 && $bbbsession['bigbluebuttonbn']->recordings_preview == '1');
1288
}
1289
1290
/**
1291
 * Helper function converts recording date used in row for the data used by the recording table.
1292
 *
1293
 * @param array $recording
1294
 *
1295
 * @return integer
1296
 */
1297
function bigbluebuttonbn_get_recording_data_row_date($recording) {
1298
    if (!isset($recording['startTime'])) {
1299
        return 0;
1300
    }
1301
    return floatval($recording['startTime']);
1302
}
1303
1304
/**
1305
 * Helper function format recording date used in row for the data used by the recording table.
1306
 *
1307
 * @param integer $starttime
1308
 *
1309
 * @return string
1310
 */
1311
function bigbluebuttonbn_get_recording_data_row_date_formatted($starttime) {
1312
    global $USER;
1313
    $starttime = $starttime - ($starttime % 1000);
1314
    // Set formatted date.
1315
    $dateformat = get_string('strftimerecentfull', 'langconfig').' %Z';
1316
    return userdate($starttime / 1000, $dateformat, usertimezone($USER->timezone));
1317
}
1318
1319
/**
1320
 * Helper function converts recording duration used in row for the data used by the recording table.
1321
 *
1322
 * @param array $recording
1323
 *
1324
 * @return integer
1325
 */
1326
function bigbluebuttonbn_get_recording_data_row_duration($recording) {
1327
    foreach (array_values($recording['playbacks']) as $playback) {
1328
        // Ignore restricted playbacks.
1329
        if (array_key_exists('restricted', $playback) && strtolower($playback['restricted']) == 'true') {
1330
            continue;
1331
        }
1332
        // Take the lenght form the fist playback with an actual value.
1333
        if (!empty($playback['length'])) {
1334
            return intval($playback['length']);
1335
        }
1336
    }
1337
    return 0;
1338
}
1339
1340
/**
1341
 * Helper function builds recording actionbar used in row for the data used by the recording table.
1342
 *
1343
 * @param array $recording
1344
 * @param array $tools
1345
 *
1346
 * @return string
1347
 */
1348
function bigbluebuttonbn_get_recording_data_row_actionbar($recording, $tools) {
1349
    $actionbar = '';
1350
    foreach ($tools as $tool) {
1351
        $buttonpayload = bigbluebuttonbn_get_recording_data_row_actionbar_payload($recording, $tool);
1352
        if ($tool == 'protect') {
1353
            if (isset($recording['imported'])) {
1354
                $buttonpayload['disabled'] = 'disabled';
1355
            }
1356
            if (!isset($recording['protected'])) {
1357
                $buttonpayload['disabled'] = 'invisible';
1358
            }
1359
        }
1360
        $actionbar .= bigbluebuttonbn_actionbar_render_button($recording, $buttonpayload);
1361
    }
1362
    $head = html_writer::start_tag('div', array(
1363
        'id' => 'recording-actionbar-' . $recording['recordID'],
1364
        'data-recordingid' => $recording['recordID'],
1365
        'data-meetingid' => $recording['meetingID']));
1366
    $tail = html_writer::end_tag('div');
1367
    return $head . $actionbar . $tail;
1368
}
1369
1370
/**
1371
 * Helper function returns the corresponding payload for an actionbar button used in row
1372
 * for the data used by the recording table.
1373
 *
1374
 * @param array $recording
1375
 * @param array $tool
1376
 *
1377
 * @return array
1378
 */
1379
function bigbluebuttonbn_get_recording_data_row_actionbar_payload($recording, $tool) {
1380
    if ($tool == 'protect') {
1381
        $protected = 'false';
1382
        if (isset($recording['protected'])) {
1383
            $protected = $recording['protected'];
1384
        }
1385
        return bigbluebuttonbn_get_recording_data_row_action_protect($protected);
1386
    }
1387
    if ($tool == 'publish') {
1388
        return bigbluebuttonbn_get_recording_data_row_action_publish($recording['published']);
1389
    }
1390
    return array('action' => $tool, 'tag' => $tool);
1391
}
1392
1393
/**
1394
 * Helper function returns the payload for protect action button used in row
1395
 * for the data used by the recording table.
1396
 *
1397
 * @param string $protected
1398
 *
1399
 * @return array
1400
 */
1401
function bigbluebuttonbn_get_recording_data_row_action_protect($protected) {
1402
    if ($protected == 'true') {
1403
        return array('action' => 'unprotect', 'tag' => 'lock');
1404
    }
1405
    return array('action' => 'protect', 'tag' => 'unlock');
1406
}
1407
1408
/**
1409
 * Helper function returns the payload for publish action button used in row
1410
 * for the data used by the recording table.
1411
 *
1412
 * @param string $published
1413
 *
1414
 * @return array
1415
 */
1416
function bigbluebuttonbn_get_recording_data_row_action_publish($published) {
1417
    if ($published == 'true') {
1418
        return array('action' => 'unpublish', 'tag' => 'hide');
1419
    }
1420
    return array('action' => 'publish', 'tag' => 'show');
1421
}
1422
1423
/**
1424
 * Helper function builds recording preview used in row for the data used by the recording table.
1425
 *
1426
 * @param array $recording
1427
 *
1428
 * @return string
1429
 */
1430
function bigbluebuttonbn_get_recording_data_row_preview($recording) {
1431
    $options = array('id' => 'preview-'.$recording['recordID']);
1432
    if ($recording['published'] === 'false') {
1433
        $options['hidden'] = 'hidden';
1434
    }
1435
    $recordingpreview = html_writer::start_tag('div', $options);
1436
    foreach ($recording['playbacks'] as $playback) {
1437
        if (isset($playback['preview'])) {
1438
            $recordingpreview .= bigbluebuttonbn_get_recording_data_row_preview_images($playback);
1439
            break;
1440
        }
1441
    }
1442
    $recordingpreview .= html_writer::end_tag('div');
1443
    return $recordingpreview;
1444
}
1445
1446
/**
1447
 * Helper function builds element with actual images used in recording preview row based on a selected playback.
1448
 *
1449
 * @param array $playback
1450
 *
1451
 * @return string
1452
 */
1453
function bigbluebuttonbn_get_recording_data_row_preview_images($playback) {
1454
    $recordingpreview  = html_writer::start_tag('div', array('class' => 'container-fluid'));
1455
    $recordingpreview .= html_writer::start_tag('div', array('class' => 'row'));
1456
    foreach ($playback['preview'] as $image) {
1457
        if (!bigbluebuttonbn_is_valid_resource(trim($image['url']))) {
1458
            return '';
1459
        }
1460
        $recordingpreview .= html_writer::start_tag('div', array('class' => ''));
1461
        $recordingpreview .= html_writer::empty_tag('img',
1462
            array('src' => trim($image['url']) . '?' . time(), 'class' => 'recording-thumbnail pull-left'));
1463
        $recordingpreview .= html_writer::end_tag('div');
1464
    }
1465
    $recordingpreview .= html_writer::end_tag('div');
1466
    $recordingpreview .= html_writer::start_tag('div', array('class' => 'row'));
1467
    $recordingpreview .= html_writer::tag('div', get_string('view_recording_preview_help', 'bigbluebuttonbn'),
1468
        array('class' => 'text-center text-muted small'));
1469
    $recordingpreview .= html_writer::end_tag('div');
1470
    $recordingpreview .= html_writer::end_tag('div');
1471
    return $recordingpreview;
1472
}
1473
1474
/**
1475
 * Helper function renders recording types to be used in row for the data used by the recording table.
1476
 *
1477
 * @param array $recording
1478
 * @param array $bbbsession
1479
 *
1480
 * @return string
1481
 */
1482
function bigbluebuttonbn_get_recording_data_row_types($recording, $bbbsession) {
1483
    $dataimported = 'false';
1484
    $title = '';
1485
    if (isset($recording['imported'])) {
1486
        $dataimported = 'true';
1487
        $title = get_string('view_recording_link_warning', 'bigbluebuttonbn');
1488
    }
1489
    $visibility = '';
1490
    if ($recording['published'] === 'false') {
1491
        $visibility = 'hidden ';
1492
    }
1493
    $id = 'playbacks-'.$recording['recordID'];
1494
    $recordingtypes = html_writer::start_tag('div', array('id' => $id, 'data-imported' => $dataimported,
1495
          'data-meetingid' => $recording['meetingID'], 'data-recordingid' => $recording['recordID'],
1496
          'title' => $title, $visibility => $visibility));
1497
    foreach ($recording['playbacks'] as $playback) {
1498
        $recordingtypes .= bigbluebuttonbn_get_recording_data_row_type($recording, $bbbsession, $playback);
1499
    }
1500
    $recordingtypes .= html_writer::end_tag('div');
1501
    return $recordingtypes;
1502
}
1503
1504
/**
1505
 * Helper function renders the link used for recording type in row for the data used by the recording table.
1506
 *
1507
 * @param array $recording
1508
 * @param array $bbbsession
1509
 * @param array $playback
1510
 *
1511
 * @return string
1512
 */
1513
function bigbluebuttonbn_get_recording_data_row_type($recording, $bbbsession, $playback) {
1514
    global $CFG, $OUTPUT;
1515
    if (!bigbluebuttonbn_include_recording_data_row_type($recording, $bbbsession, $playback)) {
1516
        return '';
1517
    }
1518
    $text = get_string('view_recording_format_'.$playback['type'], 'bigbluebuttonbn');
1519
    $href = $CFG->wwwroot . '/mod/bigbluebuttonbn/bbb_view.php?action=play&bn=' . $bbbsession['bigbluebuttonbn']->id .
1520
      '&mid='.$recording['meetingID'] . '&rid=' . $recording['recordID'] . '&rtype=' . $playback['type'];
1521
    if (!isset($recording['imported']) || !isset($recording['protected']) || $recording['protected'] === 'false') {
1522
        $href .= '&href='.urlencode(trim($playback['url']));
1523
    }
1524
    $linkattributes = array(
1525
        'id' => 'recording-play-' . $playback['type'] . '-' . $recording['recordID'],
1526
        'class' => 'btn btn-sm btn-default',
1527
        'onclick' => 'M.mod_bigbluebuttonbn.recordings.recordingPlay(this);',
1528
        'data-action' => 'play',
1529
        'data-target' => $playback['type'],
1530
        'data-href' => $href,
1531
      );
1532
    if (!bigbluebuttonbn_is_bn_server() && !bigbluebuttonbn_is_valid_resource(trim($playback['url']))) {
1533
        $linkattributes['class'] = 'btn btn-sm btn-warning';
1534
        $linkattributes['title'] = get_string('view_recording_format_errror_unreachable', 'bigbluebuttonbn');
1535
        unset($linkattributes['data-href']);
1536
    }
1537
    return $OUTPUT->action_link('#', $text, null, $linkattributes) . '&#32;';
1538
}
1539
1540
/**
1541
 * Helper function validates a remote resource.
1542
 *
1543
 * @param string $url
1544
 *
1545
 * @return boolean
1546
 */
1547
function bigbluebuttonbn_is_valid_resource($url) {
1548
    $urlhost = parse_url($url, PHP_URL_HOST);
1549
    $serverurlhost = parse_url(\mod_bigbluebuttonbn\locallib\config::get('server_url'), PHP_URL_HOST);
1550
    // Skip validation when the recording URL host is the same as the configured BBB server.
1551
    if ($urlhost == $serverurlhost) {
1552
        return true;
1553
    }
1554
    // Skip validation when the recording URL was already validated.
1555
    $validatedurls = bigbluebuttonbn_cache_get('recordings_cache', 'validated_urls', array());
0 ignored issues
show
Documentation introduced by
array() is of type array, but the function expects a integer|null.

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

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

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

function acceptsInteger($int) { }

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

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
1556
    if (array_key_exists($urlhost, $validatedurls)) {
1557
        return $validatedurls[$urlhost];
1558
    }
1559
    // Validate the recording URL.
1560
    $validatedurls[$urlhost] = true;
1561
    $curlinfo = bigbluebuttonbn_wrap_xml_load_file_curl_request($url, 'HEAD');
1562
    if (!isset($curlinfo['http_code']) || $curlinfo['http_code'] != 200) {
1563
        $error = "Resources hosted by " . $urlhost . " are unreachable. Server responded with code " . $curlinfo['http_code'];
1564
        debugging($error, DEBUG_DEVELOPER);
1565
        $validatedurls[$urlhost] = false;
1566
    }
1567
    bigbluebuttonbn_cache_set('recordings_cache', 'validated_urls', $validatedurls);
1568
    return $validatedurls[$urlhost];
1569
}
1570
1571
/**
1572
 * Helper function renders the name for recording used in row for the data used by the recording table.
1573
 *
1574
 * @param array $recording
1575
 * @param array $bbbsession
1576
 *
1577
 * @return string
1578
 */
1579
function bigbluebuttonbn_get_recording_data_row_meta_activity($recording, $bbbsession) {
1580
    $payload = array();
1581 View Code Duplication
    if (bigbluebuttonbn_get_recording_data_row_editable($bbbsession)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
1582
        $payload = array('recordingid' => $recording['recordID'], 'meetingid' => $recording['meetingID'],
1583
            'action' => 'edit', 'tag' => 'edit',
1584
            'target' => 'name');
1585
    }
1586
    $oldsource = 'meta_contextactivity';
1587
    if (isset($recording[$oldsource])) {
1588
        $metaname = trim($recording[$oldsource]);
1589
        return bigbluebuttonbn_get_recording_data_row_text($recording, $metaname, $oldsource, $payload);
1590
    }
1591
    $newsource = 'meta_bbb-recording-name';
1592 View Code Duplication
    if (isset($recording[$newsource])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
1593
        $metaname = trim($recording[$newsource]);
1594
        return bigbluebuttonbn_get_recording_data_row_text($recording, $metaname, $newsource, $payload);
1595
    }
1596
    $metaname = trim($recording['meetingName']);
1597
    return bigbluebuttonbn_get_recording_data_row_text($recording, $metaname, $newsource, $payload);
1598
}
1599
1600
/**
1601
 * Helper function renders the description for recording used in row for the data used by the recording table.
1602
 *
1603
 * @param array $recording
1604
 * @param array $bbbsession
1605
 *
1606
 * @return string
1607
 */
1608
function bigbluebuttonbn_get_recording_data_row_meta_description($recording, $bbbsession) {
1609
    $payload = array();
1610 View Code Duplication
    if (bigbluebuttonbn_get_recording_data_row_editable($bbbsession)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
1611
        $payload = array('recordingid' => $recording['recordID'], 'meetingid' => $recording['meetingID'],
1612
            'action' => 'edit', 'tag' => 'edit',
1613
            'target' => 'description');
1614
    }
1615
    $oldsource = 'meta_contextactivitydescription';
1616 View Code Duplication
    if (isset($recording[$oldsource])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
1617
        $metadescription = trim($recording[$oldsource]);
1618
        return bigbluebuttonbn_get_recording_data_row_text($recording, $metadescription, $oldsource, $payload);
1619
    }
1620
    $newsource = 'meta_bbb-recording-description';
1621 View Code Duplication
    if (isset($recording[$newsource])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
1622
        $metadescription = trim($recording[$newsource]);
1623
        return bigbluebuttonbn_get_recording_data_row_text($recording, $metadescription, $newsource, $payload);
1624
    }
1625
    return bigbluebuttonbn_get_recording_data_row_text($recording, '', $newsource, $payload);
1626
}
1627
1628
/**
1629
 * Helper function renders text element for recording used in row for the data used by the recording table.
1630
 *
1631
 * @param array $recording
1632
 * @param string $text
1633
 * @param string $source
1634
 * @param array $data
1635
 *
1636
 * @return string
1637
 */
1638
function bigbluebuttonbn_get_recording_data_row_text($recording, $text, $source, $data) {
1639
    $htmltext = '<span>' . htmlentities($text) . '</span>';
1640
    if (empty($data)) {
1641
        return $htmltext;
1642
    }
1643
    $target = $data['action'] . '-' . $data['target'];
1644
    $id = 'recording-' . $target . '-' . $data['recordingid'];
1645
    $attributes = array('id' => $id, 'class' => 'quickeditlink col-md-20',
1646
        'data-recordingid' => $data['recordingid'], 'data-meetingid' => $data['meetingid'],
1647
        'data-target' => $data['target'], 'data-source' => $source);
1648
    $head = html_writer::start_tag('div', $attributes);
1649
    $tail = html_writer::end_tag('div');
1650
    $payload = array('action' => $data['action'], 'tag' => $data['tag'], 'target' => $data['target']);
1651
    $htmllink = bigbluebuttonbn_actionbar_render_button($recording, $payload);
1652
    return $head . $htmltext . $htmllink . $tail;
1653
}
1654
1655
/**
1656
 * Helper function render a button for the recording action bar
1657
 *
1658
 * @param array $recording
1659
 * @param array $data
1660
 *
1661
 * @return string
1662
 */
1663
function bigbluebuttonbn_actionbar_render_button($recording, $data) {
1664
    global $OUTPUT;
1665
    if (empty($data)) {
1666
        return '';
1667
    }
1668
    $target = $data['action'];
1669
    if (isset($data['target'])) {
1670
        $target .= '-' . $data['target'];
1671
    }
1672
    $id = 'recording-' . $target . '-' . $recording['recordID'];
1673
    $onclick = 'M.mod_bigbluebuttonbn.recordings.recording' . ucfirst($data['action']) . '(this);';
1674
    if ((boolean)\mod_bigbluebuttonbn\locallib\config::get('recording_icons_enabled')) {
1675
        // With icon for $manageaction.
1676
        $iconattributes = array('id' => $id, 'class' => 'iconsmall');
1677
        $linkattributes = array(
1678
            'id' => $id,
1679
            'onclick' => $onclick,
1680
            'data-action' => $data['action']
1681
          );
1682
        if (!isset($recording['imported'])) {
1683
            $linkattributes['data-links'] = bigbluebuttonbn_count_recording_imported_instances(
1684
              $recording['recordID']);
1685
        }
1686
        if (isset($data['disabled'])) {
1687
            $iconattributes['class'] .= ' fa-' . $data['disabled'];
1688
            $linkattributes['class'] = 'disabled';
1689
            unset($linkattributes['onclick']);
1690
        }
1691
        $icon = new pix_icon('i/'.$data['tag'],
1692
            get_string('view_recording_list_actionbar_' . $data['action'], 'bigbluebuttonbn'),
1693
            'moodle', $iconattributes);
1694
        return $OUTPUT->action_icon('#', $icon, null, $linkattributes, false);
1695
    }
1696
    // With text for $manageaction.
1697
    $linkattributes = array('title' => get_string($data['tag']), 'class' => 'btn btn-xs btn-danger',
1698
        'onclick' => $onclick);
1699
    return $OUTPUT->action_link('#', get_string($data['action']), null, $linkattributes);
1700
}
1701
1702
/**
1703
 * Helper function builds the data used for headers by the recording table.
1704
 *
1705
 * @param array $bbbsession
1706
 *
1707
 * @return array
1708
 */
1709
function bigbluebuttonbn_get_recording_columns($bbbsession) {
1710
    $columns = array();
1711
    // Initialize table headers.
1712
    $columns[] = array('key' => 'recording', 'label' => get_string('view_recording_recording', 'bigbluebuttonbn'),
1713
        'width' => '125px', 'allowHTML' => true);
1714
    $columns[] = array('key' => 'activity', 'label' => get_string('view_recording_activity', 'bigbluebuttonbn'),
1715
        'sortable' => true, 'width' => '175px', 'allowHTML' => true);
1716
    $columns[] = array('key' => 'description', 'label' => get_string('view_recording_description', 'bigbluebuttonbn'),
1717
        'sortable' => true, 'width' => '250px', 'allowHTML' => true);
1718
    if (bigbluebuttonbn_get_recording_data_preview_enabled($bbbsession)) {
1719
        $columns[] = array('key' => 'preview', 'label' => get_string('view_recording_preview', 'bigbluebuttonbn'),
1720
            'width' => '250px', 'allowHTML' => true);
1721
    }
1722
    $columns[] = array('key' => 'date', 'label' => get_string('view_recording_date', 'bigbluebuttonbn'),
1723
        'sortable' => true, 'width' => '225px', 'allowHTML' => true);
1724
    $columns[] = array('key' => 'duration', 'label' => get_string('view_recording_duration', 'bigbluebuttonbn'),
1725
        'width' => '50px');
1726
    if ($bbbsession['managerecordings']) {
1727
        $columns[] = array('key' => 'actionbar', 'label' => get_string('view_recording_actionbar', 'bigbluebuttonbn'),
1728
            'width' => '120px', 'allowHTML' => true);
1729
    }
1730
    return $columns;
1731
}
1732
1733
/**
1734
 * Helper function builds the data used by the recording table.
1735
 *
1736
 * @param array $bbbsession
1737
 * @param array $recordings
1738
 * @param array $tools
1739
 *
1740
 * @return array
1741
 */
1742
function bigbluebuttonbn_get_recording_data($bbbsession, $recordings, $tools = ['protect', 'publish', 'delete']) {
1743
    $tabledata = array();
1744
    // Build table content.
1745
    if (isset($recordings) && !array_key_exists('messageKey', $recordings)) {
1746
        // There are recordings for this meeting.
1747
        foreach ($recordings as $recording) {
1748
            $rowdata = bigbluebuttonbn_get_recording_data_row($bbbsession, $recording, $tools);
1749
            if (!empty($rowdata)) {
1750
                array_push($tabledata, $rowdata);
1751
            }
1752
        }
1753
    }
1754
    return $tabledata;
1755
}
1756
1757
/**
1758
 * Helper function builds the recording table.
1759
 *
1760
 * @param array $bbbsession
1761
 * @param array $recordings
1762
 * @param array $tools
1763
 *
1764
 * @return object
1765
 */
1766
function bigbluebuttonbn_get_recording_table($bbbsession, $recordings, $tools = ['protect', 'publish', 'delete']) {
1767
    // Declare the table.
1768
    $table = new html_table();
1769
    $table->data = array();
1770
    // Initialize table headers.
1771
    $table->head[] = get_string('view_recording_playback', 'bigbluebuttonbn');
1772
    $table->head[] = get_string('view_recording_recording', 'bigbluebuttonbn');
1773
    $table->head[] = get_string('view_recording_description', 'bigbluebuttonbn');
1774
    if (bigbluebuttonbn_get_recording_data_preview_enabled($bbbsession)) {
1775
        $table->head[] = get_string('view_recording_preview', 'bigbluebuttonbn');
1776
    }
1777
    $table->head[] = get_string('view_recording_date', 'bigbluebuttonbn');
1778
    $table->head[] = get_string('view_recording_duration', 'bigbluebuttonbn');
1779
    $table->align = array('left', 'left', 'left', 'left', 'left', 'center');
1780
    $table->size = array('', '', '', '', '', '');
1781
    if ($bbbsession['managerecordings']) {
1782
        $table->head[] = get_string('view_recording_actionbar', 'bigbluebuttonbn');
1783
        $table->align[] = 'left';
1784
        $table->size[] = (count($tools) * 40) . 'px';
1785
    }
1786
    // Build table content.
1787
    foreach ($recordings as $recording) {
1788
        $rowdata = bigbluebuttonbn_get_recording_data_row($bbbsession, $recording, $tools);
1789
        if (!empty($rowdata)) {
1790
            $row = bigbluebuttonbn_get_recording_table_row($bbbsession, $recording, $rowdata);
1791
            array_push($table->data, $row);
1792
        }
1793
    }
1794
    return $table;
1795
}
1796
1797
/**
1798
 * Helper function builds the recording table row and insert into table.
1799
 *
1800
 * @param array $bbbsession
1801
 * @param array $recording
1802
 * @param object $rowdata
1803
 *
1804
 * @return object
1805
 */
1806
function bigbluebuttonbn_get_recording_table_row($bbbsession, $recording, $rowdata) {
1807
    $row = new html_table_row();
1808
    $row->id = 'recording-tr-'.$recording['recordID'];
1809
    $row->attributes['data-imported'] = 'false';
1810
    $texthead = '';
1811
    $texttail = '';
1812
    if (isset($recording['imported'])) {
1813
        $row->attributes['title'] = get_string('view_recording_link_warning', 'bigbluebuttonbn');
1814
        $row->attributes['data-imported'] = 'true';
1815
        $texthead = '<em>';
1816
        $texttail = '</em>';
1817
    }
1818
    $rowdata->date_formatted = str_replace(' ', '&nbsp;', $rowdata->date_formatted);
1819
    $row->cells = array();
1820
    $row->cells[] = $texthead . $rowdata->recording . $texttail;
1821
    $row->cells[] = $texthead . $rowdata->activity . $texttail;
1822
    $row->cells[] = $texthead . $rowdata->description . $texttail;
1823
    if (bigbluebuttonbn_get_recording_data_preview_enabled($bbbsession)) {
1824
        $row->cells[] = $rowdata->preview;
1825
    }
1826
    $row->cells[] = $texthead . $rowdata->date_formatted . $texttail;
1827
    $row->cells[] = $rowdata->duration_formatted;
1828
    if ($bbbsession['managerecordings']) {
1829
        $row->cells[] = $rowdata->actionbar;
1830
    }
1831
    return $row;
1832
}
1833
1834
/**
1835
 * Helper function evaluates if recording row should be included in the table.
1836
 *
1837
 * @param array $bbbsession
1838
 * @param array $recording
1839
 *
1840
 * @return boolean
1841
 */
1842
function bigbluebuttonbn_include_recording_table_row($bbbsession, $recording) {
1843
    // Exclude unpublished recordings, only if user has no rights to manage them.
1844
    if ($recording['published'] != 'true' && !$bbbsession['managerecordings']) {
1845
        return false;
1846
    }
1847
    // Imported recordings are always shown as long as they are published.
1848
    if (isset($recording['imported'])) {
1849
        return true;
1850
    }
1851
    // When groups are enabled, exclude those to which the user doesn't have access to.
1852
    if (isset($bbbsession['group']) && $recording['meetingID'] != $bbbsession['meetingid']) {
1853
        return false;
1854
    }
1855
    return true;
1856
}
1857
1858
/**
1859
 * Helper function triggers a send notification when the recording is ready.
1860
 *
1861
 * @param object $bigbluebuttonbn
1862
 *
1863
 * @return void
1864
 */
1865
function bigbluebuttonbn_send_notification_recording_ready($bigbluebuttonbn) {
1866
    $sender = get_admin();
1867
    // Prepare message.
1868
    $messagetext = '<p>'.get_string('email_body_recording_ready_for', 'bigbluebuttonbn').
1869
        ' &quot;' . $bigbluebuttonbn->name . '&quot; '.
1870
        get_string('email_body_recording_ready_is_ready', 'bigbluebuttonbn').'.</p>';
1871
    $context = context_course::instance($bigbluebuttonbn->course);
1872
    \mod_bigbluebuttonbn\locallib\notifier::notification_send($context, $sender, $bigbluebuttonbn, $messagetext);
1873
}
1874
1875
/**
1876
 * Helper evaluates if the bigbluebutton server used belongs to blindsidenetworks domain.
1877
 *
1878
 * @return boolean
1879
 */
1880
function bigbluebuttonbn_is_bn_server() {
1881
    $parsedurl = parse_url(\mod_bigbluebuttonbn\locallib\config::get('server_url'));
1882
    if (!isset($parsedurl['host'])) {
1883
        return false;
1884
    }
1885
    $h = $parsedurl['host'];
1886
    $hends = explode('.', $h);
1887
    $hendslength = count($hends);
1888
    return ($hends[$hendslength - 1] == 'com' && $hends[$hendslength - 2] == 'blindsidenetworks');
1889
}
1890
1891
/**
1892
 * Helper function returns a list of courses a user has access to, wrapped in an array that can be used
1893
 * by a html select.
1894
 *
1895
 * @param array $bbbsession
1896
 *
1897
 * @return array
1898
 */
1899
function bigbluebuttonbn_import_get_courses_for_select(array $bbbsession) {
1900
    if ($bbbsession['administrator']) {
1901
        $courses = get_courses('all', 'c.fullname ASC', 'c.id,c.shortname,c.fullname');
1902
        // It includes the name of the site as a course (category 0), so remove the first one.
1903
        unset($courses['1']);
1904
    } else {
1905
        $courses = enrol_get_users_courses($bbbsession['userID'], false, 'id,shortname,fullname');
1906
    }
1907
    $coursesforselect = [];
1908
    foreach ($courses as $course) {
1909
        $coursesforselect[$course->id] = $course->fullname;
1910
    }
1911
    return $coursesforselect;
1912
}
1913
1914
/**
1915
 * Helper function renders recording table.
1916
 *
1917
 * @param array $bbbsession
1918
 * @param array $recordings
1919
 * @param array $tools
1920
 *
1921
 * @return array
1922
 */
1923
function bigbluebuttonbn_output_recording_table($bbbsession, $recordings, $tools = ['protect', 'publish', 'delete']) {
1924
    if (isset($recordings) && !empty($recordings)) {
1925
        // There are recordings for this meeting.
1926
        $table = bigbluebuttonbn_get_recording_table($bbbsession, $recordings, $tools);
1927
    }
1928
    if (!isset($table) || !isset($table->data)) {
1929
        // Render a table with "No recordings".
1930
        return html_writer::div(get_string('view_message_norecordings', 'bigbluebuttonbn'), '',
1931
            array('id' => 'bigbluebuttonbn_recordings_table'));
1932
    }
1933
    // Render the table.
1934
    return html_writer::div(html_writer::table($table), '', array('id' => 'bigbluebuttonbn_recordings_table'));
1935
}
1936
1937
/**
1938
 * Helper function to convert an html string to plain text.
1939
 *
1940
 * @param string $html
1941
 * @param integer $len
1942
 *
1943
 * @return string
1944
 */
1945
function bigbluebuttonbn_html2text($html, $len = 0) {
1946
    $text = strip_tags($html);
1947
    $text = str_replace('&nbsp;', ' ', $text);
1948
    $textlen = strlen($text);
1949
    $text = substr($text, 0, $len);
1950
    if ($textlen > $len) {
1951
        $text .= '...';
1952
    }
1953
    return $text;
1954
}
1955
1956
/**
1957
 * Helper function to obtain the tags linked to a bigbluebuttonbn activity
1958
 *
1959
 * @param string $id
1960
 *
1961
 * @return string containing the tags separated by commas
1962
 */
1963
function bigbluebuttonbn_get_tags($id) {
1964
    if (class_exists('core_tag_tag')) {
1965
        return implode(',', core_tag_tag::get_item_tags_array('core', 'course_modules', $id));
1966
    }
1967
    return implode(',', tag_get_tags('bigbluebuttonbn', $id));
1968
}
1969
1970
/**
1971
 * Helper function to define the sql used for gattering the bigbluebuttonbnids whose meetingids should be included
1972
 * in the getRecordings request
1973
 *
1974
 * @param string $courseid
1975
 * @param string $bigbluebuttonbnid
1976
 * @param bool   $subset
1977
 *
1978
 * @return string containing the sql used for getting the target bigbluebuttonbn instances
1979
 */
1980
function bigbluebuttonbn_get_recordings_sql_select($courseid, $bigbluebuttonbnid = null, $subset = true) {
1981
    if (empty($courseid)) {
1982
        $courseid = 0;
1983
    }
1984
    if (empty($bigbluebuttonbnid)) {
1985
        return "course = '{$courseid}'";
1986
    }
1987
    if ($subset) {
1988
        return "id = '{$bigbluebuttonbnid}'";
1989
    }
1990
    return "id <> '{$bigbluebuttonbnid}' AND course = '{$courseid}'";
1991
}
1992
1993
/**
1994
 * Helper function to define the sql used for gattering the bigbluebuttonbnids whose meetingids should be included
1995
 * in the getRecordings request considering only those that belong to deleted activities.
1996
 *
1997
 * @param string $courseid
1998
 * @param string $bigbluebuttonbnid
1999
 * @param bool   $subset
2000
 *
2001
 * @return string containing the sql used for getting the target bigbluebuttonbn instances
2002
 */
2003 View Code Duplication
function bigbluebuttonbn_get_recordings_deleted_sql_select($courseid = 0, $bigbluebuttonbnid = null, $subset = true) {
0 ignored issues
show
Duplication introduced by
This function seems to be duplicated in your project.

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

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

Loading history...
2004
    $sql = "log = '" . BIGBLUEBUTTONBN_LOG_EVENT_DELETE . "' AND meta like '%has_recordings%' AND meta like '%true%'";
2005
    if (empty($courseid)) {
2006
        $courseid = 0;
2007
    }
2008
    if (empty($bigbluebuttonbnid)) {
2009
        return $sql . " AND courseid = {$courseid}";
2010
    }
2011
    if ($subset) {
2012
        return $sql . " AND bigbluebuttonbnid = '{$bigbluebuttonbnid}'";
2013
    }
2014
    return $sql . " AND courseid = {$courseid} AND bigbluebuttonbnid <> '{$bigbluebuttonbnid}'";
2015
}
2016
2017
/**
2018
 * Helper function to define the sql used for gattering the bigbluebuttonbnids whose meetingids should be included
2019
 * in the getRecordings request considering only those that belong to imported recordings.
2020
 *
2021
 * @param string $courseid
2022
 * @param string $bigbluebuttonbnid
2023
 * @param bool   $subset
2024
 *
2025
 * @return string containing the sql used for getting the target bigbluebuttonbn instances
2026
 */
2027 View Code Duplication
function bigbluebuttonbn_get_recordings_imported_sql_select($courseid = 0, $bigbluebuttonbnid = null, $subset = true) {
0 ignored issues
show
Duplication introduced by
This function seems to be duplicated in your project.

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

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

Loading history...
2028
    $sql = "log = '" . BIGBLUEBUTTONBN_LOG_EVENT_IMPORT . "'";
2029
    if (empty($courseid)) {
2030
        $courseid = 0;
2031
    }
2032
    if (empty($bigbluebuttonbnid)) {
2033
        return $sql . " AND courseid = '{$courseid}'";
2034
    }
2035
    if ($subset) {
2036
        return $sql . " AND bigbluebuttonbnid = '{$bigbluebuttonbnid}'";
2037
    }
2038
    return $sql . " AND courseid = '{$courseid}' AND bigbluebuttonbnid <> '{$bigbluebuttonbnid}'";
2039
}
2040
2041
/**
2042
 * Helper function to get recordings  and imported recordings together.
2043
 *
2044
 * @param string $courseid
2045
 * @param string $bigbluebuttonbnid
2046
 * @param bool   $subset
2047
 * @param bool   $includedeleted
2048
 *
2049
 * @return associative array containing the recordings indexed by recordID, each recording is also a
2050
 * non sequential associative array itself that corresponds to the actual recording in BBB
2051
 */
2052
function bigbluebuttonbn_get_allrecordings($courseid = 0, $bigbluebuttonbnid = null, $subset = true, $includedeleted = false) {
2053
    $recordings = bigbluebuttonbn_get_recordings($courseid, $bigbluebuttonbnid, $subset, $includedeleted);
2054
    $recordingsimported = bigbluebuttonbn_get_recordings_imported_array($courseid, $bigbluebuttonbnid, $subset);
2055
    return ($recordings + $recordingsimported);
2056
}
2057
2058
/**
2059
 * Helper function to retrieve recordings from the BigBlueButton. The references are stored as events
2060
 * in bigbluebuttonbn_logs.
2061
 *
2062
 * @param string $courseid
2063
 * @param string $bigbluebuttonbnid
2064
 * @param bool   $subset
2065
 * @param bool   $includedeleted
2066
 *
2067
 * @return associative array containing the recordings indexed by recordID, each recording is also a
2068
 * non sequential associative array itself that corresponds to the actual recording in BBB
2069
 */
2070
function bigbluebuttonbn_get_recordings($courseid = 0, $bigbluebuttonbnid = null, $subset = true, $includedeleted = false) {
2071
    global $DB;
2072
    $select = bigbluebuttonbn_get_recordings_sql_select($courseid, $bigbluebuttonbnid, $subset);
2073
    $bigbluebuttonbns = $DB->get_records_select_menu('bigbluebuttonbn', $select, null, 'id', 'id, meetingid');
2074
    /* Consider logs from deleted bigbluebuttonbn instances whose meetingids should be included in
2075
     * the getRecordings request. */
2076
    if ($includedeleted) {
2077
        $selectdeleted = bigbluebuttonbn_get_recordings_deleted_sql_select($courseid, $bigbluebuttonbnid, $subset);
2078
        $bigbluebuttonbnsdel = $DB->get_records_select_menu('bigbluebuttonbn_logs', $selectdeleted, null,
2079
            'bigbluebuttonbnid', 'bigbluebuttonbnid, meetingid');
2080
        if (!empty($bigbluebuttonbnsdel)) {
2081
            // Merge bigbluebuttonbnis from deleted instances, only keys are relevant.
2082
            // Artimetic merge is used in order to keep the keys.
2083
            $bigbluebuttonbns += $bigbluebuttonbnsdel;
2084
        }
2085
    }
2086
    // Gather the meetingids from bigbluebuttonbn logs that include a create with record=true.
2087
    if (empty($bigbluebuttonbns)) {
2088
        return array();
2089
    }
2090
    // Prepare select for loading records based on existent bigbluebuttonbns.
2091
    $sql = 'SELECT DISTINCT meetingid, bigbluebuttonbnid FROM {bigbluebuttonbn_logs} WHERE ';
2092
    $sql .= '(bigbluebuttonbnid='.implode(' OR bigbluebuttonbnid=', array_keys($bigbluebuttonbns)).')';
2093
    // Include only Create events and exclude those with record not true.
2094
    $sql .= ' AND log = ? AND meta LIKE ? AND meta LIKE ?';
2095
    // Execute select for loading records based on existent bigbluebuttonbns.
2096
    $records = $DB->get_records_sql_menu($sql, array(BIGBLUEBUTTONBN_LOG_EVENT_CREATE, '%record%', '%true%'));
2097
    // Get actual recordings.
2098
    return bigbluebuttonbn_get_recordings_array(array_keys($records));
2099
}
2100
2101
/**
2102
 * Helper function iterates an array with recordings and unset those already imported.
2103
 *
2104
 * @param array $recordings
2105
 * @param integer $courseid
2106
 * @param integer $bigbluebuttonbnid
2107
 *
2108
 * @return array
2109
 */
2110
function bigbluebuttonbn_unset_existent_recordings_already_imported($recordings, $courseid, $bigbluebuttonbnid) {
2111
    $recordingsimported = bigbluebuttonbn_get_recordings_imported_array($courseid, $bigbluebuttonbnid, true);
2112
    foreach ($recordings as $key => $recording) {
2113
        if (isset($recordingsimported[$recording['recordID']])) {
2114
            unset($recordings[$key]);
2115
        }
2116
    }
2117
    return $recordings;
2118
}
2119
2120
/**
2121
 * Helper function to count the imported recordings for a recordingid.
2122
 *
2123
 * @param string $recordid
2124
 *
2125
 * @return integer
2126
 */
2127
function bigbluebuttonbn_count_recording_imported_instances($recordid) {
2128
    global $DB;
2129
    $sql = 'SELECT COUNT(DISTINCT id) FROM {bigbluebuttonbn_logs} WHERE log = ? AND meta LIKE ? AND meta LIKE ?';
2130
    return $DB->count_records_sql($sql, array(BIGBLUEBUTTONBN_LOG_EVENT_IMPORT, '%recordID%', "%{$recordid}%"));
2131
}
2132
2133
/**
2134
 * Helper function returns an array with all the instances of imported recordings for a recordingid.
2135
 *
2136
 * @param string $recordid
2137
 *
2138
 * @return array
2139
 */
2140
function bigbluebuttonbn_get_recording_imported_instances($recordid) {
2141
    global $DB;
2142
    $sql = 'SELECT * FROM {bigbluebuttonbn_logs} WHERE log = ? AND meta LIKE ? AND meta LIKE ?';
2143
    $recordingsimported = $DB->get_records_sql($sql, array(BIGBLUEBUTTONBN_LOG_EVENT_IMPORT, '%recordID%',
2144
        "%{$recordid}%"));
2145
    return $recordingsimported;
2146
}
2147
2148
/**
2149
 * Helper function to get how much callback events are logged.
2150
 *
2151
 * @param string $recordid
2152
 *
2153
 * @return integer
2154
 */
2155
function bigbluebuttonbn_get_count_callback_event_log($recordid) {
2156
    global $DB;
2157
    $sql = 'SELECT count(DISTINCT id) FROM {bigbluebuttonbn_logs} WHERE log = ? AND meta LIKE ? AND meta LIKE ?';
2158
    return $DB->count_records_sql($sql, array(BIGBLUEBUTTON_LOG_EVENT_CALLBACK, '%recordid%', "%{$recordid}%"));
2159
}
2160
2161
/**
2162
 * Helper function returns an array with the profiles (with features per profile) for the different types
2163
 * of bigbluebuttonbn instances.
2164
 *
2165
 * @return array
2166
 */
2167
function bigbluebuttonbn_get_instance_type_profiles() {
2168
    $instanceprofiles = array(
2169
        BIGBLUEBUTTONBN_TYPE_ALL => array('id' => BIGBLUEBUTTONBN_TYPE_ALL,
2170
                  'name' => get_string('instance_type_default', 'bigbluebuttonbn'),
2171
                  'features' => array('all')),
2172
        BIGBLUEBUTTONBN_TYPE_ROOM_ONLY => array('id' => BIGBLUEBUTTONBN_TYPE_ROOM_ONLY,
2173
                  'name' => get_string('instance_type_room_only', 'bigbluebuttonbn'),
2174
                  'features' => array('showroom', 'welcomemessage', 'voicebridge', 'waitformoderator', 'userlimit',
2175
                      'recording', 'sendnotifications', 'preuploadpresentation', 'permissions', 'schedule', 'groups',
2176
                      'modstandardelshdr', 'availabilityconditionsheader', 'tagshdr', 'competenciessection',
2177
                      'clienttype')),
2178
        BIGBLUEBUTTONBN_TYPE_RECORDING_ONLY => array('id' => BIGBLUEBUTTONBN_TYPE_RECORDING_ONLY,
2179
                  'name' => get_string('instance_type_recording_only', 'bigbluebuttonbn'),
2180
                  'features' => array('showrecordings', 'importrecordings'))
2181
    );
2182
    return $instanceprofiles;
2183
}
2184
2185
2186
/**
2187
 * Helper function returns an array with enabled features for an specific profile type.
2188
 *
2189
 * @param array $typeprofiles
2190
 * @param string $type
2191
 *
2192
 * @return array
2193
 */
2194
function bigbluebuttonbn_get_enabled_features($typeprofiles, $type = null) {
2195
    $enabledfeatures = array();
2196
    $features = $typeprofiles[BIGBLUEBUTTONBN_TYPE_ALL]['features'];
2197
    if (!is_null($type) && key_exists($type, $typeprofiles)) {
2198
        $features = $typeprofiles[$type]['features'];
2199
    }
2200
    $enabledfeatures['showroom'] = (in_array('all', $features) || in_array('showroom', $features));
2201
    // Evaluates if recordings are enabled for the Moodle site.
2202
    $enabledfeatures['showrecordings'] = false;
2203
    if (\mod_bigbluebuttonbn\locallib\config::recordings_enabled()) {
2204
        $enabledfeatures['showrecordings'] = (in_array('all', $features) || in_array('showrecordings', $features));
2205
    }
2206
    $enabledfeatures['importrecordings'] = false;
2207
    if (\mod_bigbluebuttonbn\locallib\config::importrecordings_enabled()) {
2208
        $enabledfeatures['importrecordings'] = (in_array('all', $features) || in_array('importrecordings', $features));
2209
    }
2210
    // Evaluates if clienttype is enabled for the Moodle site.
2211
    $enabledfeatures['clienttype'] = false;
2212
    if (\mod_bigbluebuttonbn\locallib\config::clienttype_enabled()) {
2213
        $enabledfeatures['clienttype'] = (in_array('all', $features) || in_array('clienttype', $features));
2214
    }
2215
    return $enabledfeatures;
2216
}
2217
2218
/**
2219
 * Helper function returns an array with the profiles (with features per profile) for the different types
2220
 * of bigbluebuttonbn instances that the user is allowed to create.
2221
 *
2222
 * @param boolean $room
2223
 * @param boolean $recording
2224
 *
2225
 * @return array
2226
 */
2227
function bigbluebuttonbn_get_instance_type_profiles_create_allowed($room, $recording) {
2228
    $profiles = bigbluebuttonbn_get_instance_type_profiles();
2229
    if (!$room) {
2230
        unset($profiles[BIGBLUEBUTTONBN_TYPE_ROOM_ONLY]);
2231
        unset($profiles[BIGBLUEBUTTONBN_TYPE_ALL]);
2232
    }
2233
    if (!$recording) {
2234
        unset($profiles[BIGBLUEBUTTONBN_TYPE_RECORDING_ONLY]);
2235
        unset($profiles[BIGBLUEBUTTONBN_TYPE_ALL]);
2236
    }
2237
    return $profiles;
2238
}
2239
2240
/**
2241
 * Helper function returns an array with the profiles (with features per profile) for the different types
2242
 * of bigbluebuttonbn instances.
2243
 *
2244
 * @param array $profiles
2245
 *
2246
 * @return array
2247
 */
2248
function bigbluebuttonbn_get_instance_profiles_array($profiles = []) {
2249
    $profilesarray = array();
2250
    foreach ($profiles as $key => $profile) {
2251
        $profilesarray[$profile['id']] = $profile['name'];
2252
    }
2253
    return $profilesarray;
2254
}
2255
2256
/**
2257
 * Helper function returns time in a formatted string.
2258
 *
2259
 * @param integer $time
2260
 *
2261
 * @return string
2262
 */
2263
function bigbluebuttonbn_format_activity_time($time) {
2264
    $activitytime = '';
2265
    if ($time) {
2266
        $activitytime = calendar_day_representation($time).' '.
2267
          get_string('mod_form_field_notification_msg_at', 'bigbluebuttonbn').' '.
2268
          calendar_time_representation($time);
2269
    }
2270
    return $activitytime;
2271
}
2272
2273
/**
2274
 * Helper function returns array with all the strings to be used in javascript.
2275
 *
2276
 * @return array
2277
 */
2278
function bigbluebuttonbn_get_strings_for_js() {
2279
    $locale = bigbluebuttonbn_get_locale();
2280
    $stringman = get_string_manager();
2281
    $strings = $stringman->load_component_strings('bigbluebuttonbn', $locale);
2282
    return $strings;
2283
}
2284
2285
/**
2286
 * Helper function returns the locale set by moodle.
2287
 *
2288
 * @return string
2289
 */
2290
function bigbluebuttonbn_get_locale() {
2291
    $lang = get_string('locale', 'core_langconfig');
2292
    return substr($lang, 0, strpos($lang, '.'));
2293
}
2294
2295
/**
2296
 * Helper function returns the locale code based on the locale set by moodle.
2297
 *
2298
 * @return string
2299
 */
2300
function bigbluebuttonbn_get_localcode() {
2301
    $locale = bigbluebuttonbn_get_locale();
2302
    return substr($locale, 0, strpos($locale, '_'));
2303
}
2304
2305
/**
2306
 * Helper function returns array with the instance settings used in views.
2307
 *
2308
 * @param string $id
2309
 * @param object $bigbluebuttonbnid
2310
 *
2311
 * @return array
2312
 */
2313
function bigbluebuttonbn_view_validator($id, $bigbluebuttonbnid) {
2314
    if ($id) {
2315
        return bigbluebuttonbn_view_instance_id($id);
2316
    }
2317
    if ($bigbluebuttonbnid) {
2318
        return bigbluebuttonbn_view_instance_bigbluebuttonbn($bigbluebuttonbnid);
2319
    }
2320
    return;
2321
}
2322
2323
/**
2324
 * Helper function returns array with the instance settings used in views based on id.
2325
 *
2326
 * @param string $id
2327
 *
2328
 * @return array
2329
 */
2330 View Code Duplication
function bigbluebuttonbn_view_instance_id($id) {
0 ignored issues
show
Duplication introduced by
This function seems to be duplicated in your project.

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

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

Loading history...
2331
    global $DB;
2332
    $cm = get_coursemodule_from_id('bigbluebuttonbn', $id, 0, false, MUST_EXIST);
2333
    $course = $DB->get_record('course', array('id' => $cm->course), '*', MUST_EXIST);
2334
    $bigbluebuttonbn = $DB->get_record('bigbluebuttonbn', array('id' => $cm->instance), '*', MUST_EXIST);
2335
    return array('cm' => $cm, 'course' => $course, 'bigbluebuttonbn' => $bigbluebuttonbn);
2336
}
2337
2338
/**
2339
 * Helper function returns array with the instance settings used in views based on bigbluebuttonbnid.
2340
 *
2341
 * @param object $bigbluebuttonbnid
2342
 *
2343
 * @return array
2344
 */
2345 View Code Duplication
function bigbluebuttonbn_view_instance_bigbluebuttonbn($bigbluebuttonbnid) {
0 ignored issues
show
Duplication introduced by
This function seems to be duplicated in your project.

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

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

Loading history...
2346
    global $DB;
2347
    $bigbluebuttonbn = $DB->get_record('bigbluebuttonbn', array('id' => $bigbluebuttonbnid), '*', MUST_EXIST);
2348
    $course = $DB->get_record('course', array('id' => $bigbluebuttonbn->course), '*', MUST_EXIST);
2349
    $cm = get_coursemodule_from_instance('bigbluebuttonbn', $bigbluebuttonbn->id, $course->id, false, MUST_EXIST);
2350
    return array('cm' => $cm, 'course' => $course, 'bigbluebuttonbn' => $bigbluebuttonbn);
2351
}
2352
2353
/**
2354
 * Helper function renders general warning message for settings (if any).
2355
 *
2356
 * @param object $renderer
2357
 *
2358
 * @return void
2359
 */
2360
function bigbluebuttonbn_settings_general_warning(&$renderer) {
0 ignored issues
show
Unused Code introduced by
The parameter $renderer is not used and could be removed.

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

Loading history...
2361
    return;
2362
}
2363
2364
/**
2365
 * Helper function renders general settings if the feature is enabled.
2366
 *
2367
 * @param object $renderer
2368
 *
2369
 * @return void
2370
 */
2371
function bigbluebuttonbn_settings_general(&$renderer) {
2372
    // Configuration for BigBlueButton.
2373
    if ((boolean)\mod_bigbluebuttonbn\settings\validator::section_general_shown()) {
2374
        $renderer->render_group_header('general');
2375
        $renderer->render_group_element('server_url',
2376
            $renderer->render_group_element_text('server_url', BIGBLUEBUTTONBN_DEFAULT_SERVER_URL));
2377
        $renderer->render_group_element('shared_secret',
2378
            $renderer->render_group_element_text('shared_secret', BIGBLUEBUTTONBN_DEFAULT_SHARED_SECRET));
2379
    }
2380
}
2381
2382
/**
2383
 * Helper function renders record settings if the feature is enabled.
2384
 *
2385
 * @param object $renderer
2386
 *
2387
 * @return void
2388
 */
2389
function bigbluebuttonbn_settings_record(&$renderer) {
2390
    // Configuration for 'recording' feature.
2391 View Code Duplication
    if ((boolean)\mod_bigbluebuttonbn\settings\validator::section_record_meeting_shown()) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

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

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

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

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

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

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

Loading history...
2619
    // Configuration for BigBlueButton.
2620
    if ((boolean)\mod_bigbluebuttonbn\settings\validator::section_muteonstart_shown()) {
2621
        $renderer->render_group_header('muteonstart');
2622
        $renderer->render_group_element('muteonstart_default',
2623
            $renderer->render_group_element_checkbox('muteonstart_default', 0));
2624
        $renderer->render_group_element('muteonstart_editable',
2625
            $renderer->render_group_element_checkbox('muteonstart_editable', 0));
2626
    }
2627
}
2628
2629
/**
2630
 * Helper function renders extended settings if any of the features there is enabled.
2631
 *
2632
 * @param object $renderer
2633
 *
2634
 * @return void
2635
 */
2636 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...
2637
    // Configuration for extended BN capabilities.
2638
    if (!bigbluebuttonbn_is_bn_server()) {
2639
        return;
2640
    }
2641
    // Configuration for 'notify users when recording ready' feature.
2642
    if ((boolean)\mod_bigbluebuttonbn\settings\validator::section_settings_extended_shown()) {
2643
        $renderer->render_group_header('extended_capabilities');
2644
        // UI for 'notify users when recording ready' feature.
2645
        $renderer->render_group_element('recordingready_enabled',
2646
            $renderer->render_group_element_checkbox('recordingready_enabled', 0));
2647
        // UI for 'register meeting events' feature.
2648
        $renderer->render_group_element('meetingevents_enabled',
2649
            $renderer->render_group_element_checkbox('meetingevents_enabled', 0));
2650
    }
2651
}
2652
2653
/**
2654
 * Helper function returns a sha1 encoded string that is unique and will be used as a seed for meetingid.
2655
 *
2656
 * @return string
2657
 */
2658
function bigbluebuttonbn_unique_meetingid_seed() {
2659
    global $DB;
2660
    do {
2661
        $encodedseed = sha1(bigbluebuttonbn_random_password(12));
2662
        $meetingid = (string)$DB->get_field('bigbluebuttonbn', 'meetingid', array('meetingid' => $encodedseed));
2663
    } while ($meetingid == $encodedseed);
2664
    return $encodedseed;
2665
}
2666
2667
/**
2668
 * Helper function renders the link used for recording type in row for the data used by the recording table.
2669
 *
2670
 * @param array $recording
2671
 * @param array $bbbsession
2672
 * @param array $playback
2673
 *
2674
 * @return boolean
2675
 */
2676
function bigbluebuttonbn_include_recording_data_row_type($recording, $bbbsession, $playback) {
2677
    // All types that are not restricted are included.
2678
    if (array_key_exists('restricted', $playback) && strtolower($playback['restricted']) == 'false') {
2679
        return true;
2680
    }
2681
    // All types that are not statistics are included.
2682
    if ($playback['type'] != 'statistics') {
2683
        return true;
2684
    }
2685
    // Exclude imported recordings.
2686
    if (isset($recording['imported'])) {
2687
        return false;
2688
    }
2689
    // Exclude non moderators.
2690
    if (!$bbbsession['administrator'] && !$bbbsession['moderator']) {
2691
        return false;
2692
    }
2693
    return true;
2694
}
2695
2696
/**
2697
 * Renders the general warning message.
2698
 *
2699
 * @param string $message
2700
 * @param string $type
2701
 * @param string $href
2702
 * @param string $text
2703
 * @param string $class
2704
 *
2705
 * @return string
2706
 */
2707
function bigbluebuttonbn_render_warning($message, $type='info', $href='', $text='', $class='') {
2708
    global $OUTPUT;
2709
    $output = "\n";
2710
    // Evaluates if config_warning is enabled.
2711
    if (empty($message)) {
2712
        return $output;
2713
    }
2714
    $output .= $OUTPUT->box_start('box boxalignleft adminerror alert alert-' . $type . ' alert-block fade in',
2715
      'bigbluebuttonbn_view_general_warning') . "\n";
2716
    $output .= '    ' . $message . "\n";
2717
    $output .= '  <div class="singlebutton pull-right">' . "\n";
2718
    if (!empty($href)) {
2719
        $output .= bigbluebuttonbn_render_warning_button($href, $text, $class);
2720
    }
2721
    $output .= '  </div>' . "\n";
2722
    $output .= $OUTPUT->box_end() . "\n";
2723
    return $output;
2724
}
2725
2726
/**
2727
 * Renders the general warning button.
2728
 *
2729
 * @param string $href
2730
 * @param string $text
2731
 * @param string $class
2732
 * @param string $title
2733
 *
2734
 * @return string
2735
 */
2736
function bigbluebuttonbn_render_warning_button($href, $text = '', $class = '', $title = '') {
2737
    if ($text == '') {
2738
        $text = get_string('ok', 'moodle');
2739
    }
2740
    if ($title == '') {
2741
        $title = $text;
2742
    }
2743
    if ($class == '') {
2744
        $class = 'btn btn-secondary';
2745
    }
2746
    $output  = '  <form method="post" action="' . $href . '" class="form-inline">'."\n";
2747
    $output .= '      <button type="submit" class="' . $class . '"'."\n";
2748
    $output .= '          title="' . $title . '"'."\n";
2749
    $output .= '          >' . $text . '</button>'."\n";
2750
    $output .= '  </form>'."\n";
2751
    return $output;
2752
}
2753
2754
/**
2755
 * Check if a BigBlueButtonBN is available to be used by the current user.
2756
 *
2757
 * @param  stdClass  $bigbluebuttonbn  BigBlueButtonBN instance
2758
 *
2759
 * @return boolean                     status if room available and current user allowed to join
2760
 */
2761
function bigbluebuttonbn_get_availability_status($bigbluebuttonbn) {
2762
    list($roomavailable) = bigbluebuttonbn_room_is_available($bigbluebuttonbn);
2763
    list($usercanjoin) = bigbluebuttonbn_user_can_join_meeting($bigbluebuttonbn);
2764
2765
    return ($roomavailable && $usercanjoin);
2766
}
2767
2768
/**
2769
 * Helper for evaluating if scheduled activity is avaiable.
2770
 *
2771
 * @param  stdClass  $bigbluebuttonbn  BigBlueButtonBN instance
2772
 *
2773
 * @return array                       status (room available or not and possible warnings)
2774
 */
2775
function bigbluebuttonbn_room_is_available($bigbluebuttonbn) {
2776
    $open = true;
2777
    $closed = false;
2778
    $warnings = array();
2779
2780
    $timenow = time();
2781
    $timeopen = $bigbluebuttonbn->openingtime;
2782
    $timeclose = $bigbluebuttonbn->closingtime;
2783
    if (!empty($timeopen) && $timeopen > $timenow) {
2784
        $open = false;
2785
    }
2786
    if (!empty($timeclose) && $timenow > $timeclose) {
2787
        $closed = true;
2788
    }
2789
2790
    if (!$open || $closed) {
2791
        if (!$open) {
2792
            $warnings['notopenyet'] = userdate($timeopen);
2793
        }
2794
        if ($closed) {
2795
            $warnings['expired'] = userdate($timeclose);
2796
        }
2797
        return array(false, $warnings);
2798
    }
2799
2800
    return array(true, $warnings);
2801
}
2802
2803
/**
2804
 * Helper for evaluating if meeting can be joined.
2805
 *
2806
 * @param  stdClass $bigbluebuttonbn  BigBlueButtonBN instance
2807
 * @param  string   $mid
2808
 * @param  integer  $userid
2809
 *
2810
 * @return array    status (user allowed to join or not and possible message)
2811
 */
2812
function bigbluebuttonbn_user_can_join_meeting($bigbluebuttonbn, $mid = null, $userid = null) {
2813
2814
    // By default, use a meetingid without groups.
2815
    if (empty($mid)) {
2816
        $mid = $bigbluebuttonbn->meetingid . '-' . $bigbluebuttonbn->course . '-' . $bigbluebuttonbn->id;
2817
    }
2818
2819
    // When meeting is running, all authorized users can join right in.
2820
    if (bigbluebuttonbn_is_meeting_running($mid)) {
2821
        return array(true, get_string('view_message_conference_in_progress', 'bigbluebuttonbn'));
2822
    }
2823
2824
    // When meeting is not running, see if the user can join.
2825
    $context = context_course::instance($bigbluebuttonbn->course);
2826
    $participantlist = bigbluebuttonbn_get_participant_list($bigbluebuttonbn, $context);
2827
    $isadmin = is_siteadmin($userid);
2828
    $ismoderator = bigbluebuttonbn_is_moderator($context, $participantlist, $userid);
2829
    // If user is administrator, moderator or if is viewer and no waiting is required, join allowed.
2830
    if ($isadmin || $ismoderator || !$bigbluebuttonbn->wait) {
2831
        return array(true, get_string('view_message_conference_room_ready', 'bigbluebuttonbn'));
2832
    }
2833
    // Otherwise, no join allowed.
2834
    return array(false, get_string('view_message_conference_wait_for_moderator', 'bigbluebuttonbn'));
2835
}
2836
2837
/**
2838
 * Helper for getting a value from a bigbluebuttonbn cache.
2839
 *
2840
 * @param  string   $name       BigBlueButtonBN cache
2841
 * @param  string   $key        Key to be retrieved
2842
 * @param  integer  $default    Default value in case key is not found or it is empty
2843
 *
2844
 * @return variable key value
2845
 */
2846
function bigbluebuttonbn_cache_get($name, $key, $default = null) {
2847
    $cache = cache::make_from_params(cache_store::MODE_APPLICATION, 'mod_bigbluebuttonbn', $name);
2848
    $result = $cache->get($key);
2849
    if (!empty($result)) {
2850
        return $result;
2851
    }
2852
    return $default;
2853
}
2854
2855
/**
2856
 * Helper for setting a value in a bigbluebuttonbn cache.
2857
 *
2858
 * @param  string   $name       BigBlueButtonBN cache
2859
 * @param  string   $key        Key to be created/updated
2860
 * @param  variable $value      Default value to be set
2861
 */
2862
function bigbluebuttonbn_cache_set($name, $key, $value) {
2863
    $cache = cache::make_from_params(cache_store::MODE_APPLICATION, 'mod_bigbluebuttonbn', $name);
2864
    $cache->set($key, $value);
2865
}
2866
2867
/**
2868
 * Helper for getting the owner userid of a bigbluebuttonbn instance.
2869
 *
2870
 * @param  stdClass $bigbluebuttonbn  BigBlueButtonBN instance
2871
 *
2872
 * @return integer ownerid (a valid user id or null if not registered/found)
2873
 */
2874
function bigbluebuttonbn_instance_ownerid($bigbluebuttonbn) {
2875
    global $DB;
2876
    $filters = array('bigbluebuttonbnid' => $bigbluebuttonbn->id, 'log' => 'Add');
2877
    $ownerid = (integer)$DB->get_field('bigbluebuttonbn_logs', 'userid', $filters);
2878
    return $ownerid;
2879
}
2880
2881
/**
2882
 * Helper evaluates if the bigbluebutton server used belongs to blindsidenetworks domain.
2883
 *
2884
 * @return boolean
2885
 */
2886
function bigbluebuttonbn_has_html5_client() {
2887
    $checkurl = \mod_bigbluebuttonbn\locallib\bigbluebutton::root() . "html5client/check";
2888
    $curlinfo = bigbluebuttonbn_wrap_xml_load_file_curl_request($checkurl, 'HEAD');
2889
    return (isset($curlinfo['http_code']) && $curlinfo['http_code'] == 200);
2890
}
2891
2892
/**
2893
 * Setup the bbbsession variable that is used all accross the plugin.
2894
 *
2895
 * @param object $context
2896
 * @param array $bbbsession
2897
 * @return void
2898
 */
2899
function bigbluebuttonbn_view_bbbsession_set($context, &$bbbsession) {
2900
    global $CFG, $USER;
2901
    // User data.
2902
    $bbbsession['username'] = fullname($USER);
2903
    $bbbsession['userID'] = $USER->id;
2904
    // User roles.
2905
    $bbbsession['administrator'] = is_siteadmin($bbbsession['userID']);
2906
    $participantlist = bigbluebuttonbn_get_participant_list($bbbsession['bigbluebuttonbn'], $context);
2907
    $bbbsession['moderator'] = bigbluebuttonbn_is_moderator($context, $participantlist);
2908
    $bbbsession['managerecordings'] = ($bbbsession['administrator']
2909
        || has_capability('mod/bigbluebuttonbn:managerecordings', $context));
2910
    $bbbsession['importrecordings'] = ($bbbsession['managerecordings']);
2911
    // Server data.
2912
    $bbbsession['modPW'] = $bbbsession['bigbluebuttonbn']->moderatorpass;
2913
    $bbbsession['viewerPW'] = $bbbsession['bigbluebuttonbn']->viewerpass;
2914
    // Database info related to the activity.
2915
    $bbbsession['meetingid'] = $bbbsession['bigbluebuttonbn']->meetingid.'-'.$bbbsession['course']->id.'-'.
2916
        $bbbsession['bigbluebuttonbn']->id;
2917
    $bbbsession['meetingname'] = $bbbsession['bigbluebuttonbn']->name;
2918
    $bbbsession['meetingdescription'] = $bbbsession['bigbluebuttonbn']->intro;
2919
    // Extra data for setting up the Meeting.
2920
    $bbbsession['userlimit'] = intval((int)\mod_bigbluebuttonbn\locallib\config::get('userlimit_default'));
2921
    if ((boolean)\mod_bigbluebuttonbn\locallib\config::get('userlimit_editable')) {
2922
        $bbbsession['userlimit'] = intval($bbbsession['bigbluebuttonbn']->userlimit);
2923
    }
2924
    $bbbsession['voicebridge'] = $bbbsession['bigbluebuttonbn']->voicebridge;
2925
    if ($bbbsession['bigbluebuttonbn']->voicebridge > 0) {
2926
        $bbbsession['voicebridge'] = 70000 + $bbbsession['bigbluebuttonbn']->voicebridge;
2927
    }
2928
    $bbbsession['wait'] = $bbbsession['bigbluebuttonbn']->wait;
2929
    $bbbsession['record'] = $bbbsession['bigbluebuttonbn']->record;
2930
    $bbbsession['welcome'] = $bbbsession['bigbluebuttonbn']->welcome;
2931
    if (!isset($bbbsession['welcome']) || $bbbsession['welcome'] == '') {
2932
        $bbbsession['welcome'] = get_string('mod_form_field_welcome_default', 'bigbluebuttonbn');
2933
    }
2934
    if ($bbbsession['bigbluebuttonbn']->record) {
2935
        $bbbsession['welcome'] .= '<br><br>'.get_string('bbbrecordwarning', 'bigbluebuttonbn');
2936
    }
2937
    $bbbsession['openingtime'] = $bbbsession['bigbluebuttonbn']->openingtime;
2938
    $bbbsession['closingtime'] = $bbbsession['bigbluebuttonbn']->closingtime;
2939
    // Additional info related to the course.
2940
    $bbbsession['context'] = $context;
2941
    // Metadata (origin).
2942
    $bbbsession['origin'] = 'Moodle';
2943
    $bbbsession['originVersion'] = $CFG->release;
2944
    $parsedurl = parse_url($CFG->wwwroot);
2945
    $bbbsession['originServerName'] = $parsedurl['host'];
2946
    $bbbsession['originServerUrl'] = $CFG->wwwroot;
2947
    $bbbsession['originServerCommonName'] = '';
2948
    $bbbsession['originTag'] = 'moodle-mod_bigbluebuttonbn ('.get_config('mod_bigbluebuttonbn', 'version').')';
2949
    $bbbsession['bnserver'] = bigbluebuttonbn_is_bn_server();
2950
    // Setting for clienttype, assign flash if not enabled, or default if not editable.
2951
    $bbbsession['clienttype'] = \mod_bigbluebuttonbn\locallib\config::get('clienttype_default');
2952
    if (\mod_bigbluebuttonbn\locallib\config::get('clienttype_editable')) {
2953
        $bbbsession['clienttype'] = $bbbsession['bigbluebuttonbn']->clienttype;
2954
    }
2955
    if (!\mod_bigbluebuttonbn\locallib\config::clienttype_enabled()) {
2956
        $bbbsession['clienttype'] = BIGBLUEBUTTON_CLIENTTYPE_FLASH;
2957
    }
2958
}
2959
2960
/**
2961
 * Return the status of an activity [open|not_started|ended].
2962
 *
2963
 * @param array $bbbsession
2964
 * @return string
2965
 */
2966
function bigbluebuttonbn_view_get_activity_status(&$bbbsession) {
2967
    $now = time();
2968 View Code Duplication
    if (!empty($bbbsession['bigbluebuttonbn']->openingtime) && $now < $bbbsession['bigbluebuttonbn']->openingtime) {
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...
2969
        // The activity has not been opened.
2970
        return 'not_started';
2971
    }
2972
    if (!empty($bbbsession['bigbluebuttonbn']->closingtime) && $now > $bbbsession['bigbluebuttonbn']->closingtime) {
2973
        // The activity has been closed.
2974
        $bbbsession['presentation'] = bigbluebuttonbn_get_presentation_array(
2975
            $bbbsession['context'], $bbbsession['bigbluebuttonbn']->presentation);
2976
        return 'ended';
2977
    }
2978
    // The activity is open.
2979
    $bbbsession['presentation'] = bigbluebuttonbn_get_presentation_array(
2980
        $bbbsession['context'], $bbbsession['bigbluebuttonbn']->presentation, $bbbsession['bigbluebuttonbn']->id);
2981
    return 'open';
2982
}
2983