Completed
Push — master ( 59bc19...b8c79f )
by Jesus
02:06
created

locallib.php ➔ bigbluebuttonbn_views_instance_id()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 6

Duplication

Lines 7
Ratio 100 %

Importance

Changes 0
Metric Value
cc 1
eloc 6
nc 1
nop 1
dl 7
loc 7
rs 9.4285
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
 * @author    Fred Dixon  (ffdixon [at] blindsidenetworks [dt] com)
21
 * @author    Jesus Federico  (jesus [at] blindsidenetworks [dt] com)
22
 * @copyright 2010-2017 Blindside Networks Inc
23
 * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v2 or later
24
 */
25
26
defined('MOODLE_INTERNAL') || die;
27
28
global $CFG;
29
30
require_once(dirname(__FILE__).'/lib.php');
31
32
const BIGBLUEBUTTONBN_FORCED = true;
33
34
const BIGBLUEBUTTONBN_TYPE_ALL = 0;
35
const BIGBLUEBUTTONBN_TYPE_ROOM_ONLY = 1;
36
const BIGBLUEBUTTONBN_TYPE_RECORDING_ONLY = 2;
37
38
const BIGBLUEBUTTONBN_ROLE_VIEWER = 'viewer';
39
const BIGBLUEBUTTONBN_ROLE_MODERATOR = 'moderator';
40
const BIGBLUEBUTTONBN_METHOD_GET = 'GET';
41
const BIGBLUEBUTTONBN_METHOD_POST = 'POST';
42
43
const BIGBLUEBUTTON_EVENT_ACTIVITY_VIEWED = 'activity_viewed';
44
const BIGBLUEBUTTON_EVENT_ACTIVITY_MANAGEMENT_VIEWED = 'activity_management_viewed';
45
const BIGBLUEBUTTON_EVENT_LIVE_SESSION = 'live_session';
46
const BIGBLUEBUTTON_EVENT_MEETING_CREATED = 'meeting_created';
47
const BIGBLUEBUTTON_EVENT_MEETING_ENDED = 'meeting_ended';
48
const BIGBLUEBUTTON_EVENT_MEETING_JOINED = 'meeting_joined';
49
const BIGBLUEBUTTON_EVENT_MEETING_LEFT = 'meeting_left';
50
const BIGBLUEBUTTON_EVENT_RECORDING_DELETED = 'recording_deleted';
51
const BIGBLUEBUTTON_EVENT_RECORDING_IMPORTED = 'recording_imported';
52
const BIGBLUEBUTTON_EVENT_RECORDING_PROTECTED = 'recording_protected';
53
const BIGBLUEBUTTON_EVENT_RECORDING_PUBLISHED = 'recording_published';
54
const BIGBLUEBUTTON_EVENT_RECORDING_UNPROTECTED = 'recording_unprotected';
55
const BIGBLUEBUTTON_EVENT_RECORDING_UNPUBLISHED = 'recording_unpublished';
56
const BIGBLUEBUTTON_EVENT_RECORDING_EDITED = 'recording_edited';
57
const BIGBLUEBUTTON_EVENT_RECORDING_VIEWED = 'recording_viewed';
58
59
/**
60
 * @param array  $bbbsession
61
 * @param string $event
62
 * @param array  $overrides
63
 * @param string $meta
64
 */
65
function bigbluebuttonbn_logs(array $bbbsession, $event, array $overrides = [], $meta = null) {
66
    global $DB;
67
68
    $log = new stdClass();
69
70
    // Default values.
71
    $log->courseid = $bbbsession['course']->id;
72
    $log->bigbluebuttonbnid = $bbbsession['bigbluebuttonbn']->id;
73
    $log->userid = $bbbsession['userID'];
74
    $log->meetingid = $bbbsession['meetingid'];
75
    $log->timecreated = time();
76
    // Overrides.
77
    foreach ($overrides as $key => $value) {
78
        $log->$key = $value;
79
    }
80
81
    $log->log = $event;
82
    if (isset($meta)) {
83
        $log->meta = $meta;
84
    } else if ($event == BIGBLUEBUTTONBN_LOG_EVENT_CREATE) {
85
        $log->meta = '{"record":'.($bbbsession['record'] ? 'true' : 'false').'}';
86
    }
87
88
    $DB->insert_record('bigbluebuttonbn_logs', $log);
89
}
90
91
/**
92
 * @param string $meetingid
93
 * @param string $username
94
 * @param string $pw
95
 * @param string $logouturl
96
 * @param string $configtoken
97
 * @param string $userid
98
 */
99
function bigbluebuttonbn_get_join_url($meetingid, $username, $pw, $logouturl, $configtoken = null, $userid = null) {
100
    $data = ['meetingID' => $meetingid,
101
              'fullName' => $username,
102
              'password' => $pw,
103
              'logoutURL' => $logouturl,
104
            ];
105
106
    if (!is_null($configtoken)) {
107
        $data['configToken'] = $configtoken;
108
    }
109
    if (!is_null($userid)) {
110
        $data['userID'] = $userid;
111
    }
112
113
    return \mod_bigbluebuttonbn\locallib\bigbluebutton::action_url('join', $data);
114
}
115
116
/**
117
 * @param string $recordid
118
 * @param array  $metadata
119
 */
120
function bigbluebuttonbn_get_update_recordings_url($recordid, $metadata = array()) {
121
    return \mod_bigbluebuttonbn\locallib\bigbluebutton::action_url('updateRecordings', ['recordID' => $recordid], $metadata);
122
}
123
124
/**
125
 * @param array  $data
126
 * @param array  $metadata
127
 * @param string $pname
128
 * @param string $purl
129
 */
130
function bigbluebuttonbn_get_create_meeting_array($data, $metadata = array(), $pname = null, $purl = null) {
131
    $createmeetingurl = \mod_bigbluebuttonbn\locallib\bigbluebutton::action_url('create', $data, $metadata);
132
    $method = BIGBLUEBUTTONBN_METHOD_GET;
133
    $data = null;
134
135
    if (!is_null($pname) && !is_null($purl)) {
136
        $method = BIGBLUEBUTTONBN_METHOD_POST;
137
        $data = "<?xml version='1.0' encoding='UTF-8'?><modules><module name='" . $pname . "'><document url='".
138
            $purl."' /></module></modules>";
139
    }
140
141
    $xml = bigbluebuttonbn_wrap_xml_load_file($createmeetingurl, $method, $data);
142
143
    if ($xml) {
144
        $response = array('returncode' => $xml->returncode, 'message' => $xml->message, 'messageKey' => $xml->messageKey);
145
        if ($xml->meetingID) {
146
            $response += array('meetingID' => $xml->meetingID, 'attendeePW' => $xml->attendeePW,
147
                'moderatorPW' => $xml->moderatorPW, 'hasBeenForciblyEnded' => $xml->hasBeenForciblyEnded);
148
        }
149
150
        return $response;
151
    }
152
153
    return null;
154
}
155
156
/**
157
 * @param string $meetingid
158
 */
159
function bigbluebuttonbn_get_meeting_array($meetingid) {
160
    $meetings = bigbluebuttonbn_get_meetings_array();
161
    if ($meetings) {
162
        foreach ($meetings as $meeting) {
163
            if ($meeting['meetingID'] == $meetingid) {
164
                return $meeting;
165
            }
166
        }
167
    }
168
169
    return null;
170
}
171
172
function bigbluebuttonbn_get_meetings_array() {
173
    $xml = bigbluebuttonbn_wrap_xml_load_file(\mod_bigbluebuttonbn\locallib\bigbluebutton::action_url('getMeetings'));
174
175
    if ($xml && $xml->returncode == 'SUCCESS' && empty($xml->messageKey)) {
176
        // Meetings were returned.
177
        $meetings = array();
178
        foreach ($xml->meetings->meeting as $meeting) {
179
            $meetings[] = array('meetingID' => $meeting->meetingID,
180
                                'moderatorPW' => $meeting->moderatorPW,
181
                                'attendeePW' => $meeting->attendeePW,
182
                                'hasBeenForciblyEnded' => $meeting->hasBeenForciblyEnded,
183
                                'running' => $meeting->running, );
184
        }
185
186
        return $meetings;
187
    }
188
189 View Code Duplication
    if ($xml) {
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...
190
        // Either failure or success without meetings.
191
        return array('returncode' => $xml->returncode, 'message' => $xml->message, 'messageKey' => $xml->messageKey);
192
    }
193
194
    // If the server is unreachable, then prompts the user of the necessary action.
195
    return null;
196
}
197
198
/**
199
 * @param string $meetingid
200
 */
201
function bigbluebuttonbn_get_meeting_info_array($meetingid) {
202
    $xml = bigbluebuttonbn_wrap_xml_load_file(
203
        \mod_bigbluebuttonbn\locallib\bigbluebutton::action_url('getMeetingInfo', ['meetingID' => $meetingid])
204
      );
205
206
    if ($xml && $xml->returncode == 'SUCCESS' && empty($xml->messageKey)) {
207
        // Meeting info was returned.
208
        return array('returncode' => $xml->returncode,
209
                     'meetingID' => $xml->meetingID,
210
                     'moderatorPW' => $xml->moderatorPW,
211
                     'attendeePW' => $xml->attendeePW,
212
                     'hasBeenForciblyEnded' => $xml->hasBeenForciblyEnded,
213
                     'running' => $xml->running,
214
                     'recording' => $xml->recording,
215
                     'startTime' => $xml->startTime,
216
                     'endTime' => $xml->endTime,
217
                     'participantCount' => $xml->participantCount,
218
                     'moderatorCount' => $xml->moderatorCount,
219
                     'attendees' => $xml->attendees,
220
                     'metadata' => $xml->metadata,
221
                   );
222
    }
223
224 View Code Duplication
    if ($xml) {
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...
225
        // Either failure or success without meeting info.
226
        return array('returncode' => $xml->returncode, 'message' => $xml->message, 'messageKey' => $xml->messageKey);
227
    }
228
229
    // If the server is unreachable, then prompts the user of the necessary action.
230
    return null;
231
}
232
233
/**
234
 * helper function to retrieve recordings from a BigBlueButton server.
235
 *
236
 * @param string or array $meetingids   list of meetingIDs "mid1,mid2,mid3" or array("mid1","mid2","mid3")
237
 * @param string or array $recordingids list of $recordingids "rid1,rid2,rid3" or array("rid1","rid2","rid3") for filtering
238
 *
239
 * @return associative array with recordings indexed by recordID, each recording is a non sequential associative array
240
 */
241
function bigbluebuttonbn_get_recordings_array($meetingids, $recordingids = []) {
242
    $meetingidsarray = $meetingids;
243
    if (!is_array($meetingids)) {
244
        $meetingidsarray = explode(',', $meetingids);
245
    }
246
247
    // If $meetingidsarray is empty there is no need to go further.
248
    if (empty($meetingidsarray)) {
249
        return array();
250
    }
251
    $recordings = bigbluebuttonbn_get_recordings_array_fetch($meetingidsarray);
252
253
    // Filter recordings based on recordingIDs.
254
    $recordingidsarray = $recordingids;
255
    if (!is_array($recordingids)) {
256
        $recordingidsarray = explode(',', $recordingids);
257
    }
258
259
    if (empty($recordingidsarray)) {
260
        // No recording ids, no need to filter.
261
        return $recordings;
262
    }
263
264
    return bigbluebuttonbn_get_recordings_array_filter($recordingidsarray, $recordings);
265
}
266
267
/**
268
 * helper function to fetch recordings from a BigBlueButton server.
269
 *
270
 * @param array $meetingidsarray   array with meeting ids in the form array("mid1","mid2","mid3")
271
 *
272
 * @return associative array with recordings indexed by recordID, each recording is a non sequential associative array
273
 */
274
function bigbluebuttonbn_get_recordings_array_fetch($meetingidsarray) {
275
276
    $recordings = array();
277
278
    // Execute a paginated getRecordings request.
279
    $pages = floor(count($meetingidsarray) / 25) + 1;
280
    for ($page = 1; $page <= $pages; ++$page) {
281
        $mids = array_slice($meetingidsarray, ($page - 1) * 25, 25);
282
        // Do getRecordings is executed using a method GET (supported by all versions of BBB).
283
        $xml = bigbluebuttonbn_wrap_xml_load_file(
284
            \mod_bigbluebuttonbn\locallib\bigbluebutton::action_url('getRecordings', ['meetingID' => implode(',', $mids)])
285
          );
286
        if ($xml && $xml->returncode == 'SUCCESS' && isset($xml->recordings)) {
287
            // If there were meetings already created.
288
            foreach ($xml->recordings->recording as $recording) {
289
                $recordingarrayvalue = bigbluebuttonbn_get_recording_array_value($recording);
290
                $recordings[$recordingarrayvalue['recordID']] = $recordingarrayvalue;
291
            }
292
            uasort($recordings, 'bigbluebuttonbn_recording_build_sorter');
293
        }
294
    }
295
296
    return $recordings;
297
}
298
299
function bigbluebuttonbn_get_recordings_array_filter($recordingidsarray, &$recordings) {
300
301
    foreach ($recordings as $key => $recording) {
302
        if (!in_array($recording['recordID'], $recordingidsarray)) {
303
            unset($recordings[$key]);
304
        }
305
    }
306
307
    return $recordings;
308
}
309
310
/**
311
 * Helper function to retrieve imported recordings from the Moodle database.
312
 * The references are stored as events in bigbluebuttonbn_logs.
313
 *
314
 * @param string $courseid
315
 * @param string $bigbluebuttonbnid
316
 * @param bool   $subset
317
 *
318
 * @return associative array with imported recordings indexed by recordID, each recording is a non sequential associative
319
 * array that corresponds to the actual recording in BBB
320
 */
321
function bigbluebuttonbn_get_recordings_imported_array($courseid, $bigbluebuttonbnid = null, $subset = true) {
322
    global $DB;
323
324
    $select = "courseid = '{$courseid}' AND bigbluebuttonbnid <> '{$bigbluebuttonbnid}' AND log = '" .
325
        BIGBLUEBUTTONBN_LOG_EVENT_IMPORT . "'";
326
    if ($bigbluebuttonbnid === null) {
327
        $select = "courseid = '{$courseid}' AND log = '" . BIGBLUEBUTTONBN_LOG_EVENT_IMPORT . "'";
328
    } else if ($subset) {
329
        $select = "bigbluebuttonbnid = '{$bigbluebuttonbnid}' AND log = '" . BIGBLUEBUTTONBN_LOG_EVENT_IMPORT . "'";
330
    }
331
    $recordsimported = $DB->get_records_select('bigbluebuttonbn_logs', $select);
332
333
    $recordsimportedarray = array();
334
    foreach ($recordsimported as $recordimported) {
335
        $meta = json_decode($recordimported->meta, true);
336
        $recording = $meta['recording'];
337
        // Override imported flag with actual ID.
338
        $recording['imported'] = $recordimported->id;
339
        if (isset($recordimported->protected)) {
340
            $recording['protected'] = (string) $recordimported->protected;
341
        }
342
        $recordsimportedarray[$recording['recordID']] = $recording;
343
    }
344
345
    return $recordsimportedarray;
346
}
347
348
function bigbluebuttonbn_get_default_config_xml() {
349
    $xml = bigbluebuttonbn_wrap_xml_load_file(
350
        \mod_bigbluebuttonbn\locallib\bigbluebutton::action_url('getDefaultConfigXML')
351
      );
352
353
    return $xml;
354
}
355
356
function bigbluebuttonbn_get_default_config_xml_array() {
357
    $defaultconfigxml = bigbluebuttonbn_getDefaultConfigXML();
358
359
    return (array) $defaultconfigxml;
360
}
361
362
function bigbluebuttonbn_get_recording_array_value($recording) {
363
    // Add formats.
364
    $playbackarray = array();
365
    foreach ($recording->playback->format as $format) {
366
        $playbackarray[(string) $format->type] = array('type' => (string) $format->type,
367
            'url' => (string) $format->url, 'length' => (string) $format->length);
368
        // Add preview per format when existing.
369
        if ($format->preview) {
370
            $imagesarray = array();
371
            foreach ($format->preview->images->image as $image) {
372
                $imagearray = array('url' => (string) $image);
373
                foreach ($image->attributes() as $attkey => $attvalue) {
374
                    $imagearray[$attkey] = (string) $attvalue;
375
                }
376
                array_push($imagesarray, $imagearray);
377
            }
378
            $playbackarray[(string) $format->type]['preview'] = $imagesarray;
379
        }
380
    }
381
382
    // Add the metadata to the recordings array.
383
    $metadataarray = bigbluebuttonbn_get_recording_array_meta(get_object_vars($recording->metadata));
384
    $recordingarray = array('recordID' => (string) $recording->recordID,
385
        'meetingID' => (string) $recording->meetingID, 'meetingName' => (string) $recording->name,
386
        'published' => (string) $recording->published, 'startTime' => (string) $recording->startTime,
387
        'endTime' => (string) $recording->endTime, 'playbacks' => $playbackarray);
388
    if (isset($recording->protected)) {
389
        $recordingarray['protected'] = (string) $recording->protected;
390
    }
391
    return $recordingarray + $metadataarray;
392
}
393
394
function bigbluebuttonbn_get_recording_array_meta($metadata) {
395
    $metadataarray = array();
396
    foreach ($metadata as $key => $value) {
397
        if (is_object($value)) {
398
            $value = '';
399
        }
400
        $metadataarray['meta_'.$key] = $value;
401
    }
402
    return $metadataarray;
403
}
404
405
function bigbluebuttonbn_recording_build_sorter($a, $b) {
406
    if ($a['startTime'] < $b['startTime']) {
407
        return -1;
408
    }
409
    if ($a['startTime'] == $b['startTime']) {
410
        return 0;
411
    }
412
    return 1;
413
}
414
415
/**
416
 * @param string $recordids
417
 */
418 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...
419
    $ids = explode(',', $recordids);
420
    foreach ($ids as $id) {
421
        $xml = bigbluebuttonbn_wrap_xml_load_file(
422
            \mod_bigbluebuttonbn\locallib\bigbluebutton::action_url('deleteRecordings', ['recordID' => $id])
423
          );
424
        if ($xml && $xml->returncode != 'SUCCESS') {
425
            return false;
426
        }
427
    }
428
429
    return true;
430
}
431
432
/**
433
 * @param string $recordids
434
 * @param string $publish
435
 */
436 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...
437
    $ids = explode(',', $recordids);
438
    foreach ($ids as $id) {
439
        $xml = bigbluebuttonbn_wrap_xml_load_file(
440
            \mod_bigbluebuttonbn\locallib\bigbluebutton::action_url('publishRecordings', ['recordID' => $id, 'publish' => $publish])
441
          );
442
        if ($xml && $xml->returncode != 'SUCCESS') {
443
            return false;
444
        }
445
    }
446
447
    return true;
448
}
449
450
/**
451
 * @param string $recordids
452
 * @param array $params ['key'=>param_key, 'value']
453
 */
454 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...
455
    $ids = explode(',', $recordids);
456
    foreach ($ids as $id) {
457
        $xml = bigbluebuttonbn_wrap_xml_load_file(
458
            \mod_bigbluebuttonbn\locallib\bigbluebutton::action_url('updateRecordings', ['recordID' => $id] + (array) $params)
459
          );
460
        if ($xml && $xml->returncode != 'SUCCESS') {
461
            return false;
462
        }
463
    }
464
465
    return true;
466
}
467
468
/**
469
 * @param string $meetingid
470
 * @param string $modpw
471
 */
472
function bigbluebuttonbn_end_meeting($meetingid, $modpw) {
473
    $xml = bigbluebuttonbn_wrap_xml_load_file(
474
        \mod_bigbluebuttonbn\locallib\bigbluebutton::action_url('end', ['meetingID' => $meetingid, 'password' => $modpw])
475
      );
476
477 View Code Duplication
    if ($xml) {
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...
478
        // If the xml packet returned failure it displays the message to the user.
479
        return array('returncode' => $xml->returncode, 'message' => $xml->message, 'messageKey' => $xml->messageKey);
480
    }
481
482
    // If the server is unreachable, then prompts the user of the necessary action.
483
    return null;
484
}
485
486
/**
487
 * @param string $meetingid
488
 */
489
function bigbluebuttonbn_is_meeting_running($meetingid) {
490
    $xml = bigbluebuttonbn_wrap_xml_load_file(
491
        \mod_bigbluebuttonbn\locallib\bigbluebutton::action_url('isMeetingRunning', ['meetingID' => $meetingid])
492
      );
493
494
    if ($xml && $xml->returncode == 'SUCCESS') {
495
        return ($xml->running == 'true');
496
    }
497
498
    return false;
499
}
500
501
function bigbluebuttonbn_get_server_version() {
502
    $xml = bigbluebuttonbn_wrap_xml_load_file(
503
        \mod_bigbluebuttonbn\locallib\bigbluebutton::action_url()
504
      );
505
506
    if ($xml && $xml->returncode == 'SUCCESS') {
507
        return $xml->version;
508
    }
509
510
    return null;
511
}
512
513
/**
514
 * @param string $url
515
 * @param string $data
516
 */
517
function bigbluebuttonbn_wrap_xml_load_file($url, $method = BIGBLUEBUTTONBN_METHOD_GET,
518
    $data = null, $contenttype = 'text/xml') {
519
520
    if (extension_loaded('curl')) {
521
        $response = bigbluebuttonbn_wrap_xml_load_file_curl_request($url, $method, $data, $contenttype);
522
523
        if (!$response) {
524
            debugging('No response on wrap_simplexml_load_file', DEBUG_DEVELOPER);
525
            return null;
526
        }
527
528
        $previous = libxml_use_internal_errors(true);
529
        try {
530
            $xml = simplexml_load_string($response, 'SimpleXMLElement', LIBXML_NOCDATA | LIBXML_NOBLANKS);
531
532
            return $xml;
533
        } catch (Exception $e) {
534
            libxml_use_internal_errors($previous);
535
            $error = 'Caught exception: '.$e->getMessage();
536
            debugging($error, DEBUG_DEVELOPER);
537
            return null;
538
        }
539
    }
540
541
    // Alternative request non CURL based.
542
    $previous = libxml_use_internal_errors(true);
543
    try {
544
        $response = simplexml_load_file($url, 'SimpleXMLElement', LIBXML_NOCDATA | LIBXML_NOBLANKS);
545
        return $response;
546
    } catch (Exception $e) {
547
        $error = 'Caught exception: '.$e->getMessage();
548
        debugging($error, DEBUG_DEVELOPER);
549
        libxml_use_internal_errors($previous);
550
        return null;
551
    }
552
}
553
554
function bigbluebuttonbn_wrap_xml_load_file_curl_request($url, $method = BIGBLUEBUTTONBN_METHOD_GET,
555
    $data = null, $contenttype = 'text/xml') {
556
    $c = new curl();
557
    $c->setopt(array('SSL_VERIFYPEER' => true));
558
    if ($method == BIGBLUEBUTTONBN_METHOD_POST) {
559
        if (is_null($data) || is_array($data)) {
560
            return $c->post($url);
561
        }
562
563
        $options = array();
564
        $options['CURLOPT_HTTPHEADER'] = array(
565
                 'Content-Type: '.$contenttype,
566
                 'Content-Length: '.strlen($data),
567
                 'Content-Language: en-US',
568
               );
569
570
        return $c->post($url, $data, $options);
571
    }
572
573
    return $c->get($url);
574
}
575
576
function bigbluebuttonbn_get_user_roles($context, $userid) {
577
    global $DB;
578
579
    $userroles = get_user_roles($context, $userid);
580
    if ($userroles) {
581
        $where = '';
582
        foreach ($userroles as $value) {
583
            $where .= (empty($where) ? ' WHERE' : ' AND').' id='.$value->roleid;
584
        }
585
        $userroles = $DB->get_records_sql('SELECT * FROM {role}'.$where);
586
    }
587
588
    return $userroles;
589
}
590
591
function bigbluebuttonbn_get_guest_role() {
592
    $guestrole = get_guest_role();
593
594
    return array($guestrole->id => $guestrole);
595
}
596
597
function bigbluebuttonbn_get_users(context $context = null) {
598
    $users = (array) get_enrolled_users($context, '', 0, 'u.*', null, 0, 0, true);
599
    foreach ($users as $key => $value) {
600
        $users[$key] = fullname($value);
601
    }
602
    return $users;
603
}
604
605
function bigbluebuttonbn_get_users_select(context $context = null) {
606
    $users = (array) get_enrolled_users($context, '', 0, 'u.*', null, 0, 0, true);
607
    foreach ($users as $key => $value) {
608
        $users[$key] = array('id' => $value->id, 'name' => fullname($value));
609
    }
610
    return $users;
611
}
612
613
function bigbluebuttonbn_get_roles(context $context = null) {
614
    $roles = (array) role_get_names($context);
615
    foreach ($roles as $key => $value) {
616
        $roles[$key] = $value->localname;
617
    }
618
    return $roles;
619
}
620
621
function bigbluebuttonbn_get_roles_select(context $context = null) {
622
    $roles = (array) role_get_names($context);
623
    foreach ($roles as $key => $value) {
624
        $roles[$key] = array('id' => $value->id, 'name' => $value->localname);
625
    }
626
    return $roles;
627
}
628
629
function bigbluebuttonbn_get_role($id) {
630
    $roles = (array) role_get_names();
631
    if (is_numeric($id)) {
632
        return (object)$roles[$id];
633
    }
634
    foreach ($roles as $role) {
635
        if ($role->shortname == $id) {
636
            return $role;
637
        }
638
    }
639
}
640
641
function bigbluebuttonbn_role_unknown() {
642
    return array(
643
              "id" => "0",
644
              "name" => "",
645
              "shortname" => "unknown",
646
              "description" => "",
647
              "sortorder" => "0",
648
              "archetype" => "guest",
649
              "localname" => "Unknown"
650
            );
651
}
652
653
function bigbluebuttonbn_get_participant_data($context) {
654
    $data = array(
655
        'all' => array(
656
            'name' => get_string('mod_form_field_participant_list_type_all', 'bigbluebuttonbn'),
657
            'children' => []
658
          )
659
      );
660
    $data['role'] = array(
661
        'name' => get_string('mod_form_field_participant_list_type_role', 'bigbluebuttonbn'),
662
        'children' => bigbluebuttonbn_get_roles_select($context)
663
      );
664
    $data['user'] = array(
665
        'name' => get_string('mod_form_field_participant_list_type_user', 'bigbluebuttonbn'),
666
        'children' => bigbluebuttonbn_get_users_select($context)
667
      );
668
    return $data;
669
}
670
671
function bigbluebuttonbn_get_participant_list($bigbluebuttonbn, $context) {
672
    if ($bigbluebuttonbn == null) {
673
        return bigbluebuttonbn_get_participant_list_default($context);
674
    }
675
    return bigbluebuttonbn_get_participant_rules_encoded($bigbluebuttonbn);
676
}
677
678
function bigbluebuttonbn_get_participant_rules_encoded($bigbluebuttonbn) {
679
    $rules = json_decode($bigbluebuttonbn->participants, true);
680
    if (!is_array($rules)) {
681
        return array();
682
    }
683
    foreach ($rules as $key => $rule) {
684
        if ( $rule['selectiontype'] !== 'role' || is_numeric($rule['selectionid']) ) {
685
            continue;
686
        }
687
        $role = bigbluebuttonbn_get_role($rule['selectionid']);
688
        if ( $role == null ) {
689
            unset($rules[$key]);
690
            continue;
691
        }
692
        $rule['selectionid'] = $role->id;
693
        $rules[$key] = $rule;
694
    }
695
    return $rules;
696
}
697
698
function bigbluebuttonbn_get_participant_list_default($context) {
699
    global $USER;
700
    $participantlistarray = array();
701
    $participantlistarray[] = array(
702
        'selectiontype' => 'all',
703
        'selectionid' => 'all',
704
        'role' => BIGBLUEBUTTONBN_ROLE_VIEWER);
705
    $moderatordefaults = explode(',', \mod_bigbluebuttonbn\locallib\config::get('moderator_default'));
706
    foreach ($moderatordefaults as $moderatordefault) {
707
        if ($moderatordefault == 'owner') {
708
            if (is_enrolled($context, $USER->id)) {
709
                $participantlistarray[] = array(
710
                    'selectiontype' => 'user',
711
                    'selectionid' => $USER->id,
712
                    'role' => BIGBLUEBUTTONBN_ROLE_MODERATOR);
713
            }
714
            continue;
715
        }
716
        $participantlistarray[] = array(
717
              'selectiontype' => 'role',
718
              'selectionid' => $moderatordefault,
719
              'role' => BIGBLUEBUTTONBN_ROLE_MODERATOR);
720
    }
721
    return $participantlistarray;
722
}
723
724
function bigbluebuttonbn_get_participant_selection_data() {
725
    return [
726
        'type_options' => [
727
            'all' => get_string('mod_form_field_participant_list_type_all', 'bigbluebuttonbn'),
728
            'role' => get_string('mod_form_field_participant_list_type_role', 'bigbluebuttonbn'),
729
            'user' => get_string('mod_form_field_participant_list_type_user', 'bigbluebuttonbn'),
730
          ],
731
        'type_selected' => 'all',
732
        'options' => ['all' => '---------------'],
733
        'selected' => 'all',
734
      ];
735
}
736
737
function bigbluebuttonbn_is_moderator($context, $participants, $userid = null, $userroles = null) {
738
    global $USER;
739
    if (empty($participants)) {
740
        // The room that is being used comes from a previous version.
741
        return has_capability('mod/bigbluebuttonbn:moderate', $context);
742
    }
743
    $participantlist = json_decode($participants);
744
    if (!is_array($participantlist)) {
745
        return false;
746
    }
747
    if (empty($userid)) {
748
        $userid = $USER->id;
749
    }
750
    if (empty($userroles)) {
751
        $userroles = get_user_roles($context, $userid, true);
752
    }
753
    return bigbluebuttonbn_is_moderator_validator($participantlist, $userid , $userroles);
754
}
755
756
function bigbluebuttonbn_is_moderator_validator($participantlist, $userid , $userroles) {
757
    // Iterate participant rules.
758
    foreach ($participantlist as $participant) {
759
        if (bigbluebuttonbn_is_moderator_validate_rule($participant, $userid, $userroles)) {
760
            return true;
761
        }
762
    }
763
    return false;
764
}
765
766
function bigbluebuttonbn_is_moderator_validate_rule($participant, $userid, $userroles) {
767
    if ($participant->role == BIGBLUEBUTTONBN_ROLE_VIEWER) {
768
        return false;
769
    }
770
    // Looks for all configuration.
771
    if ($participant->selectiontype == 'all') {
772
        return true;
773
    }
774
    // Looks for users.
775
    if ($participant->selectiontype == 'user' && $participant->selectionid == $userid) {
776
        return true;
777
    }
778
    // Looks for roles.
779
    $role = bigbluebuttonbn_get_role($participant->selectionid);
780
    if (array_key_exists($role->id, $userroles)) {
781
        return true;
782
    }
783
    return false;
784
}
785
786
function bigbluebuttonbn_get_error_key($messagekey, $defaultkey = null) {
787
    if ($messagekey == 'checksumError') {
788
        return 'index_error_checksum';
789
    }
790
    if ($messagekey == 'maxConcurrent') {
791
        return 'view_error_max_concurrent';
792
    }
793
    return $defaultkey;
794
}
795
796
function bigbluebuttonbn_voicebridge_unique($voicebridge, $id = null) {
797
    global $DB;
798
    $isunique = true;
799
    if ($voicebridge != 0) {
800
        $table = 'bigbluebuttonbn';
801
        $select = 'voicebridge = '.$voicebridge;
802
        if ($id) {
803
            $select .= ' AND id <> '.$id;
804
        }
805
        if ($DB->get_records_select($table, $select)) {
806
            $isunique = false;
807
        }
808
    }
809
    return $isunique;
810
}
811
812
function bigbluebuttonbn_get_duration($closingtime) {
813
    $duration = 0;
814
    $now = time();
815
    if ($closingtime > 0 && $now < $closingtime) {
816
        $duration = ceil(($closingtime - $now) / 60);
817
        $compensationtime = intval((int)\mod_bigbluebuttonbn\locallib\config::get('scheduled_duration_compensation'));
818
        $duration = intval($duration) + $compensationtime;
819
    }
820
    return $duration;
821
}
822
823
function bigbluebuttonbn_get_presentation_array($context, $presentation, $id = null) {
824
    $pname = null;
825
    $purl = null;
826
    $picon = null;
827
    $pmimetypedescrip = null;
828
    if (!empty($presentation)) {
829
        $fs = get_file_storage();
830
        $files = $fs->get_area_files($context->id, 'mod_bigbluebuttonbn', 'presentation', 0,
831
            'itemid, filepath, filename', false);
832
        if (count($files) >= 1) {
833
            $file = reset($files);
834
            unset($files);
835
            $pname = $file->get_filename();
836
            $picon = file_file_icon($file, 24);
837
            $pmimetypedescrip = get_mimetype_description($file);
838
            $pnoncevalue = null;
839
            if (!is_null($id)) {
840
                // Create the nonce component for granting a temporary public access.
841
                $cache = cache::make_from_params(cache_store::MODE_APPLICATION, 'mod_bigbluebuttonbn',
842
                    'presentation_cache');
843
                $pnoncekey = sha1($id);
844
                /* The item id was adapted for granting public access to the presentation once in order
845
                 * to allow BigBlueButton to gather the file. */
846
                $pnoncevalue = bigbluebuttonbn_generate_nonce();
847
                $cache->set($pnoncekey, array('value' => $pnoncevalue, 'counter' => 0));
848
            }
849
            $url = moodle_url::make_pluginfile_url($file->get_contextid(), $file->get_component(),
850
                $file->get_filearea(), $pnoncevalue, $file->get_filepath(), $file->get_filename());
851
852
            $purl = $url->out(false);
853
        }
854
    }
855
    $parray = array('url' => $purl, 'name' => $pname,
856
                               'icon' => $picon,
857
                               'mimetype_description' => $pmimetypedescrip);
858
    return $parray;
859
}
860
861
function bigbluebuttonbn_generate_nonce() {
862
    $mt = microtime();
863
    $rand = mt_rand();
864
    return md5($mt.$rand);
865
}
866
867
function bigbluebuttonbn_random_password($length = 8) {
868
    $chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*()_-=+;:,.?';
869
    $password = substr(str_shuffle($chars), 0, $length);
870
    return $password;
871
}
872
873
function bigbluebuttonbn_events() {
874
    return array(
875
        (string) BIGBLUEBUTTON_EVENT_ACTIVITY_VIEWED,
876
        (string) BIGBLUEBUTTON_EVENT_ACTIVITY_MANAGEMENT_VIEWED,
877
        (string) BIGBLUEBUTTON_EVENT_LIVE_SESSION,
878
        (string) BIGBLUEBUTTON_EVENT_MEETING_CREATED,
879
        (string) BIGBLUEBUTTON_EVENT_MEETING_ENDED,
880
        (string) BIGBLUEBUTTON_EVENT_MEETING_JOINED,
881
        (string) BIGBLUEBUTTON_EVENT_MEETING_LEFT,
882
        (string) BIGBLUEBUTTON_EVENT_RECORDING_DELETED,
883
        (string) BIGBLUEBUTTON_EVENT_RECORDING_IMPORTED,
884
        (string) BIGBLUEBUTTON_EVENT_RECORDING_PROTECTED,
885
        (string) BIGBLUEBUTTON_EVENT_RECORDING_PUBLISHED,
886
        (string) BIGBLUEBUTTON_EVENT_RECORDING_UNPROTECTED,
887
        (string) BIGBLUEBUTTON_EVENT_RECORDING_UNPUBLISHED,
888
        (string) BIGBLUEBUTTON_EVENT_RECORDING_EDITED,
889
        (string) BIGBLUEBUTTON_EVENT_RECORDING_VIEWED
890
    );
891
}
892
893
function bigbluebuttonbn_events_action() {
894
    return array(
895
        'view' => (string) BIGBLUEBUTTON_EVENT_ACTIVITY_VIEWED,
896
        'view_management' => (string) BIGBLUEBUTTON_EVENT_ACTIVITY_MANAGEMENT_VIEWED,
897
        'live_action' => (string) BIGBLUEBUTTON_EVENT_LIVE_SESSION,
898
        'meeting_create' => (string) BIGBLUEBUTTON_EVENT_MEETING_CREATED,
899
        'meeting_end' => (string) BIGBLUEBUTTON_EVENT_MEETING_ENDED,
900
        'meeting_join' => (string) BIGBLUEBUTTON_EVENT_MEETING_JOINED,
901
        'meeting_left' => (string) BIGBLUEBUTTON_EVENT_MEETING_LEFT,
902
        'recording_delete' => (string) BIGBLUEBUTTON_EVENT_RECORDING_DELETED,
903
        'recording_import' => (string) BIGBLUEBUTTON_EVENT_RECORDING_IMPORTED,
904
        'recording_protect' => (string) BIGBLUEBUTTON_EVENT_RECORDING_PROTECTED,
905
        'recording_publish' => (string) BIGBLUEBUTTON_EVENT_RECORDING_PUBLISHED,
906
        'recording_unprotect' => (string) BIGBLUEBUTTON_EVENT_RECORDING_UNPROTECTED,
907
        'recording_unpublish' => (string) BIGBLUEBUTTON_EVENT_RECORDING_UNPUBLISHED,
908
        'recording_edit' => (string) BIGBLUEBUTTON_EVENT_RECORDING_EDITED,
909
        'recording_play' => (string) BIGBLUEBUTTON_EVENT_RECORDING_VIEWED
910
    );
911
}
912
913
function bigbluebuttonbn_event_log_standard($eventtype, $bigbluebuttonbn, $cm, $options = []) {
914
    $events = bigbluebuttonbn_events();
915
    if (!in_array($eventtype, $events)) {
916
        // No log will be created.
917
        return;
918
    }
919
    $context = context_module::instance($cm->id);
920
    $eventproperties = array('context' => $context, 'objectid' => $bigbluebuttonbn->id);
921
    if (array_key_exists('timecreated', $options)) {
922
        $eventproperties['timecreated'] = $options['timecreated'];
923
    }
924
    if (array_key_exists('userid', $options)) {
925
        $eventproperties['userid'] = $options['userid'];
926
    }
927
    if (array_key_exists('other', $options)) {
928
        $eventproperties['other'] = $options['other'];
929
    }
930
    $event = call_user_func_array('\mod_bigbluebuttonbn\event\bigbluebuttonbn_'.$eventtype.'::create',
931
      array($eventproperties));
932
    $event->trigger();
933
}
934
935
function bigbluebuttonbn_event_log($eventtype, $bigbluebuttonbn, $cm, $options = []) {
936
    bigbluebuttonbn_event_log_standard($eventtype, $bigbluebuttonbn, $cm, $options);
937
}
938
939
function bigbluebuttonbn_live_session_event_log($event, $bigbluebuttonbn, $cm) {
940
    bigbluebuttonbn_event_log_standard(BIGBLUEBUTTON_EVENT_LIVE_SESSION, $bigbluebuttonbn, $cm,
941
        ['timecreated' => $event->timestamp, 'userid' => $event->user, 'other' => $event->event]);
942
}
943
944
/**
945
 * @param string $meetingid
946
 * @param bool $ismoderator
947
 */
948
function bigbluebuttonbn_participant_joined($meetingid, $ismoderator) {
949
    $cache = cache::make_from_params(cache_store::MODE_APPLICATION, 'mod_bigbluebuttonbn', 'meetings_cache');
950
    $result = $cache->get($meetingid);
951
    $meetinginfo = json_decode($result['meeting_info']);
952
    $meetinginfo->participantCount += 1;
953
    if ($ismoderator) {
954
        $meetinginfo->moderatorCount += 1;
955
    }
956
    $cache->set($meetingid, array('creation_time' => $result['creation_time'],
957
        'meeting_info' => json_encode($meetinginfo)));
958
}
959
960
/**
961
 * @param string $meetingid
962
 * @param boolean $forced
963
 */
964
function bigbluebuttonbn_get_meeting_info($meetingid, $forced = false) {
965
    $cachettl = (int)\mod_bigbluebuttonbn\locallib\config::get('waitformoderator_cache_ttl');
966
    $cache = cache::make_from_params(cache_store::MODE_APPLICATION, 'mod_bigbluebuttonbn', 'meetings_cache');
967
    $result = $cache->get($meetingid);
968
    $now = time();
969
    if (!$forced && isset($result) && $now < ($result['creation_time'] + $cachettl)) {
970
        // Use the value in the cache.
971
        return (array) json_decode($result['meeting_info']);
972
    }
973
    // Ping again and refresh the cache.
974
    $meetinginfo = (array) bigbluebuttonbn_wrap_xml_load_file(
975
        \mod_bigbluebuttonbn\locallib\bigbluebutton::action_url('getMeetingInfo', ['meetingID' => $meetingid])
976
      );
977
    $cache->set($meetingid, array('creation_time' => time(), 'meeting_info' => json_encode($meetinginfo)));
978
    return $meetinginfo;
979
}
980
981
/**
982
 * @param string $id
983
 * @param boolean $publish
984
 */
985 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...
986
    global $DB;
987
    // Locate the record to be updated.
988
    $record = $DB->get_record('bigbluebuttonbn_logs', array('id' => $id));
989
    $meta = json_decode($record->meta, true);
990
    // Prepare data for the update.
991
    $meta['recording']['published'] = ($publish) ? 'true' : 'false';
992
    $record->meta = json_encode($meta);
993
    // Proceed with the update.
994
    $DB->update_record('bigbluebuttonbn_logs', $record);
995
    return true;
996
}
997
998
/**
999
 * @param string $id
1000
 */
1001
function bigbluebuttonbn_delete_recording_imported($id) {
1002
    global $DB;
1003
    // Execute delete.
1004
    $DB->delete_records('bigbluebuttonbn_logs', array('id' => $id));
1005
    return true;
1006
}
1007
1008
/**
1009
 * @param string $id
1010
 * @param array $params ['key'=>param_key, 'value']
1011
 */
1012
function bigbluebuttonbn_update_recording_imported($id, $params) {
1013
    global $DB;
1014
    // Locate the record to be updated.
1015
    $record = $DB->get_record('bigbluebuttonbn_logs', array('id' => $id));
1016
    $meta = json_decode($record->meta, true);
1017
    // Prepare data for the update.
1018
    $meta['recording'] = $params + $meta['recording'];
1019
    $record->meta = json_encode($meta);
1020
    // Proceed with the update.
1021
    if (!$DB->update_record('bigbluebuttonbn_logs', $record)) {
1022
        return false;
1023
    }
1024
    return true;
1025
}
1026
1027
/**
1028
 * @param string $id
1029
 * @param boolean $protect
1030
 */
1031 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...
1032
    global $DB;
1033
    // Locate the record to be updated.
1034
    $record = $DB->get_record('bigbluebuttonbn_logs', array('id' => $id));
1035
    $meta = json_decode($record->meta, true);
1036
    // Prepare data for the update.
1037
    $meta['recording']['protected'] = ($protect) ? 'true' : 'false';
1038
    $record->meta = json_encode($meta);
1039
    // Proceed with the update.
1040
    $DB->update_record('bigbluebuttonbn_logs', $record);
1041
    return true;
1042
}
1043
1044
/**
1045
 * @param string $meetingid
1046
 * @param string $configxml
1047
 */
1048
function bigbluebuttonbn_set_config_xml_params($meetingid, $configxml) {
1049
    $params = 'configXML='.urlencode($configxml).'&meetingID='.urlencode($meetingid);
1050
    $configxmlparams = $params.'&checksum='.sha1('setConfigXML'.$params.\mod_bigbluebuttonbn\locallib\config::get('shared_secret'));
1051
    return $configxmlparams;
1052
}
1053
1054
/**
1055
 * @param string $meetingid
1056
 * @param string $configxml
1057
 */
1058
function bigbluebuttonbn_set_config_xml($meetingid, $configxml) {
1059
    $urldefaultconfig = \mod_bigbluebuttonbn\locallib\config::get('server_url').'api/setConfigXML?';
1060
    $configxmlparams = bigbluebuttonbn_set_config_xml_params($meetingid, $configxml);
1061
    $xml = bigbluebuttonbn_wrap_xml_load_file($urldefaultconfig, BIGBLUEBUTTONBN_METHOD_POST,
1062
        $configxmlparams, 'application/x-www-form-urlencoded');
1063
    return $xml;
1064
}
1065
1066
/**
1067
 * @param string $meetingid
1068
 * @param string $configxml
1069
 */
1070
function bigbluebuttonbn_set_config_xml_array($meetingid, $configxml) {
1071
    $configxml = bigbluebuttonbn_setConfigXML($meetingid, $configxml);
1072
    $configxmlarray = (array) $configxml;
1073
    if ($configxmlarray['returncode'] != 'SUCCESS') {
1074
        debugging('BigBlueButton was not able to set the custom config.xml file', DEBUG_DEVELOPER);
1075
        return '';
1076
    }
1077
    return $configxmlarray['configToken'];
1078
}
1079
1080
function bigbluebuttonbn_get_recording_data_row($bbbsession, $recording, $tools = ['protect', 'publish', 'delete']) {
1081
    if (!$bbbsession['managerecordings'] && $recording['published'] != 'true') {
1082
        return;
1083
    }
1084
    $editable = bigbluebuttonbn_get_recording_data_row_editable($bbbsession);
1085
    $row = new stdClass();
1086
    // Set recording_types.
1087
    $row->recording = bigbluebuttonbn_get_recording_data_row_types($recording, $bbbsession['bigbluebuttonbn']->id);
1088
    // Set activity name.
1089
    $row->activity = bigbluebuttonbn_get_recording_data_row_meta_activity($recording, $editable);
1090
    // Set activity description.
1091
    $row->description = bigbluebuttonbn_get_recording_data_row_meta_description($recording, $editable);
1092
    // Set recording_preview.
1093
    $row->preview = bigbluebuttonbn_get_recording_data_row_preview($recording);
1094
    // Set date.
1095
    $row->date = bigbluebuttonbn_get_recording_data_row_date($recording);
1096
    // Set formatted date.
1097
    $row->date_formatted = bigbluebuttonbn_get_recording_data_row_date_formatted($row->date);
1098
    // Set formatted duration.
1099
    $row->duration_formatted = $row->duration = bigbluebuttonbn_get_recording_data_row_duration($recording);
1100
    // Set actionbar, if user is allowed to manage recordings.
1101
    if ($bbbsession['managerecordings']) {
1102
        $row->actionbar = bigbluebuttonbn_get_recording_data_row_actionbar($recording, $tools);
1103
    }
1104
    return $row;
1105
}
1106
1107
function bigbluebuttonbn_get_recording_data_row_editable($bbbsession) {
1108
    return ($bbbsession['managerecordings'] && (double)$bbbsession['serverversion'] >= 1.0);
1109
}
1110
1111
function bigbluebuttonbn_get_recording_data_row_date($recording) {
1112
    if (!isset($recording['startTime'])) {
1113
        return 0;
1114
    }
1115
    return floatval($recording['startTime']);
1116
}
1117
1118
function bigbluebuttonbn_get_recording_data_row_date_formatted($starttime) {
1119
    global $USER;
1120
    $starttime = $starttime - ($starttime % 1000);
1121
    // Set formatted date.
1122
    $dateformat = get_string('strftimerecentfull', 'langconfig').' %Z';
1123
    return userdate($starttime / 1000, $dateformat, usertimezone($USER->timezone));
1124
}
1125
1126
function bigbluebuttonbn_get_recording_data_row_duration($recording) {
1127
    $firstplayback = array_values($recording['playbacks'])[0];
1128
    $length = 0;
1129
    if (isset($firstplayback['length'])) {
1130
        $length = $firstplayback['length'];
1131
    }
1132
    return intval($length);
1133
}
1134
1135
function bigbluebuttonbn_get_recording_data_row_actionbar($recording, $tools) {
1136
    $actionbar = '';
1137
    foreach ($tools as $tool) {
1138
        if ( $tool == 'protect' && !isset($recording['protected']) ) {
1139
            continue;
1140
        }
1141
        $buttonpayload = bigbluebuttonbn_get_recording_data_row_actionbar_payload($recording, $tool);
1142
        $actionbar .= bigbluebuttonbn_actionbar_render_button($recording, $buttonpayload);
1143
    }
1144
    $head = html_writer::start_tag('div', array(
1145
        'id' => 'recording-actionbar-' . $recording['recordID'],
1146
        'data-recordingid' => $recording['recordID'],
1147
        'data-meetingid' => $recording['meetingID']));
1148
    $tail = html_writer::end_tag('div');
1149
    return $head . $actionbar . $tail;
1150
}
1151
1152
function bigbluebuttonbn_get_recording_data_row_actionbar_payload($recording, $tool) {
1153
    if ($tool == 'protect') {
1154
        return bigbluebuttonbn_get_recording_data_row_action_protect($recording['protected']);
1155
    }
1156
    if ($tool == 'publish') {
1157
        return bigbluebuttonbn_get_recording_data_row_action_publish($recording['published']);
1158
    }
1159
    return array('action' => $tool, 'tag' => $tool);
1160
}
1161
1162
function bigbluebuttonbn_get_recording_data_row_action_protect($protected) {
1163
    if ($protected == 'true') {
1164
        return array('action' => 'unprotect', 'tag' => 'lock');
1165
    }
1166
    return array('action' => 'protect', 'tag' => 'unlock');
1167
}
1168
1169
function bigbluebuttonbn_get_recording_data_row_action_publish($published) {
1170
    if ($published == 'true') {
1171
        return array('action' => 'unpublish', 'tag' => 'hide');
1172
    }
1173
    return array('action' => 'publish', 'tag' => 'show');
1174
}
1175
1176
function bigbluebuttonbn_get_recording_data_row_preview($recording) {
1177
    $visibility = '';
1178
    if ($recording['published'] === 'false') {
1179
        $visibility = 'hidden ';
1180
    }
1181
    $recordingpreview = html_writer::start_tag('div',
1182
        array('id' => 'preview-'.$recording['recordID'], $visibility => $visibility));
1183
    foreach ($recording['playbacks'] as $playback) {
1184
        if (isset($playback['preview'])) {
1185
            foreach ($playback['preview'] as $image) {
1186
                $recordingpreview .= html_writer::empty_tag('img',
1187
                    array('src' => $image['url'] . '?' . time(), 'class' => 'thumbnail'));
1188
            }
1189
            $recordingpreview .= html_writer::empty_tag('br');
1190
            $recordingpreview .= html_writer::tag('div',
1191
                get_string('view_recording_preview_help', 'bigbluebuttonbn'), array('class' => 'text-muted small'));
1192
            break;
1193
        }
1194
    }
1195
    $recordingpreview .= html_writer::end_tag('div');
1196
    return $recordingpreview;
1197
}
1198
1199
function bigbluebuttonbn_get_recording_data_row_types($recording, $bigbluebuttonbnid) {
1200
    $dataimported = 'false';
1201
    $title = '';
1202
    if (isset($recording['imported'])) {
1203
        $dataimported = 'true';
1204
        $title = get_string('view_recording_link_warning', 'bigbluebuttonbn');
1205
    }
1206
    $visibility = '';
1207
    if ($recording['published'] === 'false') {
1208
        $visibility = 'hidden ';
1209
    }
1210
    $id = 'playbacks-'.$recording['recordID'];
1211
    $recordingtypes = html_writer::start_tag('div', array('id' => $id, 'data-imported' => $dataimported,
1212
          'data-meetingid' => $recording['meetingID'], 'data-recordingid' => $recording['recordID'],
1213
          'title' => $title, $visibility => $visibility));
1214
    foreach ($recording['playbacks'] as $playback) {
1215
        $recordingtypes .= bigbluebuttonbn_get_recording_data_row_type($recording, $bigbluebuttonbnid,
1216
            $playback).'&#32;';
1217
    }
1218
    $recordingtypes .= html_writer::end_tag('div');
1219
    return $recordingtypes;
1220
}
1221
1222
function bigbluebuttonbn_get_recording_data_row_type($recording, $bigbluebuttonbnid, $playback) {
1223
    global $CFG, $OUTPUT;
1224
    $title = get_string('view_recording_format_'.$playback['type'], 'bigbluebuttonbn');
1225
    $onclick = 'M.mod_bigbluebuttonbn.recordings.recording_play(this);';
1226
    $href = $CFG->wwwroot.'/mod/bigbluebuttonbn/bbb_view.php?action=playback&bn='.$bigbluebuttonbnid.
1227
      '&mid='.$recording['meetingID'].'&rid='.$recording['recordID'].'&rtype='.$playback['type'];
1228
    if (!isset($recording['imported']) || !isset($recording['protected']) || $recording['protected'] === 'false') {
1229
        $href .= '&href='.urlencode($playback['url']);
1230
    }
1231
    $linkattributes = array('title' => $title,
1232
        'class' => 'btn btn-sm btn-default', 'onclick' => $onclick,
1233
        'data-action' => 'play', 'data-href' => $href);
1234
    return $OUTPUT->action_link('#', $title, null, $linkattributes);
1235
}
1236
1237
function bigbluebuttonbn_get_recording_data_row_meta_activity($recording, $editable) {
1238
    $payload = array();
1239 View Code Duplication
    if ($editable) {
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...
1240
        $payload = array('recordingid' => $recording['recordID'], 'meetingid' => $recording['meetingID'],
1241
            'action' => 'edit', 'tag' => 'edit',
1242
            'target' => 'name');
1243
    }
1244
1245
    $oldsource = 'meta_contextactivity';
1246 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...
1247
        $metaname = trim($recording[$oldsource]);
1248
        return bigbluebuttonbn_get_recording_data_row_text($recording, $metaname, $oldsource, $payload);
1249
    }
1250
1251
    $newsource = 'meta_bbb-recording-name';
1252 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...
1253
        $metaname = trim($recording[$newsource]);
1254
        return bigbluebuttonbn_get_recording_data_row_text($recording, $metaname, $newsource, $payload);
1255
    }
1256
1257
    $metaname = trim($recording['meetingName']);
1258
    return bigbluebuttonbn_get_recording_data_row_text($recording, $metaname, $newsource, $payload);
1259
}
1260
1261
function bigbluebuttonbn_get_recording_data_row_meta_description($recording, $editable) {
1262
    $payload = array();
1263 View Code Duplication
    if ($editable) {
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...
1264
        $payload = array('recordingid' => $recording['recordID'], 'meetingid' => $recording['meetingID'],
1265
            'action' => 'edit', 'tag' => 'edit',
1266
            'target' => 'description');
1267
    }
1268
1269
    $oldsource = 'meta_contextactivitydescription';
1270 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...
1271
        $metadescription = trim($recording[$oldsource]);
1272
        return bigbluebuttonbn_get_recording_data_row_text($recording, $metadescription, $oldsource, $payload);
1273
    }
1274
1275
    $newsource = 'meta_bbb-recording-description';
1276
    if (isset($recording[$newsource])) {
1277
        $metadescription = trim($recording[$newsource]);
1278
        return bigbluebuttonbn_get_recording_data_row_text($recording, $metadescription, $newsource, $payload);
1279
    }
1280
1281
    return bigbluebuttonbn_get_recording_data_row_text($recording, '', $newsource, $payload);
1282
}
1283
1284
function bigbluebuttonbn_get_recording_data_row_text($recording, $text, $source, $data) {
1285
    $htmltext = '<span>' . htmlentities($text) . '</span>';
1286
1287
    if (empty($data)) {
1288
        return $htmltext;
1289
    }
1290
1291
    $target = $data['action'] . '-' . $data['target'];
1292
    $id = 'recording-' . $target . '-' . $data['recordingid'];
1293
    $attributes = array('id' => $id, 'class' => 'quickeditlink col-md-20',
1294
        'data-recordingid' => $data['recordingid'], 'data-meetingid' => $data['meetingid'],
1295
        'data-target' => $data['target'], 'data-source' => $source);
1296
    $head = html_writer::start_tag('div', $attributes);
1297
    $tail = html_writer::end_tag('div');
1298
1299
    $payload = array('action' => $data['action'], 'tag' => $data['tag'], 'target' => $data['target']);
1300
    $htmllink = bigbluebuttonbn_actionbar_render_button($recording, $payload);
1301
1302
    return $head . $htmltext . $htmllink . $tail;
1303
}
1304
1305
function bigbluebuttonbn_actionbar_render_button($recording, $data) {
1306
    global $OUTPUT;
1307
1308
    if (!$data) {
1309
        return '';
1310
    }
1311
1312
    $target = $data['action'];
1313
    if (isset($data['target'])) {
1314
        $target .= '-' . $data['target'];
1315
    }
1316
    $id = 'recording-' . $target . '-' . $recording['recordID'];
1317
    $onclick = 'M.mod_bigbluebuttonbn.recordings.recording_'.$data['action'].'(this);';
1318
    if ((boolean)\mod_bigbluebuttonbn\locallib\config::get('recording_icons_enabled')) {
1319
        // With icon for $manageaction.
1320
        $iconattributes = array('id' => $id, 'class' => 'iconsmall');
1321
        $icon = new pix_icon('i/'.$data['tag'],
1322
            get_string('view_recording_list_actionbar_' . $data['action'], 'bigbluebuttonbn'),
1323
            'moodle', $iconattributes);
1324
        $linkattributes = array(
1325
            'id' => $id,
1326
            'onclick' => $onclick,
1327
            'data-action' => $data['action'],
1328
            'data-links' => bigbluebuttonbn_get_count_recording_imported_instances($recording['recordID'])
1329
          );
1330
        return $OUTPUT->action_icon('#', $icon, null, $linkattributes, false);
1331
    }
1332
1333
    // With text for $manageaction.
1334
    $linkattributes = array('title' => get_string($data['tag']), 'class' => 'btn btn-xs btn-danger',
1335
        'onclick' => $onclick);
1336
    return $OUTPUT->action_link('#', get_string($data['action']), null, $linkattributes);
1337
}
1338
1339
function bigbluebuttonbn_get_recording_columns($bbbsession) {
1340
    // Set strings to show.
1341
    $recording = get_string('view_recording_recording', 'bigbluebuttonbn');
1342
    $activity = get_string('view_recording_activity', 'bigbluebuttonbn');
1343
    $description = get_string('view_recording_description', 'bigbluebuttonbn');
1344
    $preview = get_string('view_recording_preview', 'bigbluebuttonbn');
1345
    $date = get_string('view_recording_date', 'bigbluebuttonbn');
1346
    $duration = get_string('view_recording_duration', 'bigbluebuttonbn');
1347
    $actionbar = get_string('view_recording_actionbar', 'bigbluebuttonbn');
1348
1349
    // Initialize table headers.
1350
    $recordingsbncolumns = array(
1351
        array('key' => 'recording', 'label' => $recording, 'width' => '125px', 'allowHTML' => true),
1352
        array('key' => 'activity', 'label' => $activity, 'sortable' => true, 'width' => '175px', 'allowHTML' => true),
1353
        array('key' => 'description', 'label' => $description, 'sortable' => true, 'width' => '250px', 'allowHTML' => true),
1354
        array('key' => 'preview', 'label' => $preview, 'width' => '250px', 'allowHTML' => true),
1355
        array('key' => 'date', 'label' => $date, 'sortable' => true, 'width' => '225px', 'allowHTML' => true),
1356
        array('key' => 'duration', 'label' => $duration, 'width' => '50px'),
1357
        );
1358
1359
    if ($bbbsession['managerecordings']) {
1360
        array_push($recordingsbncolumns, array('key' => 'actionbar', 'label' => $actionbar, 'width' => '120px',
1361
            'allowHTML' => true));
1362
    }
1363
1364
    return $recordingsbncolumns;
1365
}
1366
1367
function bigbluebuttonbn_get_recording_data($bbbsession, $recordings, $tools = ['protect', 'publish', 'delete']) {
1368
    $tabledata = array();
1369
1370
    // Build table content.
1371 View Code Duplication
    if (isset($recordings) && !array_key_exists('messageKey', $recordings)) {
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...
1372
        // There are recordings for this meeting.
1373
        foreach ($recordings as $recording) {
1374
            $row = bigbluebuttonbn_get_recording_data_row($bbbsession, $recording, $tools);
1375
            if ($row != null) {
1376
                array_push($tabledata, $row);
1377
            }
1378
        }
1379
    }
1380
1381
    return $tabledata;
1382
}
1383
1384
function bigbluebuttonbn_get_recording_table($bbbsession, $recordings, $tools = ['protect', 'publish', 'delete']) {
1385
    // Set strings to show.
1386
    $recording = get_string('view_recording_recording', 'bigbluebuttonbn');
1387
    $description = get_string('view_recording_description', 'bigbluebuttonbn');
1388
    $date = get_string('view_recording_date', 'bigbluebuttonbn');
1389
    $duration = get_string('view_recording_duration', 'bigbluebuttonbn');
1390
    $actionbar = get_string('view_recording_actionbar', 'bigbluebuttonbn');
1391
    $playback = get_string('view_recording_playback', 'bigbluebuttonbn');
1392
    $preview = get_string('view_recording_preview', 'bigbluebuttonbn');
1393
1394
    // Declare the table.
1395
    $table = new html_table();
1396
    $table->data = array();
1397
1398
    // Initialize table headers.
1399
    $table->head = array($playback, $recording, $description, $preview, $date, $duration);
1400
    $table->align = array('left', 'left', 'left', 'left', 'left', 'center');
1401
    $table->size = array('', '', '', '', '', '');
1402
    if ($bbbsession['managerecordings']) {
1403
        $table->head[] = $actionbar;
1404
        $table->align[] = 'left';
1405
        $table->size[] = (count($tools) * 40) . 'px';
1406
    }
1407
1408
    // Build table content.
1409 View Code Duplication
    if (isset($recordings) && !array_key_exists('messageKey', $recordings)) {
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...
1410
        // There are recordings for this meeting.
1411
        foreach ($recordings as $recording) {
1412
            if ( !bigbluebuttonbn_include_recording_table_row($bbbsession, $recording) ) {
1413
                continue;
1414
            }
1415
            bigbluebuttonbn_get_recording_table_row($bbbsession, $recording, $tools, $table);
1416
        }
1417
    }
1418
1419
    return $table;
1420
}
1421
1422
function bigbluebuttonbn_get_recording_table_row($bbbsession, $recording, $tools, &$table) {
1423
    $rowdata = bigbluebuttonbn_get_recording_data_row($bbbsession, $recording, $tools);
1424
1425
    if ($rowdata == null) {
1426
        return;
1427
    }
1428
1429
    $row = new html_table_row();
1430
    $row->id = 'recording-td-'.$recording['recordID'];
1431
    $row->attributes['data-imported'] = 'false';
1432
    $texthead = '';
1433
    $texttail = '';
1434
    if (isset($recording['imported'])) {
1435
        $row->attributes['title'] = get_string('view_recording_link_warning', 'bigbluebuttonbn');
1436
        $row->attributes['data-imported'] = 'true';
1437
        $texthead = '<em>';
1438
        $texttail = '</em>';
1439
    }
1440
    $rowdata->date_formatted = str_replace(' ', '&nbsp;', $rowdata->date_formatted);
1441
    $row->cells = array(
1442
        $texthead . $rowdata->recording . $texttail,
1443
        $texthead . $rowdata->activity . $texttail, $texthead . $rowdata->description . $texttail,
1444
        $rowdata->preview, $texthead . $rowdata->date_formatted . $texttail,
1445
        $rowdata->duration_formatted
1446
      );
1447
    if ($bbbsession['managerecordings']) {
1448
        $row->cells[] = $rowdata->actionbar;
1449
    }
1450
    array_push($table->data, $row);
1451
}
1452
1453
function bigbluebuttonbn_include_recording_table_row($bbbsession, $recording) {
1454
    if ( isset($recording['imported']) || !isset($bbbsession['group']) || $recording['meetingID'] == $bbbsession['meetingid'] ) {
1455
        return true;
1456
    }
1457
    return false;
1458
}
1459
1460
function bigbluebuttonbn_send_notification_recording_ready($bigbluebuttonbn) {
1461
    $sender = get_admin();
1462
1463
    // Prepare message.
1464
    $msg = new stdClass();
1465
1466
    // Build the message_body.
1467
    $msg->activity_type = '';
1468
    $msg->activity_title = $bigbluebuttonbn->name;
1469
    $messagetext = '<p>'.get_string('email_body_recording_ready_for', 'bigbluebuttonbn').' '.
1470
        $msg->activity_type.' &quot;'.$msg->activity_title.'&quot; '.
1471
        get_string('email_body_recording_ready_is_ready', 'bigbluebuttonbn').'.</p>';
1472
1473
    bigbluebuttonbn_send_notification($sender, $bigbluebuttonbn, $messagetext);
1474
}
1475
1476
function bigbluebuttonbn_is_bn_server() {
1477
    // Validates if the server may have extended capabilities.
1478
    $parsedurl = parse_url(\mod_bigbluebuttonbn\locallib\config::get('server_url'));
1479
    if (!isset($parsedurl['host'])) {
1480
        return false;
1481
    }
1482
1483
    $h = $parsedurl['host'];
1484
    $hends = explode('.', $h);
1485
    $hendslength = count($hends);
1486
1487
    return ($hends[$hendslength - 1] == 'com' && $hends[$hendslength - 2] == 'blindsidenetworks');
1488
}
1489
1490
function bigbluebuttonbn_import_get_courses_for_select(array $bbbsession) {
1491
    if ($bbbsession['administrator']) {
1492
        $courses = get_courses('all', 'c.id ASC', 'c.id,c.shortname,c.fullname');
1493
        // It includes the name of the site as a course (category 0), so remove the first one.
1494
        unset($courses['1']);
1495
    } else {
1496
        $courses = enrol_get_users_courses($bbbsession['userID'], false, 'id,shortname,fullname');
1497
    }
1498
1499
    $coursesforselect = [];
1500
    foreach ($courses as $course) {
1501
        $coursesforselect[$course->id] = $course->fullname;
1502
    }
1503
1504
    return $coursesforselect;
1505
}
1506
1507
function bigbluebutton_output_recording_table($bbbsession, $recordings, $tools = ['protect', 'publish', 'delete']) {
1508
    if (isset($recordings) && !empty($recordings)) {
1509
        // There are recordings for this meeting.
1510
        $table = bigbluebuttonbn_get_recording_table($bbbsession, $recordings, $tools);
1511
    }
1512
1513
    if (!isset($table) || !isset($table->data)) {
1514
        // Render a table qith "No recordings".
1515
        return html_writer::div(get_string('view_message_norecordings', 'bigbluebuttonbn'), '',
1516
            array('id' => 'bigbluebuttonbn_html_table'));
1517
    }
1518
1519
    // Render the table.
1520
    return html_writer::div(html_writer::table($table), '', array('id' => 'bigbluebuttonbn_html_table'));
1521
}
1522
1523
function bigbluebuttonbn_html2text($html, $len) {
1524
    $text = strip_tags($html);
1525
    $text = str_replace('&nbsp;', ' ', $text);
1526
    $text = substr($text, 0, $len);
1527
    if (strlen($text) > $len) {
1528
        $text .= '...';
1529
    }
1530
1531
    return $text;
1532
}
1533
1534
/**
1535
 * helper function to obtain the tags linked to a bigbluebuttonbn activity
1536
 *
1537
 * @param string $id
1538
 *
1539
 * @return string containing the tags separated by commas
1540
 */
1541
function bigbluebuttonbn_get_tags($id) {
1542
    $tagsarray = core_tag_tag::get_item_tags_array('core', 'course_modules', $id);
1543
    return implode(',', $tagsarray);
1544
}
1545
1546
1547
/**
1548
 * helper function to define the sql used for gattering the bigbluebuttonbnids whose meetingids should be included
1549
 * in the getRecordings request
1550
 *
1551
 * @param string $courseid
1552
 * @param string $bigbluebuttonbnid
1553
 * @param bool   $subset
1554
 *
1555
 * @return string containing the sql used for getting the target bigbluebuttonbn instances
1556
 */
1557
function bigbluebuttonbn_get_recordings_sql_select($courseid, $bigbluebuttonbnid = null, $subset = true) {
1558
    if ($bigbluebuttonbnid === null) {
1559
        return "course = '{$courseid}'";
1560
    }
1561
    if ($subset) {
1562
        return "id = '{$bigbluebuttonbnid}'";
1563
    }
1564
    return "id <> '{$bigbluebuttonbnid}' AND course = '{$courseid}'";
1565
}
1566
1567
function bigbluebuttonbn_get_recordings_sql_selectdeleted($courseid, $bigbluebuttonbnid = null, $subset = true) {
1568
    if ($bigbluebuttonbnid === null) {
1569
        return "courseid = '{$courseid}' AND log = '".BIGBLUEBUTTONBN_LOG_EVENT_DELETE.
1570
            "' AND meta like '%has_recordings%' AND meta like '%true%'";
1571
    }
1572
    if ($subset) {
1573
        return "bigbluebuttonbnid = '{$bigbluebuttonbnid}' AND log = '".BIGBLUEBUTTONBN_LOG_EVENT_DELETE.
1574
            "' AND meta like '%has_recordings%' AND meta like '%true%'";
1575
    }
1576
    return "courseid = '{$courseid}' AND bigbluebuttonbnid <> '{$bigbluebuttonbnid}' AND log = '".
1577
        BIGBLUEBUTTONBN_LOG_EVENT_DELETE."' AND meta like '%has_recordings%' AND meta like '%true%'";
1578
}
1579
1580
function bigbluebuttonbn_get_allrecordings($courseid, $bigbluebuttonbnid = null, $subset = true,
1581
        $includedeleted = false) {
1582
        $recordings = bigbluebuttonbn_get_recordings($courseid, $bigbluebuttonbnid, $subset, $includedeleted);
1583
        $recordingsimported = bigbluebuttonbn_get_recordings_imported_array($courseid, $bigbluebuttonbnid, $subset);
1584
        return ($recordings + $recordingsimported);
1585
}
1586
1587
/**
1588
 * helper function to retrieve recordings from the BigBlueButton. The references are stored as events
1589
 * in bigbluebuttonbn_logs.
1590
 *
1591
 * @param string $courseid
1592
 * @param string $bigbluebuttonbnid
1593
 * @param bool   $subset
1594
 * @param bool   $includedeleted
1595
 *
1596
 * @return associative array containing the recordings indexed by recordID, each recording is also a
1597
 * non sequential associative array itself that corresponds to the actual recording in BBB
1598
 */
1599
function bigbluebuttonbn_get_recordings($courseid, $bigbluebuttonbnid = null, $subset = true,
1600
        $includedeleted = false) {
1601
    global $DB;
1602
1603
    $select = bigbluebuttonbn_get_recordings_sql_select($courseid, $bigbluebuttonbnid, $subset);
1604
    $bigbluebuttonbns = $DB->get_records_select_menu('bigbluebuttonbn', $select, null, 'id', 'id, meetingid');
1605
1606
    /* Consider logs from deleted bigbluebuttonbn instances whose meetingids should be included in
1607
     * the getRecordings request. */
1608
    if ($includedeleted) {
1609
        $selectdeleted = bigbluebuttonbn_get_recordings_sql_selectdeleted($courseid, $bigbluebuttonbnid, $subset);
1610
        $bigbluebuttonbnsdel = $DB->get_records_select_menu('bigbluebuttonbn_logs', $selectdeleted, null,
1611
            'bigbluebuttonbnid', 'bigbluebuttonbnid, meetingid');
1612
        if (!empty($bigbluebuttonbnsdel)) {
1613
            // Merge bigbluebuttonbnis from deleted instances, only keys are relevant.
1614
            // Artimetic merge is used in order to keep the keys.
1615
            $bigbluebuttonbns += $bigbluebuttonbnsdel;
1616
        }
1617
    }
1618
1619
    // Gather the meetingids from bigbluebuttonbn logs that include a create with record=true.
1620
    if (empty($bigbluebuttonbns)) {
1621
        return array();
1622
    }
1623
1624
    // Prepare select for loading records based on existent bigbluebuttonbns.
1625
    $sql = 'SELECT DISTINCT meetingid, bigbluebuttonbnid FROM {bigbluebuttonbn_logs} WHERE ';
1626
    $sql .= '(bigbluebuttonbnid='.implode(' OR bigbluebuttonbnid=', array_keys($bigbluebuttonbns)).')';
1627
    // Include only Create events and exclude those with record not true.
1628
    $sql .= ' AND log = ? AND meta LIKE ? AND meta LIKE ?';
1629
    // Execute select for loading records based on existent bigbluebuttonbns.
1630
    $records = $DB->get_records_sql_menu($sql, array(BIGBLUEBUTTONBN_LOG_EVENT_CREATE, '%record%', '%true%'));
1631
    // Get actual recordings.
1632
    return bigbluebuttonbn_get_recordings_array(array_keys($records));
1633
}
1634
1635
function bigbluebuttonbn_unset_existent_recordings_already_imported($recordings, $courseid, $bigbluebuttonbnid) {
1636
    $recordingsimported = bigbluebuttonbn_get_recordings_imported_array($courseid, $bigbluebuttonbnid, true);
1637
1638
    foreach ($recordings as $key => $recording) {
1639
        if (isset($recordingsimported[$recording['recordID']])) {
1640
            unset($recordings[$key]);
1641
        }
1642
    }
1643
1644
    return $recordings;
1645
}
1646
1647
function bigbluebuttonbn_get_count_recording_imported_instances($recordid) {
1648
    global $DB;
1649
1650
    $sql = 'SELECT COUNT(DISTINCT id) FROM {bigbluebuttonbn_logs} WHERE log = ? AND meta LIKE ? AND meta LIKE ?';
1651
1652
    return $DB->count_records_sql($sql, array(BIGBLUEBUTTONBN_LOG_EVENT_IMPORT, '%recordID%', "%{$recordid}%"));
1653
}
1654
1655
function bigbluebuttonbn_get_recording_imported_instances($recordid) {
1656
    global $DB;
1657
1658
    $sql = 'SELECT * FROM {bigbluebuttonbn_logs} WHERE log = ? AND meta LIKE ? AND meta LIKE ?';
1659
    $recordingsimported = $DB->get_records_sql($sql, array(BIGBLUEBUTTONBN_LOG_EVENT_IMPORT, '%recordID%',
1660
        "%{$recordid}%"));
1661
1662
    return $recordingsimported;
1663
}
1664
1665
function bigbluebuttonbn_get_instance_type_profiles() {
1666
    $instanceprofiles = array(
1667
            array('id' => BIGBLUEBUTTONBN_TYPE_ALL, 'name' => get_string('instance_type_default', 'bigbluebuttonbn'),
1668
                'features' => array('all')),
1669
            array('id' => BIGBLUEBUTTONBN_TYPE_ROOM_ONLY, 'name' => get_string('instance_type_room_only', 'bigbluebuttonbn'),
1670
                'features' => array('showroom', 'welcomemessage', 'voicebridge', 'waitformoderator', 'userlimit', 'recording',
1671
                    'sendnotifications', 'preuploadpresentation', 'permissions', 'schedule', 'groups')),
1672
            array('id' => BIGBLUEBUTTONBN_TYPE_RECORDING_ONLY, 'name' => get_string('instance_type_recording_only',
1673
                'bigbluebuttonbn'), 'features' => array('showrecordings', 'importrecordings')),
1674
    );
1675
1676
    return $instanceprofiles;
1677
}
1678
1679
function bigbluebuttonbn_get_enabled_features($typeprofiles, $type = null) {
1680
    $enabledfeatures = array();
1681
1682
    $features = $typeprofiles[0]['features'];
1683
    if (!is_null($type)) {
1684
        $features = $typeprofiles[$type]['features'];
1685
    }
1686
    $enabledfeatures['showroom'] = (in_array('all', $features) || in_array('showroom', $features));
1687
    $enabledfeatures['showrecordings'] = (in_array('all', $features) || in_array('showrecordings', $features));
1688
    $enabledfeatures['importrecordings'] = (in_array('all', $features) || in_array('importrecordings', $features));
1689
1690
    return $enabledfeatures;
1691
}
1692
1693
function bigbluebuttonbn_get_instance_profiles_array($profiles = null) {
1694
    if (is_null($profiles) || empty($profiles)) {
1695
        $profiles = bigbluebuttonbn_get_instance_type_profiles();
1696
    }
1697
1698
    $profilesarray = array();
1699
1700
    foreach ($profiles as $profile) {
1701
        $profilesarray += array("{$profile['id']}" => $profile['name']);
1702
    }
1703
1704
    return $profilesarray;
1705
}
1706
1707
function bigbluebuttonbn_format_activity_time($time) {
1708
    $activitytime = '';
1709
    if ($time) {
1710
        $activitytime = calendar_day_representation($time).' '.
1711
          get_string('mod_form_field_notification_msg_at', 'bigbluebuttonbn').' '.
1712
          calendar_time_representation($time);
1713
    }
1714
1715
    return $activitytime;
1716
}
1717
1718
function bigbluebuttonbn_get_strings_for_js() {
1719
    $locale = bigbluebuttonbn_get_locale();
1720
    $stringman = get_string_manager();
1721
    $strings = $stringman->load_component_strings('bigbluebuttonbn', $locale);
1722
    return $strings;
1723
}
1724
1725
function bigbluebuttonbn_get_locale() {
1726
    $lang = get_string('locale', 'core_langconfig');
1727
    return substr($lang, 0, strpos($lang, '.'));
1728
}
1729
1730
function bigbluebuttonbn_get_localcode() {
1731
    $locale = bigbluebuttonbn_get_locale();
1732
    return substr($locale, 0, strpos($locale, '_'));
1733
}
1734
1735
function bigbluebuttonbn_views_validator($id, $bigbluebuttonbnid) {
1736
    if ($id) {
1737
        return bigbluebuttonbn_views_instance_id($id);
1738
    }
1739
    if ($bigbluebuttonbnid) {
1740
        return bigbluebuttonbn_views_instance_bigbluebuttonbn($bigbluebuttonbnid);
1741
    }
1742
    return;
1743
}
1744
1745 View Code Duplication
function bigbluebuttonbn_views_instance_id($id) {
0 ignored issues
show
Duplication introduced by
This function seems to be duplicated in your project.

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

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

Loading history...
1746
    global $DB;
1747
    $cm = get_coursemodule_from_id('bigbluebuttonbn', $id, 0, false, MUST_EXIST);
1748
    $course = $DB->get_record('course', array('id' => $cm->course), '*', MUST_EXIST);
1749
    $bigbluebuttonbn = $DB->get_record('bigbluebuttonbn', array('id' => $cm->instance), '*', MUST_EXIST);
1750
    return array('cm' => $cm, 'course' => $course, 'bigbluebuttonbn' => $bigbluebuttonbn);
1751
}
1752
1753 View Code Duplication
function bigbluebuttonbn_views_instance_bigbluebuttonbn($bigbluebuttonbnid) {
0 ignored issues
show
Duplication introduced by
This function seems to be duplicated in your project.

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

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

Loading history...
1754
    global $DB;
1755
    $bigbluebuttonbn = $DB->get_record('bigbluebuttonbn', array('id' => $bigbluebuttonbnid), '*', MUST_EXIST);
1756
    $course = $DB->get_record('course', array('id' => $bigbluebuttonbn->course), '*', MUST_EXIST);
1757
    $cm = get_coursemodule_from_instance('bigbluebuttonbn', $bigbluebuttonbn->id, $course->id, false, MUST_EXIST);
1758
    return array('cm' => $cm, 'course' => $course, 'bigbluebuttonbn' => $bigbluebuttonbn);
1759
}
1760