1
|
|
|
<?php |
2
|
|
|
// This file is part of Moodle - http://moodle.org/ |
3
|
|
|
// |
4
|
|
|
// Moodle is free software: you can redistribute it and/or modify |
5
|
|
|
// it under the terms of the GNU General Public License as published by |
6
|
|
|
// the Free Software Foundation, either version 3 of the License, or |
7
|
|
|
// (at your option) any later version. |
8
|
|
|
// |
9
|
|
|
// Moodle is distributed in the hope that it will be useful, |
10
|
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of |
11
|
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
12
|
|
|
// GNU General Public License for more details. |
13
|
|
|
// |
14
|
|
|
// You should have received a copy of the GNU General Public License |
15
|
|
|
// along with Moodle. If not, see <http://www.gnu.org/licenses/>. |
16
|
|
|
|
17
|
|
|
/** |
18
|
|
|
* Internal library of functions for module BigBlueButtonBN. |
19
|
|
|
* |
20
|
|
|
* @package mod_bigbluebuttonbn |
21
|
|
|
* @copyright 2010 onwards, Blindside Networks Inc |
22
|
|
|
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later |
23
|
|
|
* @author Jesus Federico (jesus [at] blindsidenetworks [dt] com) |
24
|
|
|
* @author Fred Dixon (ffdixon [at] blindsidenetworks [dt] com) |
25
|
|
|
*/ |
26
|
|
|
|
27
|
|
|
use mod_bigbluebuttonbn\locallib; |
28
|
|
|
use mod_bigbluebuttonbn\plugin; |
29
|
|
|
use mod_bigbluebuttonbn\task; |
30
|
|
|
|
31
|
|
|
defined('MOODLE_INTERNAL') || die; |
32
|
|
|
|
33
|
|
|
global $CFG; |
34
|
|
|
|
35
|
|
|
require_once(__DIR__ . '/lib.php'); |
36
|
|
|
|
37
|
|
|
/** @var BIGBLUEBUTTONBN_UPDATE_CACHE boolean set to true indicates that cache has to be updated */ |
38
|
|
|
const BIGBLUEBUTTONBN_UPDATE_CACHE = true; |
39
|
|
|
/** @var BIGBLUEBUTTONBN_TYPE_ALL integer set to 0 defines an instance type that inclueds room and recordings */ |
40
|
|
|
const BIGBLUEBUTTONBN_TYPE_ALL = 0; |
41
|
|
|
/** @var BIGBLUEBUTTONBN_TYPE_ROOM_ONLY integer set to 1 defines an instance type that inclueds only room */ |
42
|
|
|
const BIGBLUEBUTTONBN_TYPE_ROOM_ONLY = 1; |
43
|
|
|
/** @var BIGBLUEBUTTONBN_TYPE_RECORDING_ONLY integer set to 2 defines an instance type that inclueds only recordings */ |
44
|
|
|
const BIGBLUEBUTTONBN_TYPE_RECORDING_ONLY = 2; |
45
|
|
|
/** @var BIGBLUEBUTTONBN_ROLE_VIEWER string defines the bigbluebutton viewer role */ |
46
|
|
|
const BIGBLUEBUTTONBN_ROLE_VIEWER = 'viewer'; |
47
|
|
|
/** @var BIGBLUEBUTTONBN_ROLE_MODERATOR string defines the bigbluebutton moderator role */ |
48
|
|
|
const BIGBLUEBUTTONBN_ROLE_MODERATOR = 'moderator'; |
49
|
|
|
/** @var BIGBLUEBUTTON_EVENT_ACTIVITY_VIEWED string defines the bigbluebuttonbn activity_viewed event */ |
50
|
|
|
const BIGBLUEBUTTON_EVENT_ACTIVITY_VIEWED = 'activity_viewed'; |
51
|
|
|
/** @var BIGBLUEBUTTON_EVENT_ACTIVITY_MANAGEMENT_VIEWED string defines the bigbluebuttonbn activity_management_viewed event */ |
52
|
|
|
const BIGBLUEBUTTON_EVENT_ACTIVITY_MANAGEMENT_VIEWED = 'activity_management_viewed'; |
53
|
|
|
/** @var BIGBLUEBUTTON_EVENT_LIVE_SESSION string defines the bigbluebuttonbn live_session event */ |
54
|
|
|
const BIGBLUEBUTTON_EVENT_LIVE_SESSION = 'live_session'; |
55
|
|
|
/** @var BIGBLUEBUTTON_EVENT_MEETING_CREATED string defines the bigbluebuttonbn meeting_created event */ |
56
|
|
|
const BIGBLUEBUTTON_EVENT_MEETING_CREATED = 'meeting_created'; |
57
|
|
|
/** @var BIGBLUEBUTTON_EVENT_MEETING_ENDED string defines the bigbluebuttonbn meeting_ended event */ |
58
|
|
|
const BIGBLUEBUTTON_EVENT_MEETING_ENDED = 'meeting_ended'; |
59
|
|
|
/** @var BIGBLUEBUTTON_EVENT_MEETING_JOINED string defines the bigbluebuttonbn meeting_joined event */ |
60
|
|
|
const BIGBLUEBUTTON_EVENT_MEETING_JOINED = 'meeting_joined'; |
61
|
|
|
/** @var BIGBLUEBUTTON_EVENT_MEETING_LEFT string defines the bigbluebuttonbn meeting_left event */ |
62
|
|
|
const BIGBLUEBUTTON_EVENT_MEETING_LEFT = 'meeting_left'; |
63
|
|
|
/** @var BIGBLUEBUTTON_EVENT_RECORDING_DELETED string defines the bigbluebuttonbn recording_deleted event */ |
64
|
|
|
const BIGBLUEBUTTON_EVENT_RECORDING_DELETED = 'recording_deleted'; |
65
|
|
|
/** @var BIGBLUEBUTTON_EVENT_RECORDING_IMPORTED string defines the bigbluebuttonbn recording_imported event */ |
66
|
|
|
const BIGBLUEBUTTON_EVENT_RECORDING_IMPORTED = 'recording_imported'; |
67
|
|
|
/** @var BIGBLUEBUTTON_EVENT_RECORDING_PROTECTED string defines the bigbluebuttonbn recording_protected event */ |
68
|
|
|
const BIGBLUEBUTTON_EVENT_RECORDING_PROTECTED = 'recording_protected'; |
69
|
|
|
/** @var BIGBLUEBUTTON_EVENT_RECORDING_PUBLISHED string defines the bigbluebuttonbn recording_published event */ |
70
|
|
|
const BIGBLUEBUTTON_EVENT_RECORDING_PUBLISHED = 'recording_published'; |
71
|
|
|
/** @var BIGBLUEBUTTON_EVENT_RECORDING_UNPROTECTED string defines the bigbluebuttonbn recording_unprotected event */ |
72
|
|
|
const BIGBLUEBUTTON_EVENT_RECORDING_UNPROTECTED = 'recording_unprotected'; |
73
|
|
|
/** @var BIGBLUEBUTTON_EVENT_RECORDING_UNPUBLISHED string defines the bigbluebuttonbn recording_unpublished event */ |
74
|
|
|
const BIGBLUEBUTTON_EVENT_RECORDING_UNPUBLISHED = 'recording_unpublished'; |
75
|
|
|
/** @var BIGBLUEBUTTON_EVENT_RECORDING_EDITED string defines the bigbluebuttonbn recording_edited event */ |
76
|
|
|
const BIGBLUEBUTTON_EVENT_RECORDING_EDITED = 'recording_edited'; |
77
|
|
|
/** @var BIGBLUEBUTTON_EVENT_RECORDING_VIEWED string defines the bigbluebuttonbn recording_viewed event */ |
78
|
|
|
const BIGBLUEBUTTON_EVENT_RECORDING_VIEWED = 'recording_viewed'; |
79
|
|
|
/** @var BIGBLUEBUTTON_EVENT_MEETING_START string defines the bigbluebuttonbn meeting_start event */ |
80
|
|
|
const BIGBLUEBUTTON_EVENT_MEETING_START = 'meeting_start'; |
81
|
|
|
/** @var BIGBLUEBUTTON_CLIENTTYPE_FLASH integer that defines the bigbluebuttonbn default web client based on Adobe FLASH */ |
82
|
|
|
const BIGBLUEBUTTON_CLIENTTYPE_FLASH = 0; |
83
|
|
|
/** @var BIGBLUEBUTTON_CLIENTTYPE_HTML5 integer that defines the bigbluebuttonbn default web client based on HTML5 */ |
84
|
|
|
const BIGBLUEBUTTON_CLIENTTYPE_HTML5 = 1; |
85
|
|
|
/** @var BIGBLUEBUTTON_ORIGIN_BASE integer set to 0 defines that the user acceded the session from activity page */ |
86
|
|
|
const BIGBLUEBUTTON_ORIGIN_BASE = 0; |
87
|
|
|
/** @var BIGBLUEBUTTON_ORIGIN_TIMELINE integer set to 1 defines that the user acceded the session from Timeline */ |
88
|
|
|
const BIGBLUEBUTTON_ORIGIN_TIMELINE = 1; |
89
|
|
|
/** @var BIGBLUEBUTTON_ORIGIN_INDEX integer set to 2 defines that the user acceded the session from Index */ |
90
|
|
|
const BIGBLUEBUTTON_ORIGIN_INDEX = 2; |
91
|
|
|
|
92
|
|
|
/** |
93
|
|
|
* Builds and retunrs a url for joining a bigbluebutton meeting. |
94
|
|
|
* |
95
|
|
|
* @param string $meetingid |
96
|
|
|
* @param string $username |
97
|
|
|
* @param string $pw |
98
|
|
|
* @param string $logouturl |
99
|
|
|
* @param string $configtoken |
100
|
|
|
* @param string $userid |
101
|
|
|
* @param string $clienttype |
102
|
|
|
* @param string $createtime |
103
|
|
|
* |
104
|
|
|
* @return string |
105
|
|
|
*/ |
106
|
|
|
function bigbluebuttonbn_get_join_url( |
107
|
|
|
$meetingid, |
108
|
|
|
$username, |
109
|
|
|
$pw, |
110
|
|
|
$logouturl, |
111
|
|
|
$configtoken = null, |
112
|
|
|
$userid = null, |
113
|
|
|
$clienttype = BIGBLUEBUTTON_CLIENTTYPE_FLASH, |
114
|
|
|
$createtime = null |
115
|
|
|
) { |
116
|
|
|
$data = ['meetingID' => $meetingid, |
117
|
|
|
'fullName' => $username, |
118
|
|
|
'password' => $pw, |
119
|
|
|
'logoutURL' => $logouturl, |
120
|
|
|
]; |
121
|
|
|
// Choose between Adobe Flash or HTML5 Client. |
122
|
|
|
if ($clienttype == BIGBLUEBUTTON_CLIENTTYPE_HTML5) { |
123
|
|
|
$data['joinViaHtml5'] = 'true'; |
124
|
|
|
} |
125
|
|
|
if (!is_null($configtoken)) { |
126
|
|
|
$data['configToken'] = $configtoken; |
127
|
|
|
} |
128
|
|
|
if (!is_null($userid)) { |
129
|
|
|
$data['userID'] = $userid; |
130
|
|
|
} |
131
|
|
|
if (!is_null($createtime)) { |
132
|
|
|
$data['createTime'] = $createtime; |
133
|
|
|
} |
134
|
|
|
return \mod_bigbluebuttonbn\locallib\bigbluebutton::action_url('join', $data); |
135
|
|
|
} |
136
|
|
|
|
137
|
|
|
/** |
138
|
|
|
* Creates a bigbluebutton meeting and returns the response in an array. |
139
|
|
|
* |
140
|
|
|
* @param array $data |
141
|
|
|
* @param array $metadata |
142
|
|
|
* @param string $pname |
143
|
|
|
* @param string $purl |
144
|
|
|
* |
145
|
|
|
* @return array |
146
|
|
|
*/ |
147
|
|
|
function bigbluebuttonbn_get_create_meeting_array($data, $metadata = array(), $pname = null, $purl = null) { |
148
|
|
|
$createmeetingurl = \mod_bigbluebuttonbn\locallib\bigbluebutton::action_url('create', $data, $metadata); |
149
|
|
|
$method = 'GET'; |
150
|
|
|
$payload = null; |
151
|
|
|
if (!is_null($pname) && !is_null($purl)) { |
152
|
|
|
$method = 'POST'; |
153
|
|
|
$payload = "<?xml version='1.0' encoding='UTF-8'?><modules><module name='presentation'><document url='". |
154
|
|
|
$purl."' /></module></modules>"; |
155
|
|
|
} |
156
|
|
|
$xml = bigbluebuttonbn_wrap_xml_load_file($createmeetingurl, $method, $payload); |
157
|
|
|
if ($xml) { |
158
|
|
|
$response = array('returncode' => $xml->returncode, 'message' => $xml->message, 'messageKey' => $xml->messageKey); |
159
|
|
|
if ($xml->meetingID) { |
160
|
|
|
$response += array('meetingID' => $xml->meetingID, 'attendeePW' => $xml->attendeePW, |
161
|
|
|
'moderatorPW' => $xml->moderatorPW, 'hasBeenForciblyEnded' => $xml->hasBeenForciblyEnded); |
162
|
|
|
} |
163
|
|
|
return $response; |
164
|
|
|
} |
165
|
|
|
return array('returncode' => 'FAILED', 'message' => 'unreachable', 'messageKey' => 'Server is unreachable'); |
166
|
|
|
} |
167
|
|
|
|
168
|
|
|
/** |
169
|
|
|
* Fetch meeting info and wrap response in array. |
170
|
|
|
* |
171
|
|
|
* @param string $meetingid |
172
|
|
|
* |
173
|
|
|
* @return array |
174
|
|
|
*/ |
175
|
|
|
function bigbluebuttonbn_get_meeting_info_array($meetingid) { |
176
|
|
|
$xml = bigbluebuttonbn_wrap_xml_load_file( |
177
|
|
|
\mod_bigbluebuttonbn\locallib\bigbluebutton::action_url('getMeetingInfo', ['meetingID' => $meetingid]) |
178
|
|
|
); |
179
|
|
|
if ($xml && $xml->returncode == 'SUCCESS' && empty($xml->messageKey)) { |
180
|
|
|
// Meeting info was returned. |
181
|
|
|
return array('returncode' => $xml->returncode, |
182
|
|
|
'meetingID' => $xml->meetingID, |
183
|
|
|
'moderatorPW' => $xml->moderatorPW, |
184
|
|
|
'attendeePW' => $xml->attendeePW, |
185
|
|
|
'hasBeenForciblyEnded' => $xml->hasBeenForciblyEnded, |
186
|
|
|
'running' => $xml->running, |
187
|
|
|
'recording' => $xml->recording, |
188
|
|
|
'startTime' => $xml->startTime, |
189
|
|
|
'endTime' => $xml->endTime, |
190
|
|
|
'participantCount' => $xml->participantCount, |
191
|
|
|
'moderatorCount' => $xml->moderatorCount, |
192
|
|
|
'attendees' => $xml->attendees, |
193
|
|
|
'metadata' => $xml->metadata, |
194
|
|
|
); |
195
|
|
|
} |
196
|
|
|
if ($xml) { |
197
|
|
|
// Either failure or success without meeting info. |
198
|
|
|
return (array) $xml; |
199
|
|
|
} |
200
|
|
|
// If the server is unreachable, then prompts the user of the necessary action. |
201
|
|
|
return array('returncode' => 'FAILED', 'message' => 'unreachable', 'messageKey' => 'Server is unreachable'); |
202
|
|
|
} |
203
|
|
|
|
204
|
|
|
/** |
205
|
|
|
* Helper function to retrieve recordings from a BigBlueButton server. |
206
|
|
|
* |
207
|
|
|
* @param string|array $meetingids list of meetingIDs "mid1,mid2,mid3" or array("mid1","mid2","mid3") |
208
|
|
|
* @param string|array $recordingids list of $recordingids "rid1,rid2,rid3" or array("rid1","rid2","rid3") for filtering |
209
|
|
|
* |
210
|
|
|
* @return associative array with recordings indexed by recordID, each recording is a non sequential associative array |
211
|
|
|
*/ |
212
|
|
|
function bigbluebuttonbn_get_recordings_array($meetingids, $recordingids = []) { |
213
|
|
|
$meetingidsarray = $meetingids; |
214
|
|
|
if (!is_array($meetingids)) { |
215
|
|
|
$meetingidsarray = explode(',', $meetingids); |
216
|
|
|
} |
217
|
|
|
// If $meetingidsarray is empty there is no need to go further. |
218
|
|
|
if (empty($meetingidsarray)) { |
219
|
|
|
return array(); |
220
|
|
|
} |
221
|
|
|
$recordings = bigbluebuttonbn_get_recordings_array_fetch($meetingidsarray); |
|
|
|
|
222
|
|
|
// Sort recordings. |
223
|
|
|
uasort($recordings, 'bigbluebuttonbn_recording_build_sorter'); |
224
|
|
|
// Filter recordings based on recordingIDs. |
225
|
|
|
$recordingidsarray = $recordingids; |
226
|
|
|
if (!is_array($recordingids)) { |
227
|
|
|
$recordingidsarray = explode(',', $recordingids); |
228
|
|
|
} |
229
|
|
|
if (empty($recordingidsarray)) { |
230
|
|
|
// No recording ids, no need to filter. |
231
|
|
|
return $recordings; |
232
|
|
|
} |
233
|
|
|
return bigbluebuttonbn_get_recordings_array_filter($recordingidsarray, $recordings); |
|
|
|
|
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 array (associative) with recordings indexed by recordID, each recording is a non sequential associative array |
242
|
|
|
*/ |
243
|
|
|
function bigbluebuttonbn_get_recordings_array_fetch($meetingidsarray) { |
244
|
|
|
if ((defined('PHPUNIT_TEST') && PHPUNIT_TEST) |
245
|
|
|
|| defined('BEHAT_SITE_RUNNING') |
246
|
|
|
|| defined('BEHAT_TEST') |
247
|
|
|
|| defined('BEHAT_UTIL')) { |
248
|
|
|
// Just return the fake recording. |
249
|
|
|
global $CFG; |
250
|
|
|
require_once($CFG->libdir . '/testing/generator/lib.php'); |
251
|
|
|
require_once(__DIR__ . '/tests/generator/lib.php'); |
252
|
|
|
return mod_bigbluebuttonbn_generator::bigbluebuttonbn_get_recordings_array_fetch($meetingidsarray); |
253
|
|
|
} |
254
|
|
|
$recordings = array(); |
255
|
|
|
// Execute a paginated getRecordings request. |
256
|
|
|
$pagecount = 25; |
257
|
|
|
$pages = floor(count($meetingidsarray) / $pagecount) + 1; |
258
|
|
|
if (count($meetingidsarray) > 0 && count($meetingidsarray) % $pagecount == 0) { |
259
|
|
|
$pages--; |
260
|
|
|
} |
261
|
|
|
for ($page = 1; $page <= $pages; ++$page) { |
262
|
|
|
$mids = array_slice($meetingidsarray, ($page - 1) * $pagecount, $pagecount); |
263
|
|
|
$recordings += bigbluebuttonbn_get_recordings_array_fetch_page($mids); |
264
|
|
|
} |
265
|
|
|
return $recordings; |
266
|
|
|
} |
267
|
|
|
|
268
|
|
|
/** |
269
|
|
|
* Helper function to fetch one page of upto 25 recordings from a BigBlueButton server. |
270
|
|
|
* |
271
|
|
|
* @param array $mids |
272
|
|
|
* |
273
|
|
|
* @return array |
274
|
|
|
*/ |
275
|
|
|
function bigbluebuttonbn_get_recordings_array_fetch_page($mids) { |
276
|
|
|
$recordings = array(); |
277
|
|
|
// Do getRecordings is executed using a method GET (supported by all versions of BBB). |
278
|
|
|
$url = \mod_bigbluebuttonbn\locallib\bigbluebutton::action_url('getRecordings', ['meetingID' => implode(',', $mids)]); |
279
|
|
|
$xml = bigbluebuttonbn_wrap_xml_load_file($url); |
280
|
|
|
if ($xml && $xml->returncode == 'SUCCESS' && isset($xml->recordings)) { |
281
|
|
|
// If there were meetings already created. |
282
|
|
|
foreach ($xml->recordings->recording as $recordingxml) { |
283
|
|
|
$recording = bigbluebuttonbn_get_recording_array_value($recordingxml); |
284
|
|
|
$recordings[$recording['recordID']] = $recording; |
285
|
|
|
|
286
|
|
|
// Check if there is childs. |
287
|
|
|
if (isset($recordingxml->breakoutRooms->breakoutRoom)) { |
288
|
|
|
foreach ($recordingxml->breakoutRooms->breakoutRoom as $breakoutroom) { |
289
|
|
|
$url = \mod_bigbluebuttonbn\locallib\bigbluebutton::action_url( |
290
|
|
|
'getRecordings', |
291
|
|
|
['recordID' => implode(',', (array) $breakoutroom)] |
292
|
|
|
); |
293
|
|
|
$xml = bigbluebuttonbn_wrap_xml_load_file($url); |
294
|
|
|
if ($xml && $xml->returncode == 'SUCCESS' && isset($xml->recordings)) { |
295
|
|
|
// If there were meetings already created. |
296
|
|
|
foreach ($xml->recordings->recording as $recordingxml) { |
297
|
|
|
$recording = bigbluebuttonbn_get_recording_array_value($recordingxml); |
298
|
|
|
$recordings[$recording['recordID']] = $recording; |
299
|
|
|
} |
300
|
|
|
} |
301
|
|
|
} |
302
|
|
|
} |
303
|
|
|
} |
304
|
|
|
} |
305
|
|
|
return $recordings; |
306
|
|
|
} |
307
|
|
|
|
308
|
|
|
/** |
309
|
|
|
* Helper function to remove a set of recordings from an array. |
310
|
|
|
* |
311
|
|
|
* @param array $rids |
312
|
|
|
* @param array $recordings |
313
|
|
|
* |
314
|
|
|
* @return array |
315
|
|
|
*/ |
316
|
|
|
function bigbluebuttonbn_get_recordings_array_filter($rids, &$recordings) { |
317
|
|
|
foreach ($recordings as $key => $recording) { |
318
|
|
|
if (!in_array($recording['recordID'], $rids)) { |
319
|
|
|
unset($recordings[$key]); |
320
|
|
|
} |
321
|
|
|
} |
322
|
|
|
return $recordings; |
323
|
|
|
} |
324
|
|
|
|
325
|
|
|
/** |
326
|
|
|
* Helper function to retrieve imported recordings from the Moodle database. |
327
|
|
|
* The references are stored as events in bigbluebuttonbn_logs. |
328
|
|
|
* |
329
|
|
|
* @param string $courseid |
330
|
|
|
* @param string $bigbluebuttonbnid |
331
|
|
|
* @param bool $subset |
332
|
|
|
* |
333
|
|
|
* @return associative array with imported recordings indexed by recordID, each recording |
334
|
|
|
* is a non sequential associative array that corresponds to the actual recording in BBB |
335
|
|
|
*/ |
336
|
|
|
function bigbluebuttonbn_get_recordings_imported_array($courseid = 0, $bigbluebuttonbnid = null, $subset = true) { |
337
|
|
|
global $DB; |
338
|
|
|
$select = bigbluebuttonbn_get_recordings_imported_sql_select($courseid, $bigbluebuttonbnid, $subset); |
339
|
|
|
$recordsimported = $DB->get_records_select('bigbluebuttonbn_logs', $select); |
340
|
|
|
$recordsimportedarray = array(); |
341
|
|
|
foreach ($recordsimported as $recordimported) { |
342
|
|
|
$meta = json_decode($recordimported->meta, true); |
343
|
|
|
$recording = $meta['recording']; |
344
|
|
|
// Override imported flag with actual ID. |
345
|
|
|
$recording['imported'] = $recordimported->id; |
346
|
|
|
if (isset($recordimported->protected)) { |
347
|
|
|
$recording['protected'] = (string) $recordimported->protected; |
348
|
|
|
} |
349
|
|
|
$recordsimportedarray[$recording['recordID']] = $recording; |
350
|
|
|
} |
351
|
|
|
return $recordsimportedarray; |
352
|
|
|
} |
353
|
|
|
|
354
|
|
|
/** |
355
|
|
|
* Helper function to retrive the default config.xml file. |
356
|
|
|
* |
357
|
|
|
* @return string |
358
|
|
|
*/ |
359
|
|
|
function bigbluebuttonbn_get_default_config_xml() { |
360
|
|
|
$xml = bigbluebuttonbn_wrap_xml_load_file( |
361
|
|
|
\mod_bigbluebuttonbn\locallib\bigbluebutton::action_url('getDefaultConfigXML') |
362
|
|
|
); |
363
|
|
|
return $xml; |
364
|
|
|
} |
365
|
|
|
|
366
|
|
|
/** |
367
|
|
|
* Helper function to convert an xml recording object to an array in the format used by the plugin. |
368
|
|
|
* |
369
|
|
|
* @param object $recording |
370
|
|
|
* |
371
|
|
|
* @return array |
372
|
|
|
*/ |
373
|
|
|
function bigbluebuttonbn_get_recording_array_value($recording) { |
374
|
|
|
// Add formats. |
375
|
|
|
$playbackarray = array(); |
376
|
|
|
foreach ($recording->playback->format as $format) { |
377
|
|
|
$playbackarray[(string) $format->type] = array('type' => (string) $format->type, |
378
|
|
|
'url' => trim((string) $format->url), 'length' => (string) $format->length); |
379
|
|
|
// Add preview per format when existing. |
380
|
|
|
if ($format->preview) { |
381
|
|
|
$playbackarray[(string) $format->type]['preview'] = bigbluebuttonbn_get_recording_preview_images($format->preview); |
382
|
|
|
} |
383
|
|
|
} |
384
|
|
|
// Add the metadata to the recordings array. |
385
|
|
|
$metadataarray = bigbluebuttonbn_get_recording_array_meta(get_object_vars($recording->metadata)); |
386
|
|
|
$recordingarray = array('recordID' => (string) $recording->recordID, |
387
|
|
|
'meetingID' => (string) $recording->meetingID, 'meetingName' => (string) $recording->name, |
388
|
|
|
'published' => (string) $recording->published, 'startTime' => (string) $recording->startTime, |
389
|
|
|
'endTime' => (string) $recording->endTime, 'playbacks' => $playbackarray); |
390
|
|
|
if (isset($recording->protected)) { |
391
|
|
|
$recordingarray['protected'] = (string) $recording->protected; |
392
|
|
|
} |
393
|
|
|
return $recordingarray + $metadataarray; |
394
|
|
|
} |
395
|
|
|
|
396
|
|
|
/** |
397
|
|
|
* Helper function to convert an xml recording preview images to an array in the format used by the plugin. |
398
|
|
|
* |
399
|
|
|
* @param object $preview |
400
|
|
|
* |
401
|
|
|
* @return array |
402
|
|
|
*/ |
403
|
|
|
function bigbluebuttonbn_get_recording_preview_images($preview) { |
404
|
|
|
$imagesarray = array(); |
405
|
|
|
foreach ($preview->images->image as $image) { |
406
|
|
|
$imagearray = array('url' => trim((string) $image)); |
407
|
|
|
foreach ($image->attributes() as $attkey => $attvalue) { |
408
|
|
|
$imagearray[$attkey] = (string) $attvalue; |
409
|
|
|
} |
410
|
|
|
array_push($imagesarray, $imagearray); |
411
|
|
|
} |
412
|
|
|
return $imagesarray; |
413
|
|
|
} |
414
|
|
|
|
415
|
|
|
/** |
416
|
|
|
* Helper function to convert an xml recording metadata object to an array in the format used by the plugin. |
417
|
|
|
* |
418
|
|
|
* @param array $metadata |
419
|
|
|
* |
420
|
|
|
* @return array |
421
|
|
|
*/ |
422
|
|
|
function bigbluebuttonbn_get_recording_array_meta($metadata) { |
423
|
|
|
$metadataarray = array(); |
424
|
|
|
foreach ($metadata as $key => $value) { |
425
|
|
|
if (is_object($value)) { |
426
|
|
|
$value = ''; |
427
|
|
|
} |
428
|
|
|
$metadataarray['meta_' . $key] = $value; |
429
|
|
|
} |
430
|
|
|
return $metadataarray; |
431
|
|
|
} |
432
|
|
|
|
433
|
|
|
/** |
434
|
|
|
* Helper function to sort an array of recordings. It compares the startTime in two recording objecs. |
435
|
|
|
* |
436
|
|
|
* @param object $a |
437
|
|
|
* @param object $b |
438
|
|
|
* |
439
|
|
|
* @return array |
440
|
|
|
*/ |
441
|
|
|
function bigbluebuttonbn_recording_build_sorter($a, $b) { |
442
|
|
|
global $CFG; |
443
|
|
|
$resultless = !empty($CFG->bigbluebuttonbn_recordings_sortorder) ? -1 : 1; |
444
|
|
|
$resultmore = !empty($CFG->bigbluebuttonbn_recordings_sortorder) ? 1 : -1; |
445
|
|
|
if ($a['startTime'] < $b['startTime']) { |
446
|
|
|
return $resultless; |
447
|
|
|
} |
448
|
|
|
if ($a['startTime'] == $b['startTime']) { |
449
|
|
|
return 0; |
450
|
|
|
} |
451
|
|
|
return $resultmore; |
452
|
|
|
} |
453
|
|
|
|
454
|
|
|
/** |
455
|
|
|
* Perform deleteRecordings on BBB. |
456
|
|
|
* |
457
|
|
|
* @param string $recordids |
458
|
|
|
* |
459
|
|
|
* @return boolean |
460
|
|
|
*/ |
461
|
|
View Code Duplication |
function bigbluebuttonbn_delete_recordings($recordids) { |
|
|
|
|
462
|
|
|
$ids = explode(',', $recordids); |
463
|
|
|
foreach ($ids as $id) { |
464
|
|
|
$xml = bigbluebuttonbn_wrap_xml_load_file( |
465
|
|
|
\mod_bigbluebuttonbn\locallib\bigbluebutton::action_url('deleteRecordings', ['recordID' => $id]) |
466
|
|
|
); |
467
|
|
|
if ($xml && $xml->returncode != 'SUCCESS') { |
468
|
|
|
return false; |
469
|
|
|
} |
470
|
|
|
} |
471
|
|
|
return true; |
472
|
|
|
} |
473
|
|
|
|
474
|
|
|
/** |
475
|
|
|
* Perform publishRecordings on BBB. |
476
|
|
|
* |
477
|
|
|
* @param string $recordids |
478
|
|
|
* @param string $publish |
479
|
|
|
*/ |
480
|
|
View Code Duplication |
function bigbluebuttonbn_publish_recordings($recordids, $publish = 'true') { |
|
|
|
|
481
|
|
|
$ids = explode(',', $recordids); |
482
|
|
|
foreach ($ids as $id) { |
483
|
|
|
$xml = bigbluebuttonbn_wrap_xml_load_file( |
484
|
|
|
\mod_bigbluebuttonbn\locallib\bigbluebutton::action_url('publishRecordings', ['recordID' => $id, 'publish' => $publish]) |
485
|
|
|
); |
486
|
|
|
if ($xml && $xml->returncode != 'SUCCESS') { |
487
|
|
|
return false; |
488
|
|
|
} |
489
|
|
|
} |
490
|
|
|
return true; |
491
|
|
|
} |
492
|
|
|
|
493
|
|
|
/** |
494
|
|
|
* Perform updateRecordings on BBB. |
495
|
|
|
* |
496
|
|
|
* @param string $recordids |
497
|
|
|
* @param array $params ['key'=>param_key, 'value'] |
498
|
|
|
*/ |
499
|
|
View Code Duplication |
function bigbluebuttonbn_update_recordings($recordids, $params) { |
|
|
|
|
500
|
|
|
$ids = explode(',', $recordids); |
501
|
|
|
foreach ($ids as $id) { |
502
|
|
|
$xml = bigbluebuttonbn_wrap_xml_load_file( |
503
|
|
|
\mod_bigbluebuttonbn\locallib\bigbluebutton::action_url('updateRecordings', ['recordID' => $id] + (array) $params) |
504
|
|
|
); |
505
|
|
|
if ($xml && $xml->returncode != 'SUCCESS') { |
506
|
|
|
return false; |
507
|
|
|
} |
508
|
|
|
} |
509
|
|
|
return true; |
510
|
|
|
} |
511
|
|
|
|
512
|
|
|
/** |
513
|
|
|
* Perform end on BBB. |
514
|
|
|
* |
515
|
|
|
* @param string $meetingid |
516
|
|
|
* @param string $modpw |
517
|
|
|
*/ |
518
|
|
|
function bigbluebuttonbn_end_meeting($meetingid, $modpw) { |
519
|
|
|
$xml = bigbluebuttonbn_wrap_xml_load_file( |
520
|
|
|
\mod_bigbluebuttonbn\locallib\bigbluebutton::action_url('end', ['meetingID' => $meetingid, 'password' => $modpw]) |
521
|
|
|
); |
522
|
|
|
if ($xml) { |
523
|
|
|
// If the xml packet returned failure it displays the message to the user. |
524
|
|
|
return array('returncode' => $xml->returncode, 'message' => $xml->message, 'messageKey' => $xml->messageKey); |
525
|
|
|
} |
526
|
|
|
// If the server is unreachable, then prompts the user of the necessary action. |
527
|
|
|
return null; |
528
|
|
|
} |
529
|
|
|
|
530
|
|
|
/** |
531
|
|
|
* Perform api request on BBB. |
532
|
|
|
* |
533
|
|
|
* @return string |
534
|
|
|
*/ |
535
|
|
|
function bigbluebuttonbn_get_server_version() { |
536
|
|
|
$xml = bigbluebuttonbn_wrap_xml_load_file( |
537
|
|
|
\mod_bigbluebuttonbn\locallib\bigbluebutton::action_url() |
538
|
|
|
); |
539
|
|
|
if ($xml && $xml->returncode == 'SUCCESS') { |
540
|
|
|
return $xml->version; |
541
|
|
|
} |
542
|
|
|
return null; |
543
|
|
|
} |
544
|
|
|
|
545
|
|
|
/** |
546
|
|
|
* Perform api request on BBB and wraps the response in an XML object |
547
|
|
|
* |
548
|
|
|
* @param string $url |
549
|
|
|
* @param string $method |
550
|
|
|
* @param string $data |
551
|
|
|
* @param string $contenttype |
552
|
|
|
* |
553
|
|
|
* @return object |
554
|
|
|
*/ |
555
|
|
|
function bigbluebuttonbn_wrap_xml_load_file($url, $method = 'GET', $data = null, $contenttype = 'text/xml') { |
556
|
|
|
if (extension_loaded('curl')) { |
557
|
|
|
$response = bigbluebuttonbn_wrap_xml_load_file_curl_request($url, $method, $data, $contenttype); |
558
|
|
|
if (!$response) { |
559
|
|
|
debugging('No response on wrap_simplexml_load_file', DEBUG_DEVELOPER); |
560
|
|
|
return null; |
561
|
|
|
} |
562
|
|
|
$previous = libxml_use_internal_errors(true); |
563
|
|
|
try { |
564
|
|
|
$xml = simplexml_load_string($response, 'SimpleXMLElement', LIBXML_NOCDATA | LIBXML_NOBLANKS); |
565
|
|
|
return $xml; |
566
|
|
|
} catch (Exception $e) { |
567
|
|
|
libxml_use_internal_errors($previous); |
568
|
|
|
$error = 'Caught exception: ' . $e->getMessage(); |
569
|
|
|
debugging($error, DEBUG_DEVELOPER); |
570
|
|
|
return null; |
571
|
|
|
} |
572
|
|
|
} |
573
|
|
|
// Alternative request non CURL based. |
574
|
|
|
$previous = libxml_use_internal_errors(true); |
575
|
|
|
try { |
576
|
|
|
$response = simplexml_load_file($url, 'SimpleXMLElement', LIBXML_NOCDATA | LIBXML_NOBLANKS); |
577
|
|
|
return $response; |
578
|
|
|
} catch (Exception $e) { |
579
|
|
|
$error = 'Caught exception: ' . $e->getMessage(); |
580
|
|
|
debugging($error, DEBUG_DEVELOPER); |
581
|
|
|
libxml_use_internal_errors($previous); |
582
|
|
|
return null; |
583
|
|
|
} |
584
|
|
|
} |
585
|
|
|
|
586
|
|
|
/** |
587
|
|
|
* Perform api request on BBB using CURL and wraps the response in an XML object |
588
|
|
|
* |
589
|
|
|
* @param string $url |
590
|
|
|
* @param string $method |
591
|
|
|
* @param string $data |
592
|
|
|
* @param string $contenttype |
593
|
|
|
* |
594
|
|
|
* @return object |
595
|
|
|
*/ |
596
|
|
|
function bigbluebuttonbn_wrap_xml_load_file_curl_request($url, $method = 'GET', $data = null, $contenttype = 'text/xml') { |
597
|
|
|
global $CFG; |
598
|
|
|
require_once($CFG->libdir . '/filelib.php'); |
599
|
|
|
$c = new curl(); |
600
|
|
|
$c->setopt(array('SSL_VERIFYPEER' => true)); |
601
|
|
|
if ($method == 'POST') { |
602
|
|
|
if (is_null($data) || is_array($data)) { |
603
|
|
|
return $c->post($url); |
604
|
|
|
} |
605
|
|
|
$options = array(); |
606
|
|
|
$options['CURLOPT_HTTPHEADER'] = array( |
607
|
|
|
'Content-Type: ' . $contenttype, |
608
|
|
|
'Content-Length: ' . strlen($data), |
609
|
|
|
'Content-Language: en-US', |
610
|
|
|
); |
611
|
|
|
|
612
|
|
|
return $c->post($url, $data, $options); |
613
|
|
|
} |
614
|
|
|
if ($method == 'HEAD') { |
615
|
|
|
$c->head($url, array('followlocation' => true, 'timeout' => 1)); |
616
|
|
|
return $c->get_info(); |
617
|
|
|
} |
618
|
|
|
return $c->get($url); |
619
|
|
|
} |
620
|
|
|
|
621
|
|
|
/** |
622
|
|
|
* End the session associated with this instance (if it's running). |
623
|
|
|
* |
624
|
|
|
* @param object $bigbluebuttonbn |
625
|
|
|
* |
626
|
|
|
* @return void |
627
|
|
|
*/ |
628
|
|
|
function bigbluebuttonbn_end_meeting_if_running($bigbluebuttonbn) { |
629
|
|
|
$meetingid = $bigbluebuttonbn->meetingid . '-' . $bigbluebuttonbn->course . '-' . $bigbluebuttonbn->id; |
630
|
|
|
if (bigbluebuttonbn_is_meeting_running($meetingid)) { |
631
|
|
|
bigbluebuttonbn_end_meeting($meetingid, $bigbluebuttonbn->moderatorpass); |
632
|
|
|
} |
633
|
|
|
} |
634
|
|
|
|
635
|
|
|
/** |
636
|
|
|
* Returns user roles in a context. |
637
|
|
|
* |
638
|
|
|
* @param object $context |
639
|
|
|
* @param integer $userid |
640
|
|
|
* |
641
|
|
|
* @return array $userroles |
642
|
|
|
*/ |
643
|
|
|
function bigbluebuttonbn_get_user_roles($context, $userid) { |
644
|
|
|
global $DB; |
645
|
|
|
$userroles = get_user_roles($context, $userid); |
646
|
|
|
if ($userroles) { |
647
|
|
|
$where = ''; |
648
|
|
|
foreach ($userroles as $userrole) { |
649
|
|
|
$where .= (empty($where) ? ' WHERE' : ' OR') . ' id=' . $userrole->roleid; |
650
|
|
|
} |
651
|
|
|
$userroles = $DB->get_records_sql('SELECT * FROM {role}' . $where); |
652
|
|
|
} |
653
|
|
|
return $userroles; |
654
|
|
|
} |
655
|
|
|
|
656
|
|
|
/** |
657
|
|
|
* Returns guest role wrapped in an array. |
658
|
|
|
* |
659
|
|
|
* @return array |
660
|
|
|
*/ |
661
|
|
|
function bigbluebuttonbn_get_guest_role() { |
662
|
|
|
$guestrole = get_guest_role(); |
663
|
|
|
return array($guestrole->id => $guestrole); |
664
|
|
|
} |
665
|
|
|
|
666
|
|
|
/** |
667
|
|
|
* Returns an array containing all the users in a context. |
668
|
|
|
* |
669
|
|
|
* @param context $context |
670
|
|
|
* |
671
|
|
|
* @return array $users |
672
|
|
|
*/ |
673
|
|
|
function bigbluebuttonbn_get_users(context $context = null) { |
674
|
|
|
$users = (array) get_enrolled_users($context, '', 0, 'u.*', null, 0, 0, true); |
675
|
|
|
foreach ($users as $key => $value) { |
676
|
|
|
$users[$key] = fullname($value); |
677
|
|
|
} |
678
|
|
|
return $users; |
679
|
|
|
} |
680
|
|
|
|
681
|
|
|
/** |
682
|
|
|
* Returns an array containing all the users in a context wrapped for html select element. |
683
|
|
|
* |
684
|
|
|
* @param context_course $context |
685
|
|
|
* @param null $bbactivity |
686
|
|
|
* @return array $users |
687
|
|
|
* @throws coding_exception |
688
|
|
|
* @throws moodle_exception |
689
|
|
|
*/ |
690
|
|
|
function bigbluebuttonbn_get_users_select(context_course $context, $bbactivity = null) { |
691
|
|
|
// CONTRIB-7972, check the group of current user and course group mode. |
692
|
|
|
$groups = null; |
|
|
|
|
693
|
|
|
$users = (array) get_enrolled_users($context, '', 0, 'u.*', null, 0, 0, true); |
694
|
|
|
$course = get_course($context->instanceid); |
695
|
|
|
$groupmode = groups_get_course_groupmode($course); |
696
|
|
|
if ($bbactivity) { |
697
|
|
|
list($bbcourse, $cm) = get_course_and_cm_from_instance($bbactivity->id, 'bigbluebuttonbn'); |
|
|
|
|
698
|
|
|
$groupmode = groups_get_activity_groupmode($cm); |
699
|
|
|
|
700
|
|
|
} |
701
|
|
|
if ($groupmode == SEPARATEGROUPS && !has_capability('moodle/site:accessallgroups', $context)) { |
702
|
|
|
global $USER; |
703
|
|
|
$groups = groups_get_all_groups($course->id, $USER->id); |
704
|
|
|
$users = []; |
705
|
|
|
foreach ($groups as $g) { |
706
|
|
|
$users += (array) get_enrolled_users($context, '', $g->id, 'u.*', null, 0, 0, true); |
707
|
|
|
} |
708
|
|
|
} |
709
|
|
|
return array_map( |
710
|
|
|
function($u) { |
711
|
|
|
return array('id' => $u->id, 'name' => fullname($u)); |
712
|
|
|
}, |
713
|
|
|
$users); |
714
|
|
|
} |
715
|
|
|
|
716
|
|
|
/** |
717
|
|
|
* Returns an array containing all the roles in a context. |
718
|
|
|
* |
719
|
|
|
* @param context $context |
720
|
|
|
* @param bool $onlyviewableroles |
721
|
|
|
* |
722
|
|
|
* @return array $roles |
723
|
|
|
*/ |
724
|
|
|
function bigbluebuttonbn_get_roles(context $context = null, bool $onlyviewableroles = true) { |
725
|
|
|
global $CFG; |
726
|
|
|
|
727
|
|
|
if ($onlyviewableroles == true && $CFG->branch >= 35) { |
|
|
|
|
728
|
|
|
$roles = (array) get_viewable_roles($context); |
729
|
|
|
foreach ($roles as $key => $value) { |
730
|
|
|
$roles[$key] = $value; |
731
|
|
|
} |
732
|
|
|
} else { |
733
|
|
|
$roles = (array) role_get_names($context); |
734
|
|
|
foreach ($roles as $key => $value) { |
735
|
|
|
$roles[$key] = $value->localname; |
736
|
|
|
} |
737
|
|
|
} |
738
|
|
|
|
739
|
|
|
return $roles; |
740
|
|
|
} |
741
|
|
|
|
742
|
|
|
/** |
743
|
|
|
* Returns an array containing all the roles in a context wrapped for html select element. |
744
|
|
|
* |
745
|
|
|
* @param context $context |
746
|
|
|
* @param bool $onlyviewableroles |
747
|
|
|
* |
748
|
|
|
* @return array $users |
749
|
|
|
*/ |
750
|
|
|
function bigbluebuttonbn_get_roles_select(context $context = null, bool $onlyviewableroles = true) { |
751
|
|
|
global $CFG; |
752
|
|
|
|
753
|
|
|
if ($onlyviewableroles == true && $CFG->branch >= 35) { |
|
|
|
|
754
|
|
|
$roles = (array) get_viewable_roles($context); |
755
|
|
|
foreach ($roles as $key => $value) { |
756
|
|
|
$roles[$key] = array('id' => $key, 'name' => $value); |
757
|
|
|
} |
758
|
|
|
} else { |
759
|
|
|
$roles = (array) role_get_names($context); |
760
|
|
|
foreach ($roles as $key => $value) { |
761
|
|
|
$roles[$key] = array('id' => $value->id, 'name' => $value->localname); |
762
|
|
|
} |
763
|
|
|
} |
764
|
|
|
|
765
|
|
|
return $roles; |
766
|
|
|
} |
767
|
|
|
|
768
|
|
|
/** |
769
|
|
|
* Returns role that corresponds to an id. |
770
|
|
|
* |
771
|
|
|
* @param string|integer $id |
772
|
|
|
* |
773
|
|
|
* @return object $role |
774
|
|
|
*/ |
775
|
|
|
function bigbluebuttonbn_get_role($id) { |
776
|
|
|
$roles = (array) role_get_names(); |
777
|
|
|
if (is_numeric($id) && isset($roles[$id])) { |
778
|
|
|
return (object) $roles[$id]; |
779
|
|
|
} |
780
|
|
|
foreach ($roles as $role) { |
781
|
|
|
if ($role->shortname == $id) { |
782
|
|
|
return $role; |
783
|
|
|
} |
784
|
|
|
} |
785
|
|
|
} |
786
|
|
|
|
787
|
|
|
/** |
788
|
|
|
* Returns an array to populate a list of participants used in mod_form.js. |
789
|
|
|
* |
790
|
|
|
* @param context $context |
791
|
|
|
* @param null|object $bbactivity |
792
|
|
|
* @return array $data |
793
|
|
|
*/ |
794
|
|
|
function bigbluebuttonbn_get_participant_data($context, $bbactivity = null) { |
795
|
|
|
$data = array( |
796
|
|
|
'all' => array( |
797
|
|
|
'name' => get_string('mod_form_field_participant_list_type_all', 'bigbluebuttonbn'), |
798
|
|
|
'children' => [] |
799
|
|
|
), |
800
|
|
|
); |
801
|
|
|
$data['role'] = array( |
802
|
|
|
'name' => get_string('mod_form_field_participant_list_type_role', 'bigbluebuttonbn'), |
803
|
|
|
'children' => bigbluebuttonbn_get_roles_select($context, true) |
804
|
|
|
); |
805
|
|
|
$data['user'] = array( |
806
|
|
|
'name' => get_string('mod_form_field_participant_list_type_user', 'bigbluebuttonbn'), |
807
|
|
|
'children' => bigbluebuttonbn_get_users_select($context, $bbactivity), |
|
|
|
|
808
|
|
|
); |
809
|
|
|
return $data; |
810
|
|
|
} |
811
|
|
|
|
812
|
|
|
/** |
813
|
|
|
* Returns an array to populate a list of participants used in mod_form.php. |
814
|
|
|
* |
815
|
|
|
* @param object $bigbluebuttonbn |
816
|
|
|
* @param context $context |
817
|
|
|
* |
818
|
|
|
* @return array |
819
|
|
|
*/ |
820
|
|
|
function bigbluebuttonbn_get_participant_list($bigbluebuttonbn, $context) { |
821
|
|
|
global $USER; |
822
|
|
|
if ($bigbluebuttonbn == null) { |
823
|
|
|
return bigbluebuttonbn_get_participant_rules_encoded( |
824
|
|
|
bigbluebuttonbn_get_participant_list_default($context, $USER->id) |
825
|
|
|
); |
826
|
|
|
} |
827
|
|
|
if (empty($bigbluebuttonbn->participants)) { |
828
|
|
|
$bigbluebuttonbn->participants = "[]"; |
829
|
|
|
} |
830
|
|
|
$rules = json_decode($bigbluebuttonbn->participants, true); |
831
|
|
|
if (empty($rules)) { |
832
|
|
|
$rules = bigbluebuttonbn_get_participant_list_default($context, bigbluebuttonbn_instance_ownerid($bigbluebuttonbn)); |
833
|
|
|
} |
834
|
|
|
return bigbluebuttonbn_get_participant_rules_encoded($rules); |
835
|
|
|
} |
836
|
|
|
|
837
|
|
|
/** |
838
|
|
|
* Returns an array to populate a list of participants used in mod_form.php with default values. |
839
|
|
|
* |
840
|
|
|
* @param context $context |
841
|
|
|
* @param integer $ownerid |
842
|
|
|
* |
843
|
|
|
* @return array |
844
|
|
|
*/ |
845
|
|
|
function bigbluebuttonbn_get_participant_list_default($context, $ownerid = null) { |
846
|
|
|
$participantlist = array(); |
847
|
|
|
$participantlist[] = array( |
848
|
|
|
'selectiontype' => 'all', |
849
|
|
|
'selectionid' => 'all', |
850
|
|
|
'role' => BIGBLUEBUTTONBN_ROLE_VIEWER, |
851
|
|
|
); |
852
|
|
|
$defaultrules = explode(',', \mod_bigbluebuttonbn\locallib\config::get('participant_moderator_default')); |
853
|
|
|
foreach ($defaultrules as $defaultrule) { |
854
|
|
|
if ($defaultrule == '0') { |
855
|
|
|
if (!empty($ownerid) && is_enrolled($context, $ownerid)) { |
856
|
|
|
$participantlist[] = array( |
857
|
|
|
'selectiontype' => 'user', |
858
|
|
|
'selectionid' => (string) $ownerid, |
859
|
|
|
'role' => BIGBLUEBUTTONBN_ROLE_MODERATOR); |
860
|
|
|
} |
861
|
|
|
continue; |
862
|
|
|
} |
863
|
|
|
$participantlist[] = array( |
864
|
|
|
'selectiontype' => 'role', |
865
|
|
|
'selectionid' => $defaultrule, |
866
|
|
|
'role' => BIGBLUEBUTTONBN_ROLE_MODERATOR); |
867
|
|
|
} |
868
|
|
|
return $participantlist; |
869
|
|
|
} |
870
|
|
|
|
871
|
|
|
/** |
872
|
|
|
* Returns an array to populate a list of participants used in mod_form.php with bigbluebuttonbn values. |
873
|
|
|
* |
874
|
|
|
* @param array $rules |
875
|
|
|
* |
876
|
|
|
* @return array |
877
|
|
|
*/ |
878
|
|
|
function bigbluebuttonbn_get_participant_rules_encoded($rules) { |
879
|
|
|
foreach ($rules as $key => $rule) { |
880
|
|
|
if ($rule['selectiontype'] !== 'role' || is_numeric($rule['selectionid'])) { |
881
|
|
|
continue; |
882
|
|
|
} |
883
|
|
|
$role = bigbluebuttonbn_get_role($rule['selectionid']); |
884
|
|
|
if ($role == null) { |
885
|
|
|
unset($rules[$key]); |
886
|
|
|
continue; |
887
|
|
|
} |
888
|
|
|
$rule['selectionid'] = $role->id; |
889
|
|
|
$rules[$key] = $rule; |
890
|
|
|
} |
891
|
|
|
return $rules; |
892
|
|
|
} |
893
|
|
|
|
894
|
|
|
/** |
895
|
|
|
* Returns an array to populate a list of participant_selection used in mod_form.php. |
896
|
|
|
* |
897
|
|
|
* @return array |
898
|
|
|
*/ |
899
|
|
|
function bigbluebuttonbn_get_participant_selection_data() { |
900
|
|
|
return [ |
901
|
|
|
'type_options' => [ |
902
|
|
|
'all' => get_string('mod_form_field_participant_list_type_all', 'bigbluebuttonbn'), |
903
|
|
|
'role' => get_string('mod_form_field_participant_list_type_role', 'bigbluebuttonbn'), |
904
|
|
|
'user' => get_string('mod_form_field_participant_list_type_user', 'bigbluebuttonbn'), |
905
|
|
|
], |
906
|
|
|
'type_selected' => 'all', |
907
|
|
|
'options' => ['all' => '---------------'], |
908
|
|
|
'selected' => 'all', |
909
|
|
|
]; |
910
|
|
|
} |
911
|
|
|
|
912
|
|
|
/** |
913
|
|
|
* Evaluate if a user in a context is moderator based on roles and participation rules. |
914
|
|
|
* |
915
|
|
|
* @param context $context |
916
|
|
|
* @param array $participantlist |
917
|
|
|
* @param integer $userid |
918
|
|
|
* |
919
|
|
|
* @return boolean |
920
|
|
|
*/ |
921
|
|
|
function bigbluebuttonbn_is_moderator($context, $participantlist, $userid = null) { |
922
|
|
|
global $USER; |
923
|
|
|
if (!is_array($participantlist)) { |
924
|
|
|
return false; |
925
|
|
|
} |
926
|
|
|
if (empty($userid)) { |
927
|
|
|
$userid = $USER->id; |
928
|
|
|
} |
929
|
|
|
$userroles = bigbluebuttonbn_get_guest_role(); |
930
|
|
|
if (!isguestuser()) { |
931
|
|
|
$userroles = bigbluebuttonbn_get_user_roles($context, $userid); |
932
|
|
|
} |
933
|
|
|
return bigbluebuttonbn_is_moderator_validator($participantlist, $userid, $userroles); |
934
|
|
|
} |
935
|
|
|
|
936
|
|
|
/** |
937
|
|
|
* Iterates participant list rules to evaluate if a user is moderator. |
938
|
|
|
* |
939
|
|
|
* @param array $participantlist |
940
|
|
|
* @param integer $userid |
941
|
|
|
* @param array $userroles |
942
|
|
|
* |
943
|
|
|
* @return boolean |
944
|
|
|
*/ |
945
|
|
|
function bigbluebuttonbn_is_moderator_validator($participantlist, $userid, $userroles) { |
946
|
|
|
// Iterate participant rules. |
947
|
|
|
foreach ($participantlist as $participant) { |
948
|
|
|
if (bigbluebuttonbn_is_moderator_validate_rule($participant, $userid, $userroles)) { |
949
|
|
|
return true; |
950
|
|
|
} |
951
|
|
|
} |
952
|
|
|
return false; |
953
|
|
|
} |
954
|
|
|
|
955
|
|
|
/** |
956
|
|
|
* Evaluate if a user is moderator based on roles and a particular participation rule. |
957
|
|
|
* |
958
|
|
|
* @param object $participant |
959
|
|
|
* @param integer $userid |
960
|
|
|
* @param array $userroles |
961
|
|
|
* |
962
|
|
|
* @return boolean |
963
|
|
|
*/ |
964
|
|
|
function bigbluebuttonbn_is_moderator_validate_rule($participant, $userid, $userroles) { |
965
|
|
|
if ($participant['role'] == BIGBLUEBUTTONBN_ROLE_VIEWER) { |
966
|
|
|
return false; |
967
|
|
|
} |
968
|
|
|
// Validation for the 'all' rule. |
969
|
|
|
if ($participant['selectiontype'] == 'all') { |
970
|
|
|
return true; |
971
|
|
|
} |
972
|
|
|
// Validation for a 'user' rule. |
973
|
|
|
if ($participant['selectiontype'] == 'user') { |
974
|
|
|
if ($participant['selectionid'] == $userid) { |
975
|
|
|
return true; |
976
|
|
|
} |
977
|
|
|
return false; |
978
|
|
|
} |
979
|
|
|
// Validation for a 'role' rule. |
980
|
|
|
$role = bigbluebuttonbn_get_role($participant['selectionid']); |
981
|
|
|
if ($role != null && array_key_exists($role->id, $userroles)) { |
982
|
|
|
return true; |
983
|
|
|
} |
984
|
|
|
return false; |
985
|
|
|
} |
986
|
|
|
|
987
|
|
|
/** |
988
|
|
|
* Helper returns error message key for the language file that corresponds to a bigbluebutton error key. |
989
|
|
|
* |
990
|
|
|
* @param string $messagekey |
991
|
|
|
* @param string $defaultkey |
992
|
|
|
* |
993
|
|
|
* @return string |
994
|
|
|
*/ |
995
|
|
|
function bigbluebuttonbn_get_error_key($messagekey, $defaultkey = null) { |
996
|
|
|
if ($messagekey == 'checksumError') { |
997
|
|
|
return 'index_error_checksum'; |
998
|
|
|
} |
999
|
|
|
if ($messagekey == 'maxConcurrent') { |
1000
|
|
|
return 'view_error_max_concurrent'; |
1001
|
|
|
} |
1002
|
|
|
return $defaultkey; |
1003
|
|
|
} |
1004
|
|
|
|
1005
|
|
|
/** |
1006
|
|
|
* Helper evaluates if a voicebridge number is unique. |
1007
|
|
|
* |
1008
|
|
|
* @param integer $instance |
1009
|
|
|
* @param integer $voicebridge |
1010
|
|
|
* |
1011
|
|
|
* @return string |
1012
|
|
|
*/ |
1013
|
|
|
function bigbluebuttonbn_voicebridge_unique($instance, $voicebridge) { |
1014
|
|
|
global $DB; |
1015
|
|
|
if ($voicebridge == 0) { |
1016
|
|
|
return true; |
1017
|
|
|
} |
1018
|
|
|
$select = 'voicebridge = ' . $voicebridge; |
1019
|
|
|
if ($instance != 0) { |
1020
|
|
|
$select .= ' AND id <>' . $instance; |
1021
|
|
|
} |
1022
|
|
|
if (!$DB->get_records_select('bigbluebuttonbn', $select)) { |
1023
|
|
|
return true; |
1024
|
|
|
} |
1025
|
|
|
return false; |
1026
|
|
|
} |
1027
|
|
|
|
1028
|
|
|
/** |
1029
|
|
|
* Helper estimate a duration for the meeting based on the closingtime. |
1030
|
|
|
* |
1031
|
|
|
* @param integer $closingtime |
1032
|
|
|
* |
1033
|
|
|
* @return integer |
1034
|
|
|
*/ |
1035
|
|
|
function bigbluebuttonbn_get_duration($closingtime) { |
1036
|
|
|
$duration = 0; |
1037
|
|
|
$now = time(); |
1038
|
|
|
if ($closingtime > 0 && $now < $closingtime) { |
1039
|
|
|
$duration = ceil(($closingtime - $now) / 60); |
1040
|
|
|
$compensationtime = intval((int) \mod_bigbluebuttonbn\locallib\config::get('scheduled_duration_compensation')); |
1041
|
|
|
$duration = intval($duration) + $compensationtime; |
1042
|
|
|
} |
1043
|
|
|
return $duration; |
1044
|
|
|
} |
1045
|
|
|
|
1046
|
|
|
/** |
1047
|
|
|
* Helper return array containing the file descriptor for a preuploaded presentation. |
1048
|
|
|
* |
1049
|
|
|
* @param context $context |
1050
|
|
|
* @param string $presentation |
1051
|
|
|
* @param integer $id |
1052
|
|
|
* |
1053
|
|
|
* @return array |
1054
|
|
|
*/ |
1055
|
|
|
function bigbluebuttonbn_get_presentation_array($context, $presentation, $id = null) { |
1056
|
|
|
global $CFG; |
1057
|
|
|
if (empty($presentation)) { |
1058
|
|
|
if ($CFG->bigbluebuttonbn_preuploadpresentation_enabled) { |
1059
|
|
|
// Item has not presentation but presentation is enabled.. |
1060
|
|
|
// Check if exist some file by default in general mod setting ("presentationdefault"). |
1061
|
|
|
$fs = get_file_storage(); |
1062
|
|
|
$files = $fs->get_area_files( |
1063
|
|
|
context_system::instance()->id, |
1064
|
|
|
'mod_bigbluebuttonbn', |
1065
|
|
|
'presentationdefault', |
1066
|
|
|
0, |
1067
|
|
|
"filename", |
1068
|
|
|
false |
1069
|
|
|
); |
1070
|
|
|
|
1071
|
|
View Code Duplication |
if (count($files) == 0) { |
|
|
|
|
1072
|
|
|
// Not exist file by default in "presentationbydefault" setting. |
1073
|
|
|
return array('url' => null, 'name' => null, 'icon' => null, 'mimetype_description' => null); |
1074
|
|
|
} |
1075
|
|
|
|
1076
|
|
|
// Exists file in general setting to use as default for presentation. Cache image for temp public access. |
1077
|
|
|
$file = reset($files); |
1078
|
|
|
unset($files); |
1079
|
|
|
$pnoncevalue = null; |
1080
|
|
View Code Duplication |
if (!is_null($id)) { |
|
|
|
|
1081
|
|
|
// Create the nonce component for granting a temporary public access. |
1082
|
|
|
$cache = cache::make_from_params( |
1083
|
|
|
cache_store::MODE_APPLICATION, |
1084
|
|
|
'mod_bigbluebuttonbn', |
1085
|
|
|
'presentationdefault_cache' |
1086
|
|
|
); |
1087
|
|
|
$pnoncekey = sha1(context_system::instance()->id); |
1088
|
|
|
/* The item id was adapted for granting public access to the presentation once in order |
1089
|
|
|
* to allow BigBlueButton to gather the file. */ |
1090
|
|
|
$pnoncevalue = bigbluebuttonbn_generate_nonce(); |
1091
|
|
|
$cache->set($pnoncekey, array('value' => $pnoncevalue, 'counter' => 0)); |
1092
|
|
|
} |
1093
|
|
|
|
1094
|
|
|
$url = moodle_url::make_pluginfile_url( |
1095
|
|
|
$file->get_contextid(), |
1096
|
|
|
$file->get_component(), |
1097
|
|
|
$file->get_filearea(), |
1098
|
|
|
$pnoncevalue, |
1099
|
|
|
$file->get_filepath(), |
1100
|
|
|
$file->get_filename() |
1101
|
|
|
); |
1102
|
|
|
return (array('name' => $file->get_filename(), 'icon' => file_file_icon($file, 24), |
1103
|
|
|
'url' => $url->out(false), 'mimetype_description' => get_mimetype_description($file))); |
1104
|
|
|
} |
1105
|
|
|
|
1106
|
|
|
return array('url' => null, 'name' => null, 'icon' => null, 'mimetype_description' => null); |
1107
|
|
|
} |
1108
|
|
|
$fs = get_file_storage(); |
1109
|
|
|
$files = $fs->get_area_files( |
1110
|
|
|
$context->id, |
1111
|
|
|
'mod_bigbluebuttonbn', |
1112
|
|
|
'presentation', |
1113
|
|
|
0, |
1114
|
|
|
'itemid, filepath, filename', |
1115
|
|
|
false |
1116
|
|
|
); |
1117
|
|
View Code Duplication |
if (count($files) == 0) { |
|
|
|
|
1118
|
|
|
return array('url' => null, 'name' => null, 'icon' => null, 'mimetype_description' => null); |
1119
|
|
|
} |
1120
|
|
|
$file = reset($files); |
1121
|
|
|
unset($files); |
1122
|
|
|
$pnoncevalue = null; |
1123
|
|
View Code Duplication |
if (!is_null($id)) { |
|
|
|
|
1124
|
|
|
// Create the nonce component for granting a temporary public access. |
1125
|
|
|
$cache = cache::make_from_params( |
1126
|
|
|
cache_store::MODE_APPLICATION, |
1127
|
|
|
'mod_bigbluebuttonbn', |
1128
|
|
|
'presentation_cache' |
1129
|
|
|
); |
1130
|
|
|
$pnoncekey = sha1($id); |
1131
|
|
|
/* The item id was adapted for granting public access to the presentation once in order |
1132
|
|
|
* to allow BigBlueButton to gather the file. */ |
1133
|
|
|
$pnoncevalue = bigbluebuttonbn_generate_nonce(); |
1134
|
|
|
$cache->set($pnoncekey, array('value' => $pnoncevalue, 'counter' => 0)); |
1135
|
|
|
} |
1136
|
|
|
$url = moodle_url::make_pluginfile_url( |
1137
|
|
|
$file->get_contextid(), |
1138
|
|
|
$file->get_component(), |
1139
|
|
|
$file->get_filearea(), |
1140
|
|
|
$pnoncevalue, |
1141
|
|
|
$file->get_filepath(), |
1142
|
|
|
$file->get_filename() |
1143
|
|
|
); |
1144
|
|
|
return array('name' => $file->get_filename(), 'icon' => file_file_icon($file, 24), |
1145
|
|
|
'url' => $url->out(false), 'mimetype_description' => get_mimetype_description($file)); |
1146
|
|
|
} |
1147
|
|
|
|
1148
|
|
|
/** |
1149
|
|
|
* Helper generates a nonce used for the preuploaded presentation callback url. |
1150
|
|
|
* |
1151
|
|
|
* @return string |
1152
|
|
|
*/ |
1153
|
|
|
function bigbluebuttonbn_generate_nonce() { |
1154
|
|
|
$mt = microtime(); |
1155
|
|
|
$rand = mt_rand(); |
1156
|
|
|
return md5($mt . $rand); |
1157
|
|
|
} |
1158
|
|
|
|
1159
|
|
|
/** |
1160
|
|
|
* Helper generates a random password. |
1161
|
|
|
* |
1162
|
|
|
* @param integer $length |
1163
|
|
|
* @param string $unique |
1164
|
|
|
* |
1165
|
|
|
* @return string |
1166
|
|
|
*/ |
1167
|
|
|
function bigbluebuttonbn_random_password($length = 8, $unique = "") { |
1168
|
|
|
$chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'; |
1169
|
|
|
do { |
1170
|
|
|
$password = substr(str_shuffle($chars), 0, $length); |
1171
|
|
|
} while ($unique == $password); |
1172
|
|
|
return $password; |
1173
|
|
|
} |
1174
|
|
|
|
1175
|
|
|
/** |
1176
|
|
|
* Helper register a bigbluebuttonbn event. |
1177
|
|
|
* |
1178
|
|
|
* @param string $type |
1179
|
|
|
* @param object $bigbluebuttonbn |
1180
|
|
|
* @param array $options [timecreated, userid, other] |
1181
|
|
|
* |
1182
|
|
|
* @return void |
1183
|
|
|
*/ |
1184
|
|
|
function bigbluebuttonbn_event_log($type, $bigbluebuttonbn, $options = []) { |
1185
|
|
|
global $DB; |
1186
|
|
|
if (!in_array($type, \mod_bigbluebuttonbn\event\events::$events)) { |
1187
|
|
|
// No log will be created. |
1188
|
|
|
return; |
1189
|
|
|
} |
1190
|
|
|
$course = $DB->get_record('course', array('id' => $bigbluebuttonbn->course), '*', MUST_EXIST); |
1191
|
|
|
$cm = get_coursemodule_from_instance('bigbluebuttonbn', $bigbluebuttonbn->id, $course->id, false, MUST_EXIST); |
1192
|
|
|
$context = context_module::instance($cm->id); |
1193
|
|
|
$params = array('context' => $context, 'objectid' => $bigbluebuttonbn->id); |
1194
|
|
|
if (array_key_exists('timecreated', $options)) { |
1195
|
|
|
$params['timecreated'] = $options['timecreated']; |
1196
|
|
|
} |
1197
|
|
|
if (array_key_exists('userid', $options)) { |
1198
|
|
|
$params['userid'] = $options['userid']; |
1199
|
|
|
} |
1200
|
|
|
if (array_key_exists('other', $options)) { |
1201
|
|
|
$params['other'] = $options['other']; |
1202
|
|
|
} |
1203
|
|
|
$event = call_user_func_array( |
1204
|
|
|
'\mod_bigbluebuttonbn\event\\' . $type . '::create', |
1205
|
|
|
array($params) |
1206
|
|
|
); |
1207
|
|
|
$event->add_record_snapshot('course_modules', $cm); |
1208
|
|
|
$event->add_record_snapshot('course', $course); |
1209
|
|
|
$event->add_record_snapshot('bigbluebuttonbn', $bigbluebuttonbn); |
1210
|
|
|
$event->trigger(); |
1211
|
|
|
} |
1212
|
|
|
|
1213
|
|
|
/** |
1214
|
|
|
* Updates the meeting info cached object when a participant has joined. |
1215
|
|
|
* |
1216
|
|
|
* @param string $meetingid |
1217
|
|
|
* @param bool $ismoderator |
1218
|
|
|
* |
1219
|
|
|
* @return void |
1220
|
|
|
*/ |
1221
|
|
|
function bigbluebuttonbn_participant_joined($meetingid, $ismoderator) { |
1222
|
|
|
$cache = cache::make_from_params(cache_store::MODE_APPLICATION, 'mod_bigbluebuttonbn', 'meetings_cache'); |
1223
|
|
|
$result = $cache->get($meetingid); |
1224
|
|
|
$meetinginfo = json_decode($result['meeting_info']); |
1225
|
|
|
$meetinginfo->participantCount += 1; |
1226
|
|
|
if ($ismoderator) { |
1227
|
|
|
$meetinginfo->moderatorCount += 1; |
1228
|
|
|
} |
1229
|
|
|
$cache->set($meetingid, array('creation_time' => $result['creation_time'], |
1230
|
|
|
'meeting_info' => json_encode($meetinginfo))); |
1231
|
|
|
} |
1232
|
|
|
|
1233
|
|
|
/** |
1234
|
|
|
* Gets a meeting info object cached or fetched from the live session. |
1235
|
|
|
* |
1236
|
|
|
* @param string $meetingid |
1237
|
|
|
* @param boolean $updatecache |
1238
|
|
|
* |
1239
|
|
|
* @return array |
1240
|
|
|
*/ |
1241
|
|
|
function bigbluebuttonbn_get_meeting_info($meetingid, $updatecache = false) { |
1242
|
|
|
$cachettl = (int) \mod_bigbluebuttonbn\locallib\config::get('waitformoderator_cache_ttl'); |
1243
|
|
|
$cache = cache::make_from_params(cache_store::MODE_APPLICATION, 'mod_bigbluebuttonbn', 'meetings_cache'); |
1244
|
|
|
$result = $cache->get($meetingid); |
1245
|
|
|
$now = time(); |
1246
|
|
|
if (!$updatecache && !empty($result) && $now < ($result['creation_time'] + $cachettl)) { |
1247
|
|
|
// Use the value in the cache. |
1248
|
|
|
return (array) json_decode($result['meeting_info']); |
1249
|
|
|
} |
1250
|
|
|
// Ping again and refresh the cache. |
1251
|
|
|
$meetinginfo = (array) bigbluebuttonbn_wrap_xml_load_file( |
1252
|
|
|
\mod_bigbluebuttonbn\locallib\bigbluebutton::action_url('getMeetingInfo', ['meetingID' => $meetingid]) |
1253
|
|
|
); |
1254
|
|
|
$cache->set($meetingid, array('creation_time' => time(), 'meeting_info' => json_encode($meetinginfo))); |
1255
|
|
|
return $meetinginfo; |
1256
|
|
|
} |
1257
|
|
|
|
1258
|
|
|
/** |
1259
|
|
|
* Perform isMeetingRunning on BBB. |
1260
|
|
|
* |
1261
|
|
|
* @param string $meetingid |
1262
|
|
|
* @param boolean $updatecache |
1263
|
|
|
* |
1264
|
|
|
* @return boolean |
1265
|
|
|
*/ |
1266
|
|
|
function bigbluebuttonbn_is_meeting_running($meetingid, $updatecache = false) { |
1267
|
|
|
/* As a workaround to isMeetingRunning that always return SUCCESS but only returns true |
1268
|
|
|
* when at least one user is in the session, we use getMeetingInfo instead. |
1269
|
|
|
*/ |
1270
|
|
|
$meetinginfo = bigbluebuttonbn_get_meeting_info($meetingid, $updatecache); |
1271
|
|
|
return ($meetinginfo['returncode'] === 'SUCCESS'); |
1272
|
|
|
} |
1273
|
|
|
|
1274
|
|
|
/** |
1275
|
|
|
* Publish an imported recording. |
1276
|
|
|
* |
1277
|
|
|
* @param string $id |
1278
|
|
|
* @param boolean $publish |
1279
|
|
|
* |
1280
|
|
|
* @return boolean |
1281
|
|
|
*/ |
1282
|
|
View Code Duplication |
function bigbluebuttonbn_publish_recording_imported($id, $publish = true) { |
|
|
|
|
1283
|
|
|
global $DB; |
1284
|
|
|
// Locate the record to be updated. |
1285
|
|
|
$record = $DB->get_record('bigbluebuttonbn_logs', array('id' => $id)); |
1286
|
|
|
$meta = json_decode($record->meta, true); |
1287
|
|
|
// Prepare data for the update. |
1288
|
|
|
$meta['recording']['published'] = ($publish) ? 'true' : 'false'; |
1289
|
|
|
$record->meta = json_encode($meta); |
1290
|
|
|
// Proceed with the update. |
1291
|
|
|
$DB->update_record('bigbluebuttonbn_logs', $record); |
1292
|
|
|
return true; |
1293
|
|
|
} |
1294
|
|
|
|
1295
|
|
|
/** |
1296
|
|
|
* Delete an imported recording. |
1297
|
|
|
* |
1298
|
|
|
* @param string $id |
1299
|
|
|
* |
1300
|
|
|
* @return boolean |
1301
|
|
|
*/ |
1302
|
|
|
function bigbluebuttonbn_delete_recording_imported($id) { |
1303
|
|
|
global $DB; |
1304
|
|
|
// Execute delete. |
1305
|
|
|
$DB->delete_records('bigbluebuttonbn_logs', array('id' => $id)); |
1306
|
|
|
return true; |
1307
|
|
|
} |
1308
|
|
|
|
1309
|
|
|
/** |
1310
|
|
|
* Update an imported recording. |
1311
|
|
|
* |
1312
|
|
|
* @param string $id |
1313
|
|
|
* @param array $params ['key'=>param_key, 'value'] |
1314
|
|
|
* |
1315
|
|
|
* @return boolean |
1316
|
|
|
*/ |
1317
|
|
|
function bigbluebuttonbn_update_recording_imported($id, $params) { |
1318
|
|
|
global $DB; |
1319
|
|
|
// Locate the record to be updated. |
1320
|
|
|
$record = $DB->get_record('bigbluebuttonbn_logs', array('id' => $id)); |
1321
|
|
|
$meta = json_decode($record->meta, true); |
1322
|
|
|
// Prepare data for the update. |
1323
|
|
|
$meta['recording'] = $params + $meta['recording']; |
1324
|
|
|
$record->meta = json_encode($meta); |
1325
|
|
|
// Proceed with the update. |
1326
|
|
|
if (!$DB->update_record('bigbluebuttonbn_logs', $record)) { |
1327
|
|
|
return false; |
1328
|
|
|
} |
1329
|
|
|
return true; |
1330
|
|
|
} |
1331
|
|
|
|
1332
|
|
|
/** |
1333
|
|
|
* Protect/Unprotect an imported recording. |
1334
|
|
|
* |
1335
|
|
|
* @param string $id |
1336
|
|
|
* @param boolean $protect |
1337
|
|
|
* |
1338
|
|
|
* @return boolean |
1339
|
|
|
*/ |
1340
|
|
View Code Duplication |
function bigbluebuttonbn_protect_recording_imported($id, $protect = true) { |
|
|
|
|
1341
|
|
|
global $DB; |
1342
|
|
|
// Locate the record to be updated. |
1343
|
|
|
$record = $DB->get_record('bigbluebuttonbn_logs', array('id' => $id)); |
1344
|
|
|
$meta = json_decode($record->meta, true); |
1345
|
|
|
// Prepare data for the update. |
1346
|
|
|
$meta['recording']['protected'] = ($protect) ? 'true' : 'false'; |
1347
|
|
|
$record->meta = json_encode($meta); |
1348
|
|
|
// Proceed with the update. |
1349
|
|
|
$DB->update_record('bigbluebuttonbn_logs', $record); |
1350
|
|
|
return true; |
1351
|
|
|
} |
1352
|
|
|
|
1353
|
|
|
/** |
1354
|
|
|
* Sets a custom config.xml file for being used on create. |
1355
|
|
|
* |
1356
|
|
|
* @param string $meetingid |
1357
|
|
|
* @param string $configxml |
1358
|
|
|
* |
1359
|
|
|
* @return object |
1360
|
|
|
*/ |
1361
|
|
|
function bigbluebuttonbn_set_config_xml($meetingid, $configxml) { |
1362
|
|
|
$urldefaultconfig = \mod_bigbluebuttonbn\locallib\config::get('server_url') . 'api/setConfigXML?'; |
1363
|
|
|
$configxmlparams = bigbluebuttonbn_set_config_xml_params($meetingid, $configxml); |
1364
|
|
|
$xml = bigbluebuttonbn_wrap_xml_load_file( |
1365
|
|
|
$urldefaultconfig, |
1366
|
|
|
'POST', |
1367
|
|
|
$configxmlparams, |
1368
|
|
|
'application/x-www-form-urlencoded' |
1369
|
|
|
); |
1370
|
|
|
return $xml; |
1371
|
|
|
} |
1372
|
|
|
|
1373
|
|
|
/** |
1374
|
|
|
* Sets qs used with a custom config.xml file request. |
1375
|
|
|
* |
1376
|
|
|
* @param string $meetingid |
1377
|
|
|
* @param string $configxml |
1378
|
|
|
* |
1379
|
|
|
* @return string |
1380
|
|
|
*/ |
1381
|
|
|
function bigbluebuttonbn_set_config_xml_params($meetingid, $configxml) { |
1382
|
|
|
$params = 'configXML=' . urlencode($configxml) . '&meetingID=' . urlencode($meetingid); |
1383
|
|
|
$sharedsecret = \mod_bigbluebuttonbn\locallib\config::get('shared_secret'); |
1384
|
|
|
$configxmlparams = $params . '&checksum=' . sha1('setConfigXML' . $params . $sharedsecret); |
1385
|
|
|
return $configxmlparams; |
1386
|
|
|
} |
1387
|
|
|
|
1388
|
|
|
/** |
1389
|
|
|
* Sets a custom config.xml file for being used on create. |
1390
|
|
|
* |
1391
|
|
|
* @param string $meetingid |
1392
|
|
|
* @param string $configxml |
1393
|
|
|
* |
1394
|
|
|
* @return array |
1395
|
|
|
*/ |
1396
|
|
|
function bigbluebuttonbn_set_config_xml_array($meetingid, $configxml) { |
1397
|
|
|
$configxml = bigbluebuttonbn_set_config_xml($meetingid, $configxml); |
1398
|
|
|
$configxmlarray = (array) $configxml; |
1399
|
|
|
if ($configxmlarray['returncode'] != 'SUCCESS') { |
1400
|
|
|
debugging('BigBlueButton was not able to set the custom config.xml file', DEBUG_DEVELOPER); |
1401
|
|
|
return ''; |
1402
|
|
|
} |
1403
|
|
|
return $configxmlarray['configToken']; |
1404
|
|
|
} |
1405
|
|
|
|
1406
|
|
|
/** |
1407
|
|
|
* Helper function builds a row for the data used by the recording table. |
1408
|
|
|
* |
1409
|
|
|
* @param array $bbbsession |
1410
|
|
|
* @param array $recording |
1411
|
|
|
* @param array $tools |
1412
|
|
|
* |
1413
|
|
|
* @return array |
1414
|
|
|
*/ |
1415
|
|
|
function bigbluebuttonbn_get_recording_data_row($bbbsession, $recording, $tools = ['protect', 'publish', 'delete']) { |
1416
|
|
|
if (!bigbluebuttonbn_include_recording_table_row($bbbsession, $recording)) { |
1417
|
|
|
return; |
1418
|
|
|
} |
1419
|
|
|
$rowdata = new stdClass(); |
1420
|
|
|
// Set recording_types. |
1421
|
|
|
$rowdata->playback = bigbluebuttonbn_get_recording_data_row_types($recording, $bbbsession); |
1422
|
|
|
// Set activity name. |
1423
|
|
|
$rowdata->recording = bigbluebuttonbn_get_recording_data_row_meta_activity($recording, $bbbsession); |
1424
|
|
|
// Set activity description. |
1425
|
|
|
$rowdata->description = bigbluebuttonbn_get_recording_data_row_meta_description($recording, $bbbsession); |
1426
|
|
|
if (bigbluebuttonbn_get_recording_data_preview_enabled($bbbsession)) { |
1427
|
|
|
// Set recording_preview. |
1428
|
|
|
$rowdata->preview = bigbluebuttonbn_get_recording_data_row_preview($recording); |
1429
|
|
|
} |
1430
|
|
|
// Set date. |
1431
|
|
|
$rowdata->date = bigbluebuttonbn_get_recording_data_row_date($recording); |
1432
|
|
|
// Set formatted date. |
1433
|
|
|
$rowdata->date_formatted = bigbluebuttonbn_get_recording_data_row_date_formatted($rowdata->date); |
1434
|
|
|
// Set formatted duration. |
1435
|
|
|
$rowdata->duration_formatted = $rowdata->duration = bigbluebuttonbn_get_recording_data_row_duration($recording); |
1436
|
|
|
// Set actionbar, if user is allowed to manage recordings. |
1437
|
|
|
if ($bbbsession['managerecordings']) { |
1438
|
|
|
$rowdata->actionbar = bigbluebuttonbn_get_recording_data_row_actionbar($recording, $tools); |
1439
|
|
|
} |
1440
|
|
|
return $rowdata; |
1441
|
|
|
} |
1442
|
|
|
|
1443
|
|
|
/** |
1444
|
|
|
* Helper function evaluates if a row for the data used by the recording table is editable. |
1445
|
|
|
* |
1446
|
|
|
* @param array $bbbsession |
1447
|
|
|
* |
1448
|
|
|
* @return boolean |
1449
|
|
|
*/ |
1450
|
|
|
function bigbluebuttonbn_get_recording_data_row_editable($bbbsession) { |
1451
|
|
|
return ($bbbsession['managerecordings'] && ((double) $bbbsession['serverversion'] >= 1.0 || $bbbsession['bnserver'])); |
1452
|
|
|
} |
1453
|
|
|
|
1454
|
|
|
/** |
1455
|
|
|
* Helper function evaluates if recording preview should be included. |
1456
|
|
|
* |
1457
|
|
|
* @param array $bbbsession |
1458
|
|
|
* |
1459
|
|
|
* @return boolean |
1460
|
|
|
*/ |
1461
|
|
|
function bigbluebuttonbn_get_recording_data_preview_enabled($bbbsession) { |
1462
|
|
|
return ((double) $bbbsession['serverversion'] >= 1.0 && $bbbsession['bigbluebuttonbn']->recordings_preview == '1'); |
1463
|
|
|
} |
1464
|
|
|
|
1465
|
|
|
/** |
1466
|
|
|
* Helper function converts recording date used in row for the data used by the recording table. |
1467
|
|
|
* |
1468
|
|
|
* @param array $recording |
1469
|
|
|
* |
1470
|
|
|
* @return integer |
1471
|
|
|
*/ |
1472
|
|
|
function bigbluebuttonbn_get_recording_data_row_date($recording) { |
1473
|
|
|
if (!isset($recording['startTime'])) { |
1474
|
|
|
return 0; |
1475
|
|
|
} |
1476
|
|
|
return floatval($recording['startTime']); |
1477
|
|
|
} |
1478
|
|
|
|
1479
|
|
|
/** |
1480
|
|
|
* Helper function format recording date used in row for the data used by the recording table. |
1481
|
|
|
* |
1482
|
|
|
* @param integer $starttime |
1483
|
|
|
* |
1484
|
|
|
* @return string |
1485
|
|
|
*/ |
1486
|
|
|
function bigbluebuttonbn_get_recording_data_row_date_formatted($starttime) { |
1487
|
|
|
global $USER; |
1488
|
|
|
$starttime = $starttime - ($starttime % 1000); |
1489
|
|
|
// Set formatted date. |
1490
|
|
|
$dateformat = get_string('strftimerecentfull', 'langconfig') . ' %Z'; |
1491
|
|
|
return userdate($starttime / 1000, $dateformat, usertimezone($USER->timezone)); |
1492
|
|
|
} |
1493
|
|
|
|
1494
|
|
|
/** |
1495
|
|
|
* Helper function converts recording duration used in row for the data used by the recording table. |
1496
|
|
|
* |
1497
|
|
|
* @param array $recording |
1498
|
|
|
* |
1499
|
|
|
* @return integer |
1500
|
|
|
*/ |
1501
|
|
|
function bigbluebuttonbn_get_recording_data_row_duration($recording) { |
1502
|
|
|
foreach (array_values($recording['playbacks']) as $playback) { |
1503
|
|
|
// Ignore restricted playbacks. |
1504
|
|
|
if (array_key_exists('restricted', $playback) && strtolower($playback['restricted']) == 'true') { |
1505
|
|
|
continue; |
1506
|
|
|
} |
1507
|
|
|
// Take the lenght form the fist playback with an actual value. |
1508
|
|
|
if (!empty($playback['length'])) { |
1509
|
|
|
return intval($playback['length']); |
1510
|
|
|
} |
1511
|
|
|
} |
1512
|
|
|
return 0; |
1513
|
|
|
} |
1514
|
|
|
|
1515
|
|
|
/** |
1516
|
|
|
* Helper function builds recording actionbar used in row for the data used by the recording table. |
1517
|
|
|
* |
1518
|
|
|
* @param array $recording |
1519
|
|
|
* @param array $tools |
1520
|
|
|
* |
1521
|
|
|
* @return string |
1522
|
|
|
*/ |
1523
|
|
|
function bigbluebuttonbn_get_recording_data_row_actionbar($recording, $tools) { |
1524
|
|
|
$actionbar = ''; |
1525
|
|
|
foreach ($tools as $tool) { |
1526
|
|
|
$buttonpayload = bigbluebuttonbn_get_recording_data_row_actionbar_payload($recording, $tool); |
1527
|
|
|
if ($tool == 'protect') { |
1528
|
|
|
if (isset($recording['imported'])) { |
1529
|
|
|
$buttonpayload['disabled'] = 'disabled'; |
1530
|
|
|
} |
1531
|
|
|
if (!isset($recording['protected'])) { |
1532
|
|
|
$buttonpayload['disabled'] = 'invisible'; |
1533
|
|
|
} |
1534
|
|
|
} |
1535
|
|
|
$actionbar .= bigbluebuttonbn_actionbar_render_button($recording, $buttonpayload); |
1536
|
|
|
} |
1537
|
|
|
$head = html_writer::start_tag('div', array( |
1538
|
|
|
'id' => 'recording-actionbar-' . $recording['recordID'], |
1539
|
|
|
'data-recordingid' => $recording['recordID'], |
1540
|
|
|
'data-meetingid' => $recording['meetingID'])); |
1541
|
|
|
$tail = html_writer::end_tag('div'); |
1542
|
|
|
return $head . $actionbar . $tail; |
1543
|
|
|
} |
1544
|
|
|
|
1545
|
|
|
/** |
1546
|
|
|
* Helper function returns the corresponding payload for an actionbar button used in row |
1547
|
|
|
* for the data used by the recording table. |
1548
|
|
|
* |
1549
|
|
|
* @param array $recording |
1550
|
|
|
* @param array $tool |
1551
|
|
|
* |
1552
|
|
|
* @return array |
1553
|
|
|
*/ |
1554
|
|
|
function bigbluebuttonbn_get_recording_data_row_actionbar_payload($recording, $tool) { |
1555
|
|
|
if ($tool == 'protect') { |
1556
|
|
|
$protected = 'false'; |
1557
|
|
|
if (isset($recording['protected'])) { |
1558
|
|
|
$protected = $recording['protected']; |
1559
|
|
|
} |
1560
|
|
|
return bigbluebuttonbn_get_recording_data_row_action_protect($protected); |
1561
|
|
|
} |
1562
|
|
|
if ($tool == 'publish') { |
1563
|
|
|
return bigbluebuttonbn_get_recording_data_row_action_publish($recording['published']); |
1564
|
|
|
} |
1565
|
|
|
return array('action' => $tool, 'tag' => $tool); |
1566
|
|
|
} |
1567
|
|
|
|
1568
|
|
|
/** |
1569
|
|
|
* Helper function returns the payload for protect action button used in row |
1570
|
|
|
* for the data used by the recording table. |
1571
|
|
|
* |
1572
|
|
|
* @param string $protected |
1573
|
|
|
* |
1574
|
|
|
* @return array |
1575
|
|
|
*/ |
1576
|
|
|
function bigbluebuttonbn_get_recording_data_row_action_protect($protected) { |
1577
|
|
|
if ($protected == 'true') { |
1578
|
|
|
return array('action' => 'unprotect', 'tag' => 'lock'); |
1579
|
|
|
} |
1580
|
|
|
return array('action' => 'protect', 'tag' => 'unlock'); |
1581
|
|
|
} |
1582
|
|
|
|
1583
|
|
|
/** |
1584
|
|
|
* Helper function returns the payload for publish action button used in row |
1585
|
|
|
* for the data used by the recording table. |
1586
|
|
|
* |
1587
|
|
|
* @param string $published |
1588
|
|
|
* |
1589
|
|
|
* @return array |
1590
|
|
|
*/ |
1591
|
|
|
function bigbluebuttonbn_get_recording_data_row_action_publish($published) { |
1592
|
|
|
if ($published == 'true') { |
1593
|
|
|
return array('action' => 'unpublish', 'tag' => 'hide'); |
1594
|
|
|
} |
1595
|
|
|
return array('action' => 'publish', 'tag' => 'show'); |
1596
|
|
|
} |
1597
|
|
|
|
1598
|
|
|
/** |
1599
|
|
|
* Helper function builds recording preview used in row for the data used by the recording table. |
1600
|
|
|
* |
1601
|
|
|
* @param array $recording |
1602
|
|
|
* |
1603
|
|
|
* @return string |
1604
|
|
|
*/ |
1605
|
|
|
function bigbluebuttonbn_get_recording_data_row_preview($recording) { |
1606
|
|
|
$options = array('id' => 'preview-' . $recording['recordID']); |
1607
|
|
|
if ($recording['published'] === 'false') { |
1608
|
|
|
$options['hidden'] = 'hidden'; |
1609
|
|
|
} |
1610
|
|
|
$recordingpreview = html_writer::start_tag('div', $options); |
1611
|
|
|
foreach ($recording['playbacks'] as $playback) { |
1612
|
|
|
if (isset($playback['preview'])) { |
1613
|
|
|
$recordingpreview .= bigbluebuttonbn_get_recording_data_row_preview_images($playback); |
1614
|
|
|
break; |
1615
|
|
|
} |
1616
|
|
|
} |
1617
|
|
|
$recordingpreview .= html_writer::end_tag('div'); |
1618
|
|
|
return $recordingpreview; |
1619
|
|
|
} |
1620
|
|
|
|
1621
|
|
|
/** |
1622
|
|
|
* Helper function builds element with actual images used in recording preview row based on a selected playback. |
1623
|
|
|
* |
1624
|
|
|
* @param array $playback |
1625
|
|
|
* |
1626
|
|
|
* @return string |
1627
|
|
|
*/ |
1628
|
|
|
function bigbluebuttonbn_get_recording_data_row_preview_images($playback) { |
1629
|
|
|
global $CFG; |
1630
|
|
|
$recordingpreview = html_writer::start_tag('div', array('class' => 'container-fluid')); |
1631
|
|
|
$recordingpreview .= html_writer::start_tag('div', array('class' => 'row')); |
1632
|
|
|
foreach ($playback['preview'] as $image) { |
1633
|
|
|
if ($CFG->bigbluebuttonbn_recordings_validate_url && !bigbluebuttonbn_is_valid_resource(trim($image['url']))) { |
1634
|
|
|
return ''; |
1635
|
|
|
} |
1636
|
|
|
$recordingpreview .= html_writer::start_tag('div', array('class' => '')); |
1637
|
|
|
$recordingpreview .= html_writer::empty_tag( |
1638
|
|
|
'img', |
1639
|
|
|
array('src' => trim($image['url']) . '?' . time(), 'class' => 'recording-thumbnail pull-left') |
1640
|
|
|
); |
1641
|
|
|
$recordingpreview .= html_writer::end_tag('div'); |
1642
|
|
|
} |
1643
|
|
|
$recordingpreview .= html_writer::end_tag('div'); |
1644
|
|
|
$recordingpreview .= html_writer::start_tag('div', array('class' => 'row')); |
1645
|
|
|
$recordingpreview .= html_writer::tag( |
1646
|
|
|
'div', |
1647
|
|
|
get_string('view_recording_preview_help', 'bigbluebuttonbn'), |
1648
|
|
|
array('class' => 'text-center text-muted small') |
1649
|
|
|
); |
1650
|
|
|
$recordingpreview .= html_writer::end_tag('div'); |
1651
|
|
|
$recordingpreview .= html_writer::end_tag('div'); |
1652
|
|
|
return $recordingpreview; |
1653
|
|
|
} |
1654
|
|
|
|
1655
|
|
|
/** |
1656
|
|
|
* Helper function renders recording types to be used in row for the data used by the recording table. |
1657
|
|
|
* |
1658
|
|
|
* @param array $recording |
1659
|
|
|
* @param array $bbbsession |
1660
|
|
|
* |
1661
|
|
|
* @return string |
1662
|
|
|
*/ |
1663
|
|
|
function bigbluebuttonbn_get_recording_data_row_types($recording, $bbbsession) { |
1664
|
|
|
$dataimported = 'false'; |
1665
|
|
|
$title = ''; |
1666
|
|
|
if (isset($recording['imported'])) { |
1667
|
|
|
$dataimported = 'true'; |
1668
|
|
|
$title = get_string('view_recording_link_warning', 'bigbluebuttonbn'); |
1669
|
|
|
} |
1670
|
|
|
$visibility = ''; |
1671
|
|
|
if ($recording['published'] === 'false') { |
1672
|
|
|
$visibility = 'hidden '; |
1673
|
|
|
} |
1674
|
|
|
$id = 'playbacks-' . $recording['recordID']; |
1675
|
|
|
$recordingtypes = html_writer::start_tag('div', array('id' => $id, 'data-imported' => $dataimported, |
1676
|
|
|
'data-meetingid' => $recording['meetingID'], 'data-recordingid' => $recording['recordID'], |
1677
|
|
|
'title' => $title, $visibility => $visibility)); |
1678
|
|
|
foreach ($recording['playbacks'] as $playback) { |
1679
|
|
|
$recordingtypes .= bigbluebuttonbn_get_recording_data_row_type($recording, $bbbsession, $playback); |
1680
|
|
|
} |
1681
|
|
|
$recordingtypes .= html_writer::end_tag('div'); |
1682
|
|
|
return $recordingtypes; |
1683
|
|
|
} |
1684
|
|
|
|
1685
|
|
|
/** |
1686
|
|
|
* Helper function renders the link used for recording type in row for the data used by the recording table. |
1687
|
|
|
* |
1688
|
|
|
* @param array $recording |
1689
|
|
|
* @param array $bbbsession |
1690
|
|
|
* @param array $playback |
1691
|
|
|
* |
1692
|
|
|
* @return string |
1693
|
|
|
*/ |
1694
|
|
|
function bigbluebuttonbn_get_recording_data_row_type($recording, $bbbsession, $playback) { |
1695
|
|
|
global $CFG, $OUTPUT; |
1696
|
|
|
if (!bigbluebuttonbn_include_recording_data_row_type($recording, $bbbsession, $playback)) { |
1697
|
|
|
return ''; |
1698
|
|
|
} |
1699
|
|
|
$text = bigbluebuttonbn_get_recording_type_text($playback['type']); |
1700
|
|
|
$href = $CFG->wwwroot . '/mod/bigbluebuttonbn/bbb_view.php?action=play&bn=' . $bbbsession['bigbluebuttonbn']->id . |
1701
|
|
|
'&mid=' . $recording['meetingID'] . '&rid=' . $recording['recordID'] . '&rtype=' . $playback['type']; |
1702
|
|
|
if (!isset($recording['imported']) || !isset($recording['protected']) || $recording['protected'] === 'false') { |
1703
|
|
|
$href .= '&href=' . urlencode(trim($playback['url'])); |
1704
|
|
|
} |
1705
|
|
|
$linkattributes = array( |
1706
|
|
|
'id' => 'recording-play-' . $playback['type'] . '-' . $recording['recordID'], |
1707
|
|
|
'class' => 'btn btn-sm btn-default', |
1708
|
|
|
'onclick' => 'M.mod_bigbluebuttonbn.recordings.recordingPlay(this);', |
1709
|
|
|
'data-action' => 'play', |
1710
|
|
|
'data-target' => $playback['type'], |
1711
|
|
|
'data-href' => $href, |
1712
|
|
|
); |
1713
|
|
|
if ($CFG->bigbluebuttonbn_recordings_validate_url && !bigbluebuttonbn_is_bn_server() |
1714
|
|
|
&& !bigbluebuttonbn_is_valid_resource(trim($playback['url']))) { |
1715
|
|
|
$linkattributes['class'] = 'btn btn-sm btn-warning'; |
1716
|
|
|
$linkattributes['title'] = get_string('view_recording_format_errror_unreachable', 'bigbluebuttonbn'); |
1717
|
|
|
unset($linkattributes['data-href']); |
1718
|
|
|
} |
1719
|
|
|
return $OUTPUT->action_link('#', $text, null, $linkattributes) . ' '; |
1720
|
|
|
} |
1721
|
|
|
|
1722
|
|
|
/** |
1723
|
|
|
* Helper function to handle yet unknown recording types |
1724
|
|
|
* |
1725
|
|
|
* @param string $playbacktype : for now presentation, video, statistics, capture, notes, podcast |
1726
|
|
|
* |
1727
|
|
|
* @return string the matching language string or a capitalised version of the provided string |
1728
|
|
|
*/ |
1729
|
|
|
function bigbluebuttonbn_get_recording_type_text($playbacktype) { |
1730
|
|
|
// Check first if string exists, and if it does'nt just default to the capitalised version of the string. |
1731
|
|
|
$text = ucwords($playbacktype); |
1732
|
|
|
$typestringid = 'view_recording_format_' . $playbacktype; |
1733
|
|
|
if (get_string_manager()->string_exists($typestringid, 'bigbluebuttonbn')) { |
1734
|
|
|
$text = get_string($typestringid, 'bigbluebuttonbn'); |
1735
|
|
|
} |
1736
|
|
|
return $text; |
1737
|
|
|
} |
1738
|
|
|
|
1739
|
|
|
/** |
1740
|
|
|
* Helper function validates a remote resource. |
1741
|
|
|
* |
1742
|
|
|
* @param string $url |
1743
|
|
|
* |
1744
|
|
|
* @return boolean |
1745
|
|
|
*/ |
1746
|
|
|
function bigbluebuttonbn_is_valid_resource($url) { |
1747
|
|
|
$urlhost = parse_url($url, PHP_URL_HOST); |
1748
|
|
|
$serverurlhost = parse_url(\mod_bigbluebuttonbn\locallib\config::get('server_url'), PHP_URL_HOST); |
1749
|
|
|
// Skip validation when the recording URL host is the same as the configured BBB server. |
1750
|
|
|
if ($urlhost == $serverurlhost) { |
1751
|
|
|
return true; |
1752
|
|
|
} |
1753
|
|
|
// Skip validation when the recording URL was already validated. |
1754
|
|
|
$validatedurls = bigbluebuttonbn_cache_get('recordings_cache', 'validated_urls', array()); |
|
|
|
|
1755
|
|
|
if (array_key_exists($urlhost, $validatedurls)) { |
1756
|
|
|
return $validatedurls[$urlhost]; |
1757
|
|
|
} |
1758
|
|
|
// Validate the recording URL. |
1759
|
|
|
$validatedurls[$urlhost] = true; |
1760
|
|
|
$curlinfo = bigbluebuttonbn_wrap_xml_load_file_curl_request($url, 'HEAD'); |
1761
|
|
|
if (!isset($curlinfo['http_code']) || $curlinfo['http_code'] != 200) { |
1762
|
|
|
$error = "Resources hosted by " . $urlhost . " are unreachable. Server responded with code " . $curlinfo['http_code']; |
1763
|
|
|
debugging($error, DEBUG_DEVELOPER); |
1764
|
|
|
$validatedurls[$urlhost] = false; |
1765
|
|
|
} |
1766
|
|
|
bigbluebuttonbn_cache_set('recordings_cache', 'validated_urls', $validatedurls); |
1767
|
|
|
return $validatedurls[$urlhost]; |
1768
|
|
|
} |
1769
|
|
|
|
1770
|
|
|
/** |
1771
|
|
|
* Helper function renders the name for meeting used in row for the data used by the recording table. |
1772
|
|
|
* |
1773
|
|
|
* @param array $recording |
1774
|
|
|
* @param array $bbbsession |
1775
|
|
|
* |
1776
|
|
|
* @return string |
1777
|
|
|
*/ |
1778
|
|
|
function bigbluebuttonbn_get_recording_data_row_meeting($recording, $bbbsession) { |
|
|
|
|
1779
|
|
|
$payload = array(); |
1780
|
|
|
$source = 'meetingName'; |
1781
|
|
|
$metaname = trim($recording['meetingName']); |
1782
|
|
|
return bigbluebuttonbn_get_recording_data_row_text($recording, $metaname, $source, $payload); |
1783
|
|
|
} |
1784
|
|
|
|
1785
|
|
|
/** |
1786
|
|
|
* Helper function renders the name for recording used in row for the data used by the recording table. |
1787
|
|
|
* |
1788
|
|
|
* @param array $recording |
1789
|
|
|
* @param array $bbbsession |
1790
|
|
|
* |
1791
|
|
|
* @return string |
1792
|
|
|
*/ |
1793
|
|
|
function bigbluebuttonbn_get_recording_data_row_meta_activity($recording, $bbbsession) { |
1794
|
|
|
$payload = array(); |
1795
|
|
View Code Duplication |
if (bigbluebuttonbn_get_recording_data_row_editable($bbbsession)) { |
|
|
|
|
1796
|
|
|
$payload = array('recordingid' => $recording['recordID'], 'meetingid' => $recording['meetingID'], |
1797
|
|
|
'action' => 'edit', 'tag' => 'edit', |
1798
|
|
|
'target' => 'name'); |
1799
|
|
|
} |
1800
|
|
|
$oldsource = 'meta_contextactivity'; |
1801
|
|
|
if (isset($recording[$oldsource])) { |
1802
|
|
|
$metaname = trim($recording[$oldsource]); |
1803
|
|
|
return bigbluebuttonbn_get_recording_data_row_text($recording, $metaname, $oldsource, $payload); |
1804
|
|
|
} |
1805
|
|
|
$newsource = 'meta_bbb-recording-name'; |
1806
|
|
View Code Duplication |
if (isset($recording[$newsource])) { |
|
|
|
|
1807
|
|
|
$metaname = trim($recording[$newsource]); |
1808
|
|
|
return bigbluebuttonbn_get_recording_data_row_text($recording, $metaname, $newsource, $payload); |
1809
|
|
|
} |
1810
|
|
|
$metaname = trim($recording['meetingName']); |
1811
|
|
|
return bigbluebuttonbn_get_recording_data_row_text($recording, $metaname, $newsource, $payload); |
1812
|
|
|
} |
1813
|
|
|
|
1814
|
|
|
/** |
1815
|
|
|
* Helper function renders the description for recording used in row for the data used by the recording table. |
1816
|
|
|
* |
1817
|
|
|
* @param array $recording |
1818
|
|
|
* @param array $bbbsession |
1819
|
|
|
* |
1820
|
|
|
* @return string |
1821
|
|
|
*/ |
1822
|
|
|
function bigbluebuttonbn_get_recording_data_row_meta_description($recording, $bbbsession) { |
1823
|
|
|
$payload = array(); |
1824
|
|
View Code Duplication |
if (bigbluebuttonbn_get_recording_data_row_editable($bbbsession)) { |
|
|
|
|
1825
|
|
|
$payload = array('recordingid' => $recording['recordID'], 'meetingid' => $recording['meetingID'], |
1826
|
|
|
'action' => 'edit', 'tag' => 'edit', |
1827
|
|
|
'target' => 'description'); |
1828
|
|
|
} |
1829
|
|
|
$oldsource = 'meta_contextactivitydescription'; |
1830
|
|
View Code Duplication |
if (isset($recording[$oldsource])) { |
|
|
|
|
1831
|
|
|
$metadescription = trim($recording[$oldsource]); |
1832
|
|
|
return bigbluebuttonbn_get_recording_data_row_text($recording, $metadescription, $oldsource, $payload); |
1833
|
|
|
} |
1834
|
|
|
$newsource = 'meta_bbb-recording-description'; |
1835
|
|
View Code Duplication |
if (isset($recording[$newsource])) { |
|
|
|
|
1836
|
|
|
$metadescription = trim($recording[$newsource]); |
1837
|
|
|
return bigbluebuttonbn_get_recording_data_row_text($recording, $metadescription, $newsource, $payload); |
1838
|
|
|
} |
1839
|
|
|
return bigbluebuttonbn_get_recording_data_row_text($recording, '', $newsource, $payload); |
1840
|
|
|
} |
1841
|
|
|
|
1842
|
|
|
/** |
1843
|
|
|
* Helper function renders text element for recording used in row for the data used by the recording table. |
1844
|
|
|
* |
1845
|
|
|
* @param array $recording |
1846
|
|
|
* @param string $text |
1847
|
|
|
* @param string $source |
1848
|
|
|
* @param array $data |
1849
|
|
|
* |
1850
|
|
|
* @return string |
1851
|
|
|
*/ |
1852
|
|
|
function bigbluebuttonbn_get_recording_data_row_text($recording, $text, $source, $data) { |
1853
|
|
|
$htmltext = '<span>' . htmlentities($text) . '</span>'; |
1854
|
|
|
if (empty($data)) { |
1855
|
|
|
return $htmltext; |
1856
|
|
|
} |
1857
|
|
|
$target = $data['action'] . '-' . $data['target']; |
1858
|
|
|
$id = 'recording-' . $target . '-' . $data['recordingid']; |
1859
|
|
|
$attributes = array('id' => $id, 'class' => 'quickeditlink col-md-20', |
1860
|
|
|
'data-recordingid' => $data['recordingid'], 'data-meetingid' => $data['meetingid'], |
1861
|
|
|
'data-target' => $data['target'], 'data-source' => $source); |
1862
|
|
|
$head = html_writer::start_tag('div', $attributes); |
1863
|
|
|
$tail = html_writer::end_tag('div'); |
1864
|
|
|
$payload = array('action' => $data['action'], 'tag' => $data['tag'], 'target' => $data['target']); |
1865
|
|
|
$htmllink = bigbluebuttonbn_actionbar_render_button($recording, $payload); |
1866
|
|
|
return $head . $htmltext . $htmllink . $tail; |
1867
|
|
|
} |
1868
|
|
|
|
1869
|
|
|
/** |
1870
|
|
|
* Helper function render a button for the recording action bar |
1871
|
|
|
* |
1872
|
|
|
* @param array $recording |
1873
|
|
|
* @param array $data |
1874
|
|
|
* |
1875
|
|
|
* @return string |
1876
|
|
|
*/ |
1877
|
|
|
function bigbluebuttonbn_actionbar_render_button($recording, $data) { |
1878
|
|
|
global $OUTPUT; |
1879
|
|
|
if (empty($data)) { |
1880
|
|
|
return ''; |
1881
|
|
|
} |
1882
|
|
|
$target = $data['action']; |
1883
|
|
|
if (isset($data['target'])) { |
1884
|
|
|
$target .= '-' . $data['target']; |
1885
|
|
|
} |
1886
|
|
|
$id = 'recording-' . $target . '-' . $recording['recordID']; |
1887
|
|
|
$onclick = 'M.mod_bigbluebuttonbn.recordings.recording' . ucfirst($data['action']) . '(this); return false;'; |
1888
|
|
|
if ((boolean) \mod_bigbluebuttonbn\locallib\config::get('recording_icons_enabled')) { |
1889
|
|
|
// With icon for $manageaction. |
1890
|
|
|
$iconattributes = array('id' => $id, 'class' => 'iconsmall'); |
1891
|
|
|
$linkattributes = array( |
1892
|
|
|
'id' => $id, |
1893
|
|
|
'onclick' => $onclick, |
1894
|
|
|
'data-action' => $data['action'], |
1895
|
|
|
); |
1896
|
|
|
if (!isset($recording['imported'])) { |
1897
|
|
|
$linkattributes['data-links'] = bigbluebuttonbn_count_recording_imported_instances( |
1898
|
|
|
$recording['recordID'] |
1899
|
|
|
); |
1900
|
|
|
} |
1901
|
|
|
if (isset($data['disabled'])) { |
1902
|
|
|
$iconattributes['class'] .= ' fa-' . $data['disabled']; |
1903
|
|
|
$linkattributes['class'] = 'disabled'; |
1904
|
|
|
unset($linkattributes['onclick']); |
1905
|
|
|
} |
1906
|
|
|
$icon = new pix_icon( |
1907
|
|
|
'i/' . $data['tag'], |
1908
|
|
|
get_string('view_recording_list_actionbar_' . $data['action'], 'bigbluebuttonbn'), |
1909
|
|
|
'moodle', |
1910
|
|
|
$iconattributes |
1911
|
|
|
); |
1912
|
|
|
return $OUTPUT->action_icon('#', $icon, null, $linkattributes, false); |
1913
|
|
|
} |
1914
|
|
|
// With text for $manageaction. |
1915
|
|
|
$linkattributes = array('title' => get_string($data['tag']), 'class' => 'btn btn-xs btn-danger', |
1916
|
|
|
'onclick' => $onclick); |
1917
|
|
|
return $OUTPUT->action_link('#', get_string($data['action']), null, $linkattributes); |
1918
|
|
|
} |
1919
|
|
|
|
1920
|
|
|
/** |
1921
|
|
|
* Helper function builds the recording table. |
1922
|
|
|
* |
1923
|
|
|
* @param array $bbbsession |
1924
|
|
|
* @param array $recordings |
1925
|
|
|
* @param array $tools |
1926
|
|
|
* |
1927
|
|
|
* @return object |
1928
|
|
|
*/ |
1929
|
|
|
function bigbluebuttonbn_get_recording_table($bbbsession, $recordings, $tools = ['protect', 'publish', 'delete']) { |
1930
|
|
|
global $DB; |
1931
|
|
|
// Declare the table. |
1932
|
|
|
$table = new html_table(); |
1933
|
|
|
$table->data = array(); |
1934
|
|
|
// Initialize table headers. |
1935
|
|
|
$table->head[] = get_string('view_recording_playback', 'bigbluebuttonbn'); |
1936
|
|
|
$table->head[] = get_string('view_recording_name', 'bigbluebuttonbn'); |
1937
|
|
|
$table->head[] = get_string('view_recording_description', 'bigbluebuttonbn'); |
1938
|
|
|
if (bigbluebuttonbn_get_recording_data_preview_enabled($bbbsession)) { |
1939
|
|
|
$table->head[] = get_string('view_recording_preview', 'bigbluebuttonbn'); |
1940
|
|
|
} |
1941
|
|
|
$table->head[] = get_string('view_recording_date', 'bigbluebuttonbn'); |
1942
|
|
|
$table->head[] = get_string('view_recording_duration', 'bigbluebuttonbn'); |
1943
|
|
|
$table->align = array('left', 'left', 'left', 'left', 'left', 'center'); |
1944
|
|
|
$table->size = array('', '', '', '', '', ''); |
1945
|
|
View Code Duplication |
if ($bbbsession['managerecordings']) { |
|
|
|
|
1946
|
|
|
$table->head[] = get_string('view_recording_actionbar', 'bigbluebuttonbn'); |
1947
|
|
|
$table->align[] = 'left'; |
1948
|
|
|
$table->size[] = (count($tools) * 40) . 'px'; |
1949
|
|
|
} |
1950
|
|
|
// Get the groups of the user. |
1951
|
|
|
$usergroups = groups_get_all_groups($bbbsession['course']->id, $bbbsession['userID']); |
1952
|
|
|
|
1953
|
|
|
// Build table content. |
1954
|
|
|
foreach ($recordings as $recording) { |
1955
|
|
|
$meetingid = $recording['meetingID']; |
|
|
|
|
1956
|
|
|
$shortmeetingid = explode('-', $recording['meetingID']); |
1957
|
|
|
if (isset($shortmeetingid[0])) { |
1958
|
|
|
$meetingid = $shortmeetingid[0]; |
|
|
|
|
1959
|
|
|
} |
1960
|
|
|
// Check if the record belongs to a Visible Group type. |
1961
|
|
|
list($course, $cm) = get_course_and_cm_from_cmid($bbbsession['cm']->id); |
|
|
|
|
1962
|
|
|
$groupmode = groups_get_activity_groupmode($cm); |
1963
|
|
|
$displayrow = true; |
1964
|
|
View Code Duplication |
if (($groupmode != VISIBLEGROUPS) |
|
|
|
|
1965
|
|
|
&& !$bbbsession['administrator'] && !$bbbsession['moderator']) { |
1966
|
|
|
$groupid = explode('[', $recording['meetingID']); |
1967
|
|
|
if (isset($groupid[1])) { |
1968
|
|
|
// It is a group recording and the user is not moderator/administrator. Recording should not be included by default. |
1969
|
|
|
$displayrow = false; |
1970
|
|
|
$groupid = explode(']', $groupid[1]); |
1971
|
|
|
if (isset($groupid[0])) { |
1972
|
|
|
foreach ($usergroups as $usergroup) { |
1973
|
|
|
if ($usergroup->id == $groupid[0]) { |
1974
|
|
|
// Include recording if the user is in the same group. |
1975
|
|
|
$displayrow = true; |
1976
|
|
|
} |
1977
|
|
|
} |
1978
|
|
|
} |
1979
|
|
|
} |
1980
|
|
|
} |
1981
|
|
View Code Duplication |
if ($displayrow) { |
|
|
|
|
1982
|
|
|
$rowdata = bigbluebuttonbn_get_recording_data_row($bbbsession, $recording, $tools); |
1983
|
|
|
if (!empty($rowdata)) { |
1984
|
|
|
$row = bigbluebuttonbn_get_recording_table_row($bbbsession, $recording, $rowdata); |
1985
|
|
|
array_push($table->data, $row); |
1986
|
|
|
} |
1987
|
|
|
} |
1988
|
|
|
} |
1989
|
|
|
return $table; |
1990
|
|
|
} |
1991
|
|
|
|
1992
|
|
|
/** |
1993
|
|
|
* Helper function builds the recording table row and insert into table. |
1994
|
|
|
* |
1995
|
|
|
* @param array $bbbsession |
1996
|
|
|
* @param array $recording |
1997
|
|
|
* @param object $rowdata |
1998
|
|
|
* |
1999
|
|
|
* @return object |
2000
|
|
|
*/ |
2001
|
|
|
function bigbluebuttonbn_get_recording_table_row($bbbsession, $recording, $rowdata) { |
2002
|
|
|
$row = new html_table_row(); |
2003
|
|
|
$row->id = 'recording-tr-' . $recording['recordID']; |
2004
|
|
|
$row->attributes['data-imported'] = 'false'; |
2005
|
|
|
$texthead = ''; |
2006
|
|
|
$texttail = ''; |
2007
|
|
|
if (isset($recording['imported'])) { |
2008
|
|
|
$row->attributes['title'] = get_string('view_recording_link_warning', 'bigbluebuttonbn'); |
2009
|
|
|
$row->attributes['data-imported'] = 'true'; |
2010
|
|
|
$texthead = '<em>'; |
2011
|
|
|
$texttail = '</em>'; |
2012
|
|
|
} |
2013
|
|
|
$rowdata->date_formatted = str_replace(' ', ' ', $rowdata->date_formatted); |
2014
|
|
|
$row->cells = array(); |
2015
|
|
|
$row->cells[] = $texthead . $rowdata->playback . $texttail; |
2016
|
|
|
$row->cells[] = $texthead . $rowdata->recording . $texttail; |
2017
|
|
|
$row->cells[] = $texthead . $rowdata->description . $texttail; |
2018
|
|
|
if (bigbluebuttonbn_get_recording_data_preview_enabled($bbbsession)) { |
2019
|
|
|
$row->cells[] = $rowdata->preview; |
2020
|
|
|
} |
2021
|
|
|
$row->cells[] = $texthead . $rowdata->date_formatted . $texttail; |
2022
|
|
|
$row->cells[] = $rowdata->duration_formatted; |
2023
|
|
|
if ($bbbsession['managerecordings']) { |
2024
|
|
|
$row->cells[] = $rowdata->actionbar; |
2025
|
|
|
} |
2026
|
|
|
return $row; |
2027
|
|
|
} |
2028
|
|
|
|
2029
|
|
|
/** |
2030
|
|
|
* Get the basic data to display in the table view |
2031
|
|
|
* |
2032
|
|
|
* @param array $bbbsession the current session |
2033
|
|
|
* @param array $enabledfeatures feature enabled for this activity |
2034
|
|
|
* @return associative array containing the recordings indexed by recordID, each recording is also a |
2035
|
|
|
* non sequential associative array itself that corresponds to the actual recording in BBB |
2036
|
|
|
*/ |
2037
|
|
|
function bigbluebutton_get_recordings_for_table_view($bbbsession, $enabledfeatures) { |
2038
|
|
|
$bigbluebuttonbnid = null; |
2039
|
|
|
if ($enabledfeatures['showroom']) { |
2040
|
|
|
$bigbluebuttonbnid = $bbbsession['bigbluebuttonbn']->id; |
2041
|
|
|
} |
2042
|
|
|
// Get recordings. |
2043
|
|
|
$recordings = bigbluebuttonbn_get_recordings( |
2044
|
|
|
$bbbsession['course']->id, $bigbluebuttonbnid, $enabledfeatures['showroom'], |
2045
|
|
|
$bbbsession['bigbluebuttonbn']->recordings_deleted |
2046
|
|
|
); |
2047
|
|
|
if ($enabledfeatures['importrecordings']) { |
2048
|
|
|
// Get recording links. |
2049
|
|
|
$bigbluebuttonbnid = $bbbsession['bigbluebuttonbn']->id; |
2050
|
|
|
$recordingsimported = bigbluebuttonbn_get_recordings_imported_array( |
2051
|
|
|
$bbbsession['course']->id, $bigbluebuttonbnid, true |
2052
|
|
|
); |
2053
|
|
|
/* Perform aritmetic addition instead of merge so the imported recordings corresponding to existent |
2054
|
|
|
* recordings are not included. */ |
2055
|
|
|
if ($bbbsession['bigbluebuttonbn']->recordings_imported) { |
2056
|
|
|
$recordings = $recordingsimported; |
2057
|
|
|
} else { |
2058
|
|
|
$recordings += $recordingsimported; |
2059
|
|
|
} |
2060
|
|
|
} |
2061
|
|
|
return $recordings; |
2062
|
|
|
} |
2063
|
|
|
|
2064
|
|
|
/** |
2065
|
|
|
* Helper function evaluates if recording row should be included in the table. |
2066
|
|
|
* |
2067
|
|
|
* @param array $bbbsession |
2068
|
|
|
* @param array $recording |
2069
|
|
|
* |
2070
|
|
|
* @return boolean |
2071
|
|
|
*/ |
2072
|
|
|
function bigbluebuttonbn_include_recording_table_row($bbbsession, $recording) { |
2073
|
|
|
// Exclude unpublished recordings, only if user has no rights to manage them. |
2074
|
|
|
if ($recording['published'] != 'true' && !$bbbsession['managerecordings']) { |
2075
|
|
|
return false; |
2076
|
|
|
} |
2077
|
|
|
// Imported recordings are always shown as long as they are published. |
2078
|
|
|
if (isset($recording['imported'])) { |
2079
|
|
|
return true; |
2080
|
|
|
} |
2081
|
|
|
// Administrators and moderators are always allowed. |
2082
|
|
|
if ($bbbsession['administrator'] || $bbbsession['moderator']) { |
2083
|
|
|
return true; |
2084
|
|
|
} |
2085
|
|
|
// When groups are enabled, exclude those to which the user doesn't have access to. |
2086
|
|
|
if (isset($bbbsession['group']) && $recording['meetingID'] != $bbbsession['meetingid']) { |
2087
|
|
|
return false; |
2088
|
|
|
} |
2089
|
|
|
return true; |
2090
|
|
|
} |
2091
|
|
|
|
2092
|
|
|
/** |
2093
|
|
|
* Helper function triggers a send notification when the recording is ready. |
2094
|
|
|
* |
2095
|
|
|
* @param object $bigbluebuttonbn |
2096
|
|
|
* |
2097
|
|
|
* @return void |
2098
|
|
|
*/ |
2099
|
|
|
function bigbluebuttonbn_send_notification_recording_ready($bigbluebuttonbn) { |
2100
|
|
|
\mod_bigbluebuttonbn\locallib\notifier::notify_recording_ready($bigbluebuttonbn); |
2101
|
|
|
} |
2102
|
|
|
|
2103
|
|
|
/** |
2104
|
|
|
* Helper function enqueues list of meeting events to be stored and processed as for completion. |
2105
|
|
|
* |
2106
|
|
|
* @param object $bigbluebuttonbn |
2107
|
|
|
* @param object $jsonobj |
2108
|
|
|
* |
2109
|
|
|
* @return void |
2110
|
|
|
*/ |
2111
|
|
|
function bigbluebuttonbn_process_meeting_events($bigbluebuttonbn, $jsonobj) { |
2112
|
|
|
$meetingid = $jsonobj->{'meeting_id'}; |
2113
|
|
|
$recordid = $jsonobj->{'internal_meeting_id'}; |
2114
|
|
|
$attendees = $jsonobj->{'data'}->{'attendees'}; |
2115
|
|
|
foreach ($attendees as $attendee) { |
2116
|
|
|
$userid = $attendee->{'ext_user_id'}; |
2117
|
|
|
$overrides['meetingid'] = $meetingid; |
|
|
|
|
2118
|
|
|
$overrides['userid'] = $userid; |
|
|
|
|
2119
|
|
|
$meta['recordid'] = $recordid; |
|
|
|
|
2120
|
|
|
$meta['data'] = $attendee; |
2121
|
|
|
// Stores the log. |
2122
|
|
|
bigbluebuttonbn_log($bigbluebuttonbn, BIGBLUEBUTTON_LOG_EVENT_SUMMARY, $overrides, json_encode($meta)); |
2123
|
|
|
// Enqueue a task for processing the completion. |
2124
|
|
|
bigbluebuttonbn_enqueue_completion_update($bigbluebuttonbn, $userid); |
2125
|
|
|
} |
2126
|
|
|
} |
2127
|
|
|
|
2128
|
|
|
/** |
2129
|
|
|
* Helper function enqueues one user for being validated as for completion. |
2130
|
|
|
* |
2131
|
|
|
* @param object $bigbluebuttonbn |
2132
|
|
|
* @param string $userid |
2133
|
|
|
* |
2134
|
|
|
* @return void |
2135
|
|
|
*/ |
2136
|
|
|
function bigbluebuttonbn_enqueue_completion_update($bigbluebuttonbn, $userid) { |
2137
|
|
|
try { |
2138
|
|
|
// Create the instance of completion_update_state task. |
2139
|
|
|
$task = new \mod_bigbluebuttonbn\task\completion_update_state(); |
2140
|
|
|
// Add custom data. |
2141
|
|
|
$data = array( |
2142
|
|
|
'bigbluebuttonbn' => $bigbluebuttonbn, |
2143
|
|
|
'userid' => $userid, |
2144
|
|
|
); |
2145
|
|
|
$task->set_custom_data($data); |
2146
|
|
|
// CONTRIB-7457: Task should be executed by a user, maybe Teacher as Student won't have rights for overriding. |
2147
|
|
|
// $ task -> set_userid ( $ user -> id );. |
2148
|
|
|
// Enqueue it. |
2149
|
|
|
\core\task\manager::queue_adhoc_task($task); |
2150
|
|
|
} catch (Exception $e) { |
2151
|
|
|
mtrace("Error while enqueuing completion_update_state task. " . (string) $e); |
2152
|
|
|
} |
2153
|
|
|
} |
2154
|
|
|
|
2155
|
|
|
/** |
2156
|
|
|
* Helper function enqueues completion trigger. |
2157
|
|
|
* |
2158
|
|
|
* @param object $bigbluebuttonbn |
2159
|
|
|
* @param string $userid |
2160
|
|
|
* |
2161
|
|
|
* @return void |
2162
|
|
|
*/ |
2163
|
|
|
function bigbluebuttonbn_completion_update_state($bigbluebuttonbn, $userid) { |
2164
|
|
|
global $CFG; |
2165
|
|
|
require_once($CFG->libdir.'/completionlib.php'); |
2166
|
|
|
list($course, $cm) = get_course_and_cm_from_instance($bigbluebuttonbn, 'bigbluebuttonbn'); |
2167
|
|
|
$completion = new completion_info($course); |
2168
|
|
|
if (!$completion->is_enabled($cm)) { |
2169
|
|
|
mtrace("Completion not enabled"); |
2170
|
|
|
return; |
2171
|
|
|
} |
2172
|
|
|
if (bigbluebuttonbn_get_completion_state($course, $cm, $userid, COMPLETION_AND)) { |
2173
|
|
|
mtrace("Completion succeeded for user $userid"); |
2174
|
|
|
$completion->update_state($cm, COMPLETION_COMPLETE, $userid, true); |
2175
|
|
|
} else { |
2176
|
|
|
mtrace("Completion did not succeed for user $userid"); |
2177
|
|
|
} |
2178
|
|
|
} |
2179
|
|
|
|
2180
|
|
|
/** |
2181
|
|
|
* Helper evaluates if the bigbluebutton server used belongs to blindsidenetworks domain. |
2182
|
|
|
* |
2183
|
|
|
* @return boolean |
2184
|
|
|
*/ |
2185
|
|
|
function bigbluebuttonbn_is_bn_server() { |
2186
|
|
|
if (\mod_bigbluebuttonbn\locallib\config::get('bn_server')) { |
2187
|
|
|
return true; |
2188
|
|
|
} |
2189
|
|
|
$parsedurl = parse_url(\mod_bigbluebuttonbn\locallib\config::get('server_url')); |
2190
|
|
|
if (!isset($parsedurl['host'])) { |
2191
|
|
|
return false; |
2192
|
|
|
} |
2193
|
|
|
$h = $parsedurl['host']; |
2194
|
|
|
$hends = explode('.', $h); |
2195
|
|
|
$hendslength = count($hends); |
2196
|
|
|
return ($hends[$hendslength - 1] == 'com' && $hends[$hendslength - 2] == 'blindsidenetworks'); |
2197
|
|
|
} |
2198
|
|
|
|
2199
|
|
|
/** |
2200
|
|
|
* Helper function returns a list of courses a user has access to, wrapped in an array that can be used |
2201
|
|
|
* by a html select. |
2202
|
|
|
* |
2203
|
|
|
* @param array $bbbsession |
2204
|
|
|
* |
2205
|
|
|
* @return array |
2206
|
|
|
*/ |
2207
|
|
|
function bigbluebuttonbn_import_get_courses_for_select(array $bbbsession) { |
2208
|
|
|
if ($bbbsession['administrator']) { |
2209
|
|
|
$courses = get_courses('all', 'c.fullname ASC'); |
2210
|
|
|
// It includes the name of the site as a course (category 0), so remove the first one. |
2211
|
|
|
unset($courses['1']); |
2212
|
|
|
} else { |
2213
|
|
|
$courses = enrol_get_users_courses($bbbsession['userID'], false, 'id,shortname,fullname'); |
2214
|
|
|
} |
2215
|
|
|
$coursesforselect = []; |
2216
|
|
|
foreach ($courses as $course) { |
2217
|
|
|
$coursesforselect[$course->id] = $course->fullname . " (" . $course->shortname . ")"; |
2218
|
|
|
} |
2219
|
|
|
return $coursesforselect; |
2220
|
|
|
} |
2221
|
|
|
|
2222
|
|
|
/** |
2223
|
|
|
* Helper function renders recording table. |
2224
|
|
|
* |
2225
|
|
|
* @param array $bbbsession |
2226
|
|
|
* @param array $recordings |
2227
|
|
|
* @param array $tools |
2228
|
|
|
* |
2229
|
|
|
* @return array |
2230
|
|
|
*/ |
2231
|
|
|
function bigbluebuttonbn_output_recording_table($bbbsession, $recordings, $tools = ['protect', 'publish', 'delete']) { |
2232
|
|
|
if (isset($recordings) && !empty($recordings)) { |
2233
|
|
|
// There are recordings for this meeting. |
2234
|
|
|
$table = bigbluebuttonbn_get_recording_table($bbbsession, $recordings, $tools); |
2235
|
|
|
} |
2236
|
|
View Code Duplication |
if (!isset($table) || !isset($table->data)) { |
|
|
|
|
2237
|
|
|
// Render a table with "No recordings". |
2238
|
|
|
return html_writer::div( |
2239
|
|
|
get_string('view_message_norecordings', 'bigbluebuttonbn'), |
2240
|
|
|
'', |
2241
|
|
|
array('id' => 'bigbluebuttonbn_recordings_table') |
2242
|
|
|
); |
2243
|
|
|
} |
2244
|
|
|
// Render the table. |
2245
|
|
|
return html_writer::div(html_writer::table($table), '', array('id' => 'bigbluebuttonbn_recordings_table')); |
2246
|
|
|
} |
2247
|
|
|
|
2248
|
|
|
/** |
2249
|
|
|
* Helper function renders Opencast recording table. |
2250
|
|
|
* |
2251
|
|
|
* @param array $bbbsession |
2252
|
|
|
* @param array $ocrecordings |
2253
|
|
|
* |
2254
|
|
|
* @return array |
2255
|
|
|
*/ |
2256
|
|
|
function bigbluebuttonbn_output_opencast_recording_table($bbbsession, $ocrecordings) { |
2257
|
|
|
// Get the Opencast recording table. |
2258
|
|
|
$table = bigbluebuttonbn_get_opencast_recording_table($bbbsession, $ocrecordings); |
2259
|
|
|
|
2260
|
|
View Code Duplication |
if (!isset($table) || !isset($table->data)) { |
|
|
|
|
2261
|
|
|
// Render a table with "No Opencast recordings". |
2262
|
|
|
return html_writer::div( |
2263
|
|
|
get_string('view_message_opencast_norecordings', 'bigbluebuttonbn'), |
2264
|
|
|
'', |
2265
|
|
|
array('id' => 'bigbluebuttonbn_opencast_recordings_table') |
2266
|
|
|
); |
2267
|
|
|
} |
2268
|
|
|
// Render the table. |
2269
|
|
|
return html_writer::div(html_writer::table($table), '', array('id' => 'bigbluebuttonbn_opencast_recordings_table')); |
2270
|
|
|
} |
2271
|
|
|
|
2272
|
|
|
/** |
2273
|
|
|
* Helper function builds the Opencast recording table. |
2274
|
|
|
* |
2275
|
|
|
* @param array $bbbsession |
2276
|
|
|
* @param array $ocrecordings |
2277
|
|
|
* |
2278
|
|
|
* @return object |
2279
|
|
|
*/ |
2280
|
|
|
function bigbluebuttonbn_get_opencast_recording_table($bbbsession, $ocrecordings) { |
2281
|
|
|
// Declare the table. |
2282
|
|
|
$table = new html_table(); |
2283
|
|
|
$table->data = array(); |
2284
|
|
|
// Initialize table headers. |
2285
|
|
|
$table->head[] = get_string('view_recording_playback', 'bigbluebuttonbn'); |
2286
|
|
|
$table->head[] = get_string('view_recording_name', 'bigbluebuttonbn'); |
2287
|
|
|
$table->head[] = get_string('view_recording_description', 'bigbluebuttonbn'); |
2288
|
|
|
if (bigbluebuttonbn_get_recording_data_preview_enabled($bbbsession)) { |
2289
|
|
|
$table->head[] = get_string('view_recording_preview', 'bigbluebuttonbn'); |
2290
|
|
|
} |
2291
|
|
|
$table->head[] = get_string('view_recording_date', 'bigbluebuttonbn'); |
2292
|
|
|
$table->head[] = get_string('view_recording_duration', 'bigbluebuttonbn'); |
2293
|
|
|
$table->align = array('left', 'left', 'left', 'left', 'left', 'center'); |
2294
|
|
|
$table->size = array('', '', '', '', '', ''); |
2295
|
|
View Code Duplication |
if ($bbbsession['managerecordings']) { |
|
|
|
|
2296
|
|
|
$table->head[] = get_string('view_recording_actionbar', 'bigbluebuttonbn'); |
2297
|
|
|
$table->align[] = 'left'; |
2298
|
|
|
$table->size[] = (count($tools) * 40) . 'px'; |
|
|
|
|
2299
|
|
|
} |
2300
|
|
|
// Get the groups of the user. |
2301
|
|
|
$usergroups = groups_get_all_groups($bbbsession['course']->id, $bbbsession['userID']); |
2302
|
|
|
|
2303
|
|
|
// Build table content. |
2304
|
|
|
foreach ($ocrecordings as $ocrecording) { |
2305
|
|
|
// Check if the record belongs to a Visible Group type. |
2306
|
|
|
list($course, $cm) = get_course_and_cm_from_cmid($bbbsession['cm']->id); |
|
|
|
|
2307
|
|
|
$groupmode = groups_get_activity_groupmode($cm); |
2308
|
|
|
$displayrow = true; |
2309
|
|
View Code Duplication |
if (($groupmode != VISIBLEGROUPS) |
|
|
|
|
2310
|
|
|
&& !$bbbsession['administrator'] && !$bbbsession['moderator']) { |
2311
|
|
|
$groupid = explode('[', $bbbsession['meetingid']); |
2312
|
|
|
if (isset($groupid[1])) { |
2313
|
|
|
// It is a group recording and the user is not moderator/administrator. Recording should not be included by default. |
2314
|
|
|
$displayrow = false; |
2315
|
|
|
$groupid = explode(']', $groupid[1]); |
2316
|
|
|
if (isset($groupid[0])) { |
2317
|
|
|
foreach ($usergroups as $usergroup) { |
2318
|
|
|
if ($usergroup->id == $groupid[0]) { |
2319
|
|
|
// Include recording if the user is in the same group. |
2320
|
|
|
$displayrow = true; |
2321
|
|
|
} |
2322
|
|
|
} |
2323
|
|
|
} |
2324
|
|
|
} |
2325
|
|
|
} |
2326
|
|
View Code Duplication |
if ($displayrow) { |
|
|
|
|
2327
|
|
|
$rowdata = bigbluebuttonbn_get_opencast_recording_data_row($bbbsession, $ocrecording); |
2328
|
|
|
if (!empty($rowdata)) { |
2329
|
|
|
$row = bigbluebuttonbn_get_opencast_recording_table_row($bbbsession, $ocrecording, $rowdata); |
2330
|
|
|
array_push($table->data, $row); |
2331
|
|
|
} |
2332
|
|
|
} |
2333
|
|
|
} |
2334
|
|
|
return $table; |
2335
|
|
|
} |
2336
|
|
|
|
2337
|
|
|
/** |
2338
|
|
|
* Helper function builds a row for the data used by the Opencast recording table. |
2339
|
|
|
* |
2340
|
|
|
* @param array $bbbsession |
2341
|
|
|
* @param array $ocrecording |
2342
|
|
|
* |
2343
|
|
|
* @return array |
2344
|
|
|
*/ |
2345
|
|
|
function bigbluebuttonbn_get_opencast_recording_data_row($bbbsession, $ocrecording) { |
2346
|
|
|
$rowdata = new stdClass(); |
2347
|
|
|
// Set recording playback url. |
2348
|
|
|
$rowdata->playback = bigbluebuttonbn_get_opencast_recording_data_row_playback($ocrecording, $bbbsession); |
2349
|
|
|
// Set recording name from title if exists, otherwise shows "Opencast Video". |
2350
|
|
|
$rowdata->name = isset($ocrecording['title']) ? $ocrecording['title'] : get_string('view_recording_list_opencast', 'bigbluebuttonbn'); |
2351
|
|
|
// Set recording description. |
2352
|
|
|
$rowdata->description = isset($ocrecording['description']) ? $ocrecording['description'] : ''; |
2353
|
|
|
if (bigbluebuttonbn_get_recording_data_preview_enabled($bbbsession)) { |
2354
|
|
|
// Set recording_preview. |
2355
|
|
|
$rowdata->preview = bigbluebuttonbn_get_opencast_recording_data_row_preview($ocrecording); |
2356
|
|
|
} |
2357
|
|
|
// Set formatted date. |
2358
|
|
|
$rowdata->date_formatted = bigbluebuttonbn_get_opencast_recording_data_row_date_formatted($ocrecording); |
2359
|
|
|
// Set formatted duration. |
2360
|
|
|
$rowdata->duration_formatted = bigbluebuttonbn_get_opencast_recording_data_row_duration($ocrecording['duration']); |
2361
|
|
|
// Set actionbar, if user is allowed to manage recordings. |
2362
|
|
|
if ($bbbsession['managerecordings']) { |
2363
|
|
|
$rowdata->actionbar = bigbluebuttonbn_get_opencast_recording_data_row_actionbar($ocrecording, $bbbsession); |
2364
|
|
|
} |
2365
|
|
|
return $rowdata; |
2366
|
|
|
} |
2367
|
|
|
|
2368
|
|
|
/** |
2369
|
|
|
* Helper function renders the link used for Opencast recording playback in row for the data used by the recording table. |
2370
|
|
|
* To display the video, it is important for a video in Opencast to be published with engage-player, also it is required to |
2371
|
|
|
* have filter_opencast plugin installed and configured. |
2372
|
|
|
* The link redirects user to oc_view.php to authentificate the user via LTI and show the video in Opencast. |
2373
|
|
|
* |
2374
|
|
|
* @param array $ocrecording |
2375
|
|
|
* @param array $bbbsession |
2376
|
|
|
* |
2377
|
|
|
* @return string |
2378
|
|
|
*/ |
2379
|
|
|
function bigbluebuttonbn_get_opencast_recording_data_row_playback($ocrecording, $bbbsession) { |
2380
|
|
|
global $CFG, $OUTPUT; |
2381
|
|
|
$text = get_string('view_recording_list_opencast', 'bigbluebuttonbn'); |
2382
|
|
|
$href = '#'; |
2383
|
|
|
// Check if the publication status has engage-player |
2384
|
|
|
if (isset($ocrecording['publication_status']) && in_array('engage-player', $ocrecording['publication_status'])) { |
2385
|
|
|
// Check if filter_opencast is configured |
2386
|
|
|
$consumerkey = get_config('filter_opencast', 'consumerkey'); |
2387
|
|
|
$consumersecret = get_config('filter_opencast', 'consumersecret'); |
2388
|
|
|
// In order to make LTI auth both consumerkey and consumersecret are required. |
2389
|
|
|
if (!empty($consumerkey) && !empty($consumersecret)) { |
2390
|
|
|
$href = $CFG->wwwroot . '/mod/bigbluebuttonbn/oc_player.php?identifier=' . $ocrecording['identifier'] . |
2391
|
|
|
'&bn=' . $bbbsession['bigbluebuttonbn']->id; |
2392
|
|
|
} |
2393
|
|
|
} |
2394
|
|
|
|
2395
|
|
|
$linkattributes = array( |
2396
|
|
|
'id' => 'opencast-player-redirect-' . $ocrecording['identifier'], |
2397
|
|
|
'class' => 'btn btn-sm btn-default', |
2398
|
|
|
'target' => '_blank' |
2399
|
|
|
); |
2400
|
|
|
if ($href == '#' || empty($href)) { |
2401
|
|
|
$linkattributes['class'] = 'btn btn-sm btn-warning'; |
2402
|
|
|
$linkattributes['title'] = get_string('view_recording_format_errror_unreachable', 'bigbluebuttonbn'); |
2403
|
|
|
} |
2404
|
|
|
return $OUTPUT->action_link($href, $text, null, $linkattributes) . ' '; |
2405
|
|
|
} |
2406
|
|
|
|
2407
|
|
|
/** |
2408
|
|
|
* Helper function builds Opencast recording preview used in row for the data used by the recording table. |
2409
|
|
|
* |
2410
|
|
|
* @param array $ocrecording |
2411
|
|
|
* |
2412
|
|
|
* @return string |
2413
|
|
|
*/ |
2414
|
|
|
function bigbluebuttonbn_get_opencast_recording_data_row_preview($ocrecording) { |
2415
|
|
|
$options = array('id' => 'preview-' . $ocrecording['identifier']); |
2416
|
|
|
$recordingpreview = html_writer::start_tag('div', $options); |
2417
|
|
|
$imageurl = ''; |
2418
|
|
|
// Getting preview image from mediapackage attachments. |
2419
|
|
|
if (isset($ocrecording['mediapackage']['attachments']['attachment'])) { |
2420
|
|
|
foreach ($ocrecording['mediapackage']['attachments']['attachment'] as $attachment) { |
2421
|
|
|
// Looking for image only. |
2422
|
|
|
if (isset($attachment['mimetype']) && strpos($attachment['mimetype'], 'image') !== FALSE) { |
2423
|
|
|
// Looking for the url of the preview image. |
2424
|
|
|
if (empty($imageurl) && isset($attachment['type']) && isset($attachment['url'])) { |
2425
|
|
|
// There are several type of attachments which are different in size. |
2426
|
|
|
// More suitable sizes are of these types, respectively. |
2427
|
|
|
$suitabletypes = array('search', 'feed'); |
2428
|
|
|
foreach ($suitabletypes as $type) { |
2429
|
|
|
if (strpos($attachment['type'], $type) !== FALSE) { |
2430
|
|
|
$imageurl = $attachment['url']; |
2431
|
|
|
break; |
2432
|
|
|
} |
2433
|
|
|
} |
2434
|
|
|
} |
2435
|
|
|
} |
2436
|
|
|
if (!empty($imageurl)) { |
2437
|
|
|
break; |
2438
|
|
|
} |
2439
|
|
|
} |
2440
|
|
|
if (!empty($imageurl)) { |
2441
|
|
|
$recordingpreview .= bigbluebuttonbn_get_opencast_recording_data_row_preview_images($imageurl); |
2442
|
|
|
} |
2443
|
|
|
} |
2444
|
|
|
|
2445
|
|
|
$recordingpreview .= html_writer::end_tag('div'); |
2446
|
|
|
return $recordingpreview; |
2447
|
|
|
} |
2448
|
|
|
|
2449
|
|
|
/** |
2450
|
|
|
* Helper function format Opencast recording date used in row for the data used by the recording table. |
2451
|
|
|
* |
2452
|
|
|
* @param array $ocrecording |
2453
|
|
|
* |
2454
|
|
|
* @return string |
2455
|
|
|
*/ |
2456
|
|
|
function bigbluebuttonbn_get_opencast_recording_data_row_date_formatted($ocrecording) { |
2457
|
|
|
global $USER; |
2458
|
|
|
$starttime_str = !empty($ocrecording['start']) ? $ocrecording['start'] : $ocrecording['created']; |
2459
|
|
|
$starttime = strtotime($starttime_str); |
2460
|
|
|
// Set formatted date. |
2461
|
|
|
$dateformat = get_string('strftimerecentfull', 'langconfig') . ' %Z'; |
2462
|
|
|
return userdate($starttime, $dateformat, usertimezone($USER->timezone)); |
2463
|
|
|
} |
2464
|
|
|
|
2465
|
|
|
/** |
2466
|
|
|
* Helper function converts Opencast recording duration used in row for the data used by the recording table. |
2467
|
|
|
* |
2468
|
|
|
* @param array $duration |
2469
|
|
|
* |
2470
|
|
|
* @return integer |
2471
|
|
|
*/ |
2472
|
|
|
function bigbluebuttonbn_get_opencast_recording_data_row_duration($duration) { |
2473
|
|
|
if ($duration) { |
|
|
|
|
2474
|
|
|
// Convert the duration (in miliseconds) into Hours:Minutes:Seconds format |
2475
|
|
|
return gmdate('H:i:s', $duration / 1000); |
2476
|
|
|
} |
2477
|
|
|
return 0; |
2478
|
|
|
} |
2479
|
|
|
|
2480
|
|
|
/** |
2481
|
|
|
* Helper function builds Opencast recording actionbar used in row for the data used by the recording table. |
2482
|
|
|
* |
2483
|
|
|
* @param array $ocrecording |
2484
|
|
|
* @param array $bbbsession |
2485
|
|
|
* |
2486
|
|
|
* @return string |
2487
|
|
|
*/ |
2488
|
|
|
function bigbluebuttonbn_get_opencast_recording_data_row_actionbar($ocrecording, $bbbsession) { |
2489
|
|
|
global $OUTPUT; |
2490
|
|
|
if (empty($ocrecording['identifier']) || empty($bbbsession['course'])) { |
2491
|
|
|
return ''; |
2492
|
|
|
} |
2493
|
|
|
$actionbar = ''; |
2494
|
|
|
$linkattributes = array( |
2495
|
|
|
'target' => '_blank', |
2496
|
|
|
'class' => 'btn btn-xs btn-danger' |
2497
|
|
|
); |
2498
|
|
|
// Creating moodle url, to redirect to Opencast update metadata (Edit) page. |
2499
|
|
|
$opencastediturl = new \moodle_url('/blocks/opencast/updatemetadata.php', |
2500
|
|
|
array('video_identifier' => $ocrecording['identifier'], 'courseid' => $bbbsession['course']->id)); |
2501
|
|
|
$linkattributes['id'] = 'opencast-edit-episode-' . $ocrecording['identifier']; |
2502
|
|
|
// Generating Action Link for Opencast update metadata (Edit). |
2503
|
|
|
$actionbar .= $OUTPUT->action_link($opencastediturl, get_string('edit'), null, $linkattributes) . ' '; |
2504
|
|
|
|
2505
|
|
|
// Creating moodle url, to redirect to Opencast delete event (Delete) page. |
2506
|
|
|
$opencastdeleteurl = new \moodle_url('/blocks/opencast/deleteevent.php', |
2507
|
|
|
array('identifier' => $ocrecording['identifier'], 'courseid' => $bbbsession['course']->id)); |
2508
|
|
|
$linkattributes['id'] = 'opencast-delete-episode-' . $ocrecording['identifier']; |
2509
|
|
|
// Generating Action Link for Opencast delete event (Delete). |
2510
|
|
|
$actionbar .= $OUTPUT->action_link($opencastdeleteurl, get_string('delete'), null, $linkattributes) . ' '; |
2511
|
|
|
$head = html_writer::start_tag('div', array( |
2512
|
|
|
'id' => 'recording-actionbar-' . $ocrecording['identifier'], |
2513
|
|
|
'data-recordingid' => $ocrecording['identifier'], |
2514
|
|
|
'data-meetingid' => $bbbsession['meetingid'])); |
2515
|
|
|
$tail = html_writer::end_tag('div'); |
2516
|
|
|
return $head . $actionbar . $tail; |
2517
|
|
|
} |
2518
|
|
|
|
2519
|
|
|
/** |
2520
|
|
|
* Helper function builds the Opencast recording table row and insert into table. |
2521
|
|
|
* |
2522
|
|
|
* @param array $bbbsession |
2523
|
|
|
* @param object $ocrecording |
2524
|
|
|
* @param object $rowdata |
2525
|
|
|
* |
2526
|
|
|
* @return object |
2527
|
|
|
*/ |
2528
|
|
|
function bigbluebuttonbn_get_opencast_recording_table_row($bbbsession, $ocrecording, $rowdata) { |
2529
|
|
|
$row = new html_table_row(); |
2530
|
|
|
$row->id = 'recording-tr-' . $ocrecording['identifier']; |
2531
|
|
|
$rowdata->date_formatted = str_replace(' ', ' ', $rowdata->date_formatted); |
2532
|
|
|
$row->cells = array(); |
2533
|
|
|
$row->cells[] = $rowdata->playback; |
2534
|
|
|
$row->cells[] = $rowdata->name; |
2535
|
|
|
$row->cells[] = $rowdata->description; |
2536
|
|
|
if (bigbluebuttonbn_get_recording_data_preview_enabled($bbbsession)) { |
2537
|
|
|
$row->cells[] = $rowdata->preview; |
2538
|
|
|
} |
2539
|
|
|
$row->cells[] = $rowdata->date_formatted; |
2540
|
|
|
$row->cells[] = $rowdata->duration_formatted; |
2541
|
|
|
if ($bbbsession['managerecordings']) { |
2542
|
|
|
$row->cells[] = $rowdata->actionbar; |
2543
|
|
|
} |
2544
|
|
|
return $row; |
2545
|
|
|
} |
2546
|
|
|
|
2547
|
|
|
/** |
2548
|
|
|
* Helper function builds element with actual images used in Opencast recording preview row based on a selected playback. |
2549
|
|
|
* |
2550
|
|
|
* @param string $imageurl |
2551
|
|
|
* |
2552
|
|
|
* @return string |
2553
|
|
|
*/ |
2554
|
|
|
function bigbluebuttonbn_get_opencast_recording_data_row_preview_images($imageurl) { |
2555
|
|
|
global $CFG; |
2556
|
|
|
$recordingpreview = html_writer::start_tag('div', array('class' => 'container-fluid')); |
2557
|
|
|
$recordingpreview .= html_writer::start_tag('div', array('class' => 'row')); |
2558
|
|
|
$recordingpreview .= html_writer::start_tag('div', array('class' => '')); |
2559
|
|
|
$recordingpreview .= html_writer::empty_tag( |
2560
|
|
|
'img', |
2561
|
|
|
array('src' => trim($imageurl) . '?' . time(), 'class' => 'recording-thumbnail pull-left') |
2562
|
|
|
); |
2563
|
|
|
$recordingpreview .= html_writer::end_tag('div'); |
2564
|
|
|
$recordingpreview .= html_writer::end_tag('div'); |
2565
|
|
|
$recordingpreview .= html_writer::start_tag('div', array('class' => 'row')); |
2566
|
|
|
$recordingpreview .= html_writer::tag( |
2567
|
|
|
'div', |
2568
|
|
|
get_string('view_recording_preview_help', 'bigbluebuttonbn'), |
2569
|
|
|
array('class' => 'text-center text-muted small') |
2570
|
|
|
); |
2571
|
|
|
$recordingpreview .= html_writer::end_tag('div'); |
2572
|
|
|
$recordingpreview .= html_writer::end_tag('div'); |
2573
|
|
|
return $recordingpreview; |
2574
|
|
|
} |
2575
|
|
|
|
2576
|
|
|
/** |
2577
|
|
|
* Helper function to get BBB recordings from the Opencast video avaialble in the course. |
2578
|
|
|
* It uses block_opencast for getting all videos for the course and match them with meeting id. |
2579
|
|
|
* It uses tool_opencast for making an api call to get mediapackage of vidoes. |
2580
|
|
|
* |
2581
|
|
|
* @param object $bbbsession |
2582
|
|
|
* @param string $seriesid |
2583
|
|
|
* |
2584
|
|
|
*/ |
2585
|
|
|
function bigbluebutton_get_opencast_recordings_for_table_view($bbbsession, $seriesid) { |
|
|
|
|
2586
|
|
|
$bbbocvideos = array(); |
2587
|
|
|
// Initializing the api from tool_opencast plugin. |
2588
|
|
|
$api = new \tool_opencast\local\api(); |
2589
|
|
|
// Getting an instance of apibridge from block_opencast plugin. |
2590
|
|
|
$opencast = \block_opencast\local\apibridge::get_instance(); |
2591
|
|
|
// Getting the course videos from block_opencast plugin. |
2592
|
|
|
$ocvideos = $opencast->get_course_videos($bbbsession['course']->id); |
2593
|
|
|
if ($ocvideos->videos && !empty($ocvideos->videos)) { |
2594
|
|
|
foreach ($ocvideos->videos as $ocvideo) { |
2595
|
|
|
// Check subjects of opencast video contains $bbbsession['meetingid']. |
2596
|
|
|
if (in_array($bbbsession['meetingid'], $ocvideo->subjects)) { |
2597
|
|
|
// Converting $ocvideo object to array. |
2598
|
|
|
$ocvideoarray = json_decode(json_encode($ocvideo), true); |
2599
|
|
|
// Get mediapackage json using api call. |
2600
|
|
|
$url = '/search/episode.json?id=' . $ocvideo->identifier; |
2601
|
|
|
$search_result = json_decode($api->oc_get($url), true); |
2602
|
|
|
if ($api->get_http_code() == 200 && isset($search_result['search-results']['result']['mediapackage'])) { |
2603
|
|
|
// Add mediapackage to array if exists. |
2604
|
|
|
$ocvideoarray['mediapackage'] = $search_result['search-results']['result']['mediapackage']; |
2605
|
|
|
} |
2606
|
|
|
$bbbocvideos[] = $ocvideoarray; |
2607
|
|
|
} |
2608
|
|
|
} |
2609
|
|
|
} |
2610
|
|
|
return $bbbocvideos; |
2611
|
|
|
} |
2612
|
|
|
|
2613
|
|
|
/** |
2614
|
|
|
* Helper function to convert an html string to plain text. |
2615
|
|
|
* |
2616
|
|
|
* @param string $html |
2617
|
|
|
* @param integer $len |
2618
|
|
|
* |
2619
|
|
|
* @return string |
2620
|
|
|
*/ |
2621
|
|
|
function bigbluebuttonbn_html2text($html, $len = 0) { |
2622
|
|
|
$text = strip_tags($html); |
2623
|
|
|
$text = str_replace(' ', ' ', $text); |
2624
|
|
|
$textlen = strlen($text); |
2625
|
|
|
$text = mb_substr($text, 0, $len); |
2626
|
|
|
if ($textlen > $len) { |
2627
|
|
|
$text .= '...'; |
2628
|
|
|
} |
2629
|
|
|
return $text; |
2630
|
|
|
} |
2631
|
|
|
|
2632
|
|
|
/** |
2633
|
|
|
* Helper function to obtain the tags linked to a bigbluebuttonbn activity |
2634
|
|
|
* |
2635
|
|
|
* @param string $id |
2636
|
|
|
* |
2637
|
|
|
* @return string containing the tags separated by commas |
2638
|
|
|
*/ |
2639
|
|
|
function bigbluebuttonbn_get_tags($id) { |
2640
|
|
|
if (class_exists('core_tag_tag')) { |
2641
|
|
|
return implode(',', core_tag_tag::get_item_tags_array('core', 'course_modules', $id)); |
2642
|
|
|
} |
2643
|
|
|
return implode(',', tag_get_tags('bigbluebuttonbn', $id)); |
2644
|
|
|
} |
2645
|
|
|
|
2646
|
|
|
/** |
2647
|
|
|
* Helper function to define the sql used for gattering the bigbluebuttonbnids whose meetingids should be included |
2648
|
|
|
* in the getRecordings request |
2649
|
|
|
* |
2650
|
|
|
* @param string $courseid |
2651
|
|
|
* @param string $bigbluebuttonbnid |
2652
|
|
|
* @param bool $subset |
2653
|
|
|
* |
2654
|
|
|
* @return string containing the sql used for getting the target bigbluebuttonbn instances |
2655
|
|
|
*/ |
2656
|
|
|
function bigbluebuttonbn_get_recordings_sql_select($courseid, $bigbluebuttonbnid = null, $subset = true) { |
2657
|
|
|
if (empty($courseid)) { |
2658
|
|
|
$courseid = 0; |
2659
|
|
|
} |
2660
|
|
|
if (empty($bigbluebuttonbnid)) { |
2661
|
|
|
return "course = '{$courseid}'"; |
2662
|
|
|
} |
2663
|
|
|
if ($subset) { |
2664
|
|
|
return "id = '{$bigbluebuttonbnid}'"; |
2665
|
|
|
} |
2666
|
|
|
return "id <> '{$bigbluebuttonbnid}' AND course = '{$courseid}'"; |
2667
|
|
|
} |
2668
|
|
|
|
2669
|
|
|
/** |
2670
|
|
|
* Helper function to define the sql used for gattering the bigbluebuttonbnids whose meetingids should be included |
2671
|
|
|
* in the getRecordings request considering only those that belong to deleted activities. |
2672
|
|
|
* |
2673
|
|
|
* @param string $courseid |
2674
|
|
|
* @param string $bigbluebuttonbnid |
2675
|
|
|
* @param bool $subset |
2676
|
|
|
* |
2677
|
|
|
* @return string containing the sql used for getting the target bigbluebuttonbn instances |
2678
|
|
|
*/ |
2679
|
|
View Code Duplication |
function bigbluebuttonbn_get_recordings_deleted_sql_select($courseid = 0, $bigbluebuttonbnid = null, $subset = true) { |
|
|
|
|
2680
|
|
|
$sql = "log = '" . BIGBLUEBUTTONBN_LOG_EVENT_DELETE . "' AND meta like '%has_recordings%' AND meta like '%true%'"; |
2681
|
|
|
if (empty($courseid)) { |
2682
|
|
|
$courseid = 0; |
2683
|
|
|
} |
2684
|
|
|
if (empty($bigbluebuttonbnid)) { |
2685
|
|
|
return $sql . " AND courseid = {$courseid}"; |
2686
|
|
|
} |
2687
|
|
|
if ($subset) { |
2688
|
|
|
return $sql . " AND bigbluebuttonbnid = '{$bigbluebuttonbnid}'"; |
2689
|
|
|
} |
2690
|
|
|
return $sql . " AND courseid = {$courseid} AND bigbluebuttonbnid <> '{$bigbluebuttonbnid}'"; |
2691
|
|
|
} |
2692
|
|
|
|
2693
|
|
|
/** |
2694
|
|
|
* Helper function to define the sql used for gattering the bigbluebuttonbnids whose meetingids should be included |
2695
|
|
|
* in the getRecordings request considering only those that belong to imported recordings. |
2696
|
|
|
* |
2697
|
|
|
* @param string $courseid |
2698
|
|
|
* @param string $bigbluebuttonbnid |
2699
|
|
|
* @param bool $subset |
2700
|
|
|
* |
2701
|
|
|
* @return string containing the sql used for getting the target bigbluebuttonbn instances |
2702
|
|
|
*/ |
2703
|
|
View Code Duplication |
function bigbluebuttonbn_get_recordings_imported_sql_select($courseid = 0, $bigbluebuttonbnid = null, $subset = true) { |
|
|
|
|
2704
|
|
|
$sql = "log = '" . BIGBLUEBUTTONBN_LOG_EVENT_IMPORT . "'"; |
2705
|
|
|
if (empty($courseid)) { |
2706
|
|
|
$courseid = 0; |
2707
|
|
|
} |
2708
|
|
|
if (empty($bigbluebuttonbnid)) { |
2709
|
|
|
return $sql . " AND courseid = '{$courseid}'"; |
2710
|
|
|
} |
2711
|
|
|
if ($subset) { |
2712
|
|
|
return $sql . " AND bigbluebuttonbnid = '{$bigbluebuttonbnid}'"; |
2713
|
|
|
} |
2714
|
|
|
return $sql . " AND courseid = '{$courseid}' AND bigbluebuttonbnid <> '{$bigbluebuttonbnid}'"; |
2715
|
|
|
} |
2716
|
|
|
|
2717
|
|
|
/** |
2718
|
|
|
* Helper function to get recordings and imported recordings together. |
2719
|
|
|
* |
2720
|
|
|
* @param string $courseid |
2721
|
|
|
* @param string $bigbluebuttonbnid |
2722
|
|
|
* @param bool $subset |
2723
|
|
|
* @param bool $includedeleted |
2724
|
|
|
* |
2725
|
|
|
* @return associative array containing the recordings indexed by recordID, each recording is also a |
2726
|
|
|
* non sequential associative array itself that corresponds to the actual recording in BBB |
2727
|
|
|
*/ |
2728
|
|
|
function bigbluebuttonbn_get_allrecordings($courseid = 0, $bigbluebuttonbnid = null, $subset = true, $includedeleted = false) { |
2729
|
|
|
$recordings = bigbluebuttonbn_get_recordings($courseid, $bigbluebuttonbnid, $subset, $includedeleted); |
2730
|
|
|
$recordingsimported = bigbluebuttonbn_get_recordings_imported_array($courseid, $bigbluebuttonbnid, $subset); |
2731
|
|
|
return ($recordings + $recordingsimported); |
2732
|
|
|
} |
2733
|
|
|
|
2734
|
|
|
/** |
2735
|
|
|
* Helper function to retrieve recordings from the BigBlueButton. The references are stored as events |
2736
|
|
|
* in bigbluebuttonbn_logs. |
2737
|
|
|
* |
2738
|
|
|
* @param string $courseid |
2739
|
|
|
* @param string $bigbluebuttonbnid |
2740
|
|
|
* @param bool $subset |
2741
|
|
|
* @param bool $includedeleted |
2742
|
|
|
* |
2743
|
|
|
* @return associative array containing the recordings indexed by recordID, each recording is also a |
2744
|
|
|
* non sequential associative array itself that corresponds to the actual recording in BBB |
2745
|
|
|
*/ |
2746
|
|
|
function bigbluebuttonbn_get_recordings($courseid = 0, $bigbluebuttonbnid = null, $subset = true, $includedeleted = false) { |
2747
|
|
|
global $DB; |
2748
|
|
|
$select = bigbluebuttonbn_get_recordings_sql_select($courseid, $bigbluebuttonbnid, $subset); |
2749
|
|
|
$bigbluebuttonbns = $DB->get_records_select_menu('bigbluebuttonbn', $select, null, 'id', 'id, meetingid'); |
2750
|
|
|
/* Consider logs from deleted bigbluebuttonbn instances whose meetingids should be included in |
2751
|
|
|
* the getRecordings request. */ |
2752
|
|
|
if ($includedeleted) { |
2753
|
|
|
$selectdeleted = bigbluebuttonbn_get_recordings_deleted_sql_select($courseid, $bigbluebuttonbnid, $subset); |
2754
|
|
|
$bigbluebuttonbnsdel = $DB->get_records_select_menu( |
2755
|
|
|
'bigbluebuttonbn_logs', |
2756
|
|
|
$selectdeleted, |
2757
|
|
|
null, |
2758
|
|
|
'bigbluebuttonbnid', |
2759
|
|
|
'bigbluebuttonbnid, meetingid' |
2760
|
|
|
); |
2761
|
|
|
if (!empty($bigbluebuttonbnsdel)) { |
2762
|
|
|
// Merge bigbluebuttonbnis from deleted instances, only keys are relevant. |
2763
|
|
|
// Artimetic merge is used in order to keep the keys. |
2764
|
|
|
$bigbluebuttonbns += $bigbluebuttonbnsdel; |
2765
|
|
|
} |
2766
|
|
|
} |
2767
|
|
|
// Gather the meetingids from bigbluebuttonbn logs that include a create with record=true. |
2768
|
|
|
if (empty($bigbluebuttonbns)) { |
2769
|
|
|
return array(); |
2770
|
|
|
} |
2771
|
|
|
// Prepare select for loading records based on existent bigbluebuttonbns. |
2772
|
|
|
$sql = 'SELECT DISTINCT meetingid, bigbluebuttonbnid FROM {bigbluebuttonbn_logs} WHERE '; |
2773
|
|
|
$sql .= '(bigbluebuttonbnid=' . implode(' OR bigbluebuttonbnid=', array_keys($bigbluebuttonbns)) . ')'; |
2774
|
|
|
// Include only Create events and exclude those with record not true. |
2775
|
|
|
$sql .= ' AND log = ? AND meta LIKE ? AND meta LIKE ?'; |
2776
|
|
|
// Execute select for loading records based on existent bigbluebuttonbns. |
2777
|
|
|
$records = $DB->get_records_sql_menu($sql, array(BIGBLUEBUTTONBN_LOG_EVENT_CREATE, '%record%', '%true%')); |
2778
|
|
|
// Get actual recordings. |
2779
|
|
|
return bigbluebuttonbn_get_recordings_array(array_keys($records)); |
2780
|
|
|
} |
2781
|
|
|
|
2782
|
|
|
/** |
2783
|
|
|
* Helper function iterates an array with recordings and unset those already imported. |
2784
|
|
|
* |
2785
|
|
|
* @param array $recordings |
2786
|
|
|
* @param integer $courseid |
2787
|
|
|
* @param integer $bigbluebuttonbnid |
2788
|
|
|
* |
2789
|
|
|
* @return array |
2790
|
|
|
*/ |
2791
|
|
|
function bigbluebuttonbn_unset_existent_recordings_already_imported($recordings, $courseid, $bigbluebuttonbnid) { |
2792
|
|
|
$recordingsimported = bigbluebuttonbn_get_recordings_imported_array($courseid, $bigbluebuttonbnid, true); |
2793
|
|
|
foreach ($recordings as $key => $recording) { |
2794
|
|
|
if (isset($recordingsimported[$recording['recordID']])) { |
2795
|
|
|
unset($recordings[$key]); |
2796
|
|
|
} |
2797
|
|
|
} |
2798
|
|
|
return $recordings; |
2799
|
|
|
} |
2800
|
|
|
|
2801
|
|
|
/** |
2802
|
|
|
* Helper function to count the imported recordings for a recordingid. |
2803
|
|
|
* |
2804
|
|
|
* @param string $recordid |
2805
|
|
|
* |
2806
|
|
|
* @return integer |
2807
|
|
|
*/ |
2808
|
|
|
function bigbluebuttonbn_count_recording_imported_instances($recordid) { |
2809
|
|
|
global $DB; |
2810
|
|
|
$sql = 'SELECT COUNT(DISTINCT id) FROM {bigbluebuttonbn_logs} WHERE log = ? AND meta LIKE ? AND meta LIKE ?'; |
2811
|
|
|
return $DB->count_records_sql($sql, array(BIGBLUEBUTTONBN_LOG_EVENT_IMPORT, '%recordID%', "%{$recordid}%")); |
2812
|
|
|
} |
2813
|
|
|
|
2814
|
|
|
/** |
2815
|
|
|
* Helper function returns an array with all the instances of imported recordings for a recordingid. |
2816
|
|
|
* |
2817
|
|
|
* @param string $recordid |
2818
|
|
|
* |
2819
|
|
|
* @return array |
2820
|
|
|
*/ |
2821
|
|
|
function bigbluebuttonbn_get_recording_imported_instances($recordid) { |
2822
|
|
|
global $DB; |
2823
|
|
|
$sql = 'SELECT * FROM {bigbluebuttonbn_logs} WHERE log = ? AND meta LIKE ? AND meta LIKE ?'; |
2824
|
|
|
$recordingsimported = $DB->get_records_sql($sql, array(BIGBLUEBUTTONBN_LOG_EVENT_IMPORT, '%recordID%', |
2825
|
|
|
"%{$recordid}%")); |
2826
|
|
|
return $recordingsimported; |
2827
|
|
|
} |
2828
|
|
|
|
2829
|
|
|
/** |
2830
|
|
|
* Helper function to get how much callback events are logged. |
2831
|
|
|
* |
2832
|
|
|
* @param string $recordid |
2833
|
|
|
* @param string $callbacktype |
2834
|
|
|
* |
2835
|
|
|
* @return integer |
2836
|
|
|
*/ |
2837
|
|
|
function bigbluebuttonbn_get_count_callback_event_log($recordid, $callbacktype = 'recording_ready') { |
2838
|
|
|
global $DB; |
2839
|
|
|
$sql = 'SELECT count(DISTINCT id) FROM {bigbluebuttonbn_logs} WHERE log = ? AND meta LIKE ? AND meta LIKE ?'; |
2840
|
|
|
// Callback type added on version 2.4, validate recording_ready first or assume it on records with no callback. |
2841
|
|
|
if ($callbacktype == 'recording_ready') { |
2842
|
|
|
$sql .= ' AND (meta LIKE ? OR meta NOT LIKE ? )'; |
2843
|
|
|
$count = $DB->count_records_sql($sql, array(BIGBLUEBUTTON_LOG_EVENT_CALLBACK, '%recordid%', "%$recordid%", |
2844
|
|
|
$callbacktype, 'callback')); |
2845
|
|
|
return $count; |
2846
|
|
|
} |
2847
|
|
|
$sql .= ' AND meta LIKE ?;'; |
2848
|
|
|
$count = $DB->count_records_sql($sql, array(BIGBLUEBUTTON_LOG_EVENT_CALLBACK, '%recordid%', "%$recordid%", "%$callbacktype%")); |
2849
|
|
|
return $count; |
2850
|
|
|
} |
2851
|
|
|
|
2852
|
|
|
/** |
2853
|
|
|
* Helper function returns an array with the profiles (with features per profile) for the different types |
2854
|
|
|
* of bigbluebuttonbn instances. |
2855
|
|
|
* |
2856
|
|
|
* @return array |
2857
|
|
|
*/ |
2858
|
|
|
function bigbluebuttonbn_get_instance_type_profiles() { |
2859
|
|
|
$instanceprofiles = array( |
2860
|
|
|
BIGBLUEBUTTONBN_TYPE_ALL => array('id' => BIGBLUEBUTTONBN_TYPE_ALL, |
2861
|
|
|
'name' => get_string('instance_type_default', 'bigbluebuttonbn'), |
2862
|
|
|
'features' => array('all')), |
2863
|
|
|
BIGBLUEBUTTONBN_TYPE_ROOM_ONLY => array('id' => BIGBLUEBUTTONBN_TYPE_ROOM_ONLY, |
2864
|
|
|
'name' => get_string('instance_type_room_only', 'bigbluebuttonbn'), |
2865
|
|
|
'features' => array('showroom', 'welcomemessage', 'voicebridge', 'waitformoderator', 'userlimit', |
2866
|
|
|
'recording', 'sendnotifications', 'preuploadpresentation', 'permissions', 'schedule', 'groups', |
2867
|
|
|
'modstandardelshdr', 'availabilityconditionsheader', 'tagshdr', 'competenciessection', |
2868
|
|
|
'clienttype', 'completionattendance', 'completionengagement', 'availabilityconditionsheader')), |
2869
|
|
|
BIGBLUEBUTTONBN_TYPE_RECORDING_ONLY => array('id' => BIGBLUEBUTTONBN_TYPE_RECORDING_ONLY, |
2870
|
|
|
'name' => get_string('instance_type_recording_only', 'bigbluebuttonbn'), |
2871
|
|
|
'features' => array('showrecordings', 'importrecordings', 'availabilityconditionsheader')), |
2872
|
|
|
); |
2873
|
|
|
return $instanceprofiles; |
2874
|
|
|
} |
2875
|
|
|
|
2876
|
|
|
/** |
2877
|
|
|
* Helper function returns an array with enabled features for an specific profile type. |
2878
|
|
|
* |
2879
|
|
|
* @param array $typeprofiles |
2880
|
|
|
* @param string $type |
2881
|
|
|
* |
2882
|
|
|
* @return array |
2883
|
|
|
*/ |
2884
|
|
|
function bigbluebuttonbn_get_enabled_features($typeprofiles, $type = null) { |
2885
|
|
|
$enabledfeatures = array(); |
2886
|
|
|
$features = $typeprofiles[BIGBLUEBUTTONBN_TYPE_ALL]['features']; |
2887
|
|
|
if (!is_null($type) && key_exists($type, $typeprofiles)) { |
2888
|
|
|
$features = $typeprofiles[$type]['features']; |
2889
|
|
|
} |
2890
|
|
|
$enabledfeatures['showroom'] = (in_array('all', $features) || in_array('showroom', $features)); |
2891
|
|
|
// Evaluates if recordings are enabled for the Moodle site. |
2892
|
|
|
$enabledfeatures['showrecordings'] = false; |
2893
|
|
|
if (\mod_bigbluebuttonbn\locallib\config::recordings_enabled()) { |
2894
|
|
|
$enabledfeatures['showrecordings'] = (in_array('all', $features) || in_array('showrecordings', $features)); |
2895
|
|
|
} |
2896
|
|
|
$enabledfeatures['importrecordings'] = false; |
2897
|
|
|
if (\mod_bigbluebuttonbn\locallib\config::importrecordings_enabled()) { |
2898
|
|
|
$enabledfeatures['importrecordings'] = (in_array('all', $features) || in_array('importrecordings', $features)); |
2899
|
|
|
} |
2900
|
|
|
// Evaluates if clienttype is enabled for the Moodle site. |
2901
|
|
|
$enabledfeatures['clienttype'] = false; |
2902
|
|
|
if (\mod_bigbluebuttonbn\locallib\config::clienttype_enabled()) { |
2903
|
|
|
$enabledfeatures['clienttype'] = (in_array('all', $features) || in_array('clienttype', $features)); |
2904
|
|
|
} |
2905
|
|
|
return $enabledfeatures; |
2906
|
|
|
} |
2907
|
|
|
|
2908
|
|
|
/** |
2909
|
|
|
* Helper function returns an array with the profiles (with features per profile) for the different types |
2910
|
|
|
* of bigbluebuttonbn instances that the user is allowed to create. |
2911
|
|
|
* |
2912
|
|
|
* @param boolean $room |
2913
|
|
|
* @param boolean $recording |
2914
|
|
|
* |
2915
|
|
|
* @return array |
2916
|
|
|
*/ |
2917
|
|
|
function bigbluebuttonbn_get_instance_type_profiles_create_allowed($room, $recording) { |
2918
|
|
|
$profiles = bigbluebuttonbn_get_instance_type_profiles(); |
2919
|
|
|
if (!$room) { |
2920
|
|
|
unset($profiles[BIGBLUEBUTTONBN_TYPE_ROOM_ONLY]); |
2921
|
|
|
unset($profiles[BIGBLUEBUTTONBN_TYPE_ALL]); |
2922
|
|
|
} |
2923
|
|
|
if (!$recording) { |
2924
|
|
|
unset($profiles[BIGBLUEBUTTONBN_TYPE_RECORDING_ONLY]); |
2925
|
|
|
unset($profiles[BIGBLUEBUTTONBN_TYPE_ALL]); |
2926
|
|
|
} |
2927
|
|
|
return $profiles; |
2928
|
|
|
} |
2929
|
|
|
|
2930
|
|
|
/** |
2931
|
|
|
* Helper function returns an array with the profiles (with features per profile) for the different types |
2932
|
|
|
* of bigbluebuttonbn instances. |
2933
|
|
|
* |
2934
|
|
|
* @param array $profiles |
2935
|
|
|
* |
2936
|
|
|
* @return array |
2937
|
|
|
*/ |
2938
|
|
|
function bigbluebuttonbn_get_instance_profiles_array($profiles = []) { |
2939
|
|
|
$profilesarray = array(); |
2940
|
|
|
foreach ($profiles as $key => $profile) { |
2941
|
|
|
$profilesarray[$profile['id']] = $profile['name']; |
2942
|
|
|
} |
2943
|
|
|
return $profilesarray; |
2944
|
|
|
} |
2945
|
|
|
|
2946
|
|
|
/** |
2947
|
|
|
* Helper function returns time in a formatted string. |
2948
|
|
|
* |
2949
|
|
|
* @param integer $time |
2950
|
|
|
* |
2951
|
|
|
* @return string |
2952
|
|
|
*/ |
2953
|
|
|
function bigbluebuttonbn_format_activity_time($time) { |
2954
|
|
|
global $CFG; |
2955
|
|
|
require_once($CFG->dirroot.'/calendar/lib.php'); |
2956
|
|
|
$activitytime = ''; |
2957
|
|
|
if ($time) { |
2958
|
|
|
$activitytime = calendar_day_representation($time) . ' ' . |
2959
|
|
|
get_string('mod_form_field_notification_msg_at', 'bigbluebuttonbn') . ' ' . |
2960
|
|
|
calendar_time_representation($time); |
2961
|
|
|
} |
2962
|
|
|
return $activitytime; |
2963
|
|
|
} |
2964
|
|
|
|
2965
|
|
|
/** |
2966
|
|
|
* Helper function returns array with all the strings to be used in javascript. |
2967
|
|
|
* |
2968
|
|
|
* @return array |
2969
|
|
|
*/ |
2970
|
|
|
function bigbluebuttonbn_get_strings_for_js() { |
2971
|
|
|
$locale = bigbluebuttonbn_get_locale(); |
2972
|
|
|
$stringman = get_string_manager(); |
2973
|
|
|
$strings = $stringman->load_component_strings('bigbluebuttonbn', $locale); |
2974
|
|
|
return $strings; |
2975
|
|
|
} |
2976
|
|
|
|
2977
|
|
|
/** |
2978
|
|
|
* Helper function returns the locale set by moodle. |
2979
|
|
|
* |
2980
|
|
|
* @return string |
2981
|
|
|
*/ |
2982
|
|
|
function bigbluebuttonbn_get_locale() { |
2983
|
|
|
$lang = get_string('locale', 'core_langconfig'); |
2984
|
|
|
return substr($lang, 0, strpos($lang, '.')); |
2985
|
|
|
} |
2986
|
|
|
|
2987
|
|
|
/** |
2988
|
|
|
* Helper function returns the locale code based on the locale set by moodle. |
2989
|
|
|
* |
2990
|
|
|
* @return string |
2991
|
|
|
*/ |
2992
|
|
|
function bigbluebuttonbn_get_localcode() { |
2993
|
|
|
$locale = bigbluebuttonbn_get_locale(); |
2994
|
|
|
return substr($locale, 0, strpos($locale, '_')); |
2995
|
|
|
} |
2996
|
|
|
|
2997
|
|
|
/** |
2998
|
|
|
* Helper function returns array with the instance settings used in views. |
2999
|
|
|
* |
3000
|
|
|
* @param string $id |
3001
|
|
|
* @param object $bigbluebuttonbnid |
3002
|
|
|
* |
3003
|
|
|
* @return array |
3004
|
|
|
*/ |
3005
|
|
|
function bigbluebuttonbn_view_validator($id, $bigbluebuttonbnid) { |
3006
|
|
|
if ($id) { |
3007
|
|
|
return bigbluebuttonbn_view_instance_id($id); |
3008
|
|
|
} |
3009
|
|
|
if ($bigbluebuttonbnid) { |
3010
|
|
|
return bigbluebuttonbn_view_instance_bigbluebuttonbn($bigbluebuttonbnid); |
3011
|
|
|
} |
3012
|
|
|
} |
3013
|
|
|
|
3014
|
|
|
/** |
3015
|
|
|
* Helper function returns array with the instance settings used in views based on id. |
3016
|
|
|
* |
3017
|
|
|
* @param string $id |
3018
|
|
|
* |
3019
|
|
|
* @return array |
3020
|
|
|
*/ |
3021
|
|
View Code Duplication |
function bigbluebuttonbn_view_instance_id($id) { |
|
|
|
|
3022
|
|
|
global $DB; |
3023
|
|
|
$cm = get_coursemodule_from_id('bigbluebuttonbn', $id, 0, false, MUST_EXIST); |
3024
|
|
|
$course = $DB->get_record('course', array('id' => $cm->course), '*', MUST_EXIST); |
3025
|
|
|
$bigbluebuttonbn = $DB->get_record('bigbluebuttonbn', array('id' => $cm->instance), '*', MUST_EXIST); |
3026
|
|
|
return array('cm' => $cm, 'course' => $course, 'bigbluebuttonbn' => $bigbluebuttonbn); |
3027
|
|
|
} |
3028
|
|
|
|
3029
|
|
|
/** |
3030
|
|
|
* Helper function returns array with the instance settings used in views based on bigbluebuttonbnid. |
3031
|
|
|
* |
3032
|
|
|
* @param object $bigbluebuttonbnid |
3033
|
|
|
* |
3034
|
|
|
* @return array |
3035
|
|
|
*/ |
3036
|
|
View Code Duplication |
function bigbluebuttonbn_view_instance_bigbluebuttonbn($bigbluebuttonbnid) { |
|
|
|
|
3037
|
|
|
global $DB; |
3038
|
|
|
$bigbluebuttonbn = $DB->get_record('bigbluebuttonbn', array('id' => $bigbluebuttonbnid), '*', MUST_EXIST); |
3039
|
|
|
$course = $DB->get_record('course', array('id' => $bigbluebuttonbn->course), '*', MUST_EXIST); |
3040
|
|
|
$cm = get_coursemodule_from_instance('bigbluebuttonbn', $bigbluebuttonbn->id, $course->id, false, MUST_EXIST); |
3041
|
|
|
return array('cm' => $cm, 'course' => $course, 'bigbluebuttonbn' => $bigbluebuttonbn); |
3042
|
|
|
} |
3043
|
|
|
|
3044
|
|
|
/** |
3045
|
|
|
* Helper function renders general settings if the feature is enabled. |
3046
|
|
|
* |
3047
|
|
|
* @param object $renderer |
3048
|
|
|
* |
3049
|
|
|
* @return void |
3050
|
|
|
*/ |
3051
|
|
|
function bigbluebuttonbn_settings_general(&$renderer) { |
3052
|
|
|
// Configuration for BigBlueButton. |
3053
|
|
|
if ((boolean) \mod_bigbluebuttonbn\settings\validator::section_general_shown()) { |
3054
|
|
|
$renderer->render_group_header('general'); |
3055
|
|
|
$renderer->render_group_element( |
3056
|
|
|
'server_url', |
3057
|
|
|
$renderer->render_group_element_text('server_url', BIGBLUEBUTTONBN_DEFAULT_SERVER_URL) |
3058
|
|
|
); |
3059
|
|
|
$renderer->render_group_element( |
3060
|
|
|
'shared_secret', |
3061
|
|
|
$renderer->render_group_element_text('shared_secret', BIGBLUEBUTTONBN_DEFAULT_SHARED_SECRET) |
3062
|
|
|
); |
3063
|
|
|
} |
3064
|
|
|
} |
3065
|
|
|
|
3066
|
|
|
/** |
3067
|
|
|
* Helper function renders record settings if the feature is enabled. |
3068
|
|
|
* |
3069
|
|
|
* @param object $renderer |
3070
|
|
|
* |
3071
|
|
|
* @return void |
3072
|
|
|
*/ |
3073
|
|
|
function bigbluebuttonbn_settings_record(&$renderer) { |
3074
|
|
|
// Configuration for 'recording' feature. |
3075
|
|
|
if ((boolean) \mod_bigbluebuttonbn\settings\validator::section_record_meeting_shown()) { |
3076
|
|
|
$renderer->render_group_header('recording'); |
3077
|
|
|
$renderer->render_group_element( |
3078
|
|
|
'recording_default', |
3079
|
|
|
$renderer->render_group_element_checkbox('recording_default', 1) |
3080
|
|
|
); |
3081
|
|
|
$renderer->render_group_element( |
3082
|
|
|
'recording_editable', |
3083
|
|
|
$renderer->render_group_element_checkbox('recording_editable', 1) |
3084
|
|
|
); |
3085
|
|
|
$renderer->render_group_element( |
3086
|
|
|
'recording_icons_enabled', |
3087
|
|
|
$renderer->render_group_element_checkbox('recording_icons_enabled', 1) |
3088
|
|
|
); |
3089
|
|
|
|
3090
|
|
|
// Add recording start to load and allow/hide stop/pause. |
3091
|
|
|
$renderer->render_group_element( |
3092
|
|
|
'recording_all_from_start_default', |
3093
|
|
|
$renderer->render_group_element_checkbox('recording_all_from_start_default', 0) |
3094
|
|
|
); |
3095
|
|
|
$renderer->render_group_element( |
3096
|
|
|
'recording_all_from_start_editable', |
3097
|
|
|
$renderer->render_group_element_checkbox('recording_all_from_start_editable', 0) |
3098
|
|
|
); |
3099
|
|
|
$renderer->render_group_element( |
3100
|
|
|
'recording_hide_button_default', |
3101
|
|
|
$renderer->render_group_element_checkbox('recording_hide_button_default', 0) |
3102
|
|
|
); |
3103
|
|
|
$renderer->render_group_element( |
3104
|
|
|
'recording_hide_button_editable', |
3105
|
|
|
$renderer->render_group_element_checkbox('recording_hide_button_editable', 0) |
3106
|
|
|
); |
3107
|
|
|
} |
3108
|
|
|
} |
3109
|
|
|
|
3110
|
|
|
/** |
3111
|
|
|
* Helper function renders import recording settings if the feature is enabled. |
3112
|
|
|
* |
3113
|
|
|
* @param object $renderer |
3114
|
|
|
* |
3115
|
|
|
* @return void |
3116
|
|
|
*/ |
3117
|
|
View Code Duplication |
function bigbluebuttonbn_settings_importrecordings(&$renderer) { |
|
|
|
|
3118
|
|
|
// Configuration for 'import recordings' feature. |
3119
|
|
|
if ((boolean) \mod_bigbluebuttonbn\settings\validator::section_import_recordings_shown()) { |
3120
|
|
|
$renderer->render_group_header('importrecordings'); |
3121
|
|
|
$renderer->render_group_element( |
3122
|
|
|
'importrecordings_enabled', |
3123
|
|
|
$renderer->render_group_element_checkbox('importrecordings_enabled', 0) |
3124
|
|
|
); |
3125
|
|
|
$renderer->render_group_element( |
3126
|
|
|
'importrecordings_from_deleted_enabled', |
3127
|
|
|
$renderer->render_group_element_checkbox('importrecordings_from_deleted_enabled', 0) |
3128
|
|
|
); |
3129
|
|
|
} |
3130
|
|
|
} |
3131
|
|
|
|
3132
|
|
|
/** |
3133
|
|
|
* Helper function renders show recording settings if the feature is enabled. |
3134
|
|
|
* |
3135
|
|
|
* @param object $renderer |
3136
|
|
|
* |
3137
|
|
|
* @return void |
3138
|
|
|
*/ |
3139
|
|
|
function bigbluebuttonbn_settings_showrecordings(&$renderer) { |
3140
|
|
|
// Configuration for 'show recordings' feature. |
3141
|
|
|
if ((boolean) \mod_bigbluebuttonbn\settings\validator::section_show_recordings_shown()) { |
3142
|
|
|
$renderer->render_group_header('recordings'); |
3143
|
|
|
$renderer->render_group_element( |
3144
|
|
|
'recordings_html_default', |
3145
|
|
|
$renderer->render_group_element_checkbox('recordings_html_default', 1) |
3146
|
|
|
); |
3147
|
|
|
$renderer->render_group_element( |
3148
|
|
|
'recordings_html_editable', |
3149
|
|
|
$renderer->render_group_element_checkbox('recordings_html_editable', 0) |
3150
|
|
|
); |
3151
|
|
|
$renderer->render_group_element( |
3152
|
|
|
'recordings_deleted_default', |
3153
|
|
|
$renderer->render_group_element_checkbox('recordings_deleted_default', 1) |
3154
|
|
|
); |
3155
|
|
|
$renderer->render_group_element( |
3156
|
|
|
'recordings_deleted_editable', |
3157
|
|
|
$renderer->render_group_element_checkbox('recordings_deleted_editable', 0) |
3158
|
|
|
); |
3159
|
|
|
$renderer->render_group_element( |
3160
|
|
|
'recordings_imported_default', |
3161
|
|
|
$renderer->render_group_element_checkbox('recordings_imported_default', 0) |
3162
|
|
|
); |
3163
|
|
|
$renderer->render_group_element( |
3164
|
|
|
'recordings_imported_editable', |
3165
|
|
|
$renderer->render_group_element_checkbox('recordings_imported_editable', 1) |
3166
|
|
|
); |
3167
|
|
|
$renderer->render_group_element( |
3168
|
|
|
'recordings_preview_default', |
3169
|
|
|
$renderer->render_group_element_checkbox('recordings_preview_default', 1) |
3170
|
|
|
); |
3171
|
|
|
$renderer->render_group_element( |
3172
|
|
|
'recordings_preview_editable', |
3173
|
|
|
$renderer->render_group_element_checkbox('recordings_preview_editable', 0) |
3174
|
|
|
); |
3175
|
|
|
$renderer->render_group_element( |
3176
|
|
|
'recordings_sortorder', |
3177
|
|
|
$renderer->render_group_element_checkbox('recordings_sortorder', 0) |
3178
|
|
|
); |
3179
|
|
|
$renderer->render_group_element( |
3180
|
|
|
'recordings_validate_url', |
3181
|
|
|
$renderer->render_group_element_checkbox('recordings_validate_url', 1) |
3182
|
|
|
); |
3183
|
|
|
} |
3184
|
|
|
} |
3185
|
|
|
|
3186
|
|
|
/** |
3187
|
|
|
* Helper function renders wait for moderator settings if the feature is enabled. |
3188
|
|
|
* |
3189
|
|
|
* @param object $renderer |
3190
|
|
|
* |
3191
|
|
|
* @return void |
3192
|
|
|
*/ |
3193
|
|
|
function bigbluebuttonbn_settings_waitmoderator(&$renderer) { |
3194
|
|
|
// Configuration for wait for moderator feature. |
3195
|
|
|
if ((boolean) \mod_bigbluebuttonbn\settings\validator::section_wait_moderator_shown()) { |
3196
|
|
|
$renderer->render_group_header('waitformoderator'); |
3197
|
|
|
$renderer->render_group_element( |
3198
|
|
|
'waitformoderator_default', |
3199
|
|
|
$renderer->render_group_element_checkbox('waitformoderator_default', 0) |
3200
|
|
|
); |
3201
|
|
|
$renderer->render_group_element( |
3202
|
|
|
'waitformoderator_editable', |
3203
|
|
|
$renderer->render_group_element_checkbox('waitformoderator_editable', 1) |
3204
|
|
|
); |
3205
|
|
|
$renderer->render_group_element( |
3206
|
|
|
'waitformoderator_ping_interval', |
3207
|
|
|
$renderer->render_group_element_text('waitformoderator_ping_interval', 10, PARAM_INT) |
3208
|
|
|
); |
3209
|
|
|
$renderer->render_group_element( |
3210
|
|
|
'waitformoderator_cache_ttl', |
3211
|
|
|
$renderer->render_group_element_text('waitformoderator_cache_ttl', 60, PARAM_INT) |
3212
|
|
|
); |
3213
|
|
|
} |
3214
|
|
|
} |
3215
|
|
|
|
3216
|
|
|
/** |
3217
|
|
|
* Helper function renders static voice bridge settings if the feature is enabled. |
3218
|
|
|
* |
3219
|
|
|
* @param object $renderer |
3220
|
|
|
* |
3221
|
|
|
* @return void |
3222
|
|
|
*/ |
3223
|
|
|
function bigbluebuttonbn_settings_voicebridge(&$renderer) { |
3224
|
|
|
// Configuration for "static voice bridge" feature. |
3225
|
|
|
if ((boolean) \mod_bigbluebuttonbn\settings\validator::section_static_voice_bridge_shown()) { |
3226
|
|
|
$renderer->render_group_header('voicebridge'); |
3227
|
|
|
$renderer->render_group_element( |
3228
|
|
|
'voicebridge_editable', |
3229
|
|
|
$renderer->render_group_element_checkbox('voicebridge_editable', 0) |
3230
|
|
|
); |
3231
|
|
|
} |
3232
|
|
|
} |
3233
|
|
|
|
3234
|
|
|
/** |
3235
|
|
|
* Helper function renders preuploaded presentation settings if the feature is enabled. |
3236
|
|
|
* |
3237
|
|
|
* @param object $renderer |
3238
|
|
|
* |
3239
|
|
|
* @return void |
3240
|
|
|
*/ |
3241
|
|
|
function bigbluebuttonbn_settings_preupload(&$renderer) { |
3242
|
|
|
// Configuration for "preupload presentation" feature. |
3243
|
|
|
if ((boolean) \mod_bigbluebuttonbn\settings\validator::section_preupload_presentation_shown()) { |
3244
|
|
|
// This feature only works if curl is installed. |
3245
|
|
|
$preuploaddescripion = get_string('config_preuploadpresentation_description', 'bigbluebuttonbn'); |
3246
|
|
|
if (!extension_loaded('curl')) { |
3247
|
|
|
$preuploaddescripion .= '<div class="form-defaultinfo">'; |
3248
|
|
|
$preuploaddescripion .= get_string('config_warning_curl_not_installed', 'bigbluebuttonbn'); |
3249
|
|
|
$preuploaddescripion .= '</div><br>'; |
3250
|
|
|
} |
3251
|
|
|
$renderer->render_group_header('preuploadpresentation', null, $preuploaddescripion); |
3252
|
|
|
if (extension_loaded('curl')) { |
3253
|
|
|
$renderer->render_group_element( |
3254
|
|
|
'preuploadpresentation_enabled', |
3255
|
|
|
$renderer->render_group_element_checkbox('preuploadpresentation_enabled', 0) |
3256
|
|
|
); |
3257
|
|
|
} |
3258
|
|
|
} |
3259
|
|
|
} |
3260
|
|
|
|
3261
|
|
|
/** |
3262
|
|
|
* Helper function renders preuploaded presentation manage file if the feature is enabled. |
3263
|
|
|
* This allow to select a file for use as default in all BBB instances if preuploaded presetantion is enable. |
3264
|
|
|
* |
3265
|
|
|
* @param object $renderer |
3266
|
|
|
* |
3267
|
|
|
* @return void |
3268
|
|
|
*/ |
3269
|
|
|
function bigbluebuttonbn_settings_preupload_manage_default_file(&$renderer) { |
3270
|
|
|
// Configuration for "preupload presentation" feature. |
3271
|
|
|
if ((boolean) \mod_bigbluebuttonbn\settings\validator::section_preupload_presentation_shown()) { |
3272
|
|
|
if (extension_loaded('curl')) { |
3273
|
|
|
// This feature only works if curl is installed. |
3274
|
|
|
$renderer->render_filemanager_default_file_presentation("presentation_default"); |
3275
|
|
|
} |
3276
|
|
|
} |
3277
|
|
|
} |
3278
|
|
|
|
3279
|
|
|
/** |
3280
|
|
|
* Helper function renders userlimit settings if the feature is enabled. |
3281
|
|
|
* |
3282
|
|
|
* @param object $renderer |
3283
|
|
|
* |
3284
|
|
|
* @return void |
3285
|
|
|
*/ |
3286
|
|
|
function bigbluebuttonbn_settings_userlimit(&$renderer) { |
3287
|
|
|
// Configuration for "user limit" feature. |
3288
|
|
|
if ((boolean) \mod_bigbluebuttonbn\settings\validator::section_user_limit_shown()) { |
3289
|
|
|
$renderer->render_group_header('userlimit'); |
3290
|
|
|
$renderer->render_group_element( |
3291
|
|
|
'userlimit_default', |
3292
|
|
|
$renderer->render_group_element_text('userlimit_default', 0, PARAM_INT) |
3293
|
|
|
); |
3294
|
|
|
$renderer->render_group_element( |
3295
|
|
|
'userlimit_editable', |
3296
|
|
|
$renderer->render_group_element_checkbox('userlimit_editable', 0) |
3297
|
|
|
); |
3298
|
|
|
} |
3299
|
|
|
} |
3300
|
|
|
|
3301
|
|
|
/** |
3302
|
|
|
* Helper function renders duration settings if the feature is enabled. |
3303
|
|
|
* |
3304
|
|
|
* @param object $renderer |
3305
|
|
|
* |
3306
|
|
|
* @return void |
3307
|
|
|
*/ |
3308
|
|
|
function bigbluebuttonbn_settings_duration(&$renderer) { |
3309
|
|
|
// Configuration for "scheduled duration" feature. |
3310
|
|
|
if ((boolean) \mod_bigbluebuttonbn\settings\validator::section_scheduled_duration_shown()) { |
3311
|
|
|
$renderer->render_group_header('scheduled'); |
3312
|
|
|
$renderer->render_group_element( |
3313
|
|
|
'scheduled_duration_enabled', |
3314
|
|
|
$renderer->render_group_element_checkbox('scheduled_duration_enabled', 1) |
3315
|
|
|
); |
3316
|
|
|
$renderer->render_group_element( |
3317
|
|
|
'scheduled_duration_compensation', |
3318
|
|
|
$renderer->render_group_element_text('scheduled_duration_compensation', 10, PARAM_INT) |
3319
|
|
|
); |
3320
|
|
|
$renderer->render_group_element( |
3321
|
|
|
'scheduled_pre_opening', |
3322
|
|
|
$renderer->render_group_element_text('scheduled_pre_opening', 10, PARAM_INT) |
3323
|
|
|
); |
3324
|
|
|
} |
3325
|
|
|
} |
3326
|
|
|
|
3327
|
|
|
/** |
3328
|
|
|
* Helper function renders participant settings if the feature is enabled. |
3329
|
|
|
* |
3330
|
|
|
* @param object $renderer |
3331
|
|
|
* |
3332
|
|
|
* @return void |
3333
|
|
|
*/ |
3334
|
|
|
function bigbluebuttonbn_settings_participants(&$renderer) { |
3335
|
|
|
// Configuration for defining the default role/user that will be moderator on new activities. |
3336
|
|
|
if ((boolean) \mod_bigbluebuttonbn\settings\validator::section_moderator_default_shown()) { |
3337
|
|
|
$renderer->render_group_header('participant'); |
3338
|
|
|
// UI for 'participants' feature. |
3339
|
|
|
$roles = bigbluebuttonbn_get_roles(null, false); |
3340
|
|
|
$owner = array('0' => get_string('mod_form_field_participant_list_type_owner', 'bigbluebuttonbn')); |
3341
|
|
|
$renderer->render_group_element( |
3342
|
|
|
'participant_moderator_default', |
3343
|
|
|
$renderer->render_group_element_configmultiselect( |
3344
|
|
|
'participant_moderator_default', |
3345
|
|
|
array_keys($owner), |
3346
|
|
|
$owner + $roles // CONTRIB-7966: don't use array_merge here so it does not reindex the array. |
3347
|
|
|
) |
3348
|
|
|
); |
3349
|
|
|
} |
3350
|
|
|
} |
3351
|
|
|
|
3352
|
|
|
/** |
3353
|
|
|
* Helper function renders notification settings if the feature is enabled. |
3354
|
|
|
* |
3355
|
|
|
* @param object $renderer |
3356
|
|
|
* |
3357
|
|
|
* @return void |
3358
|
|
|
*/ |
3359
|
|
|
function bigbluebuttonbn_settings_notifications(&$renderer) { |
3360
|
|
|
// Configuration for "send notifications" feature. |
3361
|
|
|
if ((boolean) \mod_bigbluebuttonbn\settings\validator::section_send_notifications_shown()) { |
3362
|
|
|
$renderer->render_group_header('sendnotifications'); |
3363
|
|
|
$renderer->render_group_element( |
3364
|
|
|
'sendnotifications_enabled', |
3365
|
|
|
$renderer->render_group_element_checkbox('sendnotifications_enabled', 1) |
3366
|
|
|
); |
3367
|
|
|
} |
3368
|
|
|
} |
3369
|
|
|
|
3370
|
|
|
/** |
3371
|
|
|
* Helper function renders client type settings if the feature is enabled. |
3372
|
|
|
* |
3373
|
|
|
* @param object $renderer |
3374
|
|
|
* |
3375
|
|
|
* @return void |
3376
|
|
|
*/ |
3377
|
|
|
function bigbluebuttonbn_settings_clienttype(&$renderer) { |
3378
|
|
|
// Configuration for "clienttype" feature. |
3379
|
|
|
if ((boolean) \mod_bigbluebuttonbn\settings\validator::section_clienttype_shown()) { |
3380
|
|
|
$renderer->render_group_header('clienttype'); |
3381
|
|
|
$renderer->render_group_element( |
3382
|
|
|
'clienttype_editable', |
3383
|
|
|
$renderer->render_group_element_checkbox('clienttype_editable', 0) |
3384
|
|
|
); |
3385
|
|
|
// Web Client default. |
3386
|
|
|
$default = intval((int) \mod_bigbluebuttonbn\locallib\config::get('clienttype_default')); |
3387
|
|
|
$choices = array(BIGBLUEBUTTON_CLIENTTYPE_FLASH => get_string('mod_form_block_clienttype_flash', 'bigbluebuttonbn'), |
3388
|
|
|
BIGBLUEBUTTON_CLIENTTYPE_HTML5 => get_string('mod_form_block_clienttype_html5', 'bigbluebuttonbn')); |
3389
|
|
|
$renderer->render_group_element( |
3390
|
|
|
'clienttype_default', |
3391
|
|
|
$renderer->render_group_element_configselect( |
3392
|
|
|
'clienttype_default', |
3393
|
|
|
$default, |
3394
|
|
|
$choices |
3395
|
|
|
) |
3396
|
|
|
); |
3397
|
|
|
} |
3398
|
|
|
} |
3399
|
|
|
|
3400
|
|
|
/** |
3401
|
|
|
* Helper function renders general settings if the feature is enabled. |
3402
|
|
|
* |
3403
|
|
|
* @param object $renderer |
3404
|
|
|
* |
3405
|
|
|
* @return void |
3406
|
|
|
*/ |
3407
|
|
View Code Duplication |
function bigbluebuttonbn_settings_muteonstart(&$renderer) { |
|
|
|
|
3408
|
|
|
// Configuration for BigBlueButton. |
3409
|
|
|
if ((boolean) \mod_bigbluebuttonbn\settings\validator::section_muteonstart_shown()) { |
3410
|
|
|
$renderer->render_group_header('muteonstart'); |
3411
|
|
|
$renderer->render_group_element( |
3412
|
|
|
'muteonstart_default', |
3413
|
|
|
$renderer->render_group_element_checkbox('muteonstart_default', 0) |
3414
|
|
|
); |
3415
|
|
|
$renderer->render_group_element( |
3416
|
|
|
'muteonstart_editable', |
3417
|
|
|
$renderer->render_group_element_checkbox('muteonstart_editable', 0) |
3418
|
|
|
); |
3419
|
|
|
} |
3420
|
|
|
} |
3421
|
|
|
|
3422
|
|
|
/** |
3423
|
|
|
* Helper function renders general settings if the feature is enabled. |
3424
|
|
|
* |
3425
|
|
|
* @param object $renderer |
3426
|
|
|
* |
3427
|
|
|
* @return void |
3428
|
|
|
*/ |
3429
|
|
|
function bigbluebuttonbn_settings_locksettings(&$renderer) { |
3430
|
|
|
$renderer->render_group_header('locksettings'); |
3431
|
|
|
// Configuration for various lock settings for meetings. |
3432
|
|
|
bigbluebuttonbn_settings_disablecam($renderer); |
3433
|
|
|
bigbluebuttonbn_settings_disablemic($renderer); |
3434
|
|
|
bigbluebuttonbn_settings_disableprivatechat($renderer); |
3435
|
|
|
bigbluebuttonbn_settings_disablepublicchat($renderer); |
3436
|
|
|
bigbluebuttonbn_settings_disablenote($renderer); |
3437
|
|
|
bigbluebuttonbn_settings_hideuserlist($renderer); |
3438
|
|
|
bigbluebuttonbn_settings_lockedlayout($renderer); |
3439
|
|
|
bigbluebuttonbn_settings_lockonjoin($renderer); |
3440
|
|
|
bigbluebuttonbn_settings_lockonjoinconfigurable($renderer); |
3441
|
|
|
} |
3442
|
|
|
|
3443
|
|
|
/** |
3444
|
|
|
* Helper function renders general settings if the feature is enabled. |
3445
|
|
|
* |
3446
|
|
|
* @param object $renderer |
3447
|
|
|
* |
3448
|
|
|
* @return void |
3449
|
|
|
*/ |
3450
|
|
|
function bigbluebuttonbn_settings_disablecam(&$renderer) { |
3451
|
|
|
// Configuration for BigBlueButton. |
3452
|
|
|
if ((boolean) \mod_bigbluebuttonbn\settings\validator::section_disablecam_shown()) { |
3453
|
|
|
$renderer->render_group_element( |
3454
|
|
|
'disablecam_default', |
3455
|
|
|
$renderer->render_group_element_checkbox('disablecam_default', 0) |
3456
|
|
|
); |
3457
|
|
|
$renderer->render_group_element( |
3458
|
|
|
'disablecam_editable', |
3459
|
|
|
$renderer->render_group_element_checkbox('disablecam_editable', 1) |
3460
|
|
|
); |
3461
|
|
|
} |
3462
|
|
|
} |
3463
|
|
|
|
3464
|
|
|
/** |
3465
|
|
|
* Helper function renders general settings if the feature is enabled. |
3466
|
|
|
* |
3467
|
|
|
* @param object $renderer |
3468
|
|
|
* |
3469
|
|
|
* @return void |
3470
|
|
|
*/ |
3471
|
|
|
function bigbluebuttonbn_settings_disablemic(&$renderer) { |
3472
|
|
|
// Configuration for BigBlueButton. |
3473
|
|
|
if ((boolean) \mod_bigbluebuttonbn\settings\validator::section_disablemic_shown()) { |
3474
|
|
|
$renderer->render_group_element( |
3475
|
|
|
'disablemic_default', |
3476
|
|
|
$renderer->render_group_element_checkbox('disablemic_default', 0) |
3477
|
|
|
); |
3478
|
|
|
$renderer->render_group_element( |
3479
|
|
|
'disablecam_editable', |
3480
|
|
|
$renderer->render_group_element_checkbox('disablemic_editable', 1) |
3481
|
|
|
); |
3482
|
|
|
} |
3483
|
|
|
} |
3484
|
|
|
|
3485
|
|
|
/** |
3486
|
|
|
* Helper function renders general settings if the feature is enabled. |
3487
|
|
|
* |
3488
|
|
|
* @param object $renderer |
3489
|
|
|
* |
3490
|
|
|
* @return void |
3491
|
|
|
*/ |
3492
|
|
|
function bigbluebuttonbn_settings_disableprivatechat(&$renderer) { |
3493
|
|
|
// Configuration for BigBlueButton. |
3494
|
|
|
if ((boolean) \mod_bigbluebuttonbn\settings\validator::section_disableprivatechat_shown()) { |
3495
|
|
|
$renderer->render_group_element( |
3496
|
|
|
'disableprivatechat_default', |
3497
|
|
|
$renderer->render_group_element_checkbox('disableprivatechat_default', 0) |
3498
|
|
|
); |
3499
|
|
|
$renderer->render_group_element( |
3500
|
|
|
'disableprivatechat_editable', |
3501
|
|
|
$renderer->render_group_element_checkbox('disableprivatechat_editable', 1) |
3502
|
|
|
); |
3503
|
|
|
} |
3504
|
|
|
} |
3505
|
|
|
|
3506
|
|
|
/** |
3507
|
|
|
* Helper function renders general settings if the feature is enabled. |
3508
|
|
|
* |
3509
|
|
|
* @param object $renderer |
3510
|
|
|
* |
3511
|
|
|
* @return void |
3512
|
|
|
*/ |
3513
|
|
|
function bigbluebuttonbn_settings_disablepublicchat(&$renderer) { |
3514
|
|
|
// Configuration for BigBlueButton. |
3515
|
|
|
if ((boolean) \mod_bigbluebuttonbn\settings\validator::section_disablepublicchat_shown()) { |
3516
|
|
|
$renderer->render_group_element( |
3517
|
|
|
'disablepublicchat_default', |
3518
|
|
|
$renderer->render_group_element_checkbox('disablepublicchat_default', 0) |
3519
|
|
|
); |
3520
|
|
|
$renderer->render_group_element( |
3521
|
|
|
'disablepublicchat_editable', |
3522
|
|
|
$renderer->render_group_element_checkbox('disablepublicchat_editable', 1) |
3523
|
|
|
); |
3524
|
|
|
} |
3525
|
|
|
} |
3526
|
|
|
|
3527
|
|
|
/** |
3528
|
|
|
* Helper function renders general settings if the feature is enabled. |
3529
|
|
|
* |
3530
|
|
|
* @param object $renderer |
3531
|
|
|
* |
3532
|
|
|
* @return void |
3533
|
|
|
*/ |
3534
|
|
|
function bigbluebuttonbn_settings_disablenote(&$renderer) { |
3535
|
|
|
// Configuration for BigBlueButton. |
3536
|
|
|
if ((boolean) \mod_bigbluebuttonbn\settings\validator::section_disablenote_shown()) { |
3537
|
|
|
$renderer->render_group_element( |
3538
|
|
|
'disablenote_default', |
3539
|
|
|
$renderer->render_group_element_checkbox('disablenote_default', 0) |
3540
|
|
|
); |
3541
|
|
|
$renderer->render_group_element( |
3542
|
|
|
'disablenote_editable', |
3543
|
|
|
$renderer->render_group_element_checkbox('disablenote_editable', 1) |
3544
|
|
|
); |
3545
|
|
|
} |
3546
|
|
|
} |
3547
|
|
|
|
3548
|
|
|
/** |
3549
|
|
|
* Helper function renders general settings if the feature is enabled. |
3550
|
|
|
* |
3551
|
|
|
* @param object $renderer |
3552
|
|
|
* |
3553
|
|
|
* @return void |
3554
|
|
|
*/ |
3555
|
|
|
function bigbluebuttonbn_settings_hideuserlist(&$renderer) { |
3556
|
|
|
// Configuration for BigBlueButton. |
3557
|
|
|
if ((boolean) \mod_bigbluebuttonbn\settings\validator::section_hideuserlist_shown()) { |
3558
|
|
|
$renderer->render_group_element( |
3559
|
|
|
'hideuserlist_default', |
3560
|
|
|
$renderer->render_group_element_checkbox('hideuserlist_default', 0) |
3561
|
|
|
); |
3562
|
|
|
$renderer->render_group_element( |
3563
|
|
|
'hideuserlist_editable', |
3564
|
|
|
$renderer->render_group_element_checkbox('hideuserlist_editable', 1) |
3565
|
|
|
); |
3566
|
|
|
} |
3567
|
|
|
} |
3568
|
|
|
|
3569
|
|
|
/** |
3570
|
|
|
* Helper function renders general settings if the feature is enabled. |
3571
|
|
|
* |
3572
|
|
|
* @param object $renderer |
3573
|
|
|
* |
3574
|
|
|
* @return void |
3575
|
|
|
*/ |
3576
|
|
|
function bigbluebuttonbn_settings_lockedlayout(&$renderer) { |
3577
|
|
|
// Configuration for BigBlueButton. |
3578
|
|
|
if ((boolean) \mod_bigbluebuttonbn\settings\validator::section_lockedlayout_shown()) { |
3579
|
|
|
$renderer->render_group_element( |
3580
|
|
|
'lockedlayout_default', |
3581
|
|
|
$renderer->render_group_element_checkbox('lockedlayout_default', 0) |
3582
|
|
|
); |
3583
|
|
|
$renderer->render_group_element( |
3584
|
|
|
'lockedlayout_editable', |
3585
|
|
|
$renderer->render_group_element_checkbox('lockedlayout_editable', 1) |
3586
|
|
|
); |
3587
|
|
|
} |
3588
|
|
|
} |
3589
|
|
|
|
3590
|
|
|
/** |
3591
|
|
|
* Helper function renders general settings if the feature is enabled. |
3592
|
|
|
* |
3593
|
|
|
* @param object $renderer |
3594
|
|
|
* |
3595
|
|
|
* @return void |
3596
|
|
|
*/ |
3597
|
|
|
function bigbluebuttonbn_settings_lockonjoin(&$renderer) { |
3598
|
|
|
// Configuration for BigBlueButton. |
3599
|
|
|
if ((boolean) \mod_bigbluebuttonbn\settings\validator::section_lockonjoin_shown()) { |
3600
|
|
|
$renderer->render_group_element( |
3601
|
|
|
'lockonjoin_default', |
3602
|
|
|
$renderer->render_group_element_checkbox('lockonjoin_default', 0) |
3603
|
|
|
); |
3604
|
|
|
$renderer->render_group_element( |
3605
|
|
|
'lockonjoin_editable', |
3606
|
|
|
$renderer->render_group_element_checkbox('lockonjoin_editable', 1) |
3607
|
|
|
); |
3608
|
|
|
} |
3609
|
|
|
} |
3610
|
|
|
|
3611
|
|
|
/** |
3612
|
|
|
* Helper function renders general settings if the feature is enabled. |
3613
|
|
|
* |
3614
|
|
|
* @param object $renderer |
3615
|
|
|
* |
3616
|
|
|
* @return void |
3617
|
|
|
*/ |
3618
|
|
|
function bigbluebuttonbn_settings_lockonjoinconfigurable(&$renderer) { |
3619
|
|
|
// Configuration for BigBlueButton. |
3620
|
|
|
if ((boolean) \mod_bigbluebuttonbn\settings\validator::section_lockonjoinconfigurable_shown()) { |
3621
|
|
|
$renderer->render_group_element( |
3622
|
|
|
'lockonjoinconfigurable_default', |
3623
|
|
|
$renderer->render_group_element_checkbox('lockonjoinconfigurable_default', 0) |
3624
|
|
|
); |
3625
|
|
|
$renderer->render_group_element( |
3626
|
|
|
'lockonjoinconfigurable_editable', |
3627
|
|
|
$renderer->render_group_element_checkbox('lockonjoinconfigurable_editable', 1) |
3628
|
|
|
); |
3629
|
|
|
} |
3630
|
|
|
} |
3631
|
|
|
|
3632
|
|
|
/** |
3633
|
|
|
* Helper function renders default messages settings. |
3634
|
|
|
* |
3635
|
|
|
* @param object $renderer |
3636
|
|
|
* |
3637
|
|
|
* @return void |
3638
|
|
|
*/ |
3639
|
|
|
function bigbluebuttonbn_settings_default_messages(&$renderer) { |
3640
|
|
|
$renderer->render_group_header('default_messages'); |
3641
|
|
|
$renderer->render_group_element( |
3642
|
|
|
'welcome_default', |
3643
|
|
|
$renderer->render_group_element_textarea('welcome_default', '', PARAM_TEXT) |
3644
|
|
|
); |
3645
|
|
|
} |
3646
|
|
|
|
3647
|
|
|
/** |
3648
|
|
|
* Helper function renders extended settings if any of the features there is enabled. |
3649
|
|
|
* |
3650
|
|
|
* @param object $renderer |
3651
|
|
|
* |
3652
|
|
|
* @return void |
3653
|
|
|
*/ |
3654
|
|
|
function bigbluebuttonbn_settings_extended(&$renderer) { |
3655
|
|
|
// Configuration for extended capabilities. |
3656
|
|
|
if (!(boolean) \mod_bigbluebuttonbn\settings\validator::section_settings_extended_shown()) { |
3657
|
|
|
return; |
3658
|
|
|
} |
3659
|
|
|
$renderer->render_group_header('extended_capabilities'); |
3660
|
|
|
// UI for 'notify users when recording ready' feature. |
3661
|
|
|
$renderer->render_group_element( |
3662
|
|
|
'recordingready_enabled', |
3663
|
|
|
$renderer->render_group_element_checkbox('recordingready_enabled', 0) |
3664
|
|
|
); |
3665
|
|
|
// Configuration for extended BN capabilities should go here. |
3666
|
|
|
} |
3667
|
|
|
|
3668
|
|
|
/** |
3669
|
|
|
* Helper function renders experimental settings if any of the features there is enabled. |
3670
|
|
|
* |
3671
|
|
|
* @param object $renderer |
3672
|
|
|
* |
3673
|
|
|
* @return void |
3674
|
|
|
*/ |
3675
|
|
|
function bigbluebuttonbn_settings_experimental(&$renderer) { |
3676
|
|
|
// Configuration for experimental features should go here. |
3677
|
|
|
$renderer->render_group_header('experimental_features'); |
3678
|
|
|
// UI for 'register meeting events' feature. |
3679
|
|
|
$renderer->render_group_element( |
3680
|
|
|
'meetingevents_enabled', |
3681
|
|
|
$renderer->render_group_element_checkbox('meetingevents_enabled', 0) |
3682
|
|
|
); |
3683
|
|
|
} |
3684
|
|
|
|
3685
|
|
|
/** |
3686
|
|
|
* Helper function returns a sha1 encoded string that is unique and will be used as a seed for meetingid. |
3687
|
|
|
* |
3688
|
|
|
* @return string |
3689
|
|
|
*/ |
3690
|
|
|
function bigbluebuttonbn_unique_meetingid_seed() { |
3691
|
|
|
global $DB; |
3692
|
|
|
do { |
3693
|
|
|
$encodedseed = sha1(bigbluebuttonbn_random_password(12)); |
3694
|
|
|
$meetingid = (string) $DB->get_field('bigbluebuttonbn', 'meetingid', array('meetingid' => $encodedseed)); |
3695
|
|
|
} while ($meetingid == $encodedseed); |
3696
|
|
|
return $encodedseed; |
3697
|
|
|
} |
3698
|
|
|
|
3699
|
|
|
/** |
3700
|
|
|
* Helper function renders the link used for recording type in row for the data used by the recording table. |
3701
|
|
|
* |
3702
|
|
|
* @param array $recording |
3703
|
|
|
* @param array $bbbsession |
3704
|
|
|
* @param array $playback |
3705
|
|
|
* |
3706
|
|
|
* @return boolean |
3707
|
|
|
*/ |
3708
|
|
|
function bigbluebuttonbn_include_recording_data_row_type($recording, $bbbsession, $playback) { |
3709
|
|
|
// All types that are not restricted are included. |
3710
|
|
|
if (array_key_exists('restricted', $playback) && strtolower($playback['restricted']) == 'false') { |
3711
|
|
|
return true; |
3712
|
|
|
} |
3713
|
|
|
// All types that are not statistics are included. |
3714
|
|
|
if ($playback['type'] != 'statistics') { |
3715
|
|
|
return true; |
3716
|
|
|
} |
3717
|
|
|
// Exclude imported recordings. |
3718
|
|
|
if (isset($recording['imported'])) { |
3719
|
|
|
return false; |
3720
|
|
|
} |
3721
|
|
|
// Exclude non moderators. |
3722
|
|
|
if (!$bbbsession['administrator'] && !$bbbsession['moderator']) { |
3723
|
|
|
return false; |
3724
|
|
|
} |
3725
|
|
|
return true; |
3726
|
|
|
} |
3727
|
|
|
|
3728
|
|
|
/** |
3729
|
|
|
* Renders the general warning message. |
3730
|
|
|
* |
3731
|
|
|
* @param string $message |
3732
|
|
|
* @param string $type |
3733
|
|
|
* @param string $href |
3734
|
|
|
* @param string $text |
3735
|
|
|
* @param string $class |
3736
|
|
|
* |
3737
|
|
|
* @return string |
3738
|
|
|
*/ |
3739
|
|
|
function bigbluebuttonbn_render_warning($message, $type = 'info', $href = '', $text = '', $class = '') { |
3740
|
|
|
global $OUTPUT; |
3741
|
|
|
$output = "\n"; |
3742
|
|
|
// Evaluates if config_warning is enabled. |
3743
|
|
|
if (empty($message)) { |
3744
|
|
|
return $output; |
3745
|
|
|
} |
3746
|
|
|
$output .= $OUTPUT->box_start( |
3747
|
|
|
'box boxalignleft adminerror alert alert-' . $type . ' alert-block fade in', |
3748
|
|
|
'bigbluebuttonbn_view_general_warning' |
3749
|
|
|
) . "\n"; |
3750
|
|
|
$output .= ' ' . $message . "\n"; |
3751
|
|
|
$output .= ' <div class="singlebutton pull-right">' . "\n"; |
3752
|
|
|
if (!empty($href)) { |
3753
|
|
|
$output .= bigbluebuttonbn_render_warning_button($href, $text, $class); |
3754
|
|
|
} |
3755
|
|
|
$output .= ' </div>' . "\n"; |
3756
|
|
|
$output .= $OUTPUT->box_end() . "\n"; |
3757
|
|
|
return $output; |
3758
|
|
|
} |
3759
|
|
|
|
3760
|
|
|
/** |
3761
|
|
|
* Renders the general warning button. |
3762
|
|
|
* |
3763
|
|
|
* @param string $href |
3764
|
|
|
* @param string $text |
3765
|
|
|
* @param string $class |
3766
|
|
|
* @param string $title |
3767
|
|
|
* |
3768
|
|
|
* @return string |
3769
|
|
|
*/ |
3770
|
|
|
function bigbluebuttonbn_render_warning_button($href, $text = '', $class = '', $title = '') { |
3771
|
|
|
if ($text == '') { |
3772
|
|
|
$text = get_string('ok', 'moodle'); |
3773
|
|
|
} |
3774
|
|
|
if ($title == '') { |
3775
|
|
|
$title = $text; |
3776
|
|
|
} |
3777
|
|
|
if ($class == '') { |
3778
|
|
|
$class = 'btn btn-secondary'; |
3779
|
|
|
} |
3780
|
|
|
$output = ' <form method="post" action="' . $href . '" class="form-inline">' . "\n"; |
3781
|
|
|
$output .= ' <button type="submit" class="' . $class . '"' . "\n"; |
3782
|
|
|
$output .= ' title="' . $title . '"' . "\n"; |
3783
|
|
|
$output .= ' >' . $text . '</button>' . "\n"; |
3784
|
|
|
$output .= ' </form>' . "\n"; |
3785
|
|
|
return $output; |
3786
|
|
|
} |
3787
|
|
|
|
3788
|
|
|
/** |
3789
|
|
|
* Check if a BigBlueButtonBN is available to be used by the current user. |
3790
|
|
|
* |
3791
|
|
|
* @param stdClass $bigbluebuttonbn BigBlueButtonBN instance |
3792
|
|
|
* |
3793
|
|
|
* @return boolean status if room available and current user allowed to join |
3794
|
|
|
*/ |
3795
|
|
|
function bigbluebuttonbn_get_availability_status($bigbluebuttonbn) { |
3796
|
|
|
list($roomavailable) = bigbluebuttonbn_room_is_available($bigbluebuttonbn); |
3797
|
|
|
list($usercanjoin) = bigbluebuttonbn_user_can_join_meeting($bigbluebuttonbn); |
3798
|
|
|
return ($roomavailable && $usercanjoin); |
3799
|
|
|
} |
3800
|
|
|
|
3801
|
|
|
/** |
3802
|
|
|
* Helper for evaluating if scheduled activity is avaiable. |
3803
|
|
|
* |
3804
|
|
|
* @param stdClass $bigbluebuttonbn BigBlueButtonBN instance |
3805
|
|
|
* |
3806
|
|
|
* @return array status (room available or not and possible warnings) |
3807
|
|
|
*/ |
3808
|
|
|
function bigbluebuttonbn_room_is_available($bigbluebuttonbn) { |
3809
|
|
|
$open = true; |
3810
|
|
|
$closed = false; |
3811
|
|
|
$warnings = array(); |
3812
|
|
|
|
3813
|
|
|
$timenow = time(); |
3814
|
|
|
$timeopen = $bigbluebuttonbn->openingtime; |
3815
|
|
|
$timeclose = $bigbluebuttonbn->closingtime; |
3816
|
|
|
if (!empty($timeopen) && $timeopen > $timenow) { |
3817
|
|
|
$open = false; |
3818
|
|
|
} |
3819
|
|
|
if (!empty($timeclose) && $timenow > $timeclose) { |
3820
|
|
|
$closed = true; |
3821
|
|
|
} |
3822
|
|
|
|
3823
|
|
|
if (!$open || $closed) { |
3824
|
|
|
if (!$open) { |
3825
|
|
|
$warnings['notopenyet'] = userdate($timeopen); |
3826
|
|
|
} |
3827
|
|
|
if ($closed) { |
3828
|
|
|
$warnings['expired'] = userdate($timeclose); |
3829
|
|
|
} |
3830
|
|
|
return array(false, $warnings); |
3831
|
|
|
} |
3832
|
|
|
|
3833
|
|
|
return array(true, $warnings); |
3834
|
|
|
} |
3835
|
|
|
|
3836
|
|
|
/** |
3837
|
|
|
* Helper for evaluating if meeting can be joined. |
3838
|
|
|
* |
3839
|
|
|
* @param stdClass $bigbluebuttonbn BigBlueButtonBN instance |
3840
|
|
|
* @param string $mid |
3841
|
|
|
* @param integer $userid |
3842
|
|
|
* |
3843
|
|
|
* @return array status (user allowed to join or not and possible message) |
3844
|
|
|
*/ |
3845
|
|
|
function bigbluebuttonbn_user_can_join_meeting($bigbluebuttonbn, $mid = null, $userid = null) { |
3846
|
|
|
// By default, use a meetingid without groups. |
3847
|
|
|
if (empty($mid)) { |
3848
|
|
|
$mid = $bigbluebuttonbn->meetingid . '-' . $bigbluebuttonbn->course . '-' . $bigbluebuttonbn->id; |
3849
|
|
|
} |
3850
|
|
|
// When meeting is running, all authorized users can join right in. |
3851
|
|
|
if (bigbluebuttonbn_is_meeting_running($mid)) { |
3852
|
|
|
return array(true, get_string('view_message_conference_in_progress', 'bigbluebuttonbn')); |
3853
|
|
|
} |
3854
|
|
|
// When meeting is not running, see if the user can join. |
3855
|
|
|
$context = context_course::instance($bigbluebuttonbn->course); |
3856
|
|
|
$participantlist = bigbluebuttonbn_get_participant_list($bigbluebuttonbn, $context); |
3857
|
|
|
$isadmin = is_siteadmin($userid); |
3858
|
|
|
$ismoderator = bigbluebuttonbn_is_moderator($context, $participantlist, $userid); |
3859
|
|
|
// If user is administrator, moderator or if is viewer and no waiting is required, join allowed. |
3860
|
|
|
if ($isadmin || $ismoderator || !$bigbluebuttonbn->wait) { |
3861
|
|
|
return array(true, get_string('view_message_conference_room_ready', 'bigbluebuttonbn')); |
3862
|
|
|
} |
3863
|
|
|
// Otherwise, no join allowed. |
3864
|
|
|
return array(false, get_string('view_message_conference_wait_for_moderator', 'bigbluebuttonbn')); |
3865
|
|
|
} |
3866
|
|
|
|
3867
|
|
|
/** |
3868
|
|
|
* Helper for getting a value from a bigbluebuttonbn cache. |
3869
|
|
|
* |
3870
|
|
|
* @param string $name BigBlueButtonBN cache |
3871
|
|
|
* @param string $key Key to be retrieved |
3872
|
|
|
* @param integer $default Default value in case key is not found or it is empty |
3873
|
|
|
* |
3874
|
|
|
* @return variable key value |
3875
|
|
|
*/ |
3876
|
|
|
function bigbluebuttonbn_cache_get($name, $key, $default = null) { |
3877
|
|
|
$cache = cache::make_from_params(cache_store::MODE_APPLICATION, 'mod_bigbluebuttonbn', $name); |
3878
|
|
|
$result = $cache->get($key); |
3879
|
|
|
if (!empty($result)) { |
3880
|
|
|
return $result; |
3881
|
|
|
} |
3882
|
|
|
return $default; |
3883
|
|
|
} |
3884
|
|
|
|
3885
|
|
|
/** |
3886
|
|
|
* Helper for setting a value in a bigbluebuttonbn cache. |
3887
|
|
|
* |
3888
|
|
|
* @param string $name BigBlueButtonBN cache |
3889
|
|
|
* @param string $key Key to be created/updated |
3890
|
|
|
* @param variable $value Default value to be set |
3891
|
|
|
*/ |
3892
|
|
|
function bigbluebuttonbn_cache_set($name, $key, $value) { |
3893
|
|
|
$cache = cache::make_from_params(cache_store::MODE_APPLICATION, 'mod_bigbluebuttonbn', $name); |
3894
|
|
|
$cache->set($key, $value); |
3895
|
|
|
} |
3896
|
|
|
|
3897
|
|
|
/** |
3898
|
|
|
* Helper for getting the owner userid of a bigbluebuttonbn instance. |
3899
|
|
|
* |
3900
|
|
|
* @param stdClass $bigbluebuttonbn BigBlueButtonBN instance |
3901
|
|
|
* |
3902
|
|
|
* @return integer ownerid (a valid user id or null if not registered/found) |
3903
|
|
|
*/ |
3904
|
|
|
function bigbluebuttonbn_instance_ownerid($bigbluebuttonbn) { |
3905
|
|
|
global $DB; |
3906
|
|
|
$filters = array('bigbluebuttonbnid' => $bigbluebuttonbn->id, 'log' => 'Add'); |
3907
|
|
|
$ownerid = (integer) $DB->get_field('bigbluebuttonbn_logs', 'userid', $filters); |
3908
|
|
|
return $ownerid; |
3909
|
|
|
} |
3910
|
|
|
|
3911
|
|
|
/** |
3912
|
|
|
* Helper evaluates if the bigbluebutton server used belongs to blindsidenetworks domain. |
3913
|
|
|
* |
3914
|
|
|
* @return boolean |
3915
|
|
|
*/ |
3916
|
|
|
function bigbluebuttonbn_has_html5_client() { |
3917
|
|
|
$checkurl = \mod_bigbluebuttonbn\locallib\bigbluebutton::root() . "html5client/check"; |
3918
|
|
|
$curlinfo = bigbluebuttonbn_wrap_xml_load_file_curl_request($checkurl, 'HEAD'); |
3919
|
|
|
return (isset($curlinfo['http_code']) && $curlinfo['http_code'] == 200); |
3920
|
|
|
} |
3921
|
|
|
|
3922
|
|
|
/** |
3923
|
|
|
* Return the status of an activity [open|not_started|ended]. |
3924
|
|
|
* |
3925
|
|
|
* @param array $bbbsession |
3926
|
|
|
* @return string |
3927
|
|
|
*/ |
3928
|
|
View Code Duplication |
function bigbluebuttonbn_view_get_activity_status(&$bbbsession) { |
|
|
|
|
3929
|
|
|
$now = time(); |
3930
|
|
|
if (!empty($bbbsession['bigbluebuttonbn']->openingtime) && $now < $bbbsession['bigbluebuttonbn']->openingtime) { |
3931
|
|
|
// The activity has not been opened. |
3932
|
|
|
return 'not_started'; |
3933
|
|
|
} |
3934
|
|
|
if (!empty($bbbsession['bigbluebuttonbn']->closingtime) && $now > $bbbsession['bigbluebuttonbn']->closingtime) { |
3935
|
|
|
// The activity has been closed. |
3936
|
|
|
return 'ended'; |
3937
|
|
|
} |
3938
|
|
|
// The activity is open. |
3939
|
|
|
return 'open'; |
3940
|
|
|
} |
3941
|
|
|
|
3942
|
|
|
/** |
3943
|
|
|
* Set session URLs. |
3944
|
|
|
* |
3945
|
|
|
* @param array $bbbsession |
3946
|
|
|
* @param int $id |
3947
|
|
|
* @return string |
3948
|
|
|
*/ |
3949
|
|
|
function bigbluebuttonbn_view_session_config(&$bbbsession, $id) { |
3950
|
|
|
// Operation URLs. |
3951
|
|
|
$bbbsession['bigbluebuttonbnURL'] = plugin::necurl( |
3952
|
|
|
'/mod/bigbluebuttonbn/view.php', |
3953
|
|
|
['id' => $bbbsession['cm']->id] |
3954
|
|
|
); |
3955
|
|
|
$bbbsession['logoutURL'] = plugin::necurl( |
3956
|
|
|
'/mod/bigbluebuttonbn/bbb_view.php', |
3957
|
|
|
['action' => 'logout', 'id' => $id, 'bn' => $bbbsession['bigbluebuttonbn']->id] |
3958
|
|
|
); |
3959
|
|
|
$bbbsession['recordingReadyURL'] = plugin::necurl( |
3960
|
|
|
'/mod/bigbluebuttonbn/bbb_broker.php', |
3961
|
|
|
['action' => 'recording_ready', 'bigbluebuttonbn' => $bbbsession['bigbluebuttonbn']->id] |
3962
|
|
|
); |
3963
|
|
|
$bbbsession['meetingEventsURL'] = plugin::necurl( |
3964
|
|
|
'/mod/bigbluebuttonbn/bbb_broker.php', |
3965
|
|
|
['action' => 'meeting_events', 'bigbluebuttonbn' => $bbbsession['bigbluebuttonbn']->id] |
3966
|
|
|
); |
3967
|
|
|
$bbbsession['joinURL'] = plugin::necurl( |
3968
|
|
|
'/mod/bigbluebuttonbn/bbb_view.php', |
3969
|
|
|
['action' => 'join', 'id' => $id, 'bn' => $bbbsession['bigbluebuttonbn']->id] |
3970
|
|
|
); |
3971
|
|
|
|
3972
|
|
|
// Check status and set extra values. |
3973
|
|
|
$activitystatus = bigbluebuttonbn_view_get_activity_status($bbbsession); // In locallib. |
3974
|
|
View Code Duplication |
if ($activitystatus == 'ended') { |
|
|
|
|
3975
|
|
|
$bbbsession['presentation'] = bigbluebuttonbn_get_presentation_array( |
3976
|
|
|
$bbbsession['context'], |
3977
|
|
|
$bbbsession['bigbluebuttonbn']->presentation |
3978
|
|
|
); |
3979
|
|
|
} else if ($activitystatus == 'open') { |
3980
|
|
|
$bbbsession['presentation'] = bigbluebuttonbn_get_presentation_array( |
3981
|
|
|
$bbbsession['context'], |
3982
|
|
|
$bbbsession['bigbluebuttonbn']->presentation, |
3983
|
|
|
$bbbsession['bigbluebuttonbn']->id |
3984
|
|
|
); |
3985
|
|
|
} |
3986
|
|
|
|
3987
|
|
|
return $activitystatus; |
3988
|
|
|
} |
3989
|
|
|
|
3990
|
|
|
/** |
3991
|
|
|
* Helper for preparing metadata used while creating the meeting. |
3992
|
|
|
* |
3993
|
|
|
* @param array $bbbsession |
3994
|
|
|
* @return array |
3995
|
|
|
*/ |
3996
|
|
|
function bigbluebuttonbn_create_meeting_metadata(&$bbbsession) { |
3997
|
|
|
global $USER; |
3998
|
|
|
// Create standard metadata. |
3999
|
|
|
$metadata = [ |
4000
|
|
|
'bbb-origin' => $bbbsession['origin'], |
4001
|
|
|
'bbb-origin-version' => $bbbsession['originVersion'], |
4002
|
|
|
'bbb-origin-server-name' => $bbbsession['originServerName'], |
4003
|
|
|
'bbb-origin-server-common-name' => $bbbsession['originServerCommonName'], |
4004
|
|
|
'bbb-origin-tag' => $bbbsession['originTag'], |
4005
|
|
|
'bbb-context' => $bbbsession['course']->fullname, |
4006
|
|
|
'bbb-context-id' => $bbbsession['course']->id, |
4007
|
|
|
'bbb-context-name' => trim(html_to_text($bbbsession['course']->fullname, 0)), |
4008
|
|
|
'bbb-context-label' => trim(html_to_text($bbbsession['course']->shortname, 0)), |
4009
|
|
|
'bbb-recording-name' => bigbluebuttonbn_html2text($bbbsession['meetingname'], 64), |
4010
|
|
|
'bbb-recording-description' => bigbluebuttonbn_html2text($bbbsession['meetingdescription'], 64), |
4011
|
|
|
'bbb-recording-tags' => bigbluebuttonbn_get_tags($bbbsession['cm']->id), // Same as $id. |
4012
|
|
|
]; |
4013
|
|
|
// Special metadata for recording processing. |
4014
|
|
|
if ((boolean) \mod_bigbluebuttonbn\locallib\config::get('recordingstatus_enabled')) { |
4015
|
|
|
$metadata["bn-recording-status"] = json_encode( |
4016
|
|
|
array( |
4017
|
|
|
'email' => array('"' . fullname($USER) . '" <' . $USER->email . '>'), |
4018
|
|
|
'context' => $bbbsession['bigbluebuttonbnURL'], |
4019
|
|
|
) |
4020
|
|
|
); |
4021
|
|
|
} |
4022
|
|
|
if ((boolean) \mod_bigbluebuttonbn\locallib\config::get('recordingready_enabled')) { |
4023
|
|
|
$metadata['bn-recording-ready-url'] = $bbbsession['recordingReadyURL']; |
4024
|
|
|
} |
4025
|
|
|
if ((boolean) \mod_bigbluebuttonbn\locallib\config::get('meetingevents_enabled')) { |
4026
|
|
|
$metadata['analytics-callback-url'] = $bbbsession['meetingEventsURL']; |
4027
|
|
|
} |
4028
|
|
|
// Special metadata for Opencast recordings (passing opencast seriesid of the course as opencast-dc-isPartOf as metadata). |
4029
|
|
|
if ((boolean) \mod_bigbluebuttonbn\locallib\config::get('oc_recording')) { |
4030
|
|
|
$ocseriesid = bigbluebuttonbn_check_opencast($bbbsession['course']->id); |
4031
|
|
|
if ($ocseriesid != false) { |
4032
|
|
|
$metadata['opencast-dc-isPartOf'] = $ocseriesid; |
4033
|
|
|
$metadata['opencast-dc-subject'] = $bbbsession['meetingid']; |
4034
|
|
|
} |
4035
|
|
|
} |
4036
|
|
|
return $metadata; |
4037
|
|
|
} |
4038
|
|
|
|
4039
|
|
|
/** |
4040
|
|
|
* Helper function which checks if the Opencast plugin (block_opencast) is installed. The function is called from several places throughout mod_bigbluebuttonbn where Opencast functionality can enhance the BBB meeting recording functionality as soon as the Opencast plugin is present. |
4041
|
|
|
* If called with a course ID as parameter, the function will not only check if the Opencast plugin is installed. It will also ensure that an Opencast series exists for the given course and will return the Opencast series ID instead of a boolean. In this case, the block does not necessarily be placed in the course. |
4042
|
|
|
* |
4043
|
|
|
* @param string $courseid |
4044
|
|
|
* @return boolean|string |
4045
|
|
|
*/ |
4046
|
|
|
function bigbluebuttonbn_check_opencast($courseid = null) { |
4047
|
|
|
$blockplugins = core_plugin_manager::instance()->get_plugins_of_type('block'); |
4048
|
|
|
// If block_opencast is installed. |
4049
|
|
|
if (in_array('opencast', array_keys($blockplugins))) { |
4050
|
|
|
// Getting an instance of the block_opencast API bridge. |
4051
|
|
|
$opencast = \block_opencast\local\apibridge::get_instance(); |
4052
|
|
|
// If opencast is not configured! |
4053
|
|
|
if (!$opencast) { |
4054
|
|
|
return false; |
4055
|
|
|
} |
4056
|
|
|
// If the courseid is required (check if the course has the opencsat series). |
4057
|
|
|
if ($courseid) { |
|
|
|
|
4058
|
|
|
// Trying to get course seriesid, create if is not set before! |
4059
|
|
|
try { |
4060
|
|
|
$series = $opencast->ensure_course_series_exists($courseid); |
4061
|
|
|
if (is_object($series) && $series->identifier) { |
4062
|
|
|
$seriesid = $series->identifier; |
4063
|
|
|
} else { |
4064
|
|
|
$seriesid = $series; |
4065
|
|
|
} |
4066
|
|
|
return $seriesid; |
4067
|
|
|
} catch (Exception $e) { |
4068
|
|
|
return false; |
4069
|
|
|
} |
4070
|
|
|
} |
4071
|
|
|
return true; |
4072
|
|
|
} |
4073
|
|
|
// If block_opencast is not installed |
4074
|
|
|
return false; |
4075
|
|
|
} |
4076
|
|
|
|
4077
|
|
|
/** |
4078
|
|
|
* Helper function renders Opencast integration settings if block_opencast is installed. |
4079
|
|
|
* |
4080
|
|
|
* @param object $renderer |
4081
|
|
|
* |
4082
|
|
|
* @return void |
4083
|
|
|
*/ |
4084
|
|
|
function bigbluebuttonbn_settings_opencastintegration(&$renderer) { |
4085
|
|
|
// Configuration for 'Opencast integration' feature when Opencast plugins are installed. |
4086
|
|
|
if ((boolean) bigbluebuttonbn_check_opencast()) { |
4087
|
|
|
$renderer->render_group_header('opencast'); |
4088
|
|
|
$renderer->render_group_element( |
4089
|
|
|
'oc_recording', |
4090
|
|
|
$renderer->render_group_element_checkbox('oc_recording', 0) |
4091
|
|
|
); |
4092
|
|
|
$renderer->render_group_element( |
4093
|
|
|
'oc_show_recording', |
4094
|
|
|
$renderer->render_group_element_checkbox('oc_show_recording', 0) |
4095
|
|
|
); |
4096
|
|
|
} |
4097
|
|
|
|
4098
|
|
|
} |
4099
|
|
|
|
If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:
If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.