Completed
Pull Request — master (#39)
by Jesus
02:02
created

lib.php ➔ bigbluebuttonbn_delete_instance_log()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 20
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 17
nc 4
nop 1
dl 0
loc 20
rs 9.4285
c 0
b 0
f 0
1
<?php
2
// This file is part of Moodle - http://moodle.org/
3
//
4
// Moodle is free software: you can redistribute it and/or modify
5
// it under the terms of the GNU General Public License as published by
6
// the Free Software Foundation, either version 3 of the License, or
7
// (at your option) any later version.
8
//
9
// Moodle is distributed in the hope that it will be useful,
10
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
// GNU General Public License for more details.
13
//
14
// You should have received a copy of the GNU General Public License
15
// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
16
17
/**
18
 * Library calls for Moodle and BigBlueButton.
19
 *
20
 * @author    Fred Dixon  (ffdixon [at] blindsidenetworks [dt] com)
21
 * @author    Jesus Federico  (jesus [at] blindsidenetworks [dt] com)
22
 * @copyright 2010-2017 Blindside Networks Inc
23
 * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v2 or later
24
 */
25
26
defined('MOODLE_INTERNAL') || die;
27
28
global $CFG;
29
30
require_once($CFG->dirroot.'/calendar/lib.php');
31
require_once($CFG->dirroot.'/message/lib.php');
32
require_once($CFG->dirroot.'/mod/lti/OAuth.php');
33
require_once($CFG->libdir.'/accesslib.php');
34
require_once($CFG->libdir.'/completionlib.php');
35
require_once($CFG->libdir.'/datalib.php');
36
require_once($CFG->libdir.'/coursecatlib.php');
37
require_once($CFG->libdir.'/enrollib.php');
38
require_once($CFG->libdir.'/filelib.php');
39
require_once($CFG->libdir.'/formslib.php');
40
41
if (file_exists(dirname(__FILE__).'/vendor/firebase/php-jwt/src/JWT.php')) {
42
    require_once(dirname(__FILE__).'/vendor/firebase/php-jwt/src/JWT.php');
43
}
44
45
if (!isset($CFG->bigbluebuttonbn)) {
46
    $CFG->bigbluebuttonbn = array();
47
}
48
49
if (file_exists(dirname(__FILE__).'/config.php')) {
50
    require_once(dirname(__FILE__).'/config.php');
51
    // Old BigBlueButtonBN cfg schema. For backward compatibility.
52
    global $BIGBLUEBUTTONBN_CFG;
53
54
    if (isset($BIGBLUEBUTTONBN_CFG)) {
55
        foreach ((array) $BIGBLUEBUTTONBN_CFG as $key => $value) {
56
            $cfgkey = str_replace("bigbluebuttonbn_", "", $key);
57
            $CFG->bigbluebuttonbn[$cfgkey] = $value;
58
        }
59
    }
60
}
61
62
/*
63
 * DURATIONCOMPENSATION: Feature removed by configuration
64
 */
65
$CFG->bigbluebuttonbn['scheduled_duration_enabled'] = 0;
66
/*
67
 * Remove this block when restored
68
 */
69
70
const BIGBLUEBUTTONBN_DEFAULT_SERVER_URL = 'http://test-install.blindsidenetworks.com/bigbluebutton/';
71
const BIGBLUEBUTTONBN_DEFAULT_SHARED_SECRET = '8cd8ef52e8e101574e400365b55e11a6';
72
73
const BIGBLUEBUTTONBN_LOG_EVENT_CREATE = 'Create';
74
const BIGBLUEBUTTONBN_LOG_EVENT_JOIN = 'Join';
75
const BIGBLUEBUTTONBN_LOG_EVENT_LOGOUT = 'Logout';
76
const BIGBLUEBUTTONBN_LOG_EVENT_IMPORT = 'Import';
77
const BIGBLUEBUTTONBN_LOG_EVENT_DELETE = 'Delete';
78
79
function bigbluebuttonbn_supports($feature) {
80
81
    if (!$feature) {
82
        return null;
83
    }
84
85
    $features = array(
86
        (string) FEATURE_IDNUMBER => true,
87
        (string) FEATURE_GROUPS => true,
88
        (string) FEATURE_GROUPINGS => true,
89
        (string) FEATURE_GROUPMEMBERSONLY => true,
90
        (string) FEATURE_MOD_INTRO => true,
91
        (string) FEATURE_BACKUP_MOODLE2 => true,
92
        (string) FEATURE_COMPLETION_TRACKS_VIEWS => true,
93
        (string) FEATURE_GRADE_HAS_GRADE => false,
94
        (string) FEATURE_GRADE_OUTCOMES => false,
95
        (string) FEATURE_SHOW_DESCRIPTION => true,
96
    );
97
98
    if (isset($features[(string) $feature])) {
99
        return $features[$feature];
100
    }
101
102
    return null;
103
}
104
105
/**
106
 * Given an object containing all the necessary data,
107
 * (defined by the form in mod_form.php) this function
108
 * will create a new instance and return the id number
109
 * of the new instance.
110
 *
111
 * @param object $data  An object from the form in mod_form.php
112
 * @return int The id of the newly inserted bigbluebuttonbn record
113
 */
114
function bigbluebuttonbn_add_instance($data) {
115
    global $DB;
116
    $draftitemid = isset($data->presentation) ? $data->presentation : null;
117
    $context = context_module::instance($data->coursemodule);
118
    bigbluebuttonbn_process_pre_save($data);
119
    unset($data->presentation);
120
    $bigbluebuttonbnid = $DB->insert_record('bigbluebuttonbn', $data);
121
    $data->id = $bigbluebuttonbnid;
122
    bigbluebuttonbn_update_media_file($bigbluebuttonbnid, $context, $draftitemid);
123
    bigbluebuttonbn_process_post_save($data);
124
    return $bigbluebuttonbnid;
125
}
126
127
/**
128
 * Given an object containing all the necessary data,
129
 * (defined by the form in mod_form.php) this function
130
 * will update an existing instance with new data.
131
 *
132
 * @param object $data  An object from the form in mod_form.php
133
 * @return bool Success/Fail
134
 */
135
function bigbluebuttonbn_update_instance($data) {
136
    global $DB;
137
    $data->id = $data->instance;
138
    $draftitemid = isset($data->presentation) ? $data->presentation : null;
139
    $context = context_module::instance($data->coursemodule);
140
    bigbluebuttonbn_process_pre_save($data);
141
    unset($data->presentation);
142
    $DB->update_record('bigbluebuttonbn', $data);
143
    bigbluebuttonbn_update_media_file($data->id, $context, $draftitemid);
144
    bigbluebuttonbn_process_post_save($data);
145
    return true;
146
}
147
148
/**
149
 * Given an ID of an instance of this module,
150
 * this function will permanently delete the instance
151
 * and any data that depends on it.
152
 *
153
 * @param int $id Id of the module instance
154
 *
155
 * @return bool Success/Failure
156
 */
157
function bigbluebuttonbn_delete_instance($id) {
158
    global $DB;
159
    $bigbluebuttonbn = $DB->get_record('bigbluebuttonbn', array('id' => $id));
160
    if (!$bigbluebuttonbn) {
161
        return false;
162
    }
163
    // TODO: End the meeting if it is running.
164
165
    // Perform delete.
166
    if (!$DB->delete_records('bigbluebuttonbn', array('id' => $bigbluebuttonbn->id))) {
167
        return false;
168
    }
169
    if (!$DB->delete_records('event', array('modulename' => 'bigbluebuttonbn', 'instance' => $bigbluebuttonbn->id))) {
170
        return false;
171
    }
172
    // Log action performed.
173
    return bigbluebuttonbn_delete_instance_log($bigbluebuttonbn);
174
}
175
176
function bigbluebuttonbn_delete_instance_log($bigbluebuttonbn) {
177
    global $DB, $USER;
178
    $log = new stdClass();
179
    $log->meetingid = $bigbluebuttonbn->meetingid;
180
    $log->courseid = $bigbluebuttonbn->course;
181
    $log->bigbluebuttonbnid = $bigbluebuttonbn->id;
182
    $log->userid = $USER->id;
183
    $log->timecreated = time();
184
    $log->log = BIGBLUEBUTTONBN_LOG_EVENT_DELETE;
185
    $sql = "SELECT * FROM {bigbluebuttonbn_logs} WHERE bigbluebuttonbnid = ? AND log = ? AND " . $DB->sql_compare_text('meta') . " = ?";
186
    $logs = $DB->get_records_sql($sql, array($bigbluebuttonbn->id, BIGBLUEBUTTONBN_LOG_EVENT_CREATE, "{\"record\":true}"));
187
    $log->meta = "{\"has_recordings\":false}";
188
    if (!empty($logs)) {
189
        $log->meta = "{\"has_recordings\":true}";
190
    }
191
    if (!$DB->insert_record('bigbluebuttonbn_logs', $log)) {
192
        return false;
193
    }
194
    return true;
195
}
196
/**
197
 * Return a small object with summary information about what a
198
 * user has done with a given particular instance of this module
199
 * Used for user activity reports.
200
 * $return->time = the time they did it
201
 * $return->info = a short text description.
202
 *
203
 * @return bool
204
 */
205
function bigbluebuttonbn_user_outline($course, $user, $mod, $bigbluebuttonbn) {
0 ignored issues
show
Unused Code introduced by
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...
206
    global $DB;
207
    $completed = $DB->count_records('bigbluebuttonbn_logs', array('courseid' => $course->id,
208
                                                              'bigbluebuttonbnid' => $bigbluebuttonbn->id,
209
                                                              'userid' => $user->id,
210
                                                              'log' => 'Join', ), '*');
211
    if ($completed > 0) {
212
        return fullname($user).' '.get_string('view_message_has_joined', 'bigbluebuttonbn').' '.
213
            get_string('view_message_session_for', 'bigbluebuttonbn').' '.(string) $completed.' '.
214
            get_string('view_message_times', 'bigbluebuttonbn');
215
    }
216
    return '';
217
}
218
219
/**
220
 * Print a detailed representation of what a user has done with
221
 * a given particular instance of this module, for user activity reports.
222
 *
223
 * @return bool
224
 */
225
function bigbluebuttonbn_user_complete($course, $user, $mod, $bigbluebuttonbn) {
0 ignored issues
show
Unused Code introduced by
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...
226
    global $DB;
227
    $completed = $DB->count_recorda('bigbluebuttonbn_logs', array('courseid' => $course->id,
228
                                                              'bigbluebuttonbnid' => $bigbluebuttonbn->id,
229
                                                              'userid' => $user->id,
230
                                                              'log' => 'Join', ), '*', IGNORE_MULTIPLE);
231
    return $completed > 0;
232
}
233
234
/**
235
 * Returns all other caps used in module.
236
 *
237
 * @return string[]
238
 */
239
function bigbluebuttonbn_get_extra_capabilities() {
240
    return array('moodle/site:accessallgroups');
241
}
242
243
/**
244
 * List of view style log actions.
245
 *
246
 * @return string[]
247
 */
248
function bigbluebuttonbn_get_view_actions() {
249
    return array('view', 'view all');
250
}
251
252
/**
253
 * List of update style log actions.
254
 *
255
 * @return string[]
256
 */
257
function bigbluebuttonbn_get_post_actions() {
258
    return array('update', 'add', 'create', 'join', 'end', 'left', 'publish', 'unpublish', 'delete');
259
}
260
261
/**
262
 * @global object
263
 * @global object
264
 *
265
 * @param array $courses
266
 * @param array $htmlarray Passed by reference
267
 */
268
function bigbluebuttonbn_print_overview($courses, &$htmlarray) {
269
270
    if (empty($courses) || !is_array($courses) || count($courses) == 0) {
271
        return array();
272
    }
273
274
    $bns = get_all_instances_in_courses('bigbluebuttonbn', $courses);
275
276
    foreach ($bns as $bn) {
277
        $now = time();
278
        if ($bn->openingtime and (!$bn->closingtime or $bn->closingtime > $now)) {
279
            // A bigbluebuttonbn is scheduled.
280
            if (empty($htmlarray[$bn->course]['bigbluebuttonbn'])) {
281
                $htmlarray[$bn->course]['bigbluebuttonbn'] = '';
282
            }
283
            $htmlarray[$bn->course]['bigbluebuttonbn'] = bigbluebuttonbn_print_overview_element($bn, $now);
284
        }
285
    }
286
}
287
288
function bigbluebuttonbn_print_overview_element($bigbluebuttonbn, $now) {
289
    global $CFG;
290
291
    $start = 'started_at';
292
    if ($bigbluebuttonbn->openingtime > $now) {
293
        $start = 'starts_at';
294
    }
295
    $classes = '';
296
    if ($bigbluebuttonbn->visible) {
297
        $classes = 'class="dimmed" ';
298
    }
299
    $str = '<div class="bigbluebuttonbn overview">'."\n";
300
    $str .= '  <div class="name">'.get_string('modulename', 'bigbluebuttonbn').':&nbsp;'."\n";
301
    $str .= '    <a '.$classes.'href="'.$CFG->wwwroot.'/mod/bigbluebuttonbn/view.php?id='.$bigbluebuttonbn->coursemodule.
302
      '">'.$bigbluebuttonbn->name.'</a>'."\n";
303
    $str .= '  </div>'."\n";
304
    $str .= '  <div class="info">'.get_string($start, 'bigbluebuttonbn').': '.userdate($bigbluebuttonbn->openingtime).
305
        '</div>'."\n";
306
    $str .= '  <div class="info">'.get_string('ends_at', 'bigbluebuttonbn').': '.userdate($bigbluebuttonbn->closingtime)
307
      .'</div>'."\n";
308
    $str .= '</div>'."\n";
309
310
    return $str;
311
}
312
313
/**
314
 * Given a course_module object, this function returns any
315
 * "extra" information that may be needed when printing
316
 * this activity in a course listing.
317
 * See get_array_of_activities() in course/lib.php.
318
 *
319
 * @global object
320
 *
321
 * @param object $coursemodule
322
 *
323
 * @return null|cached_cm_info
324
 */
325
function bigbluebuttonbn_get_coursemodule_info($coursemodule) {
326
    global $DB;
327
328
    $bigbluebuttonbn = $DB->get_record('bigbluebuttonbn', array('id' => $coursemodule->instance),
329
        'id, name, intro, introformat');
330
    if (!$bigbluebuttonbn) {
331
        return null;
332
    }
333
334
    $info = new cached_cm_info();
335
    $info->name = $bigbluebuttonbn->name;
336
337
    if ($coursemodule->showdescription) {
338
        // Convert intro to html. Do not filter cached version, filters run at display time.
339
        $info->content = format_module_intro('bigbluebuttonbn', $bigbluebuttonbn, $coursemodule->id, false);
340
    }
341
342
    return $info;
343
}
344
345
/**
346
 * Runs any processes that must run before
347
 * a bigbluebuttonbn insert/update.
348
 *
349
 * @global object
350
 *
351
 * @param object $bigbluebuttonbn BigBlueButtonBN form data
352
 **/
353
function bigbluebuttonbn_process_pre_save(&$bigbluebuttonbn) {
354
    $bigbluebuttonbn->timemodified = time();
355
356
    if (!isset($bigbluebuttonbn->timecreated) || !$bigbluebuttonbn->timecreated) {
357
        $bigbluebuttonbn->timecreated = time();
358
        // Assign password only if it is a new activity.
359
        $bigbluebuttonbn->moderatorpass = bigbluebuttonbn_random_password(12);
360
        $bigbluebuttonbn->viewerpass = bigbluebuttonbn_random_password(12);
361
        $bigbluebuttonbn->timemodified = 0;
362
    }
363
364
    if (!isset($bigbluebuttonbn->wait)) {
365
        $bigbluebuttonbn->wait = 0;
366
    }
367
    if (!isset($bigbluebuttonbn->record)) {
368
        $bigbluebuttonbn->record = 0;
369
    }
370
    if (!isset($bigbluebuttonbn->recordings_html)) {
371
        $bigbluebuttonbn->recordings_html = 0;
372
    }
373
    if (!isset($bigbluebuttonbn->recordings_deleted)) {
374
        $bigbluebuttonbn->recordings_deleted = 0;
375
    }
376
    if (!isset($bigbluebuttonbn->recordings_imported)) {
377
        $bigbluebuttonbn->recordings_imported = 0;
378
    }
379
380
    $bigbluebuttonbn->participants = htmlspecialchars_decode($bigbluebuttonbn->participants);
381
}
382
383
/**
384
 * Runs any processes that must be run
385
 * after a bigbluebuttonbn insert/update.
386
 *
387
 * @global object
388
 *
389
 * @param object $bigbluebuttonbn BigBlueButtonBN form data
390
 **/
391
function bigbluebuttonbn_process_post_save(&$bigbluebuttonbn) {
392
    global $DB, $CFG;
393
394
    $action = get_string('mod_form_field_notification_msg_modified', 'bigbluebuttonbn');
395
396
    /* Now that an id was assigned, generate and set the meetingid property based on
397
     * [Moodle Instance + Activity ID + BBB Secret] (but only for new activities) */
398
    if (isset($bigbluebuttonbn->add) && !empty($bigbluebuttonbn->add)) {
399
        $meetingid = sha1($CFG->wwwroot.$bigbluebuttonbn->id.\mod_bigbluebuttonbn\locallib\config::get('shared_secret'));
400
        $DB->set_field('bigbluebuttonbn', 'meetingid', $meetingid, array('id' => $bigbluebuttonbn->id));
401
402
        $action = get_string('mod_form_field_notification_msg_created', 'bigbluebuttonbn');
403
    }
404
405
    bigbluebuttonbn_process_post_save_event($bigbluebuttonbn);
406
407
    if (isset($bigbluebuttonbn->notification) && $bigbluebuttonbn->notification) {
408
        $context = context_course::instance($bigbluebuttonbn->course);
409
        \mod_bigbluebuttonbn\locallib\notifier::notification_process($context, $bigbluebuttonbn, $action);
410
    }
411
}
412
413
/**
414
 * Generates an event after a bigbluebuttonbn insert/update.
415
 *
416
 * @global object
417
 *
418
 * @param object $bigbluebuttonbn BigBlueButtonBN form data
419
 **/
420
function bigbluebuttonbn_process_post_save_event(&$bigbluebuttonbn) {
421
    global $DB;
422
423
    // Delete evento to the calendar when/if openingtime is NOT set.
424
    if (!isset($bigbluebuttonbn->openingtime) || !$bigbluebuttonbn->openingtime) {
425
        $DB->delete_records('event', array('modulename' => 'bigbluebuttonbn', 'instance' => $bigbluebuttonbn->id));
426
427
        return;
428
    }
429
430
    // Add evento to the calendar as openingtime is set.
431
    $event = new stdClass();
432
    $event->name = $bigbluebuttonbn->name;
433
    $event->courseid = $bigbluebuttonbn->course;
434
    $event->groupid = 0;
435
    $event->userid = 0;
436
    $event->modulename = 'bigbluebuttonbn';
437
    $event->instance = $bigbluebuttonbn->id;
438
    $event->timestart = $bigbluebuttonbn->openingtime;
439
    $event->durationtime = 0;
440
441
    if ($bigbluebuttonbn->closingtime) {
442
        $event->durationtime = $bigbluebuttonbn->closingtime - $bigbluebuttonbn->openingtime;
443
    }
444
445
    $event->id = $DB->get_field('event', 'id', array('modulename' => 'bigbluebuttonbn',
446
        'instance' => $bigbluebuttonbn->id));
447
    if ($event->id) {
448
        $calendarevent = calendar_event::load($event->id);
449
        $calendarevent->update($event);
450
451
        return;
452
    }
453
454
    calendar_event::create($event);
455
}
456
457
/**
458
 * Update the bigbluebuttonbn activity to include any file
459
 * that was uploaded, or if there is none, set the
460
 * presentation field to blank.
461
 *
462
 * @param int      $bigbluebuttonbnid the bigbluebuttonbn id
463
 * @param stdClass $context            the context
464
 * @param int      $draftitemid        the draft item
465
 */
466
function bigbluebuttonbn_update_media_file($bigbluebuttonbnid, $context, $draftitemid) {
467
    global $DB;
468
469
    // Set the filestorage object.
470
    $fs = get_file_storage();
471
    // Save the file if it exists that is currently in the draft area.
472
    file_save_draft_area_files($draftitemid, $context->id, 'mod_bigbluebuttonbn', 'presentation', 0);
473
    // Get the file if it exists.
474
    $files = $fs->get_area_files($context->id, 'mod_bigbluebuttonbn', 'presentation', 0,
475
        'itemid, filepath, filename', false);
476
    // Check that there is a file to process.
477
    $filesrc = '';
478
    if (count($files) == 1) {
479
        // Get the first (and only) file.
480
        $file = reset($files);
481
        $filesrc = '/'.$file->get_filename();
482
    }
483
    // Set the presentation column in the bigbluebuttonbn table.
484
    $DB->set_field('bigbluebuttonbn', 'presentation', $filesrc, array('id' => $bigbluebuttonbnid));
485
}
486
487
/**
488
 * Serves the bigbluebuttonbn attachments. Implements needed access control ;-).
489
 *
490
 * @category files
491
 *
492
 * @param stdClass $course        course object
493
 * @param stdClass $cm            course module object
494
 * @param stdClass $context       context object
495
 * @param string   $filearea      file area
496
 * @param array    $args          extra arguments
497
 * @param bool     $forcedownload whether or not force download
498
 * @param array    $options       additional options affecting the file serving
499
 *
500
 * @return false|null false if file not found, does not return if found - justsend the file
501
 */
502
function bigbluebuttonbn_pluginfile($course, $cm, $context, $filearea, $args, $forcedownload, array $options = array()) {
503
    if (!bigbluebuttonbn_pluginfile_valid($context, $filearea)) {
504
        return false;
505
    }
506
507
    $file = bigbluebuttonbn_pluginfile_file($course, $cm, $context, $filearea, $args);
508
    if (!$file) {
509
        return false;
510
    }
511
512
    // Finally send the file.
513
    send_stored_file($file, 0, 0, $forcedownload, $options); // download MUST be forced - security!
514
}
515
516
function bigbluebuttonbn_pluginfile_valid($context, $filearea) {
517
    if ($context->contextlevel != CONTEXT_MODULE) {
518
        return false;
519
    }
520
521
    if ($filearea !== 'presentation') {
522
        return false;
523
    }
524
525
    if (!array_key_exists($filearea, bigbluebuttonbn_get_file_areas())) {
526
        return false;
527
    }
528
529
    return true;
530
}
531
532
function bigbluebuttonbn_pluginfile_file($course, $cm, $context, $filearea, $args) {
533
    $filename = bigbluebuttonbn_pluginfile_filename($course, $cm, $context, $args);
534
    if (!$filename) {
535
        return false;
536
    }
537
538
    $fullpath = "/$context->id/mod_bigbluebuttonbn/$filearea/0/".$filename;
539
    $fs = get_file_storage();
540
    $file = $fs->get_file_by_hash(sha1($fullpath));
541
    if (!$file || $file->is_directory()) {
542
        return false;
543
    }
544
545
    return $file;
546
}
547
548
function bigbluebuttonbn_pluginfile_filename($course, $cm, $context, $args) {
549
    global $DB;
550
551
    if (count($args) > 1) {
552
        if (!$bigbluebuttonbn = $DB->get_record('bigbluebuttonbn', array('id' => $cm->instance))) {
553
            return;
554
        }
555
556
        $cache = cache::make_from_params(cache_store::MODE_APPLICATION, 'mod_bigbluebuttonbn', 'presentation_cache');
557
        $noncekey = sha1($bigbluebuttonbn->id);
558
        $presentationnonce = $cache->get($noncekey);
559
        $noncevalue = $presentationnonce['value'];
560
        $noncecounter = $presentationnonce['counter'];
561
562
        if ($args['0'] != $noncevalue) {
563
            return;
564
        }
565
566
        // The nonce value is actually used twice because BigBlueButton reads the file two times.
567
        $noncecounter += 1;
568
        $cache->set($noncekey, array('value' => $noncevalue, 'counter' => $noncecounter));
569
        if ($noncecounter == 2) {
570
            $cache->delete($noncekey);
571
        }
572
573
        return $args['1'];
574
    }
575
576
    require_course_login($course, true, $cm);
577
578
    if (!has_capability('mod/bigbluebuttonbn:join', $context)) {
579
        return;
580
    }
581
582
    return implode('/', $args);
583
}
584
585
/**
586
 * Returns an array of file areas.
587
 *
588
 * @category files
589
 *
590
 * @return array a list of available file areas
591
 */
592
function bigbluebuttonbn_get_file_areas() {
593
    $areas = array();
594
    $areas['presentation'] = get_string('mod_form_block_presentation', 'bigbluebuttonbn');
595
596
    return $areas;
597
}
598