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