Differences Between: [Versions 400 and 403] [Versions 401 and 403] [Versions 402 and 403]
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_OTHER 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 * Callback method executed prior to enabling the activity module. 724 * 725 * @return bool Whether to proceed and enable the plugin or not. 726 */ 727 function bigbluebuttonbn_pre_enable_plugin_actions(): bool { 728 global $PAGE; 729 730 // If the default server configuration is used and the administrator has not accepted the default data processing 731 // agreement, do not enable the plugin. Instead, display a dynamic form where the administrator can confirm that he 732 // accepts the DPA prior to enabling the plugin. 733 if (config::get('server_url') === config::DEFAULT_SERVER_URL && !config::get('default_dpa_accepted')) { 734 $url = new moodle_url('/admin/category.php', ['category' => 'modbigbluebuttonbnfolder']); 735 \core\notification::add( 736 get_string('dpainfonotsigned', 'mod_bigbluebuttonbn', $url->out(false)), 737 \core\notification::ERROR 738 ); 739 return false; 740 } 741 // Otherwise, continue and enable the plugin. 742 return true; 743 } 744 745 /** 746 * Creates a number of BigblueButtonBN activities. 747 * 748 * @param tool_generator_course_backend $backend 749 * @param testing_data_generator $generator 750 * @param int $courseid 751 * @param int $number 752 * @return void 753 */ 754 function bigbluebuttonbn_course_backend_generator_create_activity(tool_generator_course_backend $backend, 755 testing_data_generator $generator, 756 int $courseid, 757 int $number 758 ) { 759 // Set up generator. 760 $bbbgenerator = $generator->get_plugin_generator('mod_bigbluebuttonbn'); 761 762 // Create assignments. 763 $backend->log('createbigbluebuttonbn', $number, true, 'mod_bigbluebuttonbn'); 764 for ($i = 0; $i < $number; $i++) { 765 $record = array('course' => $courseid); 766 $options = array('section' => $backend->get_target_section()); 767 $bbbgenerator->create_instance($record, $options); 768 $backend->dot($i, $number); 769 } 770 $backend->end_log(); 771 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body