See Release Notes
Long Term Support Release
Differences Between: [Versions 310 and 401] [Versions 311 and 401] [Versions 39 and 401] [Versions 400 and 401] [Versions 401 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 // This file is part of BasicLTI4Moodle 18 // 19 // BasicLTI4Moodle is an IMS BasicLTI (Basic Learning Tools for Interoperability) 20 // consumer for Moodle 1.9 and Moodle 2.0. BasicLTI is a IMS Standard that allows web 21 // based learning tools to be easily integrated in LMS as native ones. The IMS BasicLTI 22 // specification is part of the IMS standard Common Cartridge 1.1 Sakai and other main LMS 23 // are already supporting or going to support BasicLTI. This project Implements the consumer 24 // for Moodle. Moodle is a Free Open source Learning Management System by Martin Dougiamas. 25 // BasicLTI4Moodle is a project iniciated and leaded by Ludo(Marc Alier) and Jordi Piguillem 26 // at the GESSI research group at UPC. 27 // SimpleLTI consumer for Moodle is an implementation of the early specification of LTI 28 // by Charles Severance (Dr Chuck) htp://dr-chuck.com , developed by Jordi Piguillem in a 29 // Google Summer of Code 2008 project co-mentored by Charles Severance and Marc Alier. 30 // 31 // BasicLTI4Moodle is copyright 2009 by Marc Alier Forment, Jordi Piguillem and Nikolas Galanis 32 // of the Universitat Politecnica de Catalunya http://www.upc.edu 33 // Contact info: Marc Alier Forment granludo @ gmail.com or marc.alier @ upc.edu. 34 35 /** 36 * This file contains a library of functions and constants for the lti module 37 * 38 * @package mod_lti 39 * @copyright 2009 Marc Alier, Jordi Piguillem, Nikolas Galanis 40 * marc.alier@upc.edu 41 * @copyright 2009 Universitat Politecnica de Catalunya http://www.upc.edu 42 * @author Marc Alier 43 * @author Jordi Piguillem 44 * @author Nikolas Galanis 45 * @author Chris Scribner 46 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 47 */ 48 49 defined('MOODLE_INTERNAL') || die; 50 51 /** 52 * List of features supported in URL module 53 * @param string $feature FEATURE_xx constant for requested feature 54 * @return mixed True if module supports feature, false if not, null if doesn't know or string for the module purpose. 55 */ 56 function lti_supports($feature) { 57 switch ($feature) { 58 case FEATURE_GROUPS: 59 case FEATURE_GROUPINGS: 60 return false; 61 case FEATURE_MOD_INTRO: 62 case FEATURE_COMPLETION_TRACKS_VIEWS: 63 case FEATURE_GRADE_HAS_GRADE: 64 case FEATURE_GRADE_OUTCOMES: 65 case FEATURE_BACKUP_MOODLE2: 66 case FEATURE_SHOW_DESCRIPTION: 67 return true; 68 case FEATURE_MOD_PURPOSE: 69 return MOD_PURPOSE_CONTENT; 70 71 default: 72 return null; 73 } 74 } 75 76 /** 77 * Given an object containing all the necessary data, 78 * (defined by the form in mod.html) this function 79 * will create a new instance and return the id number 80 * of the new instance. 81 * 82 * @param object $instance An object from the form in mod.html 83 * @return int The id of the newly inserted basiclti record 84 **/ 85 function lti_add_instance($lti, $mform) { 86 global $DB, $CFG; 87 require_once($CFG->dirroot.'/mod/lti/locallib.php'); 88 89 if (!isset($lti->toolurl)) { 90 $lti->toolurl = ''; 91 } 92 93 lti_load_tool_if_cartridge($lti); 94 95 $lti->timecreated = time(); 96 $lti->timemodified = $lti->timecreated; 97 $lti->servicesalt = uniqid('', true); 98 if (!isset($lti->typeid)) { 99 $lti->typeid = null; 100 } 101 102 lti_force_type_config_settings($lti, lti_get_type_config_by_instance($lti)); 103 104 if (empty($lti->typeid) && isset($lti->urlmatchedtypeid)) { 105 $lti->typeid = $lti->urlmatchedtypeid; 106 } 107 108 if (!isset($lti->instructorchoiceacceptgrades) || $lti->instructorchoiceacceptgrades != LTI_SETTING_ALWAYS) { 109 // The instance does not accept grades back from the provider, so set to "No grade" value 0. 110 $lti->grade = 0; 111 } 112 113 $lti->id = $DB->insert_record('lti', $lti); 114 115 if (isset($lti->instructorchoiceacceptgrades) && $lti->instructorchoiceacceptgrades == LTI_SETTING_ALWAYS) { 116 if (!isset($lti->cmidnumber)) { 117 $lti->cmidnumber = ''; 118 } 119 120 lti_grade_item_update($lti); 121 } 122 123 $services = lti_get_services(); 124 foreach ($services as $service) { 125 $service->instance_added( $lti ); 126 } 127 128 $completiontimeexpected = !empty($lti->completionexpected) ? $lti->completionexpected : null; 129 \core_completion\api::update_completion_date_event($lti->coursemodule, 'lti', $lti->id, $completiontimeexpected); 130 131 return $lti->id; 132 } 133 134 /** 135 * Given an object containing all the necessary data, 136 * (defined by the form in mod.html) this function 137 * will update an existing instance with new data. 138 * 139 * @param object $instance An object from the form in mod.html 140 * @return boolean Success/Fail 141 **/ 142 function lti_update_instance($lti, $mform) { 143 global $DB, $CFG; 144 require_once($CFG->dirroot.'/mod/lti/locallib.php'); 145 146 lti_load_tool_if_cartridge($lti); 147 148 $lti->timemodified = time(); 149 $lti->id = $lti->instance; 150 151 if (!isset($lti->showtitlelaunch)) { 152 $lti->showtitlelaunch = 0; 153 } 154 155 if (!isset($lti->showdescriptionlaunch)) { 156 $lti->showdescriptionlaunch = 0; 157 } 158 159 lti_force_type_config_settings($lti, lti_get_type_config_by_instance($lti)); 160 161 if (isset($lti->instructorchoiceacceptgrades) && $lti->instructorchoiceacceptgrades == LTI_SETTING_ALWAYS) { 162 lti_grade_item_update($lti); 163 } else { 164 // Instance is no longer accepting grades from Provider, set grade to "No grade" value 0. 165 $lti->grade = 0; 166 $lti->instructorchoiceacceptgrades = 0; 167 168 lti_grade_item_delete($lti); 169 } 170 171 if ($lti->typeid == 0 && isset($lti->urlmatchedtypeid)) { 172 $lti->typeid = $lti->urlmatchedtypeid; 173 } 174 175 $services = lti_get_services(); 176 foreach ($services as $service) { 177 $service->instance_updated( $lti ); 178 } 179 180 $completiontimeexpected = !empty($lti->completionexpected) ? $lti->completionexpected : null; 181 \core_completion\api::update_completion_date_event($lti->coursemodule, 'lti', $lti->id, $completiontimeexpected); 182 183 return $DB->update_record('lti', $lti); 184 } 185 186 /** 187 * Given an ID of an instance of this module, 188 * this function will permanently delete the instance 189 * and any data that depends on it. 190 * 191 * @param int $id Id of the module instance 192 * @return boolean Success/Failure 193 **/ 194 function lti_delete_instance($id) { 195 global $DB, $CFG; 196 require_once($CFG->dirroot.'/mod/lti/locallib.php'); 197 198 if (! $basiclti = $DB->get_record("lti", array("id" => $id))) { 199 return false; 200 } 201 202 $result = true; 203 204 // Delete any dependent records here. 205 lti_grade_item_delete($basiclti); 206 207 $ltitype = $DB->get_record('lti_types', array('id' => $basiclti->typeid)); 208 if ($ltitype) { 209 $DB->delete_records('lti_tool_settings', 210 array('toolproxyid' => $ltitype->toolproxyid, 'course' => $basiclti->course, 'coursemoduleid' => $id)); 211 } 212 213 $cm = get_coursemodule_from_instance('lti', $id); 214 \core_completion\api::update_completion_date_event($cm->id, 'lti', $id, null); 215 216 // We must delete the module record after we delete the grade item. 217 if ($DB->delete_records("lti", array("id" => $basiclti->id)) ) { 218 $services = lti_get_services(); 219 foreach ($services as $service) { 220 $service->instance_deleted( $id ); 221 } 222 return true; 223 } 224 return false; 225 226 } 227 228 /** 229 * Return the preconfigured tools which are configured for inclusion in the activity picker. 230 * 231 * @param \core_course\local\entity\content_item $defaultmodulecontentitem reference to the content item for the LTI module. 232 * @param \stdClass $user the user object, to use for cap checks if desired. 233 * @param stdClass $course the course to scope items to. 234 * @return array the array of content items. 235 */ 236 function lti_get_course_content_items(\core_course\local\entity\content_item $defaultmodulecontentitem, \stdClass $user, 237 \stdClass $course) { 238 global $CFG, $OUTPUT; 239 require_once($CFG->dirroot.'/mod/lti/locallib.php'); 240 241 $types = []; 242 243 // The 'External tool' entry (the main module content item), should always take the id of 1. 244 if (has_capability('mod/lti:addmanualinstance', context_course::instance($course->id), $user)) { 245 $types = [new \core_course\local\entity\content_item( 246 1, 247 $defaultmodulecontentitem->get_name(), 248 $defaultmodulecontentitem->get_title(), 249 $defaultmodulecontentitem->get_link(), 250 $defaultmodulecontentitem->get_icon(), 251 $defaultmodulecontentitem->get_help(), 252 $defaultmodulecontentitem->get_archetype(), 253 $defaultmodulecontentitem->get_component_name(), 254 $defaultmodulecontentitem->get_purpose() 255 )]; 256 } 257 258 // Other, preconfigured tools take their own id + 1, so we'll never clash with the module's entry. 259 $preconfiguredtools = lti_get_configured_types($course->id, $defaultmodulecontentitem->get_link()->param('sr')); 260 foreach ($preconfiguredtools as $preconfiguredtool) { 261 262 // Append the help link to the help text. 263 if (isset($preconfiguredtool->help)) { 264 if (isset($preconfiguredtool->helplink)) { 265 $linktext = get_string('morehelp'); 266 $preconfiguredtool->help .= html_writer::tag('div', 267 $OUTPUT->doc_link($preconfiguredtool->helplink, $linktext, true), ['class' => 'helpdoclink']); 268 } 269 } else { 270 $preconfiguredtool->help = ''; 271 } 272 273 $types[] = new \core_course\local\entity\content_item( 274 $preconfiguredtool->id + 1, 275 $preconfiguredtool->name, 276 new \core_course\local\entity\string_title($preconfiguredtool->title), 277 $preconfiguredtool->link, 278 $preconfiguredtool->icon, 279 $preconfiguredtool->help, 280 $defaultmodulecontentitem->get_archetype(), 281 $defaultmodulecontentitem->get_component_name(), 282 $defaultmodulecontentitem->get_purpose() 283 ); 284 } 285 return $types; 286 } 287 288 /** 289 * Return all content items which can be added to any course. 290 * 291 * @param \core_course\local\entity\content_item $defaultmodulecontentitem 292 * @return array the array of content items. 293 */ 294 function mod_lti_get_all_content_items(\core_course\local\entity\content_item $defaultmodulecontentitem): array { 295 global $OUTPUT, $CFG; 296 require_once($CFG->dirroot . '/mod/lti/locallib.php'); // For access to constants. 297 298 // The 'External tool' entry (the main module content item), should always take the id of 1. 299 $types = [new \core_course\local\entity\content_item( 300 1, 301 $defaultmodulecontentitem->get_name(), 302 $defaultmodulecontentitem->get_title(), 303 $defaultmodulecontentitem->get_link(), 304 $defaultmodulecontentitem->get_icon(), 305 $defaultmodulecontentitem->get_help(), 306 $defaultmodulecontentitem->get_archetype(), 307 $defaultmodulecontentitem->get_component_name(), 308 $defaultmodulecontentitem->get_purpose() 309 )]; 310 311 foreach (lti_get_lti_types() as $ltitype) { 312 if ($ltitype->coursevisible != LTI_COURSEVISIBLE_ACTIVITYCHOOSER) { 313 continue; 314 } 315 $type = new stdClass(); 316 $type->id = $ltitype->id; 317 $type->modclass = MOD_CLASS_ACTIVITY; 318 $type->name = 'lti_type_' . $ltitype->id; 319 // Clean the name. We don't want tags here. 320 $type->title = clean_param($ltitype->name, PARAM_NOTAGS); 321 $trimmeddescription = trim($ltitype->description ?? ''); 322 $type->help = ''; 323 if ($trimmeddescription != '') { 324 // Clean the description. We don't want tags here. 325 $type->help = clean_param($trimmeddescription, PARAM_NOTAGS); 326 $type->helplink = get_string('modulename_shortcut_link', 'lti'); 327 } 328 if (empty($ltitype->icon)) { 329 $type->icon = $OUTPUT->pix_icon('monologo', '', 'lti', array('class' => 'icon')); 330 } else { 331 $type->icon = html_writer::empty_tag('img', array('src' => $ltitype->icon, 'alt' => $ltitype->name, 'class' => 'icon')); 332 } 333 $type->link = new moodle_url('/course/modedit.php', array('add' => 'lti', 'return' => 0, 'typeid' => $ltitype->id)); 334 335 $types[] = new \core_course\local\entity\content_item( 336 $type->id + 1, 337 $type->name, 338 new \core_course\local\entity\string_title($type->title), 339 $type->link, 340 $type->icon, 341 $type->help, 342 $defaultmodulecontentitem->get_archetype(), 343 $defaultmodulecontentitem->get_component_name(), 344 $defaultmodulecontentitem->get_purpose() 345 ); 346 } 347 348 return $types; 349 } 350 351 /** 352 * Given a coursemodule object, this function returns the extra 353 * information needed to print this activity in various places. 354 * For this module we just need to support external urls as 355 * activity icons 356 * 357 * @param stdClass $coursemodule 358 * @return cached_cm_info info 359 */ 360 function lti_get_coursemodule_info($coursemodule) { 361 global $DB, $CFG; 362 require_once($CFG->dirroot.'/mod/lti/locallib.php'); 363 364 if (!$lti = $DB->get_record('lti', array('id' => $coursemodule->instance), 365 'icon, secureicon, intro, introformat, name, typeid, toolurl, launchcontainer')) { 366 return null; 367 } 368 369 $info = new cached_cm_info(); 370 371 if ($coursemodule->showdescription) { 372 // Convert intro to html. Do not filter cached version, filters run at display time. 373 $info->content = format_module_intro('lti', $lti, $coursemodule->id, false); 374 } 375 376 if (!empty($lti->typeid)) { 377 $toolconfig = lti_get_type_config($lti->typeid); 378 } else if ($tool = lti_get_tool_by_url_match($lti->toolurl)) { 379 $toolconfig = lti_get_type_config($tool->id); 380 } else { 381 $toolconfig = array(); 382 } 383 384 // We want to use the right icon based on whether the 385 // current page is being requested over http or https. 386 if (lti_request_is_using_ssl() && 387 (!empty($lti->secureicon) || (isset($toolconfig['secureicon']) && !empty($toolconfig['secureicon'])))) { 388 if (!empty($lti->secureicon)) { 389 $info->iconurl = new moodle_url($lti->secureicon); 390 } else { 391 $info->iconurl = new moodle_url($toolconfig['secureicon']); 392 } 393 } else if (!empty($lti->icon)) { 394 $info->iconurl = new moodle_url($lti->icon); 395 } else if (isset($toolconfig['icon']) && !empty($toolconfig['icon'])) { 396 $info->iconurl = new moodle_url($toolconfig['icon']); 397 } 398 399 // Does the link open in a new window? 400 $launchcontainer = lti_get_launch_container($lti, $toolconfig); 401 if ($launchcontainer == LTI_LAUNCH_CONTAINER_WINDOW) { 402 $launchurl = new moodle_url('/mod/lti/launch.php', array('id' => $coursemodule->id)); 403 $info->onclick = "window.open('" . $launchurl->out(false) . "', 'lti-".$coursemodule->id."'); return false;"; 404 } 405 406 $info->name = $lti->name; 407 408 return $info; 409 } 410 411 /** 412 * Return a small object with summary information about what a 413 * user has done with a given particular instance of this module 414 * Used for user activity reports. 415 * $return->time = the time they did it 416 * $return->info = a short text description 417 * 418 * @return null 419 * @TODO: implement this moodle function (if needed) 420 **/ 421 function lti_user_outline($course, $user, $mod, $basiclti) { 422 return null; 423 } 424 425 /** 426 * Print a detailed representation of what a user has done with 427 * a given particular instance of this module, for user activity reports. 428 * 429 * @return boolean 430 * @TODO: implement this moodle function (if needed) 431 **/ 432 function lti_user_complete($course, $user, $mod, $basiclti) { 433 return true; 434 } 435 436 /** 437 * Given a course and a time, this module should find recent activity 438 * that has occurred in basiclti activities and print it out. 439 * Return true if there was output, or false is there was none. 440 * 441 * @uses $CFG 442 * @return boolean 443 * @TODO: implement this moodle function 444 **/ 445 function lti_print_recent_activity($course, $isteacher, $timestart) { 446 return false; // True if anything was printed, otherwise false. 447 } 448 449 /** 450 * Function to be run periodically according to the moodle cron 451 * This function searches for things that need to be done, such 452 * as sending out mail, toggling flags etc ... 453 * 454 * @uses $CFG 455 * @return boolean 456 **/ 457 function lti_cron () { 458 return true; 459 } 460 461 /** 462 * Must return an array of grades for a given instance of this module, 463 * indexed by user. It also returns a maximum allowed grade. 464 * 465 * Example: 466 * $return->grades = array of grades; 467 * $return->maxgrade = maximum allowed grade; 468 * 469 * return $return; 470 * 471 * @param int $basicltiid ID of an instance of this module 472 * @return mixed Null or object with an array of grades and with the maximum grade 473 * 474 * @TODO: implement this moodle function (if needed) 475 **/ 476 function lti_grades($basicltiid) { 477 return null; 478 } 479 480 /** 481 * @deprecated since Moodle 3.8 482 */ 483 function lti_scale_used() { 484 throw new coding_exception('lti_scale_used() can not be used anymore. Plugins can implement ' . 485 '<modname>_scale_used_anywhere, all implementations of <modname>_scale_used are now ignored'); 486 } 487 488 /** 489 * Checks if scale is being used by any instance of basiclti. 490 * This function was added in 1.9 491 * 492 * This is used to find out if scale used anywhere 493 * @param $scaleid int 494 * @return boolean True if the scale is used by any basiclti 495 * 496 */ 497 function lti_scale_used_anywhere($scaleid) { 498 global $DB; 499 500 if ($scaleid and $DB->record_exists('lti', array('grade' => -$scaleid))) { 501 return true; 502 } else { 503 return false; 504 } 505 } 506 507 /** 508 * Execute post-install custom actions for the module 509 * This function was added in 1.9 510 * 511 * @return boolean true if success, false on error 512 */ 513 function lti_install() { 514 return true; 515 } 516 517 /** 518 * Execute post-uninstall custom actions for the module 519 * This function was added in 1.9 520 * 521 * @return boolean true if success, false on error 522 */ 523 function lti_uninstall() { 524 return true; 525 } 526 527 /** 528 * Returns available Basic LTI types 529 * 530 * @return array of basicLTI types 531 */ 532 function lti_get_lti_types() { 533 global $DB; 534 535 return $DB->get_records('lti_types', null, 'state DESC, timemodified DESC'); 536 } 537 538 /** 539 * Returns available Basic LTI types that match the given 540 * tool proxy id 541 * 542 * @param int $toolproxyid Tool proxy id 543 * @return array of basicLTI types 544 */ 545 function lti_get_lti_types_from_proxy_id($toolproxyid) { 546 global $DB; 547 548 return $DB->get_records('lti_types', array('toolproxyid' => $toolproxyid), 'state DESC, timemodified DESC'); 549 } 550 551 /** 552 * Create grade item for given basiclti 553 * 554 * @category grade 555 * @param object $basiclti object with extra cmidnumber 556 * @param mixed optional array/object of grade(s); 'reset' means reset grades in gradebook 557 * @return int 0 if ok, error code otherwise 558 */ 559 function lti_grade_item_update($basiclti, $grades = null) { 560 global $CFG; 561 require_once($CFG->libdir.'/gradelib.php'); 562 require_once($CFG->dirroot.'/mod/lti/servicelib.php'); 563 564 if (!lti_accepts_grades($basiclti)) { 565 return 0; 566 } 567 568 $params = array('itemname' => $basiclti->name, 'idnumber' => $basiclti->cmidnumber); 569 570 if ($basiclti->grade > 0) { 571 $params['gradetype'] = GRADE_TYPE_VALUE; 572 $params['grademax'] = $basiclti->grade; 573 $params['grademin'] = 0; 574 575 } else if ($basiclti->grade < 0) { 576 $params['gradetype'] = GRADE_TYPE_SCALE; 577 $params['scaleid'] = -$basiclti->grade; 578 579 } else { 580 $params['gradetype'] = GRADE_TYPE_TEXT; // Allow text comments only. 581 } 582 583 if ($grades === 'reset') { 584 $params['reset'] = true; 585 $grades = null; 586 } 587 588 return grade_update('mod/lti', $basiclti->course, 'mod', 'lti', $basiclti->id, 0, $grades, $params); 589 } 590 591 /** 592 * Update activity grades 593 * 594 * @param stdClass $basiclti The LTI instance 595 * @param int $userid Specific user only, 0 means all. 596 * @param bool $nullifnone Not used 597 */ 598 function lti_update_grades($basiclti, $userid=0, $nullifnone=true) { 599 global $CFG; 600 require_once($CFG->dirroot.'/mod/lti/servicelib.php'); 601 // LTI doesn't have its own grade table so the only thing to do is update the grade item. 602 if (lti_accepts_grades($basiclti)) { 603 lti_grade_item_update($basiclti); 604 } 605 } 606 607 /** 608 * Delete grade item for given basiclti 609 * 610 * @category grade 611 * @param object $basiclti object 612 * @return object basiclti 613 */ 614 function lti_grade_item_delete($basiclti) { 615 global $CFG; 616 require_once($CFG->libdir.'/gradelib.php'); 617 618 return grade_update('mod/lti', $basiclti->course, 'mod', 'lti', $basiclti->id, 0, null, array('deleted' => 1)); 619 } 620 621 /** 622 * Log post actions 623 * 624 * @return array 625 */ 626 function lti_get_post_actions() { 627 return array(); 628 } 629 630 /** 631 * Log view actions 632 * 633 * @return array 634 */ 635 function lti_get_view_actions() { 636 return array('view all', 'view'); 637 } 638 639 /** 640 * Mark the activity completed (if required) and trigger the course_module_viewed event. 641 * 642 * @param stdClass $lti lti object 643 * @param stdClass $course course object 644 * @param stdClass $cm course module object 645 * @param stdClass $context context object 646 * @since Moodle 3.0 647 */ 648 function lti_view($lti, $course, $cm, $context) { 649 650 // Trigger course_module_viewed event. 651 $params = array( 652 'context' => $context, 653 'objectid' => $lti->id 654 ); 655 656 $event = \mod_lti\event\course_module_viewed::create($params); 657 $event->add_record_snapshot('course_modules', $cm); 658 $event->add_record_snapshot('course', $course); 659 $event->add_record_snapshot('lti', $lti); 660 $event->trigger(); 661 662 // Completion. 663 $completion = new completion_info($course); 664 $completion->set_module_viewed($cm); 665 } 666 667 /** 668 * Check if the module has any update that affects the current user since a given time. 669 * 670 * @param cm_info $cm course module data 671 * @param int $from the time to check updates from 672 * @param array $filter if we need to check only specific updates 673 * @return stdClass an object with the different type of areas indicating if they were updated or not 674 * @since Moodle 3.2 675 */ 676 function lti_check_updates_since(cm_info $cm, $from, $filter = array()) { 677 global $DB, $USER; 678 679 $updates = course_check_module_updates_since($cm, $from, array(), $filter); 680 681 // Check if there is a new submission. 682 $updates->submissions = (object) array('updated' => false); 683 $select = 'ltiid = :id AND userid = :userid AND (datesubmitted > :since1 OR dateupdated > :since2)'; 684 $params = array('id' => $cm->instance, 'userid' => $USER->id, 'since1' => $from, 'since2' => $from); 685 $submissions = $DB->get_records_select('lti_submission', $select, $params, '', 'id'); 686 if (!empty($submissions)) { 687 $updates->submissions->updated = true; 688 $updates->submissions->itemids = array_keys($submissions); 689 } 690 691 // Now, teachers should see other students updates. 692 if (has_capability('mod/lti:manage', $cm->context)) { 693 $select = 'ltiid = :id AND (datesubmitted > :since1 OR dateupdated > :since2)'; 694 $params = array('id' => $cm->instance, 'since1' => $from, 'since2' => $from); 695 696 if (groups_get_activity_groupmode($cm) == SEPARATEGROUPS) { 697 $groupusers = array_keys(groups_get_activity_shared_group_members($cm)); 698 if (empty($groupusers)) { 699 return $updates; 700 } 701 list($insql, $inparams) = $DB->get_in_or_equal($groupusers, SQL_PARAMS_NAMED); 702 $select .= ' AND userid ' . $insql; 703 $params = array_merge($params, $inparams); 704 } 705 706 $updates->usersubmissions = (object) array('updated' => false); 707 $submissions = $DB->get_records_select('lti_submission', $select, $params, '', 'id'); 708 if (!empty($submissions)) { 709 $updates->usersubmissions->updated = true; 710 $updates->usersubmissions->itemids = array_keys($submissions); 711 } 712 } 713 714 return $updates; 715 } 716 717 /** 718 * Get icon mapping for font-awesome. 719 */ 720 function mod_lti_get_fontawesome_icon_map() { 721 return [ 722 'mod_lti:warning' => 'fa-exclamation text-warning', 723 ]; 724 } 725 726 /** 727 * This function receives a calendar event and returns the action associated with it, or null if there is none. 728 * 729 * This is used by block_myoverview in order to display the event appropriately. If null is returned then the event 730 * is not displayed on the block. 731 * 732 * @param calendar_event $event 733 * @param \core_calendar\action_factory $factory 734 * @param int $userid User id to use for all capability checks, etc. Set to 0 for current user (default). 735 * @return \core_calendar\local\event\entities\action_interface|null 736 */ 737 function mod_lti_core_calendar_provide_event_action(calendar_event $event, 738 \core_calendar\action_factory $factory, 739 int $userid = 0) { 740 global $USER; 741 742 if (empty($userid)) { 743 $userid = $USER->id; 744 } 745 746 $cm = get_fast_modinfo($event->courseid, $userid)->instances['lti'][$event->instance]; 747 748 if (!$cm->uservisible) { 749 // The module is not visible to the user for any reason. 750 return null; 751 } 752 753 $completion = new \completion_info($cm->get_course()); 754 755 $completiondata = $completion->get_data($cm, false, $userid); 756 757 if ($completiondata->completionstate != COMPLETION_INCOMPLETE) { 758 return null; 759 } 760 761 return $factory->create_instance( 762 get_string('view'), 763 new \moodle_url('/mod/lti/view.php', ['id' => $cm->id]), 764 1, 765 true 766 ); 767 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body