Issues (112)

Security Analysis    not enabled

This project does not seem to handle request data directly as such no vulnerable execution paths were found.

  Cross-Site Scripting
Cross-Site Scripting enables an attacker to inject code into the response of a web-request that is viewed by other users. It can for example be used to bypass access controls, or even to take over other users' accounts.
  File Exposure
File Exposure allows an attacker to gain access to local files that he should not be able to access. These files can for example include database credentials, or other configuration files.
  File Manipulation
File Manipulation enables an attacker to write custom data to files. This potentially leads to injection of arbitrary code on the server.
  Object Injection
Object Injection enables an attacker to inject an object into PHP code, and can lead to arbitrary code execution, file exposure, or file manipulation attacks.
  Code Injection
Code Injection enables an attacker to execute arbitrary code on the server.
  Response Splitting
Response Splitting can be used to send arbitrary responses.
  File Inclusion
File Inclusion enables an attacker to inject custom files into PHP's file loading mechanism, either explicitly passed to include, or for example via PHP's auto-loading mechanism.
  Command Injection
Command Injection enables an attacker to inject a shell command that is execute with the privileges of the web-server. This can be used to expose sensitive data, or gain access of your server.
  SQL Injection
SQL Injection enables an attacker to execute arbitrary SQL code on your database server gaining access to user data, or manipulating user data.
  XPath Injection
XPath Injection enables an attacker to modify the parts of XML document that are read. If that XML document is for example used for authentication, this can lead to further vulnerabilities similar to SQL Injection.
  LDAP Injection
LDAP Injection enables an attacker to inject LDAP statements potentially granting permission to run unauthorized queries, or modify content inside the LDAP tree.
  Header Injection
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  XML Injection
XML Injection enables an attacker to read files on your local filesystem including configuration files, or can be abused to freeze your web-server process.
  Variable Injection
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
Unfortunately, the security analysis is currently not available for your project. If you are a non-commercial open-source project, please contact support to gain access.

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

Code
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
 * Library calls for Moodle and BigBlueButton.
19
 *
20
 * @package   mod_bigbluebuttonbn
21
 * @copyright 2010 onwards, Blindside Networks Inc
22
 * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
23
 * @author    Jesus Federico  (jesus [at] blindsidenetworks [dt] com)
24
 * @author    Fred Dixon  (ffdixon [at] blindsidenetworks [dt] com)
25
 */
26
27
defined('MOODLE_INTERNAL') || die;
28
29
global $CFG;
30
31
// JWT is included in Moodle 3.7 core, but a local package is still needed for backward compatibility.
32
if (!class_exists('\Firebase\JWT\JWT')) {
33
    if (file_exists($CFG->libdir.'/php-jwt/src/JWT.php')) {
34
        require_once($CFG->libdir.'/php-jwt/src/JWT.php');
35
    } else {
36
        require_once($CFG->dirroot.'/mod/bigbluebuttonbn/vendor/firebase/php-jwt/src/JWT.php');
37
    }
38
}
39
40
// Do not declare new $CFG variables if unit tests are running
41
// as it can cause "unexpected new $CFG->xxx value" warnings.
42
if (!defined('PHPUNIT_TEST') || !PHPUNIT_TEST) {
43
    if (!isset($CFG->bigbluebuttonbn)) {
44
        $CFG->bigbluebuttonbn = array();
45
    }
46
47
    if (file_exists(dirname(__FILE__).'/config.php')) {
48
        require_once(dirname(__FILE__).'/config.php');
49
    }
50
51
    /*
52
     * DURATIONCOMPENSATION: Feature removed by configuration
53
     */
54
    $CFG->bigbluebuttonbn['scheduled_duration_enabled'] = 0;
55
    /*
56
     * Remove this block when restored
57
     */
58
}
59
60
/** @var BIGBLUEBUTTONBN_DEFAULT_SERVER_URL string of default bigbluebutton server url */
61
const BIGBLUEBUTTONBN_DEFAULT_SERVER_URL = 'http://test-install.blindsidenetworks.com/bigbluebutton/';
62
/** @var BIGBLUEBUTTONBN_DEFAULT_SHARED_SECRET string of default bigbluebutton server shared secret */
63
const BIGBLUEBUTTONBN_DEFAULT_SHARED_SECRET = '8cd8ef52e8e101574e400365b55e11a6';
64
/** @var BIGBLUEBUTTONBN_LOG_EVENT_ADD string defines the bigbluebuttonbn Add event */
65
const BIGBLUEBUTTONBN_LOG_EVENT_ADD = 'Add';
66
/** @var BIGBLUEBUTTONBN_LOG_EVENT_EDIT string defines the bigbluebuttonbn Edit event */
67
const BIGBLUEBUTTONBN_LOG_EVENT_EDIT = 'Edit';
68
/** @var BIGBLUEBUTTONBN_LOG_EVENT_CREATE string defines the bigbluebuttonbn Create event */
69
const BIGBLUEBUTTONBN_LOG_EVENT_CREATE = 'Create';
70
/** @var BIGBLUEBUTTONBN_LOG_EVENT_JOIN string defines the bigbluebuttonbn Join event */
71
const BIGBLUEBUTTONBN_LOG_EVENT_JOIN = 'Join';
72
/** @var BIGBLUEBUTTONBN_LOG_EVENT_PLAYED string defines the bigbluebuttonbn Playback event */
73
const BIGBLUEBUTTONBN_LOG_EVENT_PLAYED = 'Played';
74
/** @var BIGBLUEBUTTONBN_LOG_EVENT_LOGOUT string defines the bigbluebuttonbn Logout event */
75
const BIGBLUEBUTTONBN_LOG_EVENT_LOGOUT = 'Logout';
76
/** @var BIGBLUEBUTTONBN_LOG_EVENT_IMPORT string defines the bigbluebuttonbn Import event */
77
const BIGBLUEBUTTONBN_LOG_EVENT_IMPORT = 'Import';
78
/** @var BIGBLUEBUTTONBN_LOG_EVENT_DELETE string defines the bigbluebuttonbn Delete event */
79
const BIGBLUEBUTTONBN_LOG_EVENT_DELETE = 'Delete';
80
/** @var BIGBLUEBUTTON_LOG_EVENT_CALLBACK string defines the bigbluebuttonbn Callback event */
81
const BIGBLUEBUTTON_LOG_EVENT_CALLBACK = 'Callback';
82
/** @var BIGBLUEBUTTON_LOG_EVENT_SUMMARY string defines the bigbluebuttonbn Summary event */
83
const BIGBLUEBUTTON_LOG_EVENT_SUMMARY = 'Summary';
84
/**
85
 * Indicates API features that the bigbluebuttonbn supports.
86
 *
87
 * @uses FEATURE_IDNUMBER
88
 * @uses FEATURE_GROUPS
89
 * @uses FEATURE_GROUPINGS
90
 * @uses FEATURE_GROUPMEMBERSONLY
91
 * @uses FEATURE_MOD_INTRO
92
 * @uses FEATURE_BACKUP_MOODLE2
93
 * @uses FEATURE_COMPLETION_TRACKS_VIEWS
94
 * @uses FEATURE_COMPLETION_HAS_RULES
95
 * @uses FEATURE_GRADE_HAS_GRADE
96
 * @uses FEATURE_GRADE_OUTCOMES
97
 * @uses FEATURE_SHOW_DESCRIPTION
98
 * @param string $feature
99
 * @return mixed True if yes (some features may use other values)
100
 */
101
function bigbluebuttonbn_supports($feature) {
102
    if (!$feature) {
103
        return null;
104
    }
105
    $features = array(
106
        (string) FEATURE_IDNUMBER => true,
107
        (string) FEATURE_GROUPS => true,
108
        (string) FEATURE_GROUPINGS => true,
109
        (string) FEATURE_GROUPMEMBERSONLY => true,
110
        (string) FEATURE_MOD_INTRO => true,
111
        (string) FEATURE_BACKUP_MOODLE2 => true,
112
        (string) FEATURE_COMPLETION_TRACKS_VIEWS => true,
113
        (string) FEATURE_COMPLETION_HAS_RULES => true,
114
        (string) FEATURE_GRADE_HAS_GRADE => false,
115
        (string) FEATURE_GRADE_OUTCOMES => false,
116
        (string) FEATURE_SHOW_DESCRIPTION => true,
117
    );
118
    if (isset($features[(string) $feature])) {
119
        return $features[$feature];
120
    }
121
    return null;
122
}
123
124
/**
125
 * Obtains the automatic completion state for this bigbluebuttonbn based on any conditions
126
 * in bigbluebuttonbn settings.
127
 *
128
 * @param object $course Course
129
 * @param object $cm Course-module
130
 * @param int $userid User ID
131
 * @param bool $type Type of comparison (or/and; can be used as return value if no conditions)
132
 *
133
 * @return bool True if completed, false if not. (If no conditions, then return
134
 *   value depends on comparison type)
135
 */
136
function bigbluebuttonbn_get_completion_state($course, $cm, $userid, $type) {
0 ignored issues
show
The parameter $course is not used and could be removed.

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

Loading history...
137
    global $DB;
138
139
    // Get bigbluebuttonbn details.
140
    $bigbluebuttonbn = $DB->get_record('bigbluebuttonbn', array('id' => $cm->instance), '*',
141
            MUST_EXIST);
142
    if (!$bigbluebuttonbn) {
143
        throw new Exception("Can't find bigbluebuttonbn {$cm->instance}");
144
    }
145
146
    // Default return value.
147
    $result = $type;
148
149
    $sql  = "SELECT * FROM {bigbluebuttonbn_logs} ";
150
    $sql .= "WHERE bigbluebuttonbnid = ? AND userid = ? AND log = ?";
151
    $logs = $DB->get_records_sql($sql, array($bigbluebuttonbn->id, $userid, BIGBLUEBUTTON_LOG_EVENT_SUMMARY));
152
153
    if ($bigbluebuttonbn->completionattendance) {
154
        if (!$logs) {
155
            // As completion by attendance was required, the activity hasn't been completed.
156
            return false;
157
        }
158
        $attendancecount = 0;
159
        foreach ($logs as $log) {
160
            $summary = json_decode($log->meta);
161
            $attendancecount += $summary->data->duration;
162
        }
163
        $attendancecount /= 60;
164
        $value = $bigbluebuttonbn->completionattendance <= $attendancecount;
165
        if ($type == COMPLETION_AND) {
166
            $result = $result && $value;
167
        } else {
168
            $result = $result || $value;
169
        }
170
    }
171
172 View Code Duplication
    if ($bigbluebuttonbn->completionengagementchats) {
0 ignored issues
show
This code seems to be duplicated across your project.

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

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

Loading history...
173
        if (!$logs) {
174
            // As completion by engagement with chat was required, the activity hasn't been completed.
175
            return false;
176
        }
177
        $engagementchatscount = 0;
178
        foreach ($logs as $log) {
179
            $summary = json_decode($log->meta);
180
            $engagementchatscount += $summary->data->engagement->chats;
181
        }
182
        $value = $bigbluebuttonbn->completionengagementchats <= $engagementchatscount;
183
        if ($type == COMPLETION_AND) {
184
            $result = $result && $value;
185
        } else {
186
            $result = $result || $value;
187
        }
188
    }
189
190 View Code Duplication
    if ($bigbluebuttonbn->completionengagementtalks) {
0 ignored issues
show
This code seems to be duplicated across your project.

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

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

Loading history...
191
        if (!$logs) {
192
            // As completion by engagement with talk was required, the activity hasn't been completed.
193
            return false;
194
        }
195
        $engagementtalkscount = 0;
196
        foreach ($logs as $log) {
197
            $summary = json_decode($log->meta);
198
            $engagementtalkscount += $summary->data->engagement->talks;
199
        }
200
        $value = $bigbluebuttonbn->completionengagementtalks <= $engagementtalkscount;
201
        if ($type == COMPLETION_AND) {
202
            $result = $result && $value;
203
        } else {
204
            $result = $result || $value;
205
        }
206
    }
207
208
    return $result;
209
}
210
211
/**
212
 * Given an object containing all the necessary data,
213
 * (defined by the form in mod_form.php) this function
214
 * will create a new instance and return the id number
215
 * of the new instance.
216
 *
217
 * @param object $bigbluebuttonbn  An object from the form in mod_form.php
218
 * @return int The id of the newly inserted bigbluebuttonbn record
219
 */
220 View Code Duplication
function bigbluebuttonbn_add_instance($bigbluebuttonbn) {
0 ignored issues
show
This function seems to be duplicated in your project.

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

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

Loading history...
221
    global $DB;
222
    // Excecute preprocess.
223
    bigbluebuttonbn_process_pre_save($bigbluebuttonbn);
224
    // Pre-set initial values.
225
    $bigbluebuttonbn->presentation = bigbluebuttonbn_get_media_file($bigbluebuttonbn);
226
    // Insert a record.
227
    $bigbluebuttonbn->id = $DB->insert_record('bigbluebuttonbn', $bigbluebuttonbn);
228
    // Encode meetingid.
229
    $bigbluebuttonbn->meetingid = bigbluebuttonbn_unique_meetingid_seed();
230
    // Set the meetingid column in the bigbluebuttonbn table.
231
    $DB->set_field('bigbluebuttonbn', 'meetingid', $bigbluebuttonbn->meetingid, array('id' => $bigbluebuttonbn->id));
232
    // Log insert action.
233
    bigbluebuttonbn_log($bigbluebuttonbn, BIGBLUEBUTTONBN_LOG_EVENT_ADD);
234
    // Complete the process.
235
    bigbluebuttonbn_process_post_save($bigbluebuttonbn);
236
    return $bigbluebuttonbn->id;
237
}
238
239
/**
240
 * Given an object containing all the necessary data,
241
 * (defined by the form in mod_form.php) this function
242
 * will update an existing instance with new data.
243
 *
244
 * @param object $bigbluebuttonbn  An object from the form in mod_form.php
245
 * @return bool Success/Fail
246
 */
247 View Code Duplication
function bigbluebuttonbn_update_instance($bigbluebuttonbn) {
0 ignored issues
show
This function seems to be duplicated in your project.

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

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

Loading history...
248
    global $DB;
249
    // Excecute preprocess.
250
    bigbluebuttonbn_process_pre_save($bigbluebuttonbn);
251
    // Pre-set initial values.
252
    $bigbluebuttonbn->id = $bigbluebuttonbn->instance;
253
    $bigbluebuttonbn->presentation = bigbluebuttonbn_get_media_file($bigbluebuttonbn);
254
    // Update a record.
255
    $DB->update_record('bigbluebuttonbn', $bigbluebuttonbn);
256
    // Get the meetingid column in the bigbluebuttonbn table.
257
    $bigbluebuttonbn->meetingid = (string)$DB->get_field('bigbluebuttonbn', 'meetingid', array('id' => $bigbluebuttonbn->id));
258
    // Log update action.
259
    bigbluebuttonbn_log($bigbluebuttonbn, BIGBLUEBUTTONBN_LOG_EVENT_EDIT);
260
    // Complete the process.
261
    bigbluebuttonbn_process_post_save($bigbluebuttonbn);
262
    return true;
263
}
264
265
/**
266
 * Given an ID of an instance of this module,
267
 * this function will permanently delete the instance
268
 * and any data that depends on it.
269
 *
270
 * @param int $id Id of the module instance
271
 *
272
 * @return bool Success/Failure
273
 */
274
function bigbluebuttonbn_delete_instance($id) {
275
    global $DB;
276
277
    if (!$bigbluebuttonbn = $DB->get_record('bigbluebuttonbn', array('id' => $id))) {
278
        return false;
279
    }
280
281
    // TODO: End the meeting if it is running.
282
283
    $result = true;
284
285
    // Delete any dependent records here.
286
    if (!$DB->delete_records('bigbluebuttonbn', array('id' => $bigbluebuttonbn->id))) {
287
        $result = false;
288
    }
289
290
    if (!$DB->delete_records('event', array('modulename' => 'bigbluebuttonbn', 'instance' => $bigbluebuttonbn->id))) {
291
        $result = false;
292
    }
293
294
    // Log action performed.
295
    bigbluebuttonbn_delete_instance_log($bigbluebuttonbn);
296
297
    return $result;
298
}
299
300
/**
301
 * Given an ID of an instance of this module,
302
 * this function will permanently delete the data that depends on it.
303
 *
304
 * @param object $bigbluebuttonbn Id of the module instance
305
 *
306
 * @return bool Success/Failure
307
 */
308
function bigbluebuttonbn_delete_instance_log($bigbluebuttonbn) {
309
    global $DB;
310
    $sql  = "SELECT * FROM {bigbluebuttonbn_logs} ";
311
    $sql .= "WHERE bigbluebuttonbnid = ? AND log = ? AND ". $DB->sql_compare_text('meta') . " = ?";
312
    $logs = $DB->get_records_sql($sql, array($bigbluebuttonbn->id, BIGBLUEBUTTONBN_LOG_EVENT_CREATE, "{\"record\":true}"));
313
    $meta = "{\"has_recordings\":" . empty($logs) ? "true" : "false" . "}";
314
    bigbluebuttonbn_log($bigbluebuttonbn, BIGBLUEBUTTONBN_LOG_EVENT_DELETE, [], $meta);
315
}
316
317
/**
318
 * Return a small object with summary information about what a
319
 * user has done with a given particular instance of this module
320
 * Used for user activity reports.
321
 *
322
 * @param object $course
323
 * @param object $user
324
 * @param object $mod
325
 * @param object $bigbluebuttonbn
326
 *
327
 * @return bool
328
 */
329
function bigbluebuttonbn_user_outline($course, $user, $mod, $bigbluebuttonbn) {
0 ignored issues
show
The parameter $mod is not used and could be removed.

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

Loading history...
330
    if ($completed = bigbluebuttonbn_user_complete($course, $user, $bigbluebuttonbn)) {
331
        return fullname($user) . ' ' . get_string('view_message_has_joined', 'bigbluebuttonbn') . ' ' .
332
            get_string('view_message_session_for', 'bigbluebuttonbn') . ' ' . (string) $completed . ' ' .
333
            get_string('view_message_times', 'bigbluebuttonbn');
334
    }
335
    return '';
336
}
337
338
/**
339
 * Print a detailed representation of what a user has done with
340
 * a given particular instance of this module, for user activity reports.
341
 *
342
 * @param object|int $courseorid
343
 * @param object|int $userorid
344
 * @param object $bigbluebuttonbn
345
 *
346
 * @return bool
347
 */
348
function bigbluebuttonbn_user_complete($courseorid, $userorid, $bigbluebuttonbn) {
349
    global $DB;
350
    if (is_object($courseorid)) {
351
        $course = $courseorid;
352
    } else {
353
        $course = (object)array('id' => $courseorid);
354
    }
355
    if (is_object($userorid)) {
356
        $user = $userorid;
357
    } else {
358
        $user = (object)array('id' => $userorid);
359
    }
360
    $sql = "SELECT COUNT(*) FROM {bigbluebuttonbn_logs} ";
361
    $sql .= "WHERE courseid = ? AND bigbluebuttonbnid = ? AND userid = ? AND (log = ? OR log = ?)";
362
    $result = $DB->count_records_sql($sql, array($course->id, $bigbluebuttonbn->id, $user->id,
363
                                              BIGBLUEBUTTONBN_LOG_EVENT_JOIN, BIGBLUEBUTTONBN_LOG_EVENT_PLAYED));
364
    return $result;
365
}
366
367
/**
368
 * Returns all other caps used in module.
369
 *
370
 * @return string[]
371
 */
372
function bigbluebuttonbn_get_extra_capabilities() {
373
    return array('moodle/site:accessallgroups');
374
}
375
376
/**
377
 * Define items to be reset by course/reset.php
378
 *
379
 * @return array
380
 */
381
function bigbluebuttonbn_reset_course_items() {
382
    $items = array("events" => 0, "tags" => 0, "logs" => 0);
383
    // Include recordings only if enabled.
384
    if ((boolean)\mod_bigbluebuttonbn\locallib\config::recordings_enabled()) {
385
        $items["recordings"] = 0;
386
    }
387
    return $items;
388
}
389
390
/**
391
 * Called by course/reset.php
392
 *
393
 * @param object $mform
394
 * @return void
395
 */
396
function bigbluebuttonbn_reset_course_form_definition(&$mform) {
397
    $items = bigbluebuttonbn_reset_course_items();
398
    $mform->addElement('header', 'bigbluebuttonbnheader', get_string('modulenameplural', 'bigbluebuttonbn'));
399
    foreach ($items as $item => $default) {
400
        $mform->addElement(
401
            'advcheckbox',
402
            "reset_bigbluebuttonbn_{$item}",
403
            get_string("reset{$item}", 'bigbluebuttonbn')
404
        );
405
        if ($item == 'logs' || $item == 'recordings') {
406
            $mform->addHelpButton("reset_bigbluebuttonbn_{$item}", "reset{$item}", 'bigbluebuttonbn');
407
        }
408
    }
409
}
410
411
/**
412
 * Course reset form defaults.
413
 *
414
 * @param object $course
415
 * @return array
416
 */
417
function bigbluebuttonbn_reset_course_form_defaults($course) {
0 ignored issues
show
The parameter $course is not used and could be removed.

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

Loading history...
418
    $formdefaults = array();
419
    $items = bigbluebuttonbn_reset_course_items();
420
    // All unchecked by default.
421
    foreach ($items as $item => $default) {
422
        $formdefaults["reset_bigbluebuttonbn_{$item}"] = $default;
423
    }
424
    return $formdefaults;
425
}
426
427
/**
428
 * This function is used by the reset_course_userdata function in moodlelib.
429
 *
430
 * @param array $data the data submitted from the reset course.
431
 * @return array status array
432
 */
433
function bigbluebuttonbn_reset_userdata($data) {
434
    $items = bigbluebuttonbn_reset_course_items();
435
    $status = array();
436
    // Any changes to the list of dates that needs to be rolled should be same during course restore and course reset.
437
    // See MDL-9367.
438
    if (array_key_exists('recordings', $items) && !empty($data->reset_bigbluebuttonbn_recordings)) {
439
        // Remove all the recordings from a BBB server that are linked to the room/activities in this course.
440
        bigbluebuttonbn_reset_recordings($data->courseid);
441
        unset($items['recordings']);
442
        $status[] = bigbluebuttonbn_reset_getstatus('recordings');
443
    }
444
    if (!empty($data->reset_bigbluebuttonbn_tags)) {
445
        // Remove all the tags linked to the room/activities in this course.
446
        bigbluebuttonbn_reset_tags($data->courseid);
447
        unset($items['tags']);
448
        $status[] = bigbluebuttonbn_reset_getstatus('tags');
449
    }
450
    // TODO : seems to be duplicated code unless we just want to force reset tags.
451
    foreach ($items as $item => $default) {
452
        // Remove instances or elements linked to this course, others than recordings or tags.
453
        if (!empty($data->{"reset_bigbluebuttonbn_{$item}"})) {
454
            call_user_func("bigbluebuttonbn_reset_{$item}", $data->courseid);
455
            $status[] = bigbluebuttonbn_reset_getstatus($item);
456
        }
457
    }
458
    return $status;
459
}
460
461
/**
462
 * Returns status used on every defined reset action.
463
 *
464
 * @param string $item
465
 * @return array status array
466
 */
467
function bigbluebuttonbn_reset_getstatus($item) {
468
    return array('component' => get_string('modulenameplural', 'bigbluebuttonbn')
469
        , 'item' => get_string("removed{$item}", 'bigbluebuttonbn')
470
        , 'error' => false);
471
}
472
473
/**
474
 * Used by the reset_course_userdata for deleting events linked to bigbluebuttonbn instances in the course.
475
 *
476
 * @param string $courseid
477
 * @return array status array
478
 */
479
function bigbluebuttonbn_reset_events($courseid) {
480
    global $DB;
481
    // Remove all the events.
482
    return $DB->delete_records('event', array('modulename' => 'bigbluebuttonbn', 'courseid' => $courseid));
483
}
484
485
/**
486
 * Used by the reset_course_userdata for deleting tags linked to bigbluebuttonbn instances in the course.
487
 *
488
 * @param array $courseid
489
 * @return array status array
490
 */
491
function bigbluebuttonbn_reset_tags($courseid) {
492
    global $DB;
493
    // Remove all the tags linked to the room/activities in this course.
494
    if ($bigbluebuttonbns = $DB->get_records('bigbluebuttonbn', array('course' => $courseid))) {
495
        foreach ($bigbluebuttonbns as $bigbluebuttonbn) {
496
            if (!$cm = get_coursemodule_from_instance('bigbluebuttonbn', $bigbluebuttonbn->id, $courseid)) {
497
                continue;
498
            }
499
            $context = context_module::instance($cm->id);
500
            core_tag_tag::delete_instances('mod_bigbluebuttonbn', null, $context->id);
501
        }
502
    }
503
}
504
505
/**
506
 * Used by the reset_course_userdata for deleting bigbluebuttonbn_logs linked to bigbluebuttonbn instances in the course.
507
 *
508
 * @param string $courseid
509
 * @return array status array
510
 */
511
function bigbluebuttonbn_reset_logs($courseid) {
512
    global $DB;
513
    // Remove all the logs.
514
    return $DB->delete_records('bigbluebuttonbn_logs', array('courseid' => $courseid));
515
}
516
517
/**
518
 * Used by the reset_course_userdata for deleting recordings in a BBB server linked to bigbluebuttonbn instances in the course.
519
 *
520
 * @param string $courseid
521
 * @return array status array
522
 */
523
function bigbluebuttonbn_reset_recordings($courseid) {
524
    require_once(__DIR__.'/locallib.php');
525
    // Criteria for search [courseid | bigbluebuttonbn=null | subset=false | includedeleted=true].
526
    $recordings = bigbluebuttonbn_get_recordings($courseid, null, false, true);
527
    // Remove all the recordings.
528
    bigbluebuttonbn_delete_recordings(implode(",", array_keys($recordings)));
529
}
530
531
/**
532
 * List of view style log actions.
533
 *
534
 * @return string[]
535
 */
536
function bigbluebuttonbn_get_view_actions() {
537
    return array('view', 'view all');
538
}
539
540
/**
541
 * List of update style log actions.
542
 *
543
 * @return string[]
544
 */
545
function bigbluebuttonbn_get_post_actions() {
546
    return array('update', 'add', 'delete');
547
}
548
549
/**
550
 * Print an overview of all bigbluebuttonbn instances for the courses.
551
 *
552
 * @param array $courses
553
 * @param array $htmlarray Passed by reference
554
 *
555
 * @return void
556
 */
557
function bigbluebuttonbn_print_overview($courses, &$htmlarray) {
558
    if (empty($courses) || !is_array($courses)) {
559
        return array();
560
    }
561
    $bns = get_all_instances_in_courses('bigbluebuttonbn', $courses);
562
    foreach ($bns as $bn) {
563
        $now = time();
564
        if ($bn->openingtime and (!$bn->closingtime or $bn->closingtime > $now)) {
565
            // A bigbluebuttonbn is scheduled.
566
            if (empty($htmlarray[$bn->course]['bigbluebuttonbn'])) {
567
                $htmlarray[$bn->course]['bigbluebuttonbn'] = '';
568
            }
569
            // Make sure we print all bigbluebutton instances.
570
            $htmlarray[$bn->course]['bigbluebuttonbn'] .= bigbluebuttonbn_print_overview_element($bn, $now);
571
        }
572
    }
573
}
574
575
/**
576
 * Print an overview of a bigbluebuttonbn instance.
577
 *
578
 * @param array $bigbluebuttonbn
579
 * @param int $now
580
 *
581
 * @return string
582
 */
583
function bigbluebuttonbn_print_overview_element($bigbluebuttonbn, $now) {
584
    global $CFG;
585
    $start = 'started_at';
586
    if ($bigbluebuttonbn->openingtime > $now) {
587
        $start = 'starts_at';
588
    }
589
    $classes = '';
590
    if ($bigbluebuttonbn->visible) {
591
        $classes = 'class="dimmed" ';
592
    }
593
    $str  = '<div class="bigbluebuttonbn overview">'."\n";
594
    $str .= '  <div class="name">'.get_string('modulename', 'bigbluebuttonbn').':&nbsp;'."\n";
595
    $str .= '    <a '.$classes.'href="'.$CFG->wwwroot.'/mod/bigbluebuttonbn/view.php?id='.$bigbluebuttonbn->coursemodule.
596
      '">'.$bigbluebuttonbn->name.'</a>'."\n";
597
    $str .= '  </div>'."\n";
598
    $str .= '  <div class="info">'.get_string($start, 'bigbluebuttonbn').': '.userdate($bigbluebuttonbn->openingtime).
599
        '</div>'."\n";
600
    if (!empty($bigbluebuttonbn->closingtime)) {
601
        $str .= '  <div class="info">'.get_string('ends_at', 'bigbluebuttonbn').': '.userdate($bigbluebuttonbn->closingtime)
602
                .'</div>'."\n";
603
    }
604
    $str .= '</div>'."\n";
605
    return $str;
606
}
607
608
/**
609
 * Given a course_module object, this function returns any
610
 * "extra" information that may be needed when printing
611
 * this activity in a course listing.
612
 * See get_array_of_activities() in course/lib.php.
613
 *
614
 * @param object $coursemodule
615
 *
616
 * @return null|cached_cm_info
617
 */
618
function bigbluebuttonbn_get_coursemodule_info($coursemodule) {
619
    global $DB;
620
621
    $dbparams = ['id' => $coursemodule->instance];
622
    $fields = 'id, name, intro, introformat, completionattendance';
623
    $bigbluebuttonbn = $DB->get_record('bigbluebuttonbn', $dbparams, $fields);
624
    if (!$bigbluebuttonbn) {
625
        return false;
626
    }
627
    $info = new cached_cm_info();
628
    $info->name = $bigbluebuttonbn->name;
629
    if ($coursemodule->showdescription) {
630
        // Convert intro to html. Do not filter cached version, filters run at display time.
631
        $info->content = format_module_intro('bigbluebuttonbn', $bigbluebuttonbn, $coursemodule->id, false);
632
    }
633
    // Populate the custom completion rules as key => value pairs, but only if the completion mode is 'automatic'.
634
    if ($coursemodule->completion == COMPLETION_TRACKING_AUTOMATIC) {
635
        $info->customdata['customcompletionrules']['completionattendance'] = $bigbluebuttonbn->completionattendance;
636
    }
637
638
    return $info;
639
}
640
641
/**
642
 * Callback which returns human-readable strings describing the active completion custom rules for the module instance.
643
 *
644
 * @param cm_info|stdClass $cm object with fields ->completion and ->customdata['customcompletionrules']
645
 * @return array $descriptions the array of descriptions for the custom rules.
646
 */
647
function mod_bigbluebuttonbn_get_completion_active_rule_descriptions($cm) {
648
    // Values will be present in cm_info, and we assume these are up to date.
649
    if (empty($cm->customdata['customcompletionrules'])
650
        || $cm->completion != COMPLETION_TRACKING_AUTOMATIC) {
651
        return [];
652
    }
653
654
    $descriptions = [];
655
    foreach ($cm->customdata['customcompletionrules'] as $key => $val) {
656
        switch ($key) {
657
            case 'completionattendance':
658
                if (!empty($val)) {
659
                    $descriptions[] = get_string('completionattendancedesc', 'bigbluebuttonbn', $val);
660
                    $descriptions[] = get_string('completionengagementdesc', 'bigbluebuttonbn', $val);
661
                }
662
                break;
663
            default:
664
                break;
665
        }
666
    }
667
    return $descriptions;
668
}
669
670
/**
671
 * Runs any processes that must run before a bigbluebuttonbn insert/update.
672
 *
673
 * @param object $bigbluebuttonbn BigBlueButtonBN form data
674
 *
675
 * @return void
676
 **/
677
function bigbluebuttonbn_process_pre_save(&$bigbluebuttonbn) {
678
    bigbluebuttonbn_process_pre_save_instance($bigbluebuttonbn);
679
    bigbluebuttonbn_process_pre_save_checkboxes($bigbluebuttonbn);
680
    bigbluebuttonbn_process_pre_save_common($bigbluebuttonbn);
681
    $bigbluebuttonbn->participants = htmlspecialchars_decode($bigbluebuttonbn->participants);
682
}
683
684
/**
685
 * Runs process for defining the instance (insert/update).
686
 *
687
 * @param object $bigbluebuttonbn BigBlueButtonBN form data
688
 *
689
 * @return void
690
 **/
691
function bigbluebuttonbn_process_pre_save_instance(&$bigbluebuttonbn) {
692
    require_once(__DIR__.'/locallib.php');
693
    $bigbluebuttonbn->timemodified = time();
694
    if ((integer)$bigbluebuttonbn->instance == 0) {
695
        $bigbluebuttonbn->meetingid = 0;
696
        $bigbluebuttonbn->timecreated = time();
697
        $bigbluebuttonbn->timemodified = 0;
698
        // As it is a new activity, assign passwords.
699
        $bigbluebuttonbn->moderatorpass = bigbluebuttonbn_random_password(12);
700
        $bigbluebuttonbn->viewerpass = bigbluebuttonbn_random_password(12, $bigbluebuttonbn->moderatorpass);
701
    }
702
}
703
704
/**
705
 * Runs process for assigning default value to checkboxes.
706
 *
707
 * @param object $bigbluebuttonbn BigBlueButtonBN form data
708
 *
709
 * @return void
710
 **/
711
function bigbluebuttonbn_process_pre_save_checkboxes(&$bigbluebuttonbn) {
712
    if (!isset($bigbluebuttonbn->wait)) {
713
        $bigbluebuttonbn->wait = 0;
714
    }
715
    if (!isset($bigbluebuttonbn->record)) {
716
        $bigbluebuttonbn->record = 0;
717
    }
718
    if (!isset($bigbluebuttonbn->recordallfromstart)) {
719
        $bigbluebuttonbn->recordallfromstart = 0;
720
    }
721
    if (!isset($bigbluebuttonbn->recordhidebutton)) {
722
        $bigbluebuttonbn->recordhidebutton = 0;
723
    }
724
    if (!isset($bigbluebuttonbn->recordings_html)) {
725
        $bigbluebuttonbn->recordings_html = 0;
726
    }
727
    if (!isset($bigbluebuttonbn->recordings_deleted)) {
728
        $bigbluebuttonbn->recordings_deleted = 0;
729
    }
730
    if (!isset($bigbluebuttonbn->recordings_imported)) {
731
        $bigbluebuttonbn->recordings_imported = 0;
732
    }
733
    if (!isset($bigbluebuttonbn->recordings_preview)) {
734
        $bigbluebuttonbn->recordings_preview = 0;
735
    }
736
    if (!isset($bigbluebuttonbn->muteonstart)) {
737
        $bigbluebuttonbn->muteonstart = 0;
738
    }
739
    if (!isset($bigbluebuttonbn->disablecam)) {
740
        $bigbluebuttonbn->disablecam = 0;
741
    }
742
    if (!isset($bigbluebuttonbn->disablemic)) {
743
        $bigbluebuttonbn->disablemic = 0;
744
    }
745
    if (!isset($bigbluebuttonbn->disableprivatechat)) {
746
        $bigbluebuttonbn->disableprivatechat = 0;
747
    }
748
    if (!isset($bigbluebuttonbn->disablepublicchat)) {
749
        $bigbluebuttonbn->disablepublicchat = 0;
750
    }
751
    if (!isset($bigbluebuttonbn->disablenote)) {
752
        $bigbluebuttonbn->disablenote = 0;
753
    }
754
    if (!isset($bigbluebuttonbn->hideuserlist)) {
755
        $bigbluebuttonbn->hideuserlist = 0;
756
    }
757
    if (!isset($bigbluebuttonbn->lockedlayout)) {
758
        $bigbluebuttonbn->lockedlayout = 0;
759
    }
760
    if (!isset($bigbluebuttonbn->lockonjoin)) {
761
        $bigbluebuttonbn->lockonjoin = 0;
762
    }
763
    if (!isset($bigbluebuttonbn->lockonjoinconfigurable)) {
764
        $bigbluebuttonbn->lockonjoinconfigurable = 0;
765
    }
766
    if (!isset($bigbluebuttonbn->recordings_validate_url)) {
767
        $bigbluebuttonbn->recordings_validate_url = 1;
768
    }
769
}
770
771
/**
772
 * Runs process for wipping common settings when 'recordings only'.
773
 *
774
 * @param object $bigbluebuttonbn BigBlueButtonBN form data
775
 *
776
 * @return void
777
 **/
778
function bigbluebuttonbn_process_pre_save_common(&$bigbluebuttonbn) {
779
    // Make sure common settings are removed when 'recordings only'.
780
    if ($bigbluebuttonbn->type == BIGBLUEBUTTONBN_TYPE_RECORDING_ONLY) {
781
        $bigbluebuttonbn->groupmode = 0;
782
        $bigbluebuttonbn->groupingid = 0;
783
    }
784
}
785
786
/**
787
 * Runs any processes that must be run after a bigbluebuttonbn insert/update.
788
 *
789
 * @param object $bigbluebuttonbn BigBlueButtonBN form data
790
 *
791
 * @return void
792
 **/
793
function bigbluebuttonbn_process_post_save(&$bigbluebuttonbn) {
794
    if (isset($bigbluebuttonbn->notification) && $bigbluebuttonbn->notification) {
795
        bigbluebuttonbn_process_post_save_notification($bigbluebuttonbn);
796
    }
797
    bigbluebuttonbn_process_post_save_event($bigbluebuttonbn);
798
    bigbluebuttonbn_process_post_save_completion($bigbluebuttonbn);
799
}
800
801
/**
802
 * Generates a message on insert/update which is sent to all users enrolled.
803
 *
804
 * @param object $bigbluebuttonbn BigBlueButtonBN form data
805
 *
806
 * @return void
807
 **/
808
function bigbluebuttonbn_process_post_save_notification(&$bigbluebuttonbn) {
809
    $action = get_string('mod_form_field_notification_msg_modified', 'bigbluebuttonbn');
810
    if (isset($bigbluebuttonbn->add) && !empty($bigbluebuttonbn->add)) {
811
        $action = get_string('mod_form_field_notification_msg_created', 'bigbluebuttonbn');
812
    }
813
    \mod_bigbluebuttonbn\locallib\notifier::notify_instance_updated($bigbluebuttonbn, $action);
814
}
815
816
/**
817
 * Generates an event after a bigbluebuttonbn insert/update.
818
 *
819
 * @param object $bigbluebuttonbn BigBlueButtonBN form data
820
 *
821
 * @return void
822
 **/
823
function bigbluebuttonbn_process_post_save_event(&$bigbluebuttonbn) {
824
    global $CFG, $DB;
825
    require_once($CFG->dirroot.'/calendar/lib.php');
826
    $eventid = $DB->get_field('event', 'id', array('modulename' => 'bigbluebuttonbn',
827
        'instance' => $bigbluebuttonbn->id));
828
    // Delete the event from calendar when/if openingtime is NOT set.
829
    if (!isset($bigbluebuttonbn->openingtime) || !$bigbluebuttonbn->openingtime) {
830
        if ($eventid) {
831
            $calendarevent = calendar_event::load($eventid);
832
            $calendarevent->delete();
833
        }
834
        return;
835
    }
836
    // Add evento to the calendar as openingtime is set.
837
    $event = new stdClass();
838
    $event->eventtype = BIGBLUEBUTTON_EVENT_MEETING_START;
839
    $event->type = CALENDAR_EVENT_TYPE_ACTION;
840
    $event->name = get_string('calendarstarts', 'bigbluebuttonbn', $bigbluebuttonbn->name);
841
    $event->description = format_module_intro('bigbluebuttonbn', $bigbluebuttonbn, $bigbluebuttonbn->coursemodule, false);
842
    $event->format      = FORMAT_HTML;
843
    $event->courseid = $bigbluebuttonbn->course;
844
    $event->groupid = 0;
845
    $event->userid = 0;
846
    $event->modulename = 'bigbluebuttonbn';
847
    $event->instance = $bigbluebuttonbn->id;
848
    $event->timestart = $bigbluebuttonbn->openingtime;
849
    $event->timeduration = 0;
850
    $event->timesort = $event->timestart;
851
    $event->visible = instance_is_visible('bigbluebuttonbn', $bigbluebuttonbn);
852
    $event->priority = null;
853
    // Update the event in calendar when/if eventid was found.
854
    if ($eventid) {
855
        $event->id = $eventid;
856
        $calendarevent = calendar_event::load($eventid);
857
        $calendarevent->update($event);
858
        return;
859
    }
860
    calendar_event::create($event);
861
}
862
863
/**
864
 * Generates an event after a bigbluebuttonbn activity is completed.
865
 *
866
 * @param object $bigbluebuttonbn BigBlueButtonBN form data
867
 *
868
 * @return void
869
 **/
870
function bigbluebuttonbn_process_post_save_completion($bigbluebuttonbn) {
871
    if (!empty($bigbluebuttonbn->completionexpected)) {
872
        \core_completion\api::update_completion_date_event(
873
            $bigbluebuttonbn->coursemodule,
874
            'bigbluebuttonbn',
875
            $bigbluebuttonbn->id,
876
            $bigbluebuttonbn->completionexpected
877
          );
878
    }
879
}
880
881
/**
882
 * Get a full path to the file attached as a preuploaded presentation
883
 * or if there is none, set the presentation field will be set to blank.
884
 *
885
 * @param object $bigbluebuttonbn BigBlueButtonBN form data
886
 *
887
 * @return string
888
 */
889
function bigbluebuttonbn_get_media_file(&$bigbluebuttonbn) {
890
    if (!isset($bigbluebuttonbn->presentation) || $bigbluebuttonbn->presentation == '') {
891
        return '';
892
    }
893
    $context = context_module::instance($bigbluebuttonbn->coursemodule);
894
    // Set the filestorage object.
895
    $fs = get_file_storage();
896
    // Save the file if it exists that is currently in the draft area.
897
    file_save_draft_area_files($bigbluebuttonbn->presentation, $context->id, 'mod_bigbluebuttonbn', 'presentation', 0);
898
    // Get the file if it exists.
899
    $files = $fs->get_area_files(
900
        $context->id,
901
        'mod_bigbluebuttonbn',
902
        'presentation',
903
        0,
904
        'itemid, filepath, filename',
905
        false
906
    );
907
    // Check that there is a file to process.
908
    $filesrc = '';
909
    if (count($files) == 1) {
910
        // Get the first (and only) file.
911
        $file = reset($files);
912
        $filesrc = '/'.$file->get_filename();
913
    }
914
    return $filesrc;
915
}
916
917
/**
918
 * Serves the bigbluebuttonbn attachments. Implements needed access control ;-).
919
 *
920
 * @category files
921
 *
922
 * @param stdClass $course        course object
923
 * @param stdClass $cm            course module object
924
 * @param stdClass $context       context object
925
 * @param string   $filearea      file area
926
 * @param array    $args          extra arguments
927
 * @param bool     $forcedownload whether or not force download
928
 * @param array    $options       additional options affecting the file serving
929
 *
930
 * @return false|null false if file not found, does not return if found - justsend the file
931
 */
932
function bigbluebuttonbn_pluginfile($course, $cm, $context, $filearea, $args, $forcedownload, array $options = array()) {
933
    if (!bigbluebuttonbn_pluginfile_valid($context, $filearea)) {
934
        return false;
935
    }
936
    $file = bigbluebuttonbn_pluginfile_file($course, $cm, $context, $filearea, $args);
937
    if (empty($file)) {
938
        return false;
939
    }
940
    // Finally send the file.
941
    send_stored_file($file, 0, 0, $forcedownload, $options); // Download MUST be forced - security!
942
}
943
944
/**
945
 * Helper for validating pluginfile.
946
 * @param stdClass $context       context object
947
 * @param string   $filearea      file area
948
 *
949
 * @return false|null false if file not valid
950
 */
951
function bigbluebuttonbn_pluginfile_valid($context, $filearea) {
952
953
    // Can be in context module or in context_system (if is the presentation by default).
954
    if (!in_array($context->contextlevel, array(CONTEXT_MODULE, CONTEXT_SYSTEM))) {
955
        return false;
956
    }
957
958
    if (!array_key_exists($filearea, bigbluebuttonbn_get_file_areas())) {
959
        return false;
960
    }
961
962
    return true;
963
}
964
965
/**
966
 * Helper for getting pluginfile.
967
 *
968
 * @param stdClass $course        course object
969
 * @param stdClass $cm            course module object
970
 * @param stdClass $context       context object
971
 * @param string   $filearea      file area
972
 * @param array    $args          extra arguments
973
 *
974
 * @return object
975
 */
976
function bigbluebuttonbn_pluginfile_file($course, $cm, $context, $filearea, $args) {
977
    $filename = bigbluebuttonbn_pluginfile_filename($course, $cm, $context, $args);
978
    if (!$filename) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $filename of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
979
        return false;
980
    }
981
    $fullpath = "/$context->id/mod_bigbluebuttonbn/$filearea/0/".$filename;
982
    $fs = get_file_storage();
983
    $file = $fs->get_file_by_hash(sha1($fullpath));
984
    if (!$file || $file->is_directory()) {
985
        return false;
986
    }
987
    return $file;
988
}
989
990
/**
991
 * Helper for give access to the file configured in setting as default presentation.
992
 *
993
 * @param stdClass $course        course object
994
 * @param stdClass $cm            course module object
995
 * @param stdClass $context       context object
996
 * @param array    $args          extra arguments
997
 *
998
 * @return array
999
 */
1000
function bigbluebuttonbn_default_presentation_get_file($course, $cm, $context, $args) {
1001
1002
    // The difference with the standard bigbluebuttonbn_pluginfile_filename() are.
1003
    // - Context is system, so we don't need to check the cmid in this case.
1004
    // - The area is "presentationdefault_cache".
1005
    if (count($args) > 1) {
1006
        $cache = cache::make_from_params(
1007
            cache_store::MODE_APPLICATION,
1008
            'mod_bigbluebuttonbn',
1009
            'presentationdefault_cache'
1010
        );
1011
1012
        $noncekey = sha1($context->id);
1013
        $presentationnonce = $cache->get($noncekey);
1014
        $noncevalue = $presentationnonce['value'];
1015
        $noncecounter = $presentationnonce['counter'];
1016
        if ($args['0'] != $noncevalue) {
1017
            return;
1018
        }
1019
1020
        // The nonce value is actually used twice because BigBlueButton reads the file two times.
1021
        $noncecounter += 1;
1022
        $cache->set($noncekey, array('value' => $noncevalue, 'counter' => $noncecounter));
1023
        if ($noncecounter == 2) {
1024
            $cache->delete($noncekey);
1025
        }
1026
        return($args['1']);
1027
    }
1028
    require_course_login($course, true, $cm);
1029
    if (!has_capability('mod/bigbluebuttonbn:join', $context)) {
1030
        return;
1031
    }
1032
    return implode('/', $args);
1033
}
1034
1035
/**
1036
 * Helper for getting pluginfile name.
1037
 *
1038
 * @param stdClass $course        course object
1039
 * @param stdClass $cm            course module object
1040
 * @param stdClass $context       context object
1041
 * @param array    $args          extra arguments
1042
 *
1043
 * @return array
1044
 */
1045
function bigbluebuttonbn_pluginfile_filename($course, $cm, $context, $args) {
1046
    global $DB;
1047
1048
    if ($context->contextlevel == CONTEXT_SYSTEM) {
1049
        // Plugin has a file to use as default in general setting.
1050
        return(bigbluebuttonbn_default_presentation_get_file($course, $cm, $context, $args));
1051
    }
1052
1053
    if (count($args) > 1) {
1054
        if (!$bigbluebuttonbn = $DB->get_record('bigbluebuttonbn', array('id' => $cm->instance))) {
1055
            return;
1056
        }
1057
        $cache = cache::make_from_params(cache_store::MODE_APPLICATION, 'mod_bigbluebuttonbn', 'presentation_cache');
1058
        $noncekey = sha1($bigbluebuttonbn->id);
1059
        $presentationnonce = $cache->get($noncekey);
1060
        if (!empty($presentationnonce)) {
1061
            $noncevalue = $presentationnonce['value'];
1062
            $noncecounter = $presentationnonce['counter'];
1063
        } else {
1064
            $noncevalue = null;
1065
            $noncecounter = 0;
1066
        }
1067
1068
        if ($args['0'] != $noncevalue) {
1069
            return;
1070
        }
1071
        // The nonce value is actually used twice because BigBlueButton reads the file two times.
1072
        $noncecounter += 1;
1073
        $cache->set($noncekey, array('value' => $noncevalue, 'counter' => $noncecounter));
1074
        if ($noncecounter == 2) {
1075
            $cache->delete($noncekey);
1076
        }
1077
        return $args['1'];
1078
    }
1079
    require_course_login($course, true, $cm);
1080
    if (!has_capability('mod/bigbluebuttonbn:join', $context)) {
1081
        return;
1082
    }
1083
    return implode('/', $args);
1084
}
1085
1086
/**
1087
 * Returns an array of file areas.
1088
 *
1089
 * @category files
1090
 *
1091
 * @return array a list of available file areas
1092
 */
1093
function bigbluebuttonbn_get_file_areas() {
1094
    $areas = array();
1095
    $areas['presentation'] = get_string('mod_form_block_presentation', 'bigbluebuttonbn');
1096
    $areas['presentationdefault'] = get_string('mod_form_block_presentation_default', 'bigbluebuttonbn');
1097
    return $areas;
1098
}
1099
1100
/**
1101
 * Mark the activity completed (if required) and trigger the course_module_viewed event.
1102
 *
1103
 * @param  stdClass $bigbluebuttonbn        bigbluebuttonbn object
1104
 * @param  stdClass $course     course object
1105
 * @param  stdClass $cm         course module object
1106
 * @param  stdClass $context    context object
1107
 * @since Moodle 3.0
1108
 */
1109
function bigbluebuttonbn_view($bigbluebuttonbn, $course, $cm, $context) {
1110
1111
    // Trigger course_module_viewed event.
1112
    $params = array(
1113
        'context' => $context,
1114
        'objectid' => $bigbluebuttonbn->id
1115
    );
1116
1117
    $event = \mod_bigbluebuttonbn\event\activity_viewed::create($params); // Fix event name.
1118
    $event->add_record_snapshot('course_modules', $cm);
1119
    $event->add_record_snapshot('course', $course);
1120
    $event->add_record_snapshot('bigbluebuttonbn', $bigbluebuttonbn);
1121
    $event->trigger();
1122
1123
    // Completion.
1124
    $completion = new completion_info($course);
1125
    $completion->set_module_viewed($cm);
1126
}
1127
1128
/**
1129
 * Check if the module has any update that affects the current user since a given time.
1130
 *
1131
 * @param  cm_info $cm course module data
1132
 * @param  int $from the time to check updates from
1133
 * @param  array $filter  if we need to check only specific updates
1134
 * @return stdClass an object with the different type of areas indicating if they were updated or not
1135
 * @since Moodle 3.2
1136
 */
1137
function bigbluebuttonbn_check_updates_since(cm_info $cm, $from, $filter = array()) {
1138
    $updates = course_check_module_updates_since($cm, $from, array('content'), $filter);
1139
    return $updates;
1140
}
1141
1142
1143
/**
1144
 * Get icon mapping for font-awesome.
1145
 */
1146
function mod_bigbluebuttonbn_get_fontawesome_icon_map() {
1147
    return [
1148
        'mod_bigbluebuttonbn:icon' => 'icon-bigbluebutton',
1149
    ];
1150
}
1151
1152
/**
1153
 * This function receives a calendar event and returns the action associated with it, or null if there is none.
1154
 *
1155
 * This is used by block_myoverview in order to display the event appropriately. If null is returned then the event
1156
 * is not displayed on the block.
1157
 *
1158
 * @param calendar_event $event
1159
 * @param \core_calendar\action_factory $factory
1160
 * @return \core_calendar\local\event\entities\action_interface|null
1161
 */
1162
function mod_bigbluebuttonbn_core_calendar_provide_event_action(
1163
    calendar_event $event,
1164
    \core_calendar\action_factory $factory
1165
) {
1166
    global $CFG, $DB;
1167
1168
    require_once($CFG->dirroot . '/mod/bigbluebuttonbn/locallib.php');
1169
1170
    $time = time();
1171
1172
    // Get mod info.
1173
    $cm = get_fast_modinfo($event->courseid)->instances['bigbluebuttonbn'][$event->instance];
1174
1175
    // Get bigbluebuttonbn activity.
1176
    $bigbluebuttonbn = $DB->get_record('bigbluebuttonbn', array('id' => $event->instance), '*', MUST_EXIST);
1177
1178
    // Set flag haspassed if closingtime has already passed only if it is defined.
1179
    $haspassed = ($bigbluebuttonbn->closingtime) && $bigbluebuttonbn->closingtime < $time;
1180
1181
    // Set flag hasstarted if startingtime has already passed or not defined.
1182
    $hasstarted = $bigbluebuttonbn->openingtime < $time;
1183
1184
    // Return null if it has passed or not started.
1185
    if ($haspassed || !$hasstarted) {
1186
        return null;
1187
    }
1188
1189
    // Get if the user has joined in live session or viewed the recorded.
1190
    $usercomplete = bigbluebuttonbn_user_complete($event->courseid, $event->userid, $bigbluebuttonbn);
1191
    // Get if the room is available.
1192
    list($roomavailable) = bigbluebuttonbn_room_is_available($bigbluebuttonbn);
1193
    // Get if the user can join.
1194
    list($usercanjoin) = bigbluebuttonbn_user_can_join_meeting($bigbluebuttonbn);
1195
1196
    // Check if the room is closed and the user has already joined this session or played the record.
1197
    if (!$roomavailable && $usercomplete) {
1198
        return null;
1199
    }
1200
1201
    // Check if the user can join this session.
1202
    $actionable = ($roomavailable && $usercanjoin);
1203
1204
    // Action data.
1205
    $string = get_string('view_room', 'bigbluebuttonbn');
1206
    $url = new \moodle_url('/mod/bigbluebuttonbn/view.php', array('id' => $cm->id));
1207
    if (groups_get_activity_groupmode($cm) == NOGROUPS) {
1208
        // No groups mode.
1209
        $string = get_string('view_conference_action_join', 'bigbluebuttonbn');
1210
        $url = new \moodle_url('/mod/bigbluebuttonbn/bbb_view.php', array('action' => 'join',
1211
            'id' => $cm->id, 'bn' => $bigbluebuttonbn->id, 'timeline' => 1));
1212
    }
1213
1214
    return $factory->create_instance($string, $url, 1, $actionable);
1215
}
1216
1217
/**
1218
 * Register a bigbluebuttonbn event
1219
 *
1220
 * @param object $bigbluebuttonbn
1221
 * @param string $event
1222
 * @param array  $overrides
1223
 * @param string $meta
1224
 *
1225
 * @return bool Success/Failure
1226
 */
1227
function bigbluebuttonbn_log($bigbluebuttonbn, $event, array $overrides = [], $meta = null) {
1228
    global $DB, $USER;
1229
    $log = new stdClass();
1230
    // Default values.
1231
    $log->courseid = $bigbluebuttonbn->course;
1232
    $log->bigbluebuttonbnid = $bigbluebuttonbn->id;
1233
    $log->userid = $USER->id;
1234
    $log->meetingid = $bigbluebuttonbn->meetingid;
1235
    $log->timecreated = time();
1236
    $log->log = $event;
1237
    $log->meta = $meta;
1238
    // Overrides.
1239
    foreach ($overrides as $key => $value) {
1240
        $log->$key = $value;
1241
    }
1242
    if (!$DB->insert_record('bigbluebuttonbn_logs', $log)) {
1243
        return false;
1244
    }
1245
    return true;
1246
}
1247
1248
/**
1249
 * Adds module specific settings to the settings block
1250
 *
1251
 * @param settings_navigation $settingsnav The settings navigation object
1252
 * @param navigation_node $nodenav The node to add module settings to
1253
 */
1254
function bigbluebuttonbn_extend_settings_navigation(settings_navigation $settingsnav, navigation_node $nodenav) {
0 ignored issues
show
The parameter $settingsnav is not used and could be removed.

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

Loading history...
1255
    global $PAGE, $USER;
1256
    // Don't add validate completion if the callback for meetingevents is NOT enabled.
1257
    if (!(boolean)\mod_bigbluebuttonbn\locallib\config::get('meetingevents_enabled')) {
1258
        return;
1259
    }
1260
    // Don't add validate completion if user is not allowed to edit the activity.
1261
    $context = context_module::instance($PAGE->cm->id);
1262
    if (!has_capability('moodle/course:manageactivities', $context, $USER->id)) {
1263
        return;
1264
    }
1265
    $completionvalidate = '#action=completion_validate&bigbluebuttonbn=' . $PAGE->cm->instance;
1266
    $nodenav->add(get_string('completionvalidatestate', 'bigbluebuttonbn'),
1267
        $completionvalidate, navigation_node::TYPE_CONTAINER);
1268
}
1269