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