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