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