[ Index ] |
PHP Cross Reference of moodle-2.8 |
[Summary view] [Print] [Text view]
1 <?php 2 3 // This file is part of Moodle - http://moodle.org/ 4 // 5 // Moodle is free software: you can redistribute it and/or modify 6 // it under the terms of the GNU General Public License as published by 7 // the Free Software Foundation, either version 3 of the License, or 8 // (at your option) any later version. 9 // 10 // Moodle is distributed in the hope that it will be useful, 11 // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 // GNU General Public License for more details. 14 // 15 // You should have received a copy of the GNU General Public License 16 // along with Moodle. If not, see <http://www.gnu.org/licenses/>. 17 18 /** 19 * Standard library of functions and constants for lesson 20 * 21 * @package mod_lesson 22 * @copyright 1999 onwards Martin Dougiamas {@link http://moodle.com} 23 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 24 **/ 25 26 defined('MOODLE_INTERNAL') || die(); 27 28 /* Do not include any libraries here! */ 29 30 /** 31 * Given an object containing all the necessary data, 32 * (defined by the form in mod_form.php) this function 33 * will create a new instance and return the id number 34 * of the new instance. 35 * 36 * @global object 37 * @global object 38 * @param object $lesson Lesson post data from the form 39 * @return int 40 **/ 41 function lesson_add_instance($data, $mform) { 42 global $DB; 43 44 $cmid = $data->coursemodule; 45 $draftitemid = $data->mediafile; 46 $context = context_module::instance($cmid); 47 48 lesson_process_pre_save($data); 49 50 unset($data->mediafile); 51 $lessonid = $DB->insert_record("lesson", $data); 52 $data->id = $lessonid; 53 54 $lesson = $DB->get_record('lesson', array('id'=>$lessonid), '*', MUST_EXIST); 55 56 lesson_update_media_file($lessonid, $context, $draftitemid); 57 58 lesson_process_post_save($data); 59 60 lesson_grade_item_update($data); 61 62 return $lesson->id; 63 } 64 65 /** 66 * Given an object containing all the necessary data, 67 * (defined by the form in mod_form.php) this function 68 * will update an existing instance with new data. 69 * 70 * @global object 71 * @param object $lesson Lesson post data from the form 72 * @return boolean 73 **/ 74 function lesson_update_instance($data, $mform) { 75 global $DB; 76 77 $data->id = $data->instance; 78 $cmid = $data->coursemodule; 79 $draftitemid = $data->mediafile; 80 $context = context_module::instance($cmid); 81 82 lesson_process_pre_save($data); 83 84 unset($data->mediafile); 85 $DB->update_record("lesson", $data); 86 87 lesson_update_media_file($data->id, $context, $draftitemid); 88 89 lesson_process_post_save($data); 90 91 // update grade item definition 92 lesson_grade_item_update($data); 93 94 // update grades - TODO: do it only when grading style changes 95 lesson_update_grades($data, 0, false); 96 97 return true; 98 } 99 100 101 /** 102 * Given an ID of an instance of this module, 103 * this function will permanently delete the instance 104 * and any data that depends on it. 105 * 106 * @global object 107 * @param int $id 108 * @return bool 109 */ 110 function lesson_delete_instance($id) { 111 global $DB, $CFG; 112 require_once($CFG->dirroot . '/mod/lesson/locallib.php'); 113 114 $lesson = $DB->get_record("lesson", array("id"=>$id), '*', MUST_EXIST); 115 $lesson = new lesson($lesson); 116 return $lesson->delete(); 117 } 118 119 /** 120 * Given a course object, this function will clean up anything that 121 * would be leftover after all the instances were deleted 122 * 123 * @global object 124 * @param object $course an object representing the course that is being deleted 125 * @param boolean $feedback to specify if the process must output a summary of its work 126 * @return boolean 127 */ 128 function lesson_delete_course($course, $feedback=true) { 129 return true; 130 } 131 132 /** 133 * Return a small object with summary information about what a 134 * user has done with a given particular instance of this module 135 * Used for user activity reports. 136 * $return->time = the time they did it 137 * $return->info = a short text description 138 * 139 * @global object 140 * @param object $course 141 * @param object $user 142 * @param object $mod 143 * @param object $lesson 144 * @return object 145 */ 146 function lesson_user_outline($course, $user, $mod, $lesson) { 147 global $CFG; 148 149 require_once("$CFG->libdir/gradelib.php"); 150 $grades = grade_get_grades($course->id, 'mod', 'lesson', $lesson->id, $user->id); 151 152 $return = new stdClass(); 153 if (empty($grades->items[0]->grades)) { 154 $return->info = get_string("no")." ".get_string("attempts", "lesson"); 155 } else { 156 $grade = reset($grades->items[0]->grades); 157 $return->info = get_string("grade") . ': ' . $grade->str_long_grade; 158 159 //datesubmitted == time created. dategraded == time modified or time overridden 160 //if grade was last modified by the user themselves use date graded. Otherwise use date submitted 161 //TODO: move this copied & pasted code somewhere in the grades API. See MDL-26704 162 if ($grade->usermodified == $user->id || empty($grade->datesubmitted)) { 163 $return->time = $grade->dategraded; 164 } else { 165 $return->time = $grade->datesubmitted; 166 } 167 } 168 return $return; 169 } 170 171 /** 172 * Print a detailed representation of what a user has done with 173 * a given particular instance of this module, for user activity reports. 174 * 175 * @global object 176 * @param object $course 177 * @param object $user 178 * @param object $mod 179 * @param object $lesson 180 * @return bool 181 */ 182 function lesson_user_complete($course, $user, $mod, $lesson) { 183 global $DB, $OUTPUT, $CFG; 184 185 require_once("$CFG->libdir/gradelib.php"); 186 187 $grades = grade_get_grades($course->id, 'mod', 'lesson', $lesson->id, $user->id); 188 if (!empty($grades->items[0]->grades)) { 189 $grade = reset($grades->items[0]->grades); 190 echo $OUTPUT->container(get_string('grade').': '.$grade->str_long_grade); 191 if ($grade->str_feedback) { 192 echo $OUTPUT->container(get_string('feedback').': '.$grade->str_feedback); 193 } 194 } 195 196 $params = array ("lessonid" => $lesson->id, "userid" => $user->id); 197 if ($attempts = $DB->get_records_select("lesson_attempts", "lessonid = :lessonid AND userid = :userid", $params, 198 "retry, timeseen")) { 199 echo $OUTPUT->box_start(); 200 $table = new html_table(); 201 $table->head = array (get_string("attempt", "lesson"), get_string("numberofpagesviewed", "lesson"), 202 get_string("numberofcorrectanswers", "lesson"), get_string("time")); 203 $table->width = "100%"; 204 $table->align = array ("center", "center", "center", "center"); 205 $table->size = array ("*", "*", "*", "*"); 206 $table->cellpadding = 2; 207 $table->cellspacing = 0; 208 209 $retry = 0; 210 $npages = 0; 211 $ncorrect = 0; 212 213 foreach ($attempts as $attempt) { 214 if ($attempt->retry == $retry) { 215 $npages++; 216 if ($attempt->correct) { 217 $ncorrect++; 218 } 219 $timeseen = $attempt->timeseen; 220 } else { 221 $table->data[] = array($retry + 1, $npages, $ncorrect, userdate($timeseen)); 222 $retry++; 223 $npages = 1; 224 if ($attempt->correct) { 225 $ncorrect = 1; 226 } else { 227 $ncorrect = 0; 228 } 229 } 230 } 231 if ($npages) { 232 $table->data[] = array($retry + 1, $npages, $ncorrect, userdate($timeseen)); 233 } 234 echo html_writer::table($table); 235 echo $OUTPUT->box_end(); 236 } 237 238 return true; 239 } 240 241 /** 242 * Prints lesson summaries on MyMoodle Page 243 * 244 * Prints lesson name, due date and attempt information on 245 * lessons that have a deadline that has not already passed 246 * and it is available for taking. 247 * 248 * @global object 249 * @global stdClass 250 * @global object 251 * @uses CONTEXT_MODULE 252 * @param array $courses An array of course objects to get lesson instances from 253 * @param array $htmlarray Store overview output array( course ID => 'lesson' => HTML output ) 254 * @return void 255 */ 256 function lesson_print_overview($courses, &$htmlarray) { 257 global $USER, $CFG, $DB, $OUTPUT; 258 259 if (!$lessons = get_all_instances_in_courses('lesson', $courses)) { 260 return; 261 } 262 263 /// Get Necessary Strings 264 $strlesson = get_string('modulename', 'lesson'); 265 $strnotattempted = get_string('nolessonattempts', 'lesson'); 266 $strattempted = get_string('lessonattempted', 'lesson'); 267 268 $now = time(); 269 foreach ($lessons as $lesson) { 270 if ($lesson->deadline != 0 // The lesson has a deadline 271 and $lesson->deadline >= $now // And it is before the deadline has been met 272 and ($lesson->available == 0 or $lesson->available <= $now)) { // And the lesson is available 273 274 // Lesson name 275 if (!$lesson->visible) { 276 $class = ' class="dimmed"'; 277 } else { 278 $class = ''; 279 } 280 $str = $OUTPUT->box("$strlesson: <a$class href=\"$CFG->wwwroot/mod/lesson/view.php?id=$lesson->coursemodule\">". 281 format_string($lesson->name).'</a>', 'name'); 282 283 // Deadline 284 $str .= $OUTPUT->box(get_string('lessoncloseson', 'lesson', userdate($lesson->deadline)), 'info'); 285 286 // Attempt information 287 if (has_capability('mod/lesson:manage', context_module::instance($lesson->coursemodule))) { 288 // Number of user attempts 289 $attempts = $DB->count_records('lesson_attempts', array('lessonid'=>$lesson->id)); 290 $str .= $OUTPUT->box(get_string('xattempts', 'lesson', $attempts), 'info'); 291 } else { 292 // Determine if the user has attempted the lesson or not 293 if ($DB->count_records('lesson_attempts', array('lessonid'=>$lesson->id, 'userid'=>$USER->id))) { 294 $str .= $OUTPUT->box($strattempted, 'info'); 295 } else { 296 $str .= $OUTPUT->box($strnotattempted, 'info'); 297 } 298 } 299 $str = $OUTPUT->box($str, 'lesson overview'); 300 301 if (empty($htmlarray[$lesson->course]['lesson'])) { 302 $htmlarray[$lesson->course]['lesson'] = $str; 303 } else { 304 $htmlarray[$lesson->course]['lesson'] .= $str; 305 } 306 } 307 } 308 } 309 310 /** 311 * Function to be run periodically according to the moodle cron 312 * This function searches for things that need to be done, such 313 * as sending out mail, toggling flags etc ... 314 * @global stdClass 315 * @return bool true 316 */ 317 function lesson_cron () { 318 global $CFG; 319 320 return true; 321 } 322 323 /** 324 * Return grade for given user or all users. 325 * 326 * @global stdClass 327 * @global object 328 * @param int $lessonid id of lesson 329 * @param int $userid optional user id, 0 means all users 330 * @return array array of grades, false if none 331 */ 332 function lesson_get_user_grades($lesson, $userid=0) { 333 global $CFG, $DB; 334 335 $params = array("lessonid" => $lesson->id,"lessonid2" => $lesson->id); 336 337 if (!empty($userid)) { 338 $params["userid"] = $userid; 339 $params["userid2"] = $userid; 340 $user = "AND u.id = :userid"; 341 $fuser = "AND uu.id = :userid2"; 342 } 343 else { 344 $user=""; 345 $fuser=""; 346 } 347 348 if ($lesson->retake) { 349 if ($lesson->usemaxgrade) { 350 $sql = "SELECT u.id, u.id AS userid, MAX(g.grade) AS rawgrade 351 FROM {user} u, {lesson_grades} g 352 WHERE u.id = g.userid AND g.lessonid = :lessonid 353 $user 354 GROUP BY u.id"; 355 } else { 356 $sql = "SELECT u.id, u.id AS userid, AVG(g.grade) AS rawgrade 357 FROM {user} u, {lesson_grades} g 358 WHERE u.id = g.userid AND g.lessonid = :lessonid 359 $user 360 GROUP BY u.id"; 361 } 362 unset($params['lessonid2']); 363 unset($params['userid2']); 364 } else { 365 // use only first attempts (with lowest id in lesson_grades table) 366 $firstonly = "SELECT uu.id AS userid, MIN(gg.id) AS firstcompleted 367 FROM {user} uu, {lesson_grades} gg 368 WHERE uu.id = gg.userid AND gg.lessonid = :lessonid2 369 $fuser 370 GROUP BY uu.id"; 371 372 $sql = "SELECT u.id, u.id AS userid, g.grade AS rawgrade 373 FROM {user} u, {lesson_grades} g, ($firstonly) f 374 WHERE u.id = g.userid AND g.lessonid = :lessonid 375 AND g.id = f.firstcompleted AND g.userid=f.userid 376 $user"; 377 } 378 379 return $DB->get_records_sql($sql, $params); 380 } 381 382 /** 383 * Update grades in central gradebook 384 * 385 * @category grade 386 * @param object $lesson 387 * @param int $userid specific user only, 0 means all 388 * @param bool $nullifnone 389 */ 390 function lesson_update_grades($lesson, $userid=0, $nullifnone=true) { 391 global $CFG, $DB; 392 require_once($CFG->libdir.'/gradelib.php'); 393 394 if ($lesson->grade == 0) { 395 lesson_grade_item_update($lesson); 396 397 } else if ($grades = lesson_get_user_grades($lesson, $userid)) { 398 lesson_grade_item_update($lesson, $grades); 399 400 } else if ($userid and $nullifnone) { 401 $grade = new stdClass(); 402 $grade->userid = $userid; 403 $grade->rawgrade = null; 404 lesson_grade_item_update($lesson, $grade); 405 406 } else { 407 lesson_grade_item_update($lesson); 408 } 409 } 410 411 /** 412 * Create grade item for given lesson 413 * 414 * @category grade 415 * @uses GRADE_TYPE_VALUE 416 * @uses GRADE_TYPE_NONE 417 * @param object $lesson object with extra cmidnumber 418 * @param array|object $grades optional array/object of grade(s); 'reset' means reset grades in gradebook 419 * @return int 0 if ok, error code otherwise 420 */ 421 function lesson_grade_item_update($lesson, $grades=null) { 422 global $CFG; 423 if (!function_exists('grade_update')) { //workaround for buggy PHP versions 424 require_once($CFG->libdir.'/gradelib.php'); 425 } 426 427 if (array_key_exists('cmidnumber', $lesson)) { //it may not be always present 428 $params = array('itemname'=>$lesson->name, 'idnumber'=>$lesson->cmidnumber); 429 } else { 430 $params = array('itemname'=>$lesson->name); 431 } 432 433 if ($lesson->grade > 0) { 434 $params['gradetype'] = GRADE_TYPE_VALUE; 435 $params['grademax'] = $lesson->grade; 436 $params['grademin'] = 0; 437 } else if ($lesson->grade < 0) { 438 $params['gradetype'] = GRADE_TYPE_SCALE; 439 $params['scaleid'] = -$lesson->grade; 440 441 // Make sure current grade fetched correctly from $grades 442 $currentgrade = null; 443 if (!empty($grades)) { 444 if (is_array($grades)) { 445 $currentgrade = reset($grades); 446 } else { 447 $currentgrade = $grades; 448 } 449 } 450 451 // When converting a score to a scale, use scale's grade maximum to calculate it. 452 if (!empty($currentgrade) && $currentgrade->rawgrade !== null) { 453 $grade = grade_get_grades($lesson->course, 'mod', 'lesson', $lesson->id, $currentgrade->userid); 454 $params['grademax'] = reset($grade->items)->grademax; 455 } 456 } else { 457 $params['gradetype'] = GRADE_TYPE_NONE; 458 } 459 460 if ($grades === 'reset') { 461 $params['reset'] = true; 462 $grades = null; 463 } else if (!empty($grades)) { 464 // Need to calculate raw grade (Note: $grades has many forms) 465 if (is_object($grades)) { 466 $grades = array($grades->userid => $grades); 467 } else if (array_key_exists('userid', $grades)) { 468 $grades = array($grades['userid'] => $grades); 469 } 470 foreach ($grades as $key => $grade) { 471 if (!is_array($grade)) { 472 $grades[$key] = $grade = (array) $grade; 473 } 474 //check raw grade isnt null otherwise we erroneously insert a grade of 0 475 if ($grade['rawgrade'] !== null) { 476 $grades[$key]['rawgrade'] = ($grade['rawgrade'] * $params['grademax'] / 100); 477 } else { 478 //setting rawgrade to null just in case user is deleting a grade 479 $grades[$key]['rawgrade'] = null; 480 } 481 } 482 } 483 484 return grade_update('mod/lesson', $lesson->course, 'mod', 'lesson', $lesson->id, 0, $grades, $params); 485 } 486 487 /** 488 * Delete grade item for given lesson 489 * 490 * @category grade 491 * @param object $lesson object 492 * @return object lesson 493 */ 494 function lesson_grade_item_delete($lesson) { 495 global $CFG; 496 497 } 498 499 /** 500 * List the actions that correspond to a view of this module. 501 * This is used by the participation report. 502 * 503 * Note: This is not used by new logging system. Event with 504 * crud = 'r' and edulevel = LEVEL_PARTICIPATING will 505 * be considered as view action. 506 * 507 * @return array 508 */ 509 function lesson_get_view_actions() { 510 return array('view','view all'); 511 } 512 513 /** 514 * List the actions that correspond to a post of this module. 515 * This is used by the participation report. 516 * 517 * Note: This is not used by new logging system. Event with 518 * crud = ('c' || 'u' || 'd') and edulevel = LEVEL_PARTICIPATING 519 * will be considered as post action. 520 * 521 * @return array 522 */ 523 function lesson_get_post_actions() { 524 return array('end','start'); 525 } 526 527 /** 528 * Runs any processes that must run before 529 * a lesson insert/update 530 * 531 * @global object 532 * @param object $lesson Lesson form data 533 * @return void 534 **/ 535 function lesson_process_pre_save(&$lesson) { 536 global $DB; 537 538 $lesson->timemodified = time(); 539 540 if (empty($lesson->timed)) { 541 $lesson->timed = 0; 542 } 543 if (empty($lesson->timespent) or !is_numeric($lesson->timespent) or $lesson->timespent < 0) { 544 $lesson->timespent = 0; 545 } 546 if (!isset($lesson->completed)) { 547 $lesson->completed = 0; 548 } 549 if (empty($lesson->gradebetterthan) or !is_numeric($lesson->gradebetterthan) or $lesson->gradebetterthan < 0) { 550 $lesson->gradebetterthan = 0; 551 } else if ($lesson->gradebetterthan > 100) { 552 $lesson->gradebetterthan = 100; 553 } 554 555 if (empty($lesson->width)) { 556 $lesson->width = 640; 557 } 558 if (empty($lesson->height)) { 559 $lesson->height = 480; 560 } 561 if (empty($lesson->bgcolor)) { 562 $lesson->bgcolor = '#FFFFFF'; 563 } 564 565 // Conditions for dependency 566 $conditions = new stdClass; 567 $conditions->timespent = $lesson->timespent; 568 $conditions->completed = $lesson->completed; 569 $conditions->gradebetterthan = $lesson->gradebetterthan; 570 $lesson->conditions = serialize($conditions); 571 unset($lesson->timespent); 572 unset($lesson->completed); 573 unset($lesson->gradebetterthan); 574 575 if (empty($lesson->password)) { 576 unset($lesson->password); 577 } 578 } 579 580 /** 581 * Runs any processes that must be run 582 * after a lesson insert/update 583 * 584 * @global object 585 * @param object $lesson Lesson form data 586 * @return void 587 **/ 588 function lesson_process_post_save(&$lesson) { 589 global $DB, $CFG; 590 require_once($CFG->dirroot.'/calendar/lib.php'); 591 require_once($CFG->dirroot . '/mod/lesson/locallib.php'); 592 593 if ($events = $DB->get_records('event', array('modulename'=>'lesson', 'instance'=>$lesson->id))) { 594 foreach($events as $event) { 595 $event = calendar_event::load($event->id); 596 $event->delete(); 597 } 598 } 599 600 $event = new stdClass; 601 $event->description = $lesson->name; 602 $event->courseid = $lesson->course; 603 $event->groupid = 0; 604 $event->userid = 0; 605 $event->modulename = 'lesson'; 606 $event->instance = $lesson->id; 607 $event->eventtype = 'open'; 608 $event->timestart = $lesson->available; 609 610 $event->visible = instance_is_visible('lesson', $lesson); 611 612 $event->timeduration = ($lesson->deadline - $lesson->available); 613 614 if ($lesson->deadline and $lesson->available and $event->timeduration <= LESSON_MAX_EVENT_LENGTH) { 615 // Single event for the whole lesson. 616 $event->name = $lesson->name; 617 calendar_event::create(clone($event)); 618 } else { 619 // Separate start and end events. 620 $event->timeduration = 0; 621 if ($lesson->available) { 622 $event->name = $lesson->name.' ('.get_string('lessonopens', 'lesson').')'; 623 calendar_event::create(clone($event)); 624 } 625 626 if ($lesson->deadline) { 627 $event->name = $lesson->name.' ('.get_string('lessoncloses', 'lesson').')'; 628 $event->timestart = $lesson->deadline; 629 $event->eventtype = 'close'; 630 calendar_event::create(clone($event)); 631 } 632 } 633 } 634 635 636 /** 637 * Implementation of the function for printing the form elements that control 638 * whether the course reset functionality affects the lesson. 639 * 640 * @param $mform form passed by reference 641 */ 642 function lesson_reset_course_form_definition(&$mform) { 643 $mform->addElement('header', 'lessonheader', get_string('modulenameplural', 'lesson')); 644 $mform->addElement('advcheckbox', 'reset_lesson', get_string('deleteallattempts','lesson')); 645 } 646 647 /** 648 * Course reset form defaults. 649 * @param object $course 650 * @return array 651 */ 652 function lesson_reset_course_form_defaults($course) { 653 return array('reset_lesson'=>1); 654 } 655 656 /** 657 * Removes all grades from gradebook 658 * 659 * @global stdClass 660 * @global object 661 * @param int $courseid 662 * @param string optional type 663 */ 664 function lesson_reset_gradebook($courseid, $type='') { 665 global $CFG, $DB; 666 667 $sql = "SELECT l.*, cm.idnumber as cmidnumber, l.course as courseid 668 FROM {lesson} l, {course_modules} cm, {modules} m 669 WHERE m.name='lesson' AND m.id=cm.module AND cm.instance=l.id AND l.course=:course"; 670 $params = array ("course" => $courseid); 671 if ($lessons = $DB->get_records_sql($sql,$params)) { 672 foreach ($lessons as $lesson) { 673 lesson_grade_item_update($lesson, 'reset'); 674 } 675 } 676 } 677 678 /** 679 * Actual implementation of the reset course functionality, delete all the 680 * lesson attempts for course $data->courseid. 681 * 682 * @global stdClass 683 * @global object 684 * @param object $data the data submitted from the reset course. 685 * @return array status array 686 */ 687 function lesson_reset_userdata($data) { 688 global $CFG, $DB; 689 690 $componentstr = get_string('modulenameplural', 'lesson'); 691 $status = array(); 692 693 if (!empty($data->reset_lesson)) { 694 $lessonssql = "SELECT l.id 695 FROM {lesson} l 696 WHERE l.course=:course"; 697 698 $params = array ("course" => $data->courseid); 699 $DB->delete_records_select('lesson_timer', "lessonid IN ($lessonssql)", $params); 700 $DB->delete_records_select('lesson_high_scores', "lessonid IN ($lessonssql)", $params); 701 $DB->delete_records_select('lesson_grades', "lessonid IN ($lessonssql)", $params); 702 $DB->delete_records_select('lesson_attempts', "lessonid IN ($lessonssql)", $params); 703 704 // remove all grades from gradebook 705 if (empty($data->reset_gradebook_grades)) { 706 lesson_reset_gradebook($data->courseid); 707 } 708 709 $status[] = array('component'=>$componentstr, 'item'=>get_string('deleteallattempts', 'lesson'), 'error'=>false); 710 } 711 712 /// updating dates - shift may be negative too 713 if ($data->timeshift) { 714 shift_course_mod_dates('lesson', array('available', 'deadline'), $data->timeshift, $data->courseid); 715 $status[] = array('component'=>$componentstr, 'item'=>get_string('datechanged'), 'error'=>false); 716 } 717 718 return $status; 719 } 720 721 /** 722 * Returns all other caps used in module 723 * @return array 724 */ 725 function lesson_get_extra_capabilities() { 726 return array('moodle/site:accessallgroups'); 727 } 728 729 /** 730 * @uses FEATURE_GROUPS 731 * @uses FEATURE_GROUPINGS 732 * @uses FEATURE_MOD_INTRO 733 * @uses FEATURE_COMPLETION_TRACKS_VIEWS 734 * @uses FEATURE_GRADE_HAS_GRADE 735 * @uses FEATURE_GRADE_OUTCOMES 736 * @param string $feature FEATURE_xx constant for requested feature 737 * @return mixed True if module supports feature, false if not, null if doesn't know 738 */ 739 function lesson_supports($feature) { 740 switch($feature) { 741 case FEATURE_GROUPS: 742 return false; 743 case FEATURE_GROUPINGS: 744 return false; 745 case FEATURE_GROUPMEMBERSONLY: 746 return true; 747 case FEATURE_MOD_INTRO: 748 return true; 749 case FEATURE_COMPLETION_TRACKS_VIEWS: 750 return true; 751 case FEATURE_GRADE_HAS_GRADE: 752 return true; 753 case FEATURE_GRADE_OUTCOMES: 754 return true; 755 case FEATURE_BACKUP_MOODLE2: 756 return true; 757 case FEATURE_SHOW_DESCRIPTION: 758 return true; 759 default: 760 return null; 761 } 762 } 763 764 /** 765 * This function extends the settings navigation block for the site. 766 * 767 * It is safe to rely on PAGE here as we will only ever be within the module 768 * context when this is called 769 * 770 * @param settings_navigation $settings 771 * @param navigation_node $lessonnode 772 */ 773 function lesson_extend_settings_navigation($settings, $lessonnode) { 774 global $PAGE, $DB; 775 776 $url = new moodle_url('/mod/lesson/view.php', array('id'=>$PAGE->cm->id)); 777 $lessonnode->add(get_string('preview', 'lesson'), $url); 778 779 if (has_capability('mod/lesson:edit', $PAGE->cm->context)) { 780 $url = new moodle_url('/mod/lesson/edit.php', array('id'=>$PAGE->cm->id)); 781 $lessonnode->add(get_string('edit', 'lesson'), $url); 782 } 783 784 if (has_capability('mod/lesson:manage', $PAGE->cm->context)) { 785 $reportsnode = $lessonnode->add(get_string('reports', 'lesson')); 786 $url = new moodle_url('/mod/lesson/report.php', array('id'=>$PAGE->cm->id, 'action'=>'reportoverview')); 787 $reportsnode->add(get_string('overview', 'lesson'), $url); 788 $url = new moodle_url('/mod/lesson/report.php', array('id'=>$PAGE->cm->id, 'action'=>'reportdetail')); 789 $reportsnode->add(get_string('detailedstats', 'lesson'), $url); 790 } 791 792 if (has_capability('mod/lesson:grade', $PAGE->cm->context)) { 793 $url = new moodle_url('/mod/lesson/essay.php', array('id'=>$PAGE->cm->id)); 794 $lessonnode->add(get_string('manualgrading', 'lesson'), $url); 795 } 796 797 if ($PAGE->activityrecord->highscores) { 798 $url = new moodle_url('/mod/lesson/highscores.php', array('id'=>$PAGE->cm->id)); 799 $lessonnode->add(get_string('highscores', 'lesson'), $url); 800 } 801 } 802 803 /** 804 * Get list of available import or export formats 805 * 806 * Copied and modified from lib/questionlib.php 807 * 808 * @param string $type 'import' if import list, otherwise export list assumed 809 * @return array sorted list of import/export formats available 810 */ 811 function lesson_get_import_export_formats($type) { 812 global $CFG; 813 $fileformats = core_component::get_plugin_list("qformat"); 814 815 $fileformatname=array(); 816 foreach ($fileformats as $fileformat=>$fdir) { 817 $format_file = "$fdir/format.php"; 818 if (file_exists($format_file) ) { 819 require_once($format_file); 820 } else { 821 continue; 822 } 823 $classname = "qformat_$fileformat"; 824 $format_class = new $classname(); 825 if ($type=='import') { 826 $provided = $format_class->provide_import(); 827 } else { 828 $provided = $format_class->provide_export(); 829 } 830 if ($provided) { 831 $fileformatnames[$fileformat] = get_string('pluginname', 'qformat_'.$fileformat); 832 } 833 } 834 natcasesort($fileformatnames); 835 836 return $fileformatnames; 837 } 838 839 /** 840 * Serves the lesson attachments. Implements needed access control ;-) 841 * 842 * @package mod_lesson 843 * @category files 844 * @param stdClass $course course object 845 * @param stdClass $cm course module object 846 * @param stdClass $context context object 847 * @param string $filearea file area 848 * @param array $args extra arguments 849 * @param bool $forcedownload whether or not force download 850 * @param array $options additional options affecting the file serving 851 * @return bool false if file not found, does not return if found - justsend the file 852 */ 853 function lesson_pluginfile($course, $cm, $context, $filearea, $args, $forcedownload, array $options=array()) { 854 global $CFG, $DB; 855 856 if ($context->contextlevel != CONTEXT_MODULE) { 857 return false; 858 } 859 860 $fileareas = lesson_get_file_areas(); 861 if (!array_key_exists($filearea, $fileareas)) { 862 return false; 863 } 864 865 if (!$lesson = $DB->get_record('lesson', array('id'=>$cm->instance))) { 866 return false; 867 } 868 869 require_course_login($course, true, $cm); 870 871 if ($filearea === 'page_contents') { 872 $pageid = (int)array_shift($args); 873 if (!$page = $DB->get_record('lesson_pages', array('id'=>$pageid))) { 874 return false; 875 } 876 $fullpath = "/$context->id/mod_lesson/$filearea/$pageid/".implode('/', $args); 877 878 } else if ($filearea === 'page_answers' || $filearea === 'page_responses') { 879 $itemid = (int)array_shift($args); 880 if (!$pageanswers = $DB->get_record('lesson_answers', array('id' => $itemid))) { 881 return false; 882 } 883 $fullpath = "/$context->id/mod_lesson/$filearea/$itemid/".implode('/', $args); 884 885 } else if ($filearea === 'mediafile') { 886 if (count($args) > 1) { 887 // Remove the itemid when it appears to be part of the arguments. If there is only one argument 888 // then it is surely the file name. The itemid is sometimes used to prevent browser caching. 889 array_shift($args); 890 } 891 $fullpath = "/$context->id/mod_lesson/$filearea/0/".implode('/', $args); 892 893 } else { 894 return false; 895 } 896 897 $fs = get_file_storage(); 898 if (!$file = $fs->get_file_by_hash(sha1($fullpath)) or $file->is_directory()) { 899 return false; 900 } 901 902 // finally send the file 903 send_stored_file($file, 0, 0, $forcedownload, $options); // download MUST be forced - security! 904 } 905 906 /** 907 * Returns an array of file areas 908 * 909 * @package mod_lesson 910 * @category files 911 * @return array a list of available file areas 912 */ 913 function lesson_get_file_areas() { 914 $areas = array(); 915 $areas['page_contents'] = get_string('pagecontents', 'mod_lesson'); 916 $areas['mediafile'] = get_string('mediafile', 'mod_lesson'); 917 $areas['page_answers'] = get_string('pageanswers', 'mod_lesson'); 918 $areas['page_responses'] = get_string('pageresponses', 'mod_lesson'); 919 return $areas; 920 } 921 922 /** 923 * Returns a file_info_stored object for the file being requested here 924 * 925 * @package mod_lesson 926 * @category files 927 * @global stdClass $CFG 928 * @param file_browse $browser file browser instance 929 * @param array $areas file areas 930 * @param stdClass $course course object 931 * @param stdClass $cm course module object 932 * @param stdClass $context context object 933 * @param string $filearea file area 934 * @param int $itemid item ID 935 * @param string $filepath file path 936 * @param string $filename file name 937 * @return file_info_stored 938 */ 939 function lesson_get_file_info($browser, $areas, $course, $cm, $context, $filearea, $itemid, $filepath, $filename) { 940 global $CFG, $DB; 941 942 if (!has_capability('moodle/course:managefiles', $context)) { 943 // No peaking here for students! 944 return null; 945 } 946 947 // Mediafile area does not have sub directories, so let's select the default itemid to prevent 948 // the user from selecting a directory to access the mediafile content. 949 if ($filearea == 'mediafile' && is_null($itemid)) { 950 $itemid = 0; 951 } 952 953 if (is_null($itemid)) { 954 return new mod_lesson_file_info($browser, $course, $cm, $context, $areas, $filearea); 955 } 956 957 $fs = get_file_storage(); 958 $filepath = is_null($filepath) ? '/' : $filepath; 959 $filename = is_null($filename) ? '.' : $filename; 960 if (!$storedfile = $fs->get_file($context->id, 'mod_lesson', $filearea, $itemid, $filepath, $filename)) { 961 return null; 962 } 963 964 $itemname = $filearea; 965 if ($filearea == 'page_contents') { 966 $itemname = $DB->get_field('lesson_pages', 'title', array('lessonid' => $cm->instance, 'id' => $itemid)); 967 $itemname = format_string($itemname, true, array('context' => $context)); 968 } else { 969 $areas = lesson_get_file_areas(); 970 if (isset($areas[$filearea])) { 971 $itemname = $areas[$filearea]; 972 } 973 } 974 975 $urlbase = $CFG->wwwroot . '/pluginfile.php'; 976 return new file_info_stored($browser, $context, $storedfile, $urlbase, $itemname, $itemid, true, true, false); 977 } 978 979 980 /** 981 * Return a list of page types 982 * @param string $pagetype current page type 983 * @param stdClass $parentcontext Block's parent context 984 * @param stdClass $currentcontext Current context of block 985 */ 986 function lesson_page_type_list($pagetype, $parentcontext, $currentcontext) { 987 $module_pagetype = array( 988 'mod-lesson-*'=>get_string('page-mod-lesson-x', 'lesson'), 989 'mod-lesson-view'=>get_string('page-mod-lesson-view', 'lesson'), 990 'mod-lesson-edit'=>get_string('page-mod-lesson-edit', 'lesson')); 991 return $module_pagetype; 992 } 993 994 /** 995 * Update the lesson activity to include any file 996 * that was uploaded, or if there is none, set the 997 * mediafile field to blank. 998 * 999 * @param int $lessonid the lesson id 1000 * @param stdClass $context the context 1001 * @param int $draftitemid the draft item 1002 */ 1003 function lesson_update_media_file($lessonid, $context, $draftitemid) { 1004 global $DB; 1005 1006 // Set the filestorage object. 1007 $fs = get_file_storage(); 1008 // Save the file if it exists that is currently in the draft area. 1009 file_save_draft_area_files($draftitemid, $context->id, 'mod_lesson', 'mediafile', 0); 1010 // Get the file if it exists. 1011 $files = $fs->get_area_files($context->id, 'mod_lesson', 'mediafile', 0, 'itemid, filepath, filename', false); 1012 // Check that there is a file to process. 1013 if (count($files) == 1) { 1014 // Get the first (and only) file. 1015 $file = reset($files); 1016 // Set the mediafile column in the lessons table. 1017 $DB->set_field('lesson', 'mediafile', '/' . $file->get_filename(), array('id' => $lessonid)); 1018 } else { 1019 // Set the mediafile column in the lessons table. 1020 $DB->set_field('lesson', 'mediafile', '', array('id' => $lessonid)); 1021 } 1022 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Fri Nov 28 20:29:05 2014 | Cross-referenced by PHPXref 0.7.1 |