[ Index ] |
PHP Cross Reference of Unnamed Project |
[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_update_media_file($lessonid, $context, $draftitemid); 55 56 lesson_process_post_save($data); 57 58 lesson_grade_item_update($data); 59 60 return $lessonid; 61 } 62 63 /** 64 * Given an object containing all the necessary data, 65 * (defined by the form in mod_form.php) this function 66 * will update an existing instance with new data. 67 * 68 * @global object 69 * @param object $lesson Lesson post data from the form 70 * @return boolean 71 **/ 72 function lesson_update_instance($data, $mform) { 73 global $DB; 74 75 $data->id = $data->instance; 76 $cmid = $data->coursemodule; 77 $draftitemid = $data->mediafile; 78 $context = context_module::instance($cmid); 79 80 lesson_process_pre_save($data); 81 82 unset($data->mediafile); 83 $DB->update_record("lesson", $data); 84 85 lesson_update_media_file($data->id, $context, $draftitemid); 86 87 lesson_process_post_save($data); 88 89 // update grade item definition 90 lesson_grade_item_update($data); 91 92 // update grades - TODO: do it only when grading style changes 93 lesson_update_grades($data, 0, false); 94 95 return true; 96 } 97 98 /** 99 * This function updates the events associated to the lesson. 100 * If $override is non-zero, then it updates only the events 101 * associated with the specified override. 102 * 103 * @uses LESSON_MAX_EVENT_LENGTH 104 * @param object $lesson the lesson object. 105 * @param object $override (optional) limit to a specific override 106 */ 107 function lesson_update_events($lesson, $override = null) { 108 global $CFG, $DB; 109 110 require_once($CFG->dirroot . '/calendar/lib.php'); 111 112 // Load the old events relating to this lesson. 113 $conds = array('modulename' => 'lesson', 114 'instance' => $lesson->id); 115 if (!empty($override)) { 116 // Only load events for this override. 117 if (isset($override->userid)) { 118 $conds['userid'] = $override->userid; 119 } else { 120 $conds['groupid'] = $override->groupid; 121 } 122 } 123 $oldevents = $DB->get_records('event', $conds); 124 125 // Now make a todo list of all that needs to be updated. 126 if (empty($override)) { 127 // We are updating the primary settings for the lesson, so we 128 // need to add all the overrides. 129 $overrides = $DB->get_records('lesson_overrides', array('lessonid' => $lesson->id)); 130 // As well as the original lesson (empty override). 131 $overrides[] = new stdClass(); 132 } else { 133 // Just do the one override. 134 $overrides = array($override); 135 } 136 137 foreach ($overrides as $current) { 138 $groupid = isset($current->groupid) ? $current->groupid : 0; 139 $userid = isset($current->userid) ? $current->userid : 0; 140 $available = isset($current->available) ? $current->available : $lesson->available; 141 $deadline = isset($current->deadline) ? $current->deadline : $lesson->deadline; 142 143 // Only add open/close events for an override if they differ from the lesson default. 144 $addopen = empty($current->id) || !empty($current->available); 145 $addclose = empty($current->id) || !empty($current->deadline); 146 147 if (!empty($lesson->coursemodule)) { 148 $cmid = $lesson->coursemodule; 149 } else { 150 $cmid = get_coursemodule_from_instance('lesson', $lesson->id, $lesson->course)->id; 151 } 152 153 $event = new stdClass(); 154 $event->description = format_module_intro('lesson', $lesson, $cmid); 155 // Events module won't show user events when the courseid is nonzero. 156 $event->courseid = ($userid) ? 0 : $lesson->course; 157 $event->groupid = $groupid; 158 $event->userid = $userid; 159 $event->modulename = 'lesson'; 160 $event->instance = $lesson->id; 161 $event->timestart = $available; 162 $event->timeduration = max($deadline - $available, 0); 163 $event->visible = instance_is_visible('lesson', $lesson); 164 $event->eventtype = 'open'; 165 166 // Determine the event name. 167 if ($groupid) { 168 $params = new stdClass(); 169 $params->lesson = $lesson->name; 170 $params->group = groups_get_group_name($groupid); 171 if ($params->group === false) { 172 // Group doesn't exist, just skip it. 173 continue; 174 } 175 $eventname = get_string('overridegroupeventname', 'lesson', $params); 176 } else if ($userid) { 177 $params = new stdClass(); 178 $params->lesson = $lesson->name; 179 $eventname = get_string('overrideusereventname', 'lesson', $params); 180 } else { 181 $eventname = $lesson->name; 182 } 183 if ($addopen or $addclose) { 184 if ($deadline and $available and $event->timeduration <= LESSON_MAX_EVENT_LENGTH) { 185 // Single event for the whole lesson. 186 if ($oldevent = array_shift($oldevents)) { 187 $event->id = $oldevent->id; 188 } else { 189 unset($event->id); 190 } 191 $event->name = $eventname; 192 // The method calendar_event::create will reuse a db record if the id field is set. 193 calendar_event::create($event); 194 } else { 195 // Separate start and end events. 196 $event->timeduration = 0; 197 if ($available && $addopen) { 198 if ($oldevent = array_shift($oldevents)) { 199 $event->id = $oldevent->id; 200 } else { 201 unset($event->id); 202 } 203 $event->name = $eventname.' ('.get_string('lessonopens', 'lesson').')'; 204 // The method calendar_event::create will reuse a db record if the id field is set. 205 calendar_event::create($event); 206 } 207 if ($deadline && $addclose) { 208 if ($oldevent = array_shift($oldevents)) { 209 $event->id = $oldevent->id; 210 } else { 211 unset($event->id); 212 } 213 $event->name = $eventname.' ('.get_string('lessoncloses', 'lesson').')'; 214 $event->timestart = $deadline; 215 $event->eventtype = 'close'; 216 calendar_event::create($event); 217 } 218 } 219 } 220 } 221 222 // Delete any leftover events. 223 foreach ($oldevents as $badevent) { 224 $badevent = calendar_event::load($badevent); 225 $badevent->delete(); 226 } 227 } 228 229 /** 230 * This standard function will check all instances of this module 231 * and make sure there are up-to-date events created for each of them. 232 * If courseid = 0, then every lesson event in the site is checked, else 233 * only lesson events belonging to the course specified are checked. 234 * This function is used, in its new format, by restore_refresh_events() 235 * 236 * @param int $courseid 237 * @return bool 238 */ 239 function lesson_refresh_events($courseid = 0) { 240 global $DB; 241 242 if ($courseid == 0) { 243 if (!$lessons = $DB->get_records('lessons')) { 244 return true; 245 } 246 } else { 247 if (!$lessons = $DB->get_records('lesson', array('course' => $courseid))) { 248 return true; 249 } 250 } 251 252 foreach ($lessons as $lesson) { 253 lesson_update_events($lesson); 254 } 255 256 return true; 257 } 258 259 /** 260 * Given an ID of an instance of this module, 261 * this function will permanently delete the instance 262 * and any data that depends on it. 263 * 264 * @global object 265 * @param int $id 266 * @return bool 267 */ 268 function lesson_delete_instance($id) { 269 global $DB, $CFG; 270 require_once($CFG->dirroot . '/mod/lesson/locallib.php'); 271 272 $lesson = $DB->get_record("lesson", array("id"=>$id), '*', MUST_EXIST); 273 $lesson = new lesson($lesson); 274 return $lesson->delete(); 275 } 276 277 /** 278 * Return a small object with summary information about what a 279 * user has done with a given particular instance of this module 280 * Used for user activity reports. 281 * $return->time = the time they did it 282 * $return->info = a short text description 283 * 284 * @global object 285 * @param object $course 286 * @param object $user 287 * @param object $mod 288 * @param object $lesson 289 * @return object 290 */ 291 function lesson_user_outline($course, $user, $mod, $lesson) { 292 global $CFG, $DB; 293 294 require_once("$CFG->libdir/gradelib.php"); 295 $grades = grade_get_grades($course->id, 'mod', 'lesson', $lesson->id, $user->id); 296 $return = new stdClass(); 297 298 if (empty($grades->items[0]->grades)) { 299 $return->info = get_string("nolessonattempts", "lesson"); 300 } else { 301 $grade = reset($grades->items[0]->grades); 302 if (empty($grade->grade)) { 303 304 // Check to see if it an ungraded / incomplete attempt. 305 $sql = "SELECT * 306 FROM {lesson_timer} 307 WHERE lessonid = :lessonid 308 AND userid = :userid 309 ORDER BY starttime DESC"; 310 $params = array('lessonid' => $lesson->id, 'userid' => $user->id); 311 312 if ($attempts = $DB->get_records_sql($sql, $params, 0, 1)) { 313 $attempt = reset($attempts); 314 if ($attempt->completed) { 315 $return->info = get_string("completed", "lesson"); 316 } else { 317 $return->info = get_string("notyetcompleted", "lesson"); 318 } 319 $return->time = $attempt->lessontime; 320 } else { 321 $return->info = get_string("nolessonattempts", "lesson"); 322 } 323 } else { 324 $return->info = get_string("grade") . ': ' . $grade->str_long_grade; 325 326 // Datesubmitted == time created. dategraded == time modified or time overridden. 327 // If grade was last modified by the user themselves use date graded. Otherwise use date submitted. 328 // TODO: move this copied & pasted code somewhere in the grades API. See MDL-26704. 329 if ($grade->usermodified == $user->id || empty($grade->datesubmitted)) { 330 $return->time = $grade->dategraded; 331 } else { 332 $return->time = $grade->datesubmitted; 333 } 334 } 335 } 336 return $return; 337 } 338 339 /** 340 * Print a detailed representation of what a user has done with 341 * a given particular instance of this module, for user activity reports. 342 * 343 * @global object 344 * @param object $course 345 * @param object $user 346 * @param object $mod 347 * @param object $lesson 348 * @return bool 349 */ 350 function lesson_user_complete($course, $user, $mod, $lesson) { 351 global $DB, $OUTPUT, $CFG; 352 353 require_once("$CFG->libdir/gradelib.php"); 354 355 $grades = grade_get_grades($course->id, 'mod', 'lesson', $lesson->id, $user->id); 356 357 // Display the grade and feedback. 358 if (empty($grades->items[0]->grades)) { 359 echo $OUTPUT->container(get_string("nolessonattempts", "lesson")); 360 } else { 361 $grade = reset($grades->items[0]->grades); 362 if (empty($grade->grade)) { 363 // Check to see if it an ungraded / incomplete attempt. 364 $sql = "SELECT * 365 FROM {lesson_timer} 366 WHERE lessonid = :lessonid 367 AND userid = :userid 368 ORDER by starttime desc"; 369 $params = array('lessonid' => $lesson->id, 'userid' => $user->id); 370 371 if ($attempt = $DB->get_record_sql($sql, $params, IGNORE_MULTIPLE)) { 372 if ($attempt->completed) { 373 $status = get_string("completed", "lesson"); 374 } else { 375 $status = get_string("notyetcompleted", "lesson"); 376 } 377 } else { 378 $status = get_string("nolessonattempts", "lesson"); 379 } 380 } else { 381 $status = get_string("grade") . ': ' . $grade->str_long_grade; 382 } 383 384 // Display the grade or lesson status if there isn't one. 385 echo $OUTPUT->container($status); 386 387 if ($grade->str_feedback) { 388 echo $OUTPUT->container(get_string('feedback').': '.$grade->str_feedback); 389 } 390 } 391 392 // Display the lesson progress. 393 // Attempt, pages viewed, questions answered, correct answers, time. 394 $params = array ("lessonid" => $lesson->id, "userid" => $user->id); 395 $attempts = $DB->get_records_select("lesson_attempts", "lessonid = :lessonid AND userid = :userid", $params, "retry, timeseen"); 396 $branches = $DB->get_records_select("lesson_branch", "lessonid = :lessonid AND userid = :userid", $params, "retry, timeseen"); 397 if (!empty($attempts) or !empty($branches)) { 398 echo $OUTPUT->box_start(); 399 $table = new html_table(); 400 // Table Headings. 401 $table->head = array (get_string("attemptheader", "lesson"), 402 get_string("totalpagesviewedheader", "lesson"), 403 get_string("numberofpagesviewedheader", "lesson"), 404 get_string("numberofcorrectanswersheader", "lesson"), 405 get_string("time")); 406 $table->width = "100%"; 407 $table->align = array ("center", "center", "center", "center", "center"); 408 $table->size = array ("*", "*", "*", "*", "*"); 409 $table->cellpadding = 2; 410 $table->cellspacing = 0; 411 412 $retry = 0; 413 $nquestions = 0; 414 $npages = 0; 415 $ncorrect = 0; 416 417 // Filter question pages (from lesson_attempts). 418 foreach ($attempts as $attempt) { 419 if ($attempt->retry == $retry) { 420 $npages++; 421 $nquestions++; 422 if ($attempt->correct) { 423 $ncorrect++; 424 } 425 $timeseen = $attempt->timeseen; 426 } else { 427 $table->data[] = array($retry + 1, $npages, $nquestions, $ncorrect, userdate($timeseen)); 428 $retry++; 429 $nquestions = 1; 430 $npages = 1; 431 if ($attempt->correct) { 432 $ncorrect = 1; 433 } else { 434 $ncorrect = 0; 435 } 436 } 437 } 438 439 // Filter content pages (from lesson_branch). 440 foreach ($branches as $branch) { 441 if ($branch->retry == $retry) { 442 $npages++; 443 444 $timeseen = $branch->timeseen; 445 } else { 446 $table->data[] = array($retry + 1, $npages, $nquestions, $ncorrect, userdate($timeseen)); 447 $retry++; 448 $npages = 1; 449 } 450 } 451 if ($npages > 0) { 452 $table->data[] = array($retry + 1, $npages, $nquestions, $ncorrect, userdate($timeseen)); 453 } 454 echo html_writer::table($table); 455 echo $OUTPUT->box_end(); 456 } 457 458 return true; 459 } 460 461 /** 462 * Prints lesson summaries on MyMoodle Page 463 * 464 * Prints lesson name, due date and attempt information on 465 * lessons that have a deadline that has not already passed 466 * and it is available for taking. 467 * 468 * @global object 469 * @global stdClass 470 * @global object 471 * @uses CONTEXT_MODULE 472 * @param array $courses An array of course objects to get lesson instances from 473 * @param array $htmlarray Store overview output array( course ID => 'lesson' => HTML output ) 474 * @return void 475 */ 476 function lesson_print_overview($courses, &$htmlarray) { 477 global $USER, $CFG, $DB, $OUTPUT; 478 479 if (!$lessons = get_all_instances_in_courses('lesson', $courses)) { 480 return; 481 } 482 483 // Get all of the current users attempts on all lessons. 484 $params = array($USER->id); 485 $sql = 'SELECT lessonid, userid, count(userid) as attempts 486 FROM {lesson_grades} 487 WHERE userid = ? 488 GROUP BY lessonid, userid'; 489 $allattempts = $DB->get_records_sql($sql, $params); 490 $completedattempts = array(); 491 foreach ($allattempts as $myattempt) { 492 $completedattempts[$myattempt->lessonid] = $myattempt->attempts; 493 } 494 495 // Get the current course ID. 496 $listoflessons = array(); 497 foreach ($lessons as $lesson) { 498 $listoflessons[] = $lesson->id; 499 } 500 // Get the last page viewed by the current user for every lesson in this course. 501 list($insql, $inparams) = $DB->get_in_or_equal($listoflessons, SQL_PARAMS_NAMED); 502 $dbparams = array_merge($inparams, array('userid' => $USER->id)); 503 504 // Get the lesson attempts for the user that have the maximum 'timeseen' value. 505 $select = "SELECT l.id, l.timeseen, l.lessonid, l.userid, l.retry, l.pageid, l.answerid as nextpageid, p.qtype "; 506 $from = "FROM {lesson_attempts} l 507 JOIN ( 508 SELECT idselect.lessonid, idselect.userid, MAX(idselect.id) AS id 509 FROM {lesson_attempts} idselect 510 JOIN ( 511 SELECT lessonid, userid, MAX(timeseen) AS timeseen 512 FROM {lesson_attempts} 513 WHERE userid = :userid 514 AND lessonid $insql 515 GROUP BY userid, lessonid 516 ) timeselect 517 ON timeselect.timeseen = idselect.timeseen 518 AND timeselect.userid = idselect.userid 519 AND timeselect.lessonid = idselect.lessonid 520 GROUP BY idselect.userid, idselect.lessonid 521 ) aid 522 ON l.id = aid.id 523 JOIN {lesson_pages} p 524 ON l.pageid = p.id "; 525 $lastattempts = $DB->get_records_sql($select . $from, $dbparams); 526 527 // Now, get the lesson branches for the user that have the maximum 'timeseen' value. 528 $select = "SELECT l.id, l.timeseen, l.lessonid, l.userid, l.retry, l.pageid, l.nextpageid, p.qtype "; 529 $from = str_replace('{lesson_attempts}', '{lesson_branch}', $from); 530 $lastbranches = $DB->get_records_sql($select . $from, $dbparams); 531 532 $lastviewed = array(); 533 foreach ($lastattempts as $lastattempt) { 534 $lastviewed[$lastattempt->lessonid] = $lastattempt; 535 } 536 537 // Go through the branch times and record the 'timeseen' value if it doesn't exist 538 // for the lesson, or replace it if it exceeds the current recorded time. 539 foreach ($lastbranches as $lastbranch) { 540 if (!isset($lastviewed[$lastbranch->lessonid])) { 541 $lastviewed[$lastbranch->lessonid] = $lastbranch; 542 } else if ($lastviewed[$lastbranch->lessonid]->timeseen < $lastbranch->timeseen) { 543 $lastviewed[$lastbranch->lessonid] = $lastbranch; 544 } 545 } 546 547 // Since we have lessons in this course, now include the constants we need. 548 require_once($CFG->dirroot . '/mod/lesson/locallib.php'); 549 550 $now = time(); 551 foreach ($lessons as $lesson) { 552 if ($lesson->deadline != 0 // The lesson has a deadline 553 and $lesson->deadline >= $now // And it is before the deadline has been met 554 and ($lesson->available == 0 or $lesson->available <= $now)) { // And the lesson is available 555 556 // Visibility. 557 $class = (!$lesson->visible) ? 'dimmed' : ''; 558 559 // Context. 560 $context = context_module::instance($lesson->coursemodule); 561 562 // Link to activity. 563 $url = new moodle_url('/mod/lesson/view.php', array('id' => $lesson->coursemodule)); 564 $url = html_writer::link($url, format_string($lesson->name, true, array('context' => $context)), array('class' => $class)); 565 $str = $OUTPUT->box(get_string('lessonname', 'lesson', $url), 'name'); 566 567 // Deadline. 568 $str .= $OUTPUT->box(get_string('lessoncloseson', 'lesson', userdate($lesson->deadline)), 'info'); 569 570 // Attempt information. 571 if (has_capability('mod/lesson:manage', $context)) { 572 // This is a teacher, Get the Number of user attempts. 573 $attempts = $DB->count_records('lesson_grades', array('lessonid' => $lesson->id)); 574 $str .= $OUTPUT->box(get_string('xattempts', 'lesson', $attempts), 'info'); 575 $str = $OUTPUT->box($str, 'lesson overview'); 576 } else { 577 // This is a student, See if the user has at least started the lesson. 578 if (isset($lastviewed[$lesson->id]->timeseen)) { 579 // See if the user has finished this attempt. 580 if (isset($completedattempts[$lesson->id]) && 581 ($completedattempts[$lesson->id] == ($lastviewed[$lesson->id]->retry + 1))) { 582 // Are additional attempts allowed? 583 if ($lesson->retake) { 584 // User can retake the lesson. 585 $str .= $OUTPUT->box(get_string('additionalattemptsremaining', 'lesson'), 'info'); 586 $str = $OUTPUT->box($str, 'lesson overview'); 587 } else { 588 // User has completed the lesson and no retakes are allowed. 589 $str = ''; 590 } 591 592 } else { 593 // The last attempt was not finished or the lesson does not contain questions. 594 // See if the last page viewed was a branchtable. 595 require_once($CFG->dirroot . '/mod/lesson/pagetypes/branchtable.php'); 596 if ($lastviewed[$lesson->id]->qtype == LESSON_PAGE_BRANCHTABLE) { 597 // See if the next pageid is the end of lesson. 598 if ($lastviewed[$lesson->id]->nextpageid == LESSON_EOL) { 599 // The last page viewed was the End of Lesson. 600 if ($lesson->retake) { 601 // User can retake the lesson. 602 $str .= $OUTPUT->box(get_string('additionalattemptsremaining', 'lesson'), 'info'); 603 $str = $OUTPUT->box($str, 'lesson overview'); 604 } else { 605 // User has completed the lesson and no retakes are allowed. 606 $str = ''; 607 } 608 609 } else { 610 // The last page viewed was NOT the end of lesson. 611 $str .= $OUTPUT->box(get_string('notyetcompleted', 'lesson'), 'info'); 612 $str = $OUTPUT->box($str, 'lesson overview'); 613 } 614 615 } else { 616 // Last page was a question page, so the attempt is not completed yet. 617 $str .= $OUTPUT->box(get_string('notyetcompleted', 'lesson'), 'info'); 618 $str = $OUTPUT->box($str, 'lesson overview'); 619 } 620 } 621 622 } else { 623 // User has not yet started this lesson. 624 $str .= $OUTPUT->box(get_string('nolessonattempts', 'lesson'), 'info'); 625 $str = $OUTPUT->box($str, 'lesson overview'); 626 } 627 } 628 if (!empty($str)) { 629 if (empty($htmlarray[$lesson->course]['lesson'])) { 630 $htmlarray[$lesson->course]['lesson'] = $str; 631 } else { 632 $htmlarray[$lesson->course]['lesson'] .= $str; 633 } 634 } 635 } 636 } 637 } 638 639 /** 640 * Function to be run periodically according to the moodle cron 641 * This function searches for things that need to be done, such 642 * as sending out mail, toggling flags etc ... 643 * @global stdClass 644 * @return bool true 645 */ 646 function lesson_cron () { 647 global $CFG; 648 649 return true; 650 } 651 652 /** 653 * Return grade for given user or all users. 654 * 655 * @global stdClass 656 * @global object 657 * @param int $lessonid id of lesson 658 * @param int $userid optional user id, 0 means all users 659 * @return array array of grades, false if none 660 */ 661 function lesson_get_user_grades($lesson, $userid=0) { 662 global $CFG, $DB; 663 664 $params = array("lessonid" => $lesson->id,"lessonid2" => $lesson->id); 665 666 if (!empty($userid)) { 667 $params["userid"] = $userid; 668 $params["userid2"] = $userid; 669 $user = "AND u.id = :userid"; 670 $fuser = "AND uu.id = :userid2"; 671 } 672 else { 673 $user=""; 674 $fuser=""; 675 } 676 677 if ($lesson->retake) { 678 if ($lesson->usemaxgrade) { 679 $sql = "SELECT u.id, u.id AS userid, MAX(g.grade) AS rawgrade 680 FROM {user} u, {lesson_grades} g 681 WHERE u.id = g.userid AND g.lessonid = :lessonid 682 $user 683 GROUP BY u.id"; 684 } else { 685 $sql = "SELECT u.id, u.id AS userid, AVG(g.grade) AS rawgrade 686 FROM {user} u, {lesson_grades} g 687 WHERE u.id = g.userid AND g.lessonid = :lessonid 688 $user 689 GROUP BY u.id"; 690 } 691 unset($params['lessonid2']); 692 unset($params['userid2']); 693 } else { 694 // use only first attempts (with lowest id in lesson_grades table) 695 $firstonly = "SELECT uu.id AS userid, MIN(gg.id) AS firstcompleted 696 FROM {user} uu, {lesson_grades} gg 697 WHERE uu.id = gg.userid AND gg.lessonid = :lessonid2 698 $fuser 699 GROUP BY uu.id"; 700 701 $sql = "SELECT u.id, u.id AS userid, g.grade AS rawgrade 702 FROM {user} u, {lesson_grades} g, ($firstonly) f 703 WHERE u.id = g.userid AND g.lessonid = :lessonid 704 AND g.id = f.firstcompleted AND g.userid=f.userid 705 $user"; 706 } 707 708 return $DB->get_records_sql($sql, $params); 709 } 710 711 /** 712 * Update grades in central gradebook 713 * 714 * @category grade 715 * @param object $lesson 716 * @param int $userid specific user only, 0 means all 717 * @param bool $nullifnone 718 */ 719 function lesson_update_grades($lesson, $userid=0, $nullifnone=true) { 720 global $CFG, $DB; 721 require_once($CFG->libdir.'/gradelib.php'); 722 723 if ($lesson->grade == 0 || $lesson->practice) { 724 lesson_grade_item_update($lesson); 725 726 } else if ($grades = lesson_get_user_grades($lesson, $userid)) { 727 lesson_grade_item_update($lesson, $grades); 728 729 } else if ($userid and $nullifnone) { 730 $grade = new stdClass(); 731 $grade->userid = $userid; 732 $grade->rawgrade = null; 733 lesson_grade_item_update($lesson, $grade); 734 735 } else { 736 lesson_grade_item_update($lesson); 737 } 738 } 739 740 /** 741 * Create grade item for given lesson 742 * 743 * @category grade 744 * @uses GRADE_TYPE_VALUE 745 * @uses GRADE_TYPE_NONE 746 * @param object $lesson object with extra cmidnumber 747 * @param array|object $grades optional array/object of grade(s); 'reset' means reset grades in gradebook 748 * @return int 0 if ok, error code otherwise 749 */ 750 function lesson_grade_item_update($lesson, $grades=null) { 751 global $CFG; 752 if (!function_exists('grade_update')) { //workaround for buggy PHP versions 753 require_once($CFG->libdir.'/gradelib.php'); 754 } 755 756 if (array_key_exists('cmidnumber', $lesson)) { //it may not be always present 757 $params = array('itemname'=>$lesson->name, 'idnumber'=>$lesson->cmidnumber); 758 } else { 759 $params = array('itemname'=>$lesson->name); 760 } 761 762 if (!$lesson->practice and $lesson->grade > 0) { 763 $params['gradetype'] = GRADE_TYPE_VALUE; 764 $params['grademax'] = $lesson->grade; 765 $params['grademin'] = 0; 766 } else if (!$lesson->practice and $lesson->grade < 0) { 767 $params['gradetype'] = GRADE_TYPE_SCALE; 768 $params['scaleid'] = -$lesson->grade; 769 770 // Make sure current grade fetched correctly from $grades 771 $currentgrade = null; 772 if (!empty($grades)) { 773 if (is_array($grades)) { 774 $currentgrade = reset($grades); 775 } else { 776 $currentgrade = $grades; 777 } 778 } 779 780 // When converting a score to a scale, use scale's grade maximum to calculate it. 781 if (!empty($currentgrade) && $currentgrade->rawgrade !== null) { 782 $grade = grade_get_grades($lesson->course, 'mod', 'lesson', $lesson->id, $currentgrade->userid); 783 $params['grademax'] = reset($grade->items)->grademax; 784 } 785 } else { 786 $params['gradetype'] = GRADE_TYPE_NONE; 787 } 788 789 if ($grades === 'reset') { 790 $params['reset'] = true; 791 $grades = null; 792 } else if (!empty($grades)) { 793 // Need to calculate raw grade (Note: $grades has many forms) 794 if (is_object($grades)) { 795 $grades = array($grades->userid => $grades); 796 } else if (array_key_exists('userid', $grades)) { 797 $grades = array($grades['userid'] => $grades); 798 } 799 foreach ($grades as $key => $grade) { 800 if (!is_array($grade)) { 801 $grades[$key] = $grade = (array) $grade; 802 } 803 //check raw grade isnt null otherwise we erroneously insert a grade of 0 804 if ($grade['rawgrade'] !== null) { 805 $grades[$key]['rawgrade'] = ($grade['rawgrade'] * $params['grademax'] / 100); 806 } else { 807 //setting rawgrade to null just in case user is deleting a grade 808 $grades[$key]['rawgrade'] = null; 809 } 810 } 811 } 812 813 return grade_update('mod/lesson', $lesson->course, 'mod', 'lesson', $lesson->id, 0, $grades, $params); 814 } 815 816 /** 817 * List the actions that correspond to a view of this module. 818 * This is used by the participation report. 819 * 820 * Note: This is not used by new logging system. Event with 821 * crud = 'r' and edulevel = LEVEL_PARTICIPATING will 822 * be considered as view action. 823 * 824 * @return array 825 */ 826 function lesson_get_view_actions() { 827 return array('view','view all'); 828 } 829 830 /** 831 * List the actions that correspond to a post of this module. 832 * This is used by the participation report. 833 * 834 * Note: This is not used by new logging system. Event with 835 * crud = ('c' || 'u' || 'd') and edulevel = LEVEL_PARTICIPATING 836 * will be considered as post action. 837 * 838 * @return array 839 */ 840 function lesson_get_post_actions() { 841 return array('end','start'); 842 } 843 844 /** 845 * Runs any processes that must run before 846 * a lesson insert/update 847 * 848 * @global object 849 * @param object $lesson Lesson form data 850 * @return void 851 **/ 852 function lesson_process_pre_save(&$lesson) { 853 global $DB; 854 855 $lesson->timemodified = time(); 856 857 if (empty($lesson->timelimit)) { 858 $lesson->timelimit = 0; 859 } 860 if (empty($lesson->timespent) or !is_numeric($lesson->timespent) or $lesson->timespent < 0) { 861 $lesson->timespent = 0; 862 } 863 if (!isset($lesson->completed)) { 864 $lesson->completed = 0; 865 } 866 if (empty($lesson->gradebetterthan) or !is_numeric($lesson->gradebetterthan) or $lesson->gradebetterthan < 0) { 867 $lesson->gradebetterthan = 0; 868 } else if ($lesson->gradebetterthan > 100) { 869 $lesson->gradebetterthan = 100; 870 } 871 872 if (empty($lesson->width)) { 873 $lesson->width = 640; 874 } 875 if (empty($lesson->height)) { 876 $lesson->height = 480; 877 } 878 if (empty($lesson->bgcolor)) { 879 $lesson->bgcolor = '#FFFFFF'; 880 } 881 882 // Conditions for dependency 883 $conditions = new stdClass; 884 $conditions->timespent = $lesson->timespent; 885 $conditions->completed = $lesson->completed; 886 $conditions->gradebetterthan = $lesson->gradebetterthan; 887 $lesson->conditions = serialize($conditions); 888 unset($lesson->timespent); 889 unset($lesson->completed); 890 unset($lesson->gradebetterthan); 891 892 if (empty($lesson->password)) { 893 unset($lesson->password); 894 } 895 } 896 897 /** 898 * Runs any processes that must be run 899 * after a lesson insert/update 900 * 901 * @global object 902 * @param object $lesson Lesson form data 903 * @return void 904 **/ 905 function lesson_process_post_save(&$lesson) { 906 // Update the events relating to this lesson. 907 lesson_update_events($lesson); 908 } 909 910 911 /** 912 * Implementation of the function for printing the form elements that control 913 * whether the course reset functionality affects the lesson. 914 * 915 * @param $mform form passed by reference 916 */ 917 function lesson_reset_course_form_definition(&$mform) { 918 $mform->addElement('header', 'lessonheader', get_string('modulenameplural', 'lesson')); 919 $mform->addElement('advcheckbox', 'reset_lesson', get_string('deleteallattempts','lesson')); 920 $mform->addElement('advcheckbox', 'reset_lesson_user_overrides', 921 get_string('removealluseroverrides', 'lesson')); 922 $mform->addElement('advcheckbox', 'reset_lesson_group_overrides', 923 get_string('removeallgroupoverrides', 'lesson')); 924 } 925 926 /** 927 * Course reset form defaults. 928 * @param object $course 929 * @return array 930 */ 931 function lesson_reset_course_form_defaults($course) { 932 return array('reset_lesson' => 1, 933 'reset_lesson_group_overrides' => 1, 934 'reset_lesson_user_overrides' => 1); 935 } 936 937 /** 938 * Removes all grades from gradebook 939 * 940 * @global stdClass 941 * @global object 942 * @param int $courseid 943 * @param string optional type 944 */ 945 function lesson_reset_gradebook($courseid, $type='') { 946 global $CFG, $DB; 947 948 $sql = "SELECT l.*, cm.idnumber as cmidnumber, l.course as courseid 949 FROM {lesson} l, {course_modules} cm, {modules} m 950 WHERE m.name='lesson' AND m.id=cm.module AND cm.instance=l.id AND l.course=:course"; 951 $params = array ("course" => $courseid); 952 if ($lessons = $DB->get_records_sql($sql,$params)) { 953 foreach ($lessons as $lesson) { 954 lesson_grade_item_update($lesson, 'reset'); 955 } 956 } 957 } 958 959 /** 960 * Actual implementation of the reset course functionality, delete all the 961 * lesson attempts for course $data->courseid. 962 * 963 * @global stdClass 964 * @global object 965 * @param object $data the data submitted from the reset course. 966 * @return array status array 967 */ 968 function lesson_reset_userdata($data) { 969 global $CFG, $DB; 970 971 $componentstr = get_string('modulenameplural', 'lesson'); 972 $status = array(); 973 974 if (!empty($data->reset_lesson)) { 975 $lessonssql = "SELECT l.id 976 FROM {lesson} l 977 WHERE l.course=:course"; 978 979 $params = array ("course" => $data->courseid); 980 $lessons = $DB->get_records_sql($lessonssql, $params); 981 982 // Get rid of attempts files. 983 $fs = get_file_storage(); 984 if ($lessons) { 985 foreach ($lessons as $lessonid => $unused) { 986 if (!$cm = get_coursemodule_from_instance('lesson', $lessonid)) { 987 continue; 988 } 989 $context = context_module::instance($cm->id); 990 $fs->delete_area_files($context->id, 'mod_lesson', 'essay_responses'); 991 } 992 } 993 994 $DB->delete_records_select('lesson_timer', "lessonid IN ($lessonssql)", $params); 995 $DB->delete_records_select('lesson_grades', "lessonid IN ($lessonssql)", $params); 996 $DB->delete_records_select('lesson_attempts', "lessonid IN ($lessonssql)", $params); 997 $DB->delete_records_select('lesson_branch', "lessonid IN ($lessonssql)", $params); 998 999 // remove all grades from gradebook 1000 if (empty($data->reset_gradebook_grades)) { 1001 lesson_reset_gradebook($data->courseid); 1002 } 1003 1004 $status[] = array('component'=>$componentstr, 'item'=>get_string('deleteallattempts', 'lesson'), 'error'=>false); 1005 } 1006 1007 // Remove user overrides. 1008 if (!empty($data->reset_lesson_user_overrides)) { 1009 $DB->delete_records_select('lesson_overrides', 1010 'lessonid IN (SELECT id FROM {lesson} WHERE course = ?) AND userid IS NOT NULL', array($data->courseid)); 1011 $status[] = array( 1012 'component' => $componentstr, 1013 'item' => get_string('useroverridesdeleted', 'lesson'), 1014 'error' => false); 1015 } 1016 // Remove group overrides. 1017 if (!empty($data->reset_lesson_group_overrides)) { 1018 $DB->delete_records_select('lesson_overrides', 1019 'lessonid IN (SELECT id FROM {lesson} WHERE course = ?) AND groupid IS NOT NULL', array($data->courseid)); 1020 $status[] = array( 1021 'component' => $componentstr, 1022 'item' => get_string('groupoverridesdeleted', 'lesson'), 1023 'error' => false); 1024 } 1025 /// updating dates - shift may be negative too 1026 if ($data->timeshift) { 1027 $DB->execute("UPDATE {lesson_overrides} 1028 SET available = available + ? 1029 WHERE lessonid IN (SELECT id FROM {lesson} WHERE course = ?) 1030 AND available <> 0", array($data->timeshift, $data->courseid)); 1031 $DB->execute("UPDATE {lesson_overrides} 1032 SET deadline = deadline + ? 1033 WHERE lessonid IN (SELECT id FROM {lesson} WHERE course = ?) 1034 AND deadline <> 0", array($data->timeshift, $data->courseid)); 1035 1036 shift_course_mod_dates('lesson', array('available', 'deadline'), $data->timeshift, $data->courseid); 1037 $status[] = array('component'=>$componentstr, 'item'=>get_string('datechanged'), 'error'=>false); 1038 } 1039 1040 return $status; 1041 } 1042 1043 /** 1044 * Returns all other caps used in module 1045 * @return array 1046 */ 1047 function lesson_get_extra_capabilities() { 1048 return array('moodle/site:accessallgroups'); 1049 } 1050 1051 /** 1052 * @uses FEATURE_GROUPS 1053 * @uses FEATURE_GROUPINGS 1054 * @uses FEATURE_MOD_INTRO 1055 * @uses FEATURE_COMPLETION_TRACKS_VIEWS 1056 * @uses FEATURE_GRADE_HAS_GRADE 1057 * @uses FEATURE_GRADE_OUTCOMES 1058 * @param string $feature FEATURE_xx constant for requested feature 1059 * @return mixed True if module supports feature, false if not, null if doesn't know 1060 */ 1061 function lesson_supports($feature) { 1062 switch($feature) { 1063 case FEATURE_GROUPS: 1064 return true; 1065 case FEATURE_GROUPINGS: 1066 return true; 1067 case FEATURE_MOD_INTRO: 1068 return true; 1069 case FEATURE_COMPLETION_TRACKS_VIEWS: 1070 return true; 1071 case FEATURE_GRADE_HAS_GRADE: 1072 return true; 1073 case FEATURE_COMPLETION_HAS_RULES: 1074 return true; 1075 case FEATURE_GRADE_OUTCOMES: 1076 return true; 1077 case FEATURE_BACKUP_MOODLE2: 1078 return true; 1079 case FEATURE_SHOW_DESCRIPTION: 1080 return true; 1081 default: 1082 return null; 1083 } 1084 } 1085 1086 /** 1087 * Obtains the automatic completion state for this lesson based on any conditions 1088 * in lesson settings. 1089 * 1090 * @param object $course Course 1091 * @param object $cm course-module 1092 * @param int $userid User ID 1093 * @param bool $type Type of comparison (or/and; can be used as return value if no conditions) 1094 * @return bool True if completed, false if not, $type if conditions not set. 1095 */ 1096 function lesson_get_completion_state($course, $cm, $userid, $type) { 1097 global $CFG, $DB; 1098 1099 // Get lesson details. 1100 $lesson = $DB->get_record('lesson', array('id' => $cm->instance), '*', 1101 MUST_EXIST); 1102 1103 $result = $type; // Default return value. 1104 // If completion option is enabled, evaluate it and return true/false. 1105 if ($lesson->completionendreached) { 1106 $value = $DB->record_exists('lesson_timer', array( 1107 'lessonid' => $lesson->id, 'userid' => $userid, 'completed' => 1)); 1108 if ($type == COMPLETION_AND) { 1109 $result = $result && $value; 1110 } else { 1111 $result = $result || $value; 1112 } 1113 } 1114 if ($lesson->completiontimespent != 0) { 1115 $duration = $DB->get_field_sql( 1116 "SELECT SUM(lessontime - starttime) 1117 FROM {lesson_timer} 1118 WHERE lessonid = :lessonid 1119 AND userid = :userid", 1120 array('userid' => $userid, 'lessonid' => $lesson->id)); 1121 if (!$duration) { 1122 $duration = 0; 1123 } 1124 if ($type == COMPLETION_AND) { 1125 $result = $result && ($lesson->completiontimespent < $duration); 1126 } else { 1127 $result = $result || ($lesson->completiontimespent < $duration); 1128 } 1129 } 1130 return $result; 1131 } 1132 /** 1133 * This function extends the settings navigation block for the site. 1134 * 1135 * It is safe to rely on PAGE here as we will only ever be within the module 1136 * context when this is called 1137 * 1138 * @param settings_navigation $settings 1139 * @param navigation_node $lessonnode 1140 */ 1141 function lesson_extend_settings_navigation($settings, $lessonnode) { 1142 global $PAGE, $DB; 1143 1144 // We want to add these new nodes after the Edit settings node, and before the 1145 // Locally assigned roles node. Of course, both of those are controlled by capabilities. 1146 $keys = $lessonnode->get_children_key_list(); 1147 $beforekey = null; 1148 $i = array_search('modedit', $keys); 1149 if ($i === false and array_key_exists(0, $keys)) { 1150 $beforekey = $keys[0]; 1151 } else if (array_key_exists($i + 1, $keys)) { 1152 $beforekey = $keys[$i + 1]; 1153 } 1154 1155 if (has_capability('mod/lesson:manageoverrides', $PAGE->cm->context)) { 1156 $url = new moodle_url('/mod/lesson/overrides.php', array('cmid' => $PAGE->cm->id)); 1157 $node = navigation_node::create(get_string('groupoverrides', 'lesson'), 1158 new moodle_url($url, array('mode' => 'group')), 1159 navigation_node::TYPE_SETTING, null, 'mod_lesson_groupoverrides'); 1160 $lessonnode->add_node($node, $beforekey); 1161 1162 $node = navigation_node::create(get_string('useroverrides', 'lesson'), 1163 new moodle_url($url, array('mode' => 'user')), 1164 navigation_node::TYPE_SETTING, null, 'mod_lesson_useroverrides'); 1165 $lessonnode->add_node($node, $beforekey); 1166 } 1167 1168 if (has_capability('mod/lesson:edit', $PAGE->cm->context)) { 1169 $url = new moodle_url('/mod/lesson/view.php', array('id' => $PAGE->cm->id)); 1170 $lessonnode->add(get_string('preview', 'lesson'), $url); 1171 $editnode = $lessonnode->add(get_string('edit', 'lesson')); 1172 $url = new moodle_url('/mod/lesson/edit.php', array('id' => $PAGE->cm->id, 'mode' => 'collapsed')); 1173 $editnode->add(get_string('collapsed', 'lesson'), $url); 1174 $url = new moodle_url('/mod/lesson/edit.php', array('id' => $PAGE->cm->id, 'mode' => 'full')); 1175 $editnode->add(get_string('full', 'lesson'), $url); 1176 } 1177 1178 if (has_capability('mod/lesson:viewreports', $PAGE->cm->context)) { 1179 $reportsnode = $lessonnode->add(get_string('reports', 'lesson')); 1180 $url = new moodle_url('/mod/lesson/report.php', array('id'=>$PAGE->cm->id, 'action'=>'reportoverview')); 1181 $reportsnode->add(get_string('overview', 'lesson'), $url); 1182 $url = new moodle_url('/mod/lesson/report.php', array('id'=>$PAGE->cm->id, 'action'=>'reportdetail')); 1183 $reportsnode->add(get_string('detailedstats', 'lesson'), $url); 1184 } 1185 1186 if (has_capability('mod/lesson:grade', $PAGE->cm->context)) { 1187 $url = new moodle_url('/mod/lesson/essay.php', array('id'=>$PAGE->cm->id)); 1188 $lessonnode->add(get_string('manualgrading', 'lesson'), $url); 1189 } 1190 1191 } 1192 1193 /** 1194 * Get list of available import or export formats 1195 * 1196 * Copied and modified from lib/questionlib.php 1197 * 1198 * @param string $type 'import' if import list, otherwise export list assumed 1199 * @return array sorted list of import/export formats available 1200 */ 1201 function lesson_get_import_export_formats($type) { 1202 global $CFG; 1203 $fileformats = core_component::get_plugin_list("qformat"); 1204 1205 $fileformatname=array(); 1206 foreach ($fileformats as $fileformat=>$fdir) { 1207 $format_file = "$fdir/format.php"; 1208 if (file_exists($format_file) ) { 1209 require_once($format_file); 1210 } else { 1211 continue; 1212 } 1213 $classname = "qformat_$fileformat"; 1214 $format_class = new $classname(); 1215 if ($type=='import') { 1216 $provided = $format_class->provide_import(); 1217 } else { 1218 $provided = $format_class->provide_export(); 1219 } 1220 if ($provided) { 1221 $fileformatnames[$fileformat] = get_string('pluginname', 'qformat_'.$fileformat); 1222 } 1223 } 1224 natcasesort($fileformatnames); 1225 1226 return $fileformatnames; 1227 } 1228 1229 /** 1230 * Serves the lesson attachments. Implements needed access control ;-) 1231 * 1232 * @package mod_lesson 1233 * @category files 1234 * @param stdClass $course course object 1235 * @param stdClass $cm course module object 1236 * @param stdClass $context context object 1237 * @param string $filearea file area 1238 * @param array $args extra arguments 1239 * @param bool $forcedownload whether or not force download 1240 * @param array $options additional options affecting the file serving 1241 * @return bool false if file not found, does not return if found - justsend the file 1242 */ 1243 function lesson_pluginfile($course, $cm, $context, $filearea, $args, $forcedownload, array $options=array()) { 1244 global $CFG, $DB; 1245 1246 if ($context->contextlevel != CONTEXT_MODULE) { 1247 return false; 1248 } 1249 1250 $fileareas = lesson_get_file_areas(); 1251 if (!array_key_exists($filearea, $fileareas)) { 1252 return false; 1253 } 1254 1255 if (!$lesson = $DB->get_record('lesson', array('id'=>$cm->instance))) { 1256 return false; 1257 } 1258 1259 require_course_login($course, true, $cm); 1260 1261 if ($filearea === 'page_contents') { 1262 $pageid = (int)array_shift($args); 1263 if (!$page = $DB->get_record('lesson_pages', array('id'=>$pageid))) { 1264 return false; 1265 } 1266 $fullpath = "/$context->id/mod_lesson/$filearea/$pageid/".implode('/', $args); 1267 1268 } else if ($filearea === 'page_answers' || $filearea === 'page_responses') { 1269 $itemid = (int)array_shift($args); 1270 if (!$pageanswers = $DB->get_record('lesson_answers', array('id' => $itemid))) { 1271 return false; 1272 } 1273 $fullpath = "/$context->id/mod_lesson/$filearea/$itemid/".implode('/', $args); 1274 1275 } else if ($filearea === 'essay_responses') { 1276 $itemid = (int)array_shift($args); 1277 if (!$attempt = $DB->get_record('lesson_attempts', array('id' => $itemid))) { 1278 return false; 1279 } 1280 $fullpath = "/$context->id/mod_lesson/$filearea/$itemid/".implode('/', $args); 1281 1282 } else if ($filearea === 'mediafile') { 1283 if (count($args) > 1) { 1284 // Remove the itemid when it appears to be part of the arguments. If there is only one argument 1285 // then it is surely the file name. The itemid is sometimes used to prevent browser caching. 1286 array_shift($args); 1287 } 1288 $fullpath = "/$context->id/mod_lesson/$filearea/0/".implode('/', $args); 1289 1290 } else { 1291 return false; 1292 } 1293 1294 $fs = get_file_storage(); 1295 if (!$file = $fs->get_file_by_hash(sha1($fullpath)) or $file->is_directory()) { 1296 return false; 1297 } 1298 1299 // finally send the file 1300 send_stored_file($file, 0, 0, $forcedownload, $options); // download MUST be forced - security! 1301 } 1302 1303 /** 1304 * Returns an array of file areas 1305 * 1306 * @package mod_lesson 1307 * @category files 1308 * @return array a list of available file areas 1309 */ 1310 function lesson_get_file_areas() { 1311 $areas = array(); 1312 $areas['page_contents'] = get_string('pagecontents', 'mod_lesson'); 1313 $areas['mediafile'] = get_string('mediafile', 'mod_lesson'); 1314 $areas['page_answers'] = get_string('pageanswers', 'mod_lesson'); 1315 $areas['page_responses'] = get_string('pageresponses', 'mod_lesson'); 1316 $areas['essay_responses'] = get_string('essayresponses', 'mod_lesson'); 1317 return $areas; 1318 } 1319 1320 /** 1321 * Returns a file_info_stored object for the file being requested here 1322 * 1323 * @package mod_lesson 1324 * @category files 1325 * @global stdClass $CFG 1326 * @param file_browse $browser file browser instance 1327 * @param array $areas file areas 1328 * @param stdClass $course course object 1329 * @param stdClass $cm course module object 1330 * @param stdClass $context context object 1331 * @param string $filearea file area 1332 * @param int $itemid item ID 1333 * @param string $filepath file path 1334 * @param string $filename file name 1335 * @return file_info_stored 1336 */ 1337 function lesson_get_file_info($browser, $areas, $course, $cm, $context, $filearea, $itemid, $filepath, $filename) { 1338 global $CFG, $DB; 1339 1340 if (!has_capability('moodle/course:managefiles', $context)) { 1341 // No peaking here for students! 1342 return null; 1343 } 1344 1345 // Mediafile area does not have sub directories, so let's select the default itemid to prevent 1346 // the user from selecting a directory to access the mediafile content. 1347 if ($filearea == 'mediafile' && is_null($itemid)) { 1348 $itemid = 0; 1349 } 1350 1351 if (is_null($itemid)) { 1352 return new mod_lesson_file_info($browser, $course, $cm, $context, $areas, $filearea); 1353 } 1354 1355 $fs = get_file_storage(); 1356 $filepath = is_null($filepath) ? '/' : $filepath; 1357 $filename = is_null($filename) ? '.' : $filename; 1358 if (!$storedfile = $fs->get_file($context->id, 'mod_lesson', $filearea, $itemid, $filepath, $filename)) { 1359 return null; 1360 } 1361 1362 $itemname = $filearea; 1363 if ($filearea == 'page_contents') { 1364 $itemname = $DB->get_field('lesson_pages', 'title', array('lessonid' => $cm->instance, 'id' => $itemid)); 1365 $itemname = format_string($itemname, true, array('context' => $context)); 1366 } else { 1367 $areas = lesson_get_file_areas(); 1368 if (isset($areas[$filearea])) { 1369 $itemname = $areas[$filearea]; 1370 } 1371 } 1372 1373 $urlbase = $CFG->wwwroot . '/pluginfile.php'; 1374 return new file_info_stored($browser, $context, $storedfile, $urlbase, $itemname, $itemid, true, true, false); 1375 } 1376 1377 1378 /** 1379 * Return a list of page types 1380 * @param string $pagetype current page type 1381 * @param stdClass $parentcontext Block's parent context 1382 * @param stdClass $currentcontext Current context of block 1383 */ 1384 function lesson_page_type_list($pagetype, $parentcontext, $currentcontext) { 1385 $module_pagetype = array( 1386 'mod-lesson-*'=>get_string('page-mod-lesson-x', 'lesson'), 1387 'mod-lesson-view'=>get_string('page-mod-lesson-view', 'lesson'), 1388 'mod-lesson-edit'=>get_string('page-mod-lesson-edit', 'lesson')); 1389 return $module_pagetype; 1390 } 1391 1392 /** 1393 * Update the lesson activity to include any file 1394 * that was uploaded, or if there is none, set the 1395 * mediafile field to blank. 1396 * 1397 * @param int $lessonid the lesson id 1398 * @param stdClass $context the context 1399 * @param int $draftitemid the draft item 1400 */ 1401 function lesson_update_media_file($lessonid, $context, $draftitemid) { 1402 global $DB; 1403 1404 // Set the filestorage object. 1405 $fs = get_file_storage(); 1406 // Save the file if it exists that is currently in the draft area. 1407 file_save_draft_area_files($draftitemid, $context->id, 'mod_lesson', 'mediafile', 0); 1408 // Get the file if it exists. 1409 $files = $fs->get_area_files($context->id, 'mod_lesson', 'mediafile', 0, 'itemid, filepath, filename', false); 1410 // Check that there is a file to process. 1411 if (count($files) == 1) { 1412 // Get the first (and only) file. 1413 $file = reset($files); 1414 // Set the mediafile column in the lessons table. 1415 $DB->set_field('lesson', 'mediafile', '/' . $file->get_filename(), array('id' => $lessonid)); 1416 } else { 1417 // Set the mediafile column in the lessons table. 1418 $DB->set_field('lesson', 'mediafile', '', array('id' => $lessonid)); 1419 } 1420 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Thu Aug 11 10:00:09 2016 | Cross-referenced by PHPXref 0.7.1 |