Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 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
defined('MOODLE_INTERNAL') || die;
27
 
28
use core_calendar\action_factory;
29
use core_calendar\local\event\entities\action_interface;
30
use mod_bigbluebuttonbn\completion\custom_completion;
31
use mod_bigbluebuttonbn\extension;
32
use mod_bigbluebuttonbn\instance;
33
use mod_bigbluebuttonbn\local\bigbluebutton;
34
use mod_bigbluebuttonbn\local\exceptions\server_not_available_exception;
35
use mod_bigbluebuttonbn\local\helpers\files;
36
use mod_bigbluebuttonbn\local\helpers\mod_helper;
37
use mod_bigbluebuttonbn\local\helpers\reset;
38
use mod_bigbluebuttonbn\local\proxy\bigbluebutton_proxy;
39
use mod_bigbluebuttonbn\logger;
40
use mod_bigbluebuttonbn\meeting;
41
use mod_bigbluebuttonbn\recording;
42
use mod_bigbluebuttonbn\local\config;
43
 
44
global $CFG;
45
 
46
/**
47
 * Indicates API features that the bigbluebuttonbn supports.
48
 *
49
 * @param string $feature
50
 * @return mixed True if yes (some features may use other values)
51
 * @uses FEATURE_IDNUMBER
52
 * @uses FEATURE_GROUPS
53
 * @uses FEATURE_GROUPINGS
54
 * @uses FEATURE_GROUPMEMBERSONLY
55
 * @uses FEATURE_MOD_INTRO
56
 * @uses FEATURE_BACKUP_MOODLE2
57
 * @uses FEATURE_COMPLETION_TRACKS_VIEWS
58
 * @uses FEATURE_COMPLETION_HAS_RULES
59
 * @uses FEATURE_GRADE_HAS_GRADE
60
 * @uses FEATURE_GRADE_OUTCOMES
61
 * @uses FEATURE_SHOW_DESCRIPTION
62
 */
63
function bigbluebuttonbn_supports($feature) {
64
    if (!$feature) {
65
        return null;
66
    }
67
    $features = [
68
        FEATURE_IDNUMBER => true,
69
        FEATURE_GROUPS => true,
70
        FEATURE_GROUPINGS => true,
71
        FEATURE_MOD_INTRO => true,
72
        FEATURE_BACKUP_MOODLE2 => true,
73
        FEATURE_COMPLETION_TRACKS_VIEWS => true,
74
        FEATURE_COMPLETION_HAS_RULES => true,
75
        FEATURE_GRADE_HAS_GRADE => false,
76
        FEATURE_GRADE_OUTCOMES => false,
77
        FEATURE_SHOW_DESCRIPTION => true,
78
        FEATURE_MOD_PURPOSE => MOD_PURPOSE_COMMUNICATION,
79
    ];
80
    if (isset($features[(string) $feature])) {
81
        return $features[$feature];
82
    }
83
    return null;
84
}
85
 
86
/**
87
 * Given an object containing all the necessary data,
88
 * (defined by the form in mod_form.php) this function
89
 * will create a new instance and return the id number
90
 * of the new instance.
91
 *
92
 * @param stdClass $bigbluebuttonbn An object from the form in mod_form.php
93
 * @return int The id of the newly inserted bigbluebuttonbn record
94
 */
95
function bigbluebuttonbn_add_instance($bigbluebuttonbn) {
96
    global $DB;
97
    // Excecute preprocess.
98
    mod_helper::process_pre_save($bigbluebuttonbn);
99
    // Pre-set initial values.
100
    $bigbluebuttonbn->presentation = files::save_media_file($bigbluebuttonbn);
101
    // Encode meetingid.
102
    $bigbluebuttonbn->meetingid = meeting::get_unique_meetingid_seed();
103
    [$bigbluebuttonbn->guestlinkuid, $bigbluebuttonbn->guestpassword] =
104
        \mod_bigbluebuttonbn\plugin::generate_guest_meeting_credentials();
105
    // Insert a record.
106
    $bigbluebuttonbn->id = $DB->insert_record('bigbluebuttonbn', $bigbluebuttonbn);
107
    // Log insert action.
108
    logger::log_instance_created($bigbluebuttonbn);
109
    // Complete the process.
110
    mod_helper::process_post_save($bigbluebuttonbn);
111
 
112
    // Call any active subplugin so to signal a new creation.
113
    extension::add_instance($bigbluebuttonbn);
114
    return $bigbluebuttonbn->id;
115
}
116
 
117
/**
118
 * Given an object containing all the necessary data,
119
 * (defined by the form in mod_form.php) this function
120
 * will update an existing instance with new data.
121
 *
122
 * @param stdClass $bigbluebuttonbn An object from the form in mod_form.php
123
 * @return bool Success/Fail
124
 */
125
function bigbluebuttonbn_update_instance($bigbluebuttonbn) {
126
    global $DB;
127
    // Excecute preprocess.
128
    mod_helper::process_pre_save($bigbluebuttonbn);
129
 
130
    // Pre-set initial values.
131
    $bigbluebuttonbn->id = $bigbluebuttonbn->instance;
132
    $bigbluebuttonbn->presentation = files::save_media_file($bigbluebuttonbn);
133
 
134
    if (empty($bigbluebuttonbn->guestjoinurl) || empty($bigbluebuttonbn->guestpassword)) {
135
        [$bigbluebuttonbn->guestlinkuid, $bigbluebuttonbn->guestpassword] =
136
            \mod_bigbluebuttonbn\plugin::generate_guest_meeting_credentials();
137
    }
138
    // Update a record.
139
    $DB->update_record('bigbluebuttonbn', $bigbluebuttonbn);
140
 
141
    // Get the meetingid column in the bigbluebuttonbn table.
142
    $bigbluebuttonbn->meetingid = (string) $DB->get_field('bigbluebuttonbn', 'meetingid', ['id' => $bigbluebuttonbn->id]);
143
 
144
    // Log update action.
145
    logger::log_instance_updated(instance::get_from_instanceid($bigbluebuttonbn->id));
146
 
147
    // Complete the process.
148
    mod_helper::process_post_save($bigbluebuttonbn);
149
    // Call any active subplugin so to signal update.
150
    extension::update_instance($bigbluebuttonbn);
151
    return true;
152
}
153
 
154
/**
155
 * Given an ID of an instance of this module,
156
 * this function will permanently delete the instance
157
 * and any data that depends on it.
158
 *
159
 * @param int $id Id of the module instance
160
 *
161
 * @return bool Success/Failure
162
 */
163
function bigbluebuttonbn_delete_instance($id) {
164
    global $DB;
165
 
166
    $instance = instance::get_from_instanceid($id);
167
    if (empty($instance)) {
168
        return false;
169
    }
170
    // End all meeting if any still running.
171
    try {
172
        $meeting = new meeting($instance);
173
        $meeting->end_meeting();
174
    } catch (moodle_exception $e) {
175
        // Do not log any issue when testing.
176
        if (!(defined('PHPUNIT_TEST') && PHPUNIT_TEST) && !defined('BEHAT_SITE_RUNNING')) {
177
            debugging($e->getMessage(), DEBUG_DEVELOPER, $e->getTrace());
178
        }
179
    }
180
    // Get all possible groups (course and course module).
181
    $groupids = [];
182
    if (groups_get_activity_groupmode($instance->get_cm())) {
183
        $coursegroups = groups_get_activity_allowed_groups($instance->get_cm());
184
        $groupids = array_map(
185
            function($gp) {
186
                return $gp->id;
187
            },
188
            $coursegroups);
189
    }
190
    // End all meetings for all groups.
191
    foreach ($groupids as $groupid) {
192
        try {
193
            $instance->set_group_id($groupid);
194
            $meeting = new meeting($instance);
195
            $meeting->end_meeting();
196
        } catch (moodle_exception $e) {
197
            debugging($e->getMessage() . ' for group ' . $groupid, DEBUG_NORMAL, $e->getTrace());
198
        }
199
    }
200
 
201
    $result = true;
202
 
203
    // Call any active subplugin so to signal deletion.
204
    extension::delete_instance($id);
205
 
206
    // Delete the instance.
207
    if (!$DB->delete_records('bigbluebuttonbn', ['id' => $id])) {
208
        $result = false;
209
    }
210
 
211
    // Delete dependant events.
212
    if (!$DB->delete_records('event', ['modulename' => 'bigbluebuttonbn', 'instance' => $id])) {
213
        $result = false;
214
    }
215
 
216
    // Log action performed.
217
    logger::log_instance_deleted($instance);
218
 
219
    // Mark dependent recordings as headless.
220
    foreach (recording::get_records(['bigbluebuttonbnid' => $id]) as $recording) {
221
        $recording->set('headless', recording::RECORDING_HEADLESS);
222
        $recording->update();
223
    }
224
 
225
    return $result;
226
}
227
 
228
/**
229
 * Return a small object with summary information about what a
230
 * user has done with a given particular instance of this module
231
 * Used for user activity reports.
232
 *
233
 * @param stdClass $course
234
 * @param stdClass $user
235
 * @param cm_info $mod
236
 * @param stdClass $bigbluebuttonbn
237
 *
238
 * @return stdClass with info and time (timestamp of the last log)
239
 */
240
function bigbluebuttonbn_user_outline(stdClass $course, stdClass $user, cm_info $mod, stdClass $bigbluebuttonbn): stdClass {
241
    [$infos, $logtimestamps] = \mod_bigbluebuttonbn\local\helpers\user_info::get_user_info_outline($course, $user, $mod);
242
    return (object) [
243
        'info' => join(',', $infos),
244
        'time' => !empty($logtimestamps) ? max($logtimestamps) : 0
245
    ];
246
}
247
 
248
/**
249
 * Print a detailed representation of what a user has done with
250
 * a given particular instance of this module, for user activity reports.
251
 *
252
 * @param stdClass $course
253
 * @param stdClass $user
254
 * @param cm_info $mod
255
 * @param stdClass $bigbluebuttonbn
256
 *
257
 */
258
function bigbluebuttonbn_user_complete(stdClass $course, stdClass $user, cm_info $mod, stdClass $bigbluebuttonbn) {
259
    [$infos] = \mod_bigbluebuttonbn\local\helpers\user_info::get_user_info_outline($course, $user, $mod);
260
    echo join(', ', $infos);
261
}
262
 
263
/**
264
 * This flags this module with the capability to override the completion status with the custom completion rules.
265
 *
266
 *
267
 * @return int
268
 */
269
function bigbluebuttonbn_get_completion_aggregation_state() {
270
    return COMPLETION_CUSTOM_MODULE_FLOW;
271
}
272
 
273
/**
274
 * Returns all other caps used in module.
275
 *
276
 * @return string[]
277
 */
278
function bigbluebuttonbn_get_extra_capabilities() {
279
    return ['moodle/site:accessallgroups'];
280
}
281
 
282
/**
283
 * Called by course/reset.php
284
 *
285
 * @param MoodleQuickForm $mform
286
 */
287
function bigbluebuttonbn_reset_course_form_definition(&$mform) {
288
    $items = reset::reset_course_items();
289
    $mform->addElement('header', 'bigbluebuttonbnheader', get_string('modulenameplural', 'bigbluebuttonbn'));
290
    foreach ($items as $item => $default) {
291
        $mform->addElement(
292
            'advcheckbox',
293
            "reset_bigbluebuttonbn_{$item}",
294
            get_string("reset{$item}", 'bigbluebuttonbn')
295
        );
296
        if ($item == 'logs' || $item == 'recordings') {
297
            $mform->addHelpButton("reset_bigbluebuttonbn_{$item}", "reset{$item}", 'bigbluebuttonbn');
298
        }
299
    }
300
}
301
 
302
/**
303
 * Course reset form defaults.
304
 *
305
 * @param stdClass $course
306
 * @return array
307
 */
308
function bigbluebuttonbn_reset_course_form_defaults(stdClass $course) {
309
    $formdefaults = [];
310
    $items = reset::reset_course_items();
311
    // All unchecked by default.
312
    foreach ($items as $item => $default) {
313
        $formdefaults["reset_bigbluebuttonbn_{$item}"] = $default;
314
    }
315
    return $formdefaults;
316
}
317
 
318
/**
319
 * This function is used by the reset_course_userdata function in moodlelib.
320
 *
321
 * @param stdClass $data the data submitted from the reset course.
322
 * @return array status array
323
 */
324
function bigbluebuttonbn_reset_userdata(stdClass $data) {
325
    $items = reset::reset_course_items();
326
    $status = [];
327
 
328
    // Any changes to the list of dates that needs to be rolled should be same during course restore and course reset.
329
    // See MDL-9367.
330
    if (array_key_exists('recordings', $items) && !empty($data->reset_bigbluebuttonbn_recordings)) {
331
        // Remove all the recordings from a BBB server that are linked to the room/activities in this course.
332
        reset::reset_recordings($data->courseid);
333
        unset($items['recordings']);
334
        $status[] = reset::reset_getstatus('recordings');
335
    }
336
 
337
    if (!empty($data->reset_bigbluebuttonbn_tags)) {
338
        // Remove all the tags linked to the room/activities in this course.
339
        reset::reset_tags($data->courseid);
340
        unset($items['tags']);
341
        $status[] = reset::reset_getstatus('tags');
342
    }
343
 
344
    if (!empty($data->reset_bigbluebuttonbn_logs)) {
345
        // Remove all the tags linked to the room/activities in this course.
346
        reset::reset_logs($data->courseid);
347
        unset($items['logs']);
348
        $status[] = reset::reset_getstatus('logs');
349
    }
350
    return $status;
351
}
352
 
353
/**
354
 * Given a course_module object, this function returns any
355
 * "extra" information that may be needed when printing
356
 * this activity in a course listing.
357
 * See get_array_of_activities() in course/lib.php.
358
 *
359
 * @param stdClass $coursemodule
360
 *
361
 * @return null|cached_cm_info
362
 */
363
function bigbluebuttonbn_get_coursemodule_info($coursemodule) {
364
    $instance = instance::get_from_instanceid($coursemodule->instance);
365
    if (empty($instance)) {
366
        return null;
367
    }
368
    $info = new cached_cm_info();
369
    // Warning here: if any of the instance method calls ::get_cm this will result is a recursive call.
370
    // So best is just to access instance variables not linked to the cm.
371
    $info->name = $instance->get_instance_var('name');
372
    if ($coursemodule->showdescription) {
373
        // Convert intro to html. Do not filter cached version, filters run at display time.
374
        $info->content = format_module_intro('bigbluebuttonbn', $instance->get_instance_data(), $coursemodule->id, false);
375
    }
376
    $customcompletionfields = custom_completion::get_defined_custom_rules();
377
    // Populate the custom completion rules as key => value pairs, but only if the completion mode is 'automatic'.
378
    if ($coursemodule->completion == COMPLETION_TRACKING_AUTOMATIC) {
379
        foreach ($customcompletionfields as $completiontype) {
380
            $info->customdata['customcompletionrules'][$completiontype] =
381
                $instance->get_instance_var($completiontype) ?? 0;
382
        }
383
    }
384
 
385
    return $info;
386
}
387
 
388
/**
389
 * Serves the bigbluebuttonbn attachments. Implements needed access control ;-).
390
 *
391
 * @param stdClass $course course object
392
 * @param stdClass $cm course module object
393
 * @param context $context context object
394
 * @param string $filearea file area
395
 * @param array $args extra arguments
396
 * @param bool $forcedownload whether or not force download
397
 * @param array $options additional options affecting the file serving
398
 *
399
 * @return false|null false if file not found, does not return if found - justsend the file
400
 * @category files
401
 *
402
 */
403
function bigbluebuttonbn_pluginfile($course, $cm, $context, $filearea, $args, $forcedownload, array $options = []) {
404
    if (!files::pluginfile_valid($context, $filearea)) {
405
        return false;
406
    }
407
    $file = files::pluginfile_file($course, $cm, $context, $filearea, $args);
408
    if (empty($file)) {
409
        return false;
410
    }
411
    // Finally send the file.
412
    return send_stored_file($file, 0, 0, $forcedownload, $options); // Download MUST be forced - security!
413
}
414
 
415
/**
416
 * Mark the activity completed (if required) and trigger the course_module_viewed event.
417
 *
418
 * @param stdClass $bigbluebuttonbn bigbluebuttonbn object
419
 * @param stdClass $course course object
420
 * @param cm_info $cm course module object
421
 * @param context $context context object
422
 * @since Moodle 3.0
423
 */
424
function bigbluebuttonbn_view($bigbluebuttonbn, $course, $cm, $context) {
425
 
426
    // Trigger course_module_viewed event.
427
    $params = [
428
        'context' => $context,
429
        'objectid' => $bigbluebuttonbn->id
430
    ];
431
 
432
    $event = \mod_bigbluebuttonbn\event\course_module_viewed::create($params); // Fix event name.
433
    $cmrecord = $cm->get_course_module_record();
434
    $event->add_record_snapshot('course_modules', $cmrecord);
435
    $event->add_record_snapshot('course', $course);
436
    $event->add_record_snapshot('bigbluebuttonbn', $bigbluebuttonbn);
437
    $event->trigger();
438
 
439
    // Completion.
440
    $completion = new completion_info($course);
441
    $completion->set_module_viewed($cm);
442
}
443
 
444
/**
445
 * Check if the module has any update that affects the current user since a given time.
446
 *
447
 * @param cm_info $cm course module data
448
 * @param int $from the time to check updates from
449
 * @param array $filter if we need to check only specific updates
450
 * @return stdClass an object with the different type of areas indicating if they were updated or not
451
 * @since Moodle 3.2
452
 */
453
function bigbluebuttonbn_check_updates_since(cm_info $cm, $from, $filter = []) {
454
    $updates = course_check_module_updates_since($cm, $from, ['content'], $filter);
455
    return $updates;
456
}
457
 
458
/**
459
 * This function receives a calendar event and returns the action associated with it, or null if there is none.
460
 *
461
 * This is used by block_myoverview in order to display the event appropriately. If null is returned then the event
462
 * is not displayed on the block.
463
 *
464
 * @param calendar_event $event
465
 * @param action_factory $factory
466
 * @return action_interface|null
467
 */
468
function mod_bigbluebuttonbn_core_calendar_provide_event_action(
469
    calendar_event $event,
470
    action_factory $factory
471
) {
472
    global $DB;
473
 
474
    $time = time();
475
 
476
    // Get mod info.
477
    $cm = get_fast_modinfo($event->courseid)->instances['bigbluebuttonbn'][$event->instance];
478
 
479
    // Get bigbluebuttonbn activity.
480
    $bigbluebuttonbn = $DB->get_record('bigbluebuttonbn', ['id' => $event->instance], '*', MUST_EXIST);
481
 
482
    // Set flag haspassed if closingtime has already passed only if it is defined.
483
    $haspassed = ($bigbluebuttonbn->closingtime) && $bigbluebuttonbn->closingtime < $time;
484
 
485
    // Set flag hasstarted if startingtime has already passed or not defined.
486
    $hasstarted = $bigbluebuttonbn->openingtime < $time;
487
 
488
    // Return null if it has passed or not started.
489
    if ($haspassed || !$hasstarted) {
490
        return null;
491
    }
492
 
493
    // Get if the user has joined in live session or viewed the recorded.
494
    $customcompletion = new custom_completion($cm, $event->userid);
495
    $usercomplete = $customcompletion->get_overall_completion_state();
496
    $instance = instance::get_from_instanceid($bigbluebuttonbn->id);
497
    // Get if the room is available.
498
    $roomavailable = $instance->is_currently_open();
499
 
500
    $meetinginfo = null;
501
    // Check first if the server can be contacted.
502
    try {
503
        if (empty(bigbluebutton_proxy::get_server_version())) {
504
            // In this case we should already have debugging message printed.
505
            return null;
506
        }
507
        // Get if the user can join.
508
        $meetinginfo = meeting::get_meeting_info_for_instance($instance);
509
    } catch (moodle_exception $e) {
510
        debugging('Error - Cannot retrieve info from meeting ('.$instance->get_meeting_id().') ' . $e->getMessage());
511
        return null;
512
    }
513
    $usercanjoin = $meetinginfo->canjoin;
514
 
515
    // Check if the room is closed and the user has already joined this session or played the record.
516
    if (!$roomavailable && $usercomplete) {
517
        return null;
518
    }
519
 
520
    // Check if the user can join this session.
521
    $actionable = ($roomavailable && $usercanjoin);
522
 
523
    // Action data.
524
    $string = get_string('view_room', 'bigbluebuttonbn');
525
    $url = new moodle_url('/mod/bigbluebuttonbn/view.php', ['id' => $cm->id]);
526
    if (groups_get_activity_groupmode($cm) == NOGROUPS) {
527
        // No groups mode.
528
        $string = get_string('view_conference_action_join', 'bigbluebuttonbn');
529
        $url = new moodle_url('/mod/bigbluebuttonbn/bbb_view.php', [
530
                'action' => 'join',
531
                'id' => $cm->id,
532
                'bn' => $bigbluebuttonbn->id,
533
                'timeline' => 1]
534
        );
535
    }
536
 
537
    return $factory->create_instance($string, $url, 1, $actionable);
538
}
539
 
540
/**
541
 * Is the event visible?
542
 *
543
 * @param calendar_event $event
544
 * @return bool Returns true if the event is visible to the current user, false otherwise.
545
 */
546
function mod_bigbluebuttonbn_core_calendar_is_event_visible(calendar_event $event) {
547
    $instance = instance::get_from_instanceid($event->instance);
548
    if (!$instance) {
549
        return false;
550
    }
551
    $activitystatus = mod_bigbluebuttonbn\local\proxy\bigbluebutton_proxy::view_get_activity_status($instance);
552
    return $activitystatus != 'ended';
553
}
554
 
555
/**
556
 * Adds module specific settings to the settings block
557
 *
558
 * @param settings_navigation $settingsnav The settings navigation object
559
 * @param navigation_node $nodenav The node to add module settings to
560
 */
561
function bigbluebuttonbn_extend_settings_navigation(settings_navigation $settingsnav, navigation_node $nodenav) {
562
    global $USER;
563
    // Don't add validate completion if the callback for meetingevents is NOT enabled.
564
    if (!(boolean) \mod_bigbluebuttonbn\local\config::get('meetingevents_enabled')) {
565
        return;
566
    }
567
    // Don't add validate completion if user is not allowed to edit the activity.
568
    $context = context_module::instance($settingsnav->get_page()->cm->id);
569
    if (!has_capability('moodle/course:manageactivities', $context, $USER->id)) {
570
        return;
571
    }
572
    $completionvalidate = '#action=completion_validate&bigbluebuttonbn=' . $settingsnav->get_page()->cm->instance;
573
    $nodenav->add(get_string('completionvalidatestate', 'bigbluebuttonbn'),
574
        $completionvalidate, navigation_node::TYPE_CONTAINER);
575
}
576
 
577
/**
578
 * In place editable for the recording table
579
 *
580
 * @param string $itemtype
581
 * @param string $itemid
582
 * @param mixed $newvalue
583
 * @return mixed|null
584
 */
585
function bigbluebuttonbn_inplace_editable($itemtype, $itemid, $newvalue) {
586
    $editableclass = "\\mod_bigbluebuttonbn\\output\\recording_{$itemtype}_editable";
587
    if (class_exists($editableclass)) {
588
        return call_user_func([$editableclass, 'update'], $itemid, $newvalue);
589
    }
590
    return null; // Will raise an exception in core update_inplace_editable method.
591
}
592
 
593
/**
594
 * Returns all events since a given time in specified bigbluebutton activity.
595
 * We focus here on the two events: play and join.
596
 *
597
 * @param array $activities
598
 * @param int $index
599
 * @param int $timestart
600
 * @param int $courseid
601
 * @param int $cmid
602
 * @param int $userid
603
 * @param int $groupid
604
 * @return array
605
 */
606
function bigbluebuttonbn_get_recent_mod_activity(&$activities, &$index, $timestart, $courseid, $cmid, $userid = 0,
607
    $groupid = 0): array {
608
    $instance = instance::get_from_cmid($cmid);
609
    $instance->set_group_id($groupid);
610
    $cm = $instance->get_cm();
611
    $logs =
612
        logger::get_user_completion_logs_with_userfields($instance,
613
            $userid ?? null,
614
            [logger::EVENT_JOIN, logger::EVENT_PLAYED],
615
            $timestart);
616
 
617
    foreach ($logs as $log) {
618
        $activity = new stdClass();
619
 
620
        $activity->type = 'bigbluebuttonbn';
621
        $activity->cmid = $cm->id;
622
        $activity->name = format_string($instance->get_meeting_name(), true);
623
        $activity->sectionnum = $cm->sectionnum;
624
        $activity->timestamp = $log->timecreated;
625
        $activity->user = new stdClass();
626
        $userfields = explode(',', implode(',', \core_user\fields::get_picture_fields()));
627
        foreach ($userfields as $userfield) {
628
            if ($userfield == 'id') {
629
                // Aliased in SQL above.
630
                $activity->user->{$userfield} = $log->userid;
631
            } else {
632
                $activity->user->{$userfield} = $log->{$userfield};
633
            }
634
        }
635
        $activity->user->fullname = fullname($log);
636
        $activity->content = '';
637
        $activity->eventname = logger::get_printable_event_name($log);
638
        if ($log->log == logger::EVENT_PLAYED) {
639
            if (!empty($log->meta)) {
640
                $meta = json_decode($log->meta);
641
                if (!empty($meta->recordingid)) {
642
                    $recording = recording::get_record(['id' => $meta->recordingid]);
643
                    if ($recording) {
644
                        $activity->content = $recording->get('name');
645
                    }
646
                }
647
            }
648
        }
649
        $activities[$index++] = $activity;
650
    }
651
    return $activities;
652
}
653
 
654
/**
655
 * Outputs the bigbluebutton logs indicated by $activity.
656
 *
657
 * @param stdClass $activity the activity object the bigbluebuttonbn resides in
658
 * @param int $courseid the id of the course the bigbluebuttonbn resides in
659
 * @param bool $detail not used, but required for compatibilty with other modules
660
 * @param array $modnames not used, but required for compatibilty with other modules
661
 * @param bool $viewfullnames not used, but required for compatibilty with other modules
662
 */
663
function bigbluebuttonbn_print_recent_mod_activity(stdClass $activity, int $courseid, bool $detail, array $modnames,
664
    bool $viewfullnames) {
665
    global $OUTPUT;
666
    $modinfo = [];
667
    $userpicture = $OUTPUT->user_picture($activity->user);
668
 
669
    $template = ['userpicture' => $userpicture,
670
        'submissiontimestamp' => $activity->timestamp,
671
        'modinfo' => $modinfo,
672
        'userurl' => new moodle_url('/user/view.php', array('id' => $activity->user->id, 'course' => $courseid)),
673
        'fullname' => $activity->user->fullname];
674
    if (isset($activity->eventname)) {
675
        $template['eventname'] = $activity->eventname;
676
    }
677
    echo $OUTPUT->render_from_template('mod_bigbluebuttonbn/recentactivity', $template);
678
}
679
 
680
/**
681
 * Given a course and a date, prints a summary of all the activity for this module
682
 *
683
 * @param object $course
684
 * @param bool $viewfullnames capability
685
 * @param int $timestart
686
 * @return bool success
687
 */
688
function bigbluebuttonbn_print_recent_activity(object $course, bool $viewfullnames, int $timestart): bool {
689
    global $OUTPUT;
690
    $modinfo = get_fast_modinfo($course);
691
    if (empty($modinfo->instances['bigbluebuttonbn'])) {
692
        return true;
693
    }
694
    $out = '';
695
    foreach ($modinfo->instances['bigbluebuttonbn'] as $cm) {
696
        if (!$cm->uservisible) {
697
            continue;
698
        }
699
        $instance = instance::get_from_cmid($cm->id);
700
        $logs = logger::get_user_completion_logs_with_userfields($instance,
701
            null,
702
            [logger::EVENT_JOIN, logger::EVENT_PLAYED],
703
            $timestart);
704
        if ($logs) {
705
            echo $OUTPUT->heading(get_string('new_bigblubuttonbn_activities', 'bigbluebuttonbn') . ':', 6);
706
            foreach ($logs as $log) {
707
                $activityurl = new moodle_url('/mod/bigbluebuttonbn/index.php', ['id' => $course->id]);
708
                print_recent_activity_note($log->timecreated,
709
                    $log,
710
                    logger::get_printable_event_name($log) . ' - ' . $instance->get_meeting_name(),
711
                    $activityurl->out(),
712
                    false,
713
                    $viewfullnames);
714
            }
715
        }
716
 
717
        echo $out;
718
    }
719
    return true;
720
}
721
 
722
 
723
/**
724
 * Creates a number of BigblueButtonBN activities.
725
 *
726
 * @param tool_generator_course_backend $backend
727
 * @param testing_data_generator $generator
728
 * @param int $courseid
729
 * @param int $number
730
 * @return void
731
 */
732
function bigbluebuttonbn_course_backend_generator_create_activity(tool_generator_course_backend $backend,
733
    testing_data_generator $generator,
734
    int $courseid,
735
    int $number
736
) {
737
    // Set up generator.
738
    $bbbgenerator = $generator->get_plugin_generator('mod_bigbluebuttonbn');
739
 
740
    // Create assignments.
741
    $backend->log('createbigbluebuttonbn', $number, true, 'mod_bigbluebuttonbn');
742
    for ($i = 0; $i < $number; $i++) {
743
        $record = array('course' => $courseid);
744
        $options = array('section' => $backend->get_target_section());
745
        $bbbgenerator->create_instance($record, $options);
746
        $backend->dot($i, $number);
747
    }
748
    $backend->end_log();
749
}
750
 
751
/**
752
 * Whether the activity is branded.
753
 * This information is used, for instance, to decide if a filter should be applied to the icon or not.
754
 *
755
 * @return bool True if the activity is branded, false otherwise.
756
 */
757
function bigbluebuttonbn_is_branded(): bool {
758
    return true;
759
}