3 // This file is part of Moodle - http://moodle.org/
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.
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.
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/>.
19 * Standard library of functions and constants for lesson
23 * @copyright 1999 onwards Martin Dougiamas {@link http://moodle.com}
24 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
27 defined('MOODLE_INTERNAL') || die();
29 /* Do not include any libraries here! */
32 * Given an object containing all the necessary data,
33 * (defined by the form in mod_form.php) this function
34 * will create a new instance and return the id number
35 * of the new instance.
39 * @param object $lesson Lesson post data from the form
42 function lesson_add_instance($data, $mform) {
45 $cmid = $data->coursemodule;
47 lesson_process_pre_save($data);
49 unset($data->mediafile);
50 $lessonid = $DB->insert_record("lesson", $data);
51 $data->id = $lessonid;
53 $context = get_context_instance(CONTEXT_MODULE, $cmid);
54 $lesson = $DB->get_record('lesson', array('id'=>$lessonid), '*', MUST_EXIST);
56 if ($filename = $mform->get_new_filename('mediafilepicker')) {
57 if ($file = $mform->save_stored_file('mediafilepicker', $context->id, 'mod_lesson', 'mediafile', 0, '/', $filename)) {
58 $DB->set_field('lesson', 'mediafile', '/'.$file->get_filename(), array('id'=>$lesson->id));
62 lesson_process_post_save($data);
64 lesson_grade_item_update($data);
70 * Given an object containing all the necessary data,
71 * (defined by the form in mod_form.php) this function
72 * will update an existing instance with new data.
75 * @param object $lesson Lesson post data from the form
78 function lesson_update_instance($data, $mform) {
81 $data->id = $data->instance;
82 $cmid = $data->coursemodule;
84 lesson_process_pre_save($data);
86 unset($data->mediafile);
87 $DB->update_record("lesson", $data);
89 $context = get_context_instance(CONTEXT_MODULE, $cmid);
90 if ($filename = $mform->get_new_filename('mediafilepicker')) {
91 if ($file = $mform->save_stored_file('mediafilepicker', $context->id, 'mod_lesson', 'mediafile', 0, '/', $filename, true)) {
92 $DB->set_field('lesson', 'mediafile', '/'.$file->get_filename(), array('id'=>$data->id));
94 $DB->set_field('lesson', 'mediafile', '', array('id'=>$data->id));
97 $DB->set_field('lesson', 'mediafile', '', array('id'=>$data->id));
100 lesson_process_post_save($data);
102 // update grade item definition
103 lesson_grade_item_update($data);
105 // update grades - TODO: do it only when grading style changes
106 lesson_update_grades($data, 0, false);
113 * Given an ID of an instance of this module,
114 * this function will permanently delete the instance
115 * and any data that depends on it.
121 function lesson_delete_instance($id) {
123 require_once($CFG->dirroot . '/mod/lesson/locallib.php');
125 $lesson = $DB->get_record("lesson", array("id"=>$id), '*', MUST_EXIST);
126 $lesson = new lesson($lesson);
127 return $lesson->delete();
131 * Given a course object, this function will clean up anything that
132 * would be leftover after all the instances were deleted
135 * @param object $course an object representing the course that is being deleted
136 * @param boolean $feedback to specify if the process must output a summary of its work
139 function lesson_delete_course($course, $feedback=true) {
144 * Return a small object with summary information about what a
145 * user has done with a given particular instance of this module
146 * Used for user activity reports.
147 * $return->time = the time they did it
148 * $return->info = a short text description
151 * @param object $course
152 * @param object $user
154 * @param object $lesson
157 function lesson_user_outline($course, $user, $mod, $lesson) {
160 require_once("$CFG->libdir/gradelib.php");
161 $grades = grade_get_grades($course->id, 'mod', 'lesson', $lesson->id, $user->id);
163 $return = new stdClass();
164 if (empty($grades->items[0]->grades)) {
165 $return->info = get_string("no")." ".get_string("attempts", "lesson");
167 $grade = reset($grades->items[0]->grades);
168 $return->info = get_string("grade") . ': ' . $grade->str_long_grade;
169 $return->time = $grade->dategraded;
170 $return->info = get_string("no")." ".get_string("attempts", "lesson");
176 * Print a detailed representation of what a user has done with
177 * a given particular instance of this module, for user activity reports.
180 * @param object $course
181 * @param object $user
183 * @param object $lesson
186 function lesson_user_complete($course, $user, $mod, $lesson) {
187 global $DB, $OUTPUT, $CFG;
189 require_once("$CFG->libdir/gradelib.php");
191 $grades = grade_get_grades($course->id, 'mod', 'lesson', $lesson->id, $user->id);
192 if (!empty($grades->items[0]->grades)) {
193 $grade = reset($grades->items[0]->grades);
194 echo $OUTPUT->container(get_string('grade').': '.$grade->str_long_grade);
195 if ($grade->str_feedback) {
196 echo $OUTPUT->container(get_string('feedback').': '.$grade->str_feedback);
200 $params = array ("lessonid" => $lesson->id, "userid" => $user->id);
201 if ($attempts = $DB->get_records_select("lesson_attempts", "lessonid = :lessonid AND userid = :userid", $params,
202 "retry, timeseen")) {
203 echo $OUTPUT->box_start();
204 $table = new html_table();
205 $table->head = array (get_string("attempt", "lesson"), get_string("numberofpagesviewed", "lesson"),
206 get_string("numberofcorrectanswers", "lesson"), get_string("time"));
207 $table->width = "100%";
208 $table->align = array ("center", "center", "center", "center");
209 $table->size = array ("*", "*", "*", "*");
210 $table->cellpadding = 2;
211 $table->cellspacing = 0;
217 foreach ($attempts as $attempt) {
218 if ($attempt->retry == $retry) {
220 if ($attempt->correct) {
223 $timeseen = $attempt->timeseen;
225 $table->data[] = array($retry + 1, $npages, $ncorrect, userdate($timeseen));
228 if ($attempt->correct) {
236 $table->data[] = array($retry + 1, $npages, $ncorrect, userdate($timeseen));
238 echo html_writer::table($table);
239 echo $OUTPUT->box_end();
246 * Prints lesson summaries on MyMoodle Page
248 * Prints lesson name, due date and attempt information on
249 * lessons that have a deadline that has not already passed
250 * and it is available for taking.
255 * @uses CONTEXT_MODULE
256 * @param array $courses An array of course objects to get lesson instances from
257 * @param array $htmlarray Store overview output array( course ID => 'lesson' => HTML output )
260 function lesson_print_overview($courses, &$htmlarray) {
261 global $USER, $CFG, $DB, $OUTPUT;
263 if (!$lessons = get_all_instances_in_courses('lesson', $courses)) {
267 /// Get Necessary Strings
268 $strlesson = get_string('modulename', 'lesson');
269 $strnotattempted = get_string('nolessonattempts', 'lesson');
270 $strattempted = get_string('lessonattempted', 'lesson');
273 foreach ($lessons as $lesson) {
274 if ($lesson->deadline != 0 // The lesson has a deadline
275 and $lesson->deadline >= $now // And it is before the deadline has been met
276 and ($lesson->available == 0 or $lesson->available <= $now)) { // And the lesson is available
279 if (!$lesson->visible) {
280 $class = ' class="dimmed"';
284 $str = $OUTPUT->box("$strlesson: <a$class href=\"$CFG->wwwroot/mod/lesson/view.php?id=$lesson->coursemodule\">".
285 format_string($lesson->name).'</a>', 'name');
288 $str .= $OUTPUT->box(get_string('lessoncloseson', 'lesson', userdate($lesson->deadline)), 'info');
290 // Attempt information
291 if (has_capability('mod/lesson:manage', get_context_instance(CONTEXT_MODULE, $lesson->coursemodule))) {
292 // Number of user attempts
293 $attempts = $DB->count_records('lesson_attempts', array('lessonid'=>$lesson->id));
294 $str .= $OUTPUT->box(get_string('xattempts', 'lesson', $attempts), 'info');
296 // Determine if the user has attempted the lesson or not
297 if ($DB->count_records('lesson_attempts', array('lessonid'=>$lesson->id, 'userid'=>$USER->id))) {
298 $str .= $OUTPUT->box($strattempted, 'info');
300 $str .= $OUTPUT->box($strnotattempted, 'info');
303 $str = $OUTPUT->box($str, 'lesson overview');
305 if (empty($htmlarray[$lesson->course]['lesson'])) {
306 $htmlarray[$lesson->course]['lesson'] = $str;
308 $htmlarray[$lesson->course]['lesson'] .= $str;
315 * Function to be run periodically according to the moodle cron
316 * This function searches for things that need to be done, such
317 * as sending out mail, toggling flags etc ...
321 function lesson_cron () {
328 * Return grade for given user or all users.
332 * @param int $lessonid id of lesson
333 * @param int $userid optional user id, 0 means all users
334 * @return array array of grades, false if none
336 function lesson_get_user_grades($lesson, $userid=0) {
339 $params = array("lessonid" => $lesson->id,"lessonid2" => $lesson->id);
341 if (isset($userid)) {
342 $params["userid"] = $userid;
343 $params["userid2"] = $userid;
344 $user = "AND u.id = :userid";
345 $fuser = "AND uu.id = :userid2";
352 if ($lesson->retake) {
353 if ($lesson->usemaxgrade) {
354 $sql = "SELECT u.id, u.id AS userid, MAX(g.grade) AS rawgrade
355 FROM {user} u, {lesson_grades} g
356 WHERE u.id = g.userid AND g.lessonid = :lessonid
360 $sql = "SELECT u.id, u.id AS userid, AVG(g.grade) AS rawgrade
361 FROM {user} u, {lesson_grades} g
362 WHERE u.id = g.userid AND g.lessonid = :lessonid
366 unset($params['lessonid2']);
367 unset($params['userid2']);
369 // use only first attempts (with lowest id in lesson_grades table)
370 $firstonly = "SELECT uu.id AS userid, MIN(gg.id) AS firstcompleted
371 FROM {user} uu, {lesson_grades} gg
372 WHERE uu.id = gg.userid AND gg.lessonid = :lessonid2
376 $sql = "SELECT u.id, u.id AS userid, g.grade AS rawgrade
377 FROM {user} u, {lesson_grades} g, ($firstonly) f
378 WHERE u.id = g.userid AND g.lessonid = :lessonid
379 AND g.id = f.firstcompleted AND g.userid=f.userid
383 return $DB->get_records_sql($sql, $params);
387 * Update grades in central gradebook
391 * @param object $lesson
392 * @param int $userid specific user only, 0 means all
393 * @param bool $nullifnone
395 function lesson_update_grades($lesson, $userid=0, $nullifnone=true) {
397 require_once($CFG->libdir.'/gradelib.php');
399 if ($lesson->grade == 0) {
400 lesson_grade_item_update($lesson);
402 } else if ($grades = lesson_get_user_grades($lesson, $userid)) {
403 lesson_grade_item_update($lesson, $grades);
405 } else if ($userid and $nullifnone) {
406 $grade = new stdClass();
407 $grade->userid = $userid;
408 $grade->rawgrade = NULL;
409 lesson_grade_item_update($lesson, $grade);
412 lesson_grade_item_update($lesson);
417 * Update all grades in gradebook.
421 function lesson_upgrade_grades() {
424 $sql = "SELECT COUNT('x')
425 FROM {lesson} l, {course_modules} cm, {modules} m
426 WHERE m.name='lesson' AND m.id=cm.module AND cm.instance=l.id";
427 $count = $DB->count_records_sql($sql);
429 $sql = "SELECT l.*, cm.idnumber AS cmidnumber, l.course AS courseid
430 FROM {lesson} l, {course_modules} cm, {modules} m
431 WHERE m.name='lesson' AND m.id=cm.module AND cm.instance=l.id";
432 $rs = $DB->get_recordset_sql($sql);
434 $pbar = new progress_bar('lessonupgradegrades', 500, true);
436 foreach ($rs as $lesson) {
438 upgrade_set_timeout(60*5); // set up timeout, may also abort execution
439 lesson_update_grades($lesson, 0, false);
440 $pbar->update($i, $count, "Updating Lesson grades ($i/$count).");
447 * Create grade item for given lesson
450 * @uses GRADE_TYPE_VALUE
451 * @uses GRADE_TYPE_NONE
452 * @param object $lesson object with extra cmidnumber
453 * @param array|object $grades optional array/object of grade(s); 'reset' means reset grades in gradebook
454 * @return int 0 if ok, error code otherwise
456 function lesson_grade_item_update($lesson, $grades=NULL) {
458 if (!function_exists('grade_update')) { //workaround for buggy PHP versions
459 require_once($CFG->libdir.'/gradelib.php');
462 if (array_key_exists('cmidnumber', $lesson)) { //it may not be always present
463 $params = array('itemname'=>$lesson->name, 'idnumber'=>$lesson->cmidnumber);
465 $params = array('itemname'=>$lesson->name);
468 if ($lesson->grade > 0) {
469 $params['gradetype'] = GRADE_TYPE_VALUE;
470 $params['grademax'] = $lesson->grade;
471 $params['grademin'] = 0;
472 } else if ($lesson->grade < 0) {
473 $params['gradetype'] = GRADE_TYPE_SCALE;
474 $params['scaleid'] = -$lesson->grade;
476 $params['gradetype'] = GRADE_TYPE_NONE;
479 if ($grades === 'reset') {
480 $params['reset'] = true;
482 } else if (!empty($grades)) {
483 // Need to calculate raw grade (Note: $grades has many forms)
484 if (is_object($grades)) {
485 $grades = array($grades->userid => $grades);
486 } else if (array_key_exists('userid', $grades)) {
487 $grades = array($grades['userid'] => $grades);
489 foreach ($grades as $key => $grade) {
490 if (!is_array($grade)) {
491 $grades[$key] = $grade = (array) $grade;
493 //check raw grade isnt null otherwise we erroneously insert a grade of 0
494 if ($grade['rawgrade'] !== null) {
495 $grades[$key]['rawgrade'] = ($grade['rawgrade'] * $lesson->grade / 100);
497 //setting rawgrade to null just in case user is deleting a grade
498 $grades[$key]['rawgrade'] = null;
503 return grade_update('mod/lesson', $lesson->course, 'mod', 'lesson', $lesson->id, 0, $grades, $params);
507 * Delete grade item for given lesson
510 * @param object $lesson object
511 * @return object lesson
513 function lesson_grade_item_delete($lesson) {
520 * Must return an array of user records (all data) who are participants
521 * for a given instance of lesson. Must include every user involved
522 * in the instance, independent of his role (student, teacher, admin...)
526 * @param int $lessonid
529 function lesson_get_participants($lessonid) {
533 $params = array ("lessonid" => $lessonid);
534 $students = $DB->get_records_sql("SELECT DISTINCT u.id, u.id
537 WHERE a.lessonid = :lessonid and
538 u.id = a.userid", $params);
540 //Return students array (it contains an array of unique users)
547 function lesson_get_view_actions() {
548 return array('view','view all');
554 function lesson_get_post_actions() {
555 return array('end','start');
559 * Runs any processes that must run before
560 * a lesson insert/update
563 * @param object $lesson Lesson form data
566 function lesson_process_pre_save(&$lesson) {
569 $lesson->timemodified = time();
571 if (empty($lesson->timed)) {
574 if (empty($lesson->timespent) or !is_numeric($lesson->timespent) or $lesson->timespent < 0) {
575 $lesson->timespent = 0;
577 if (!isset($lesson->completed)) {
578 $lesson->completed = 0;
580 if (empty($lesson->gradebetterthan) or !is_numeric($lesson->gradebetterthan) or $lesson->gradebetterthan < 0) {
581 $lesson->gradebetterthan = 0;
582 } else if ($lesson->gradebetterthan > 100) {
583 $lesson->gradebetterthan = 100;
586 if (empty($lesson->width)) {
587 $lesson->width = 640;
589 if (empty($lesson->height)) {
590 $lesson->height = 480;
592 if (empty($lesson->bgcolor)) {
593 $lesson->bgcolor = '#FFFFFF';
596 // Conditions for dependency
597 $conditions = new stdClass;
598 $conditions->timespent = $lesson->timespent;
599 $conditions->completed = $lesson->completed;
600 $conditions->gradebetterthan = $lesson->gradebetterthan;
601 $lesson->conditions = serialize($conditions);
602 unset($lesson->timespent);
603 unset($lesson->completed);
604 unset($lesson->gradebetterthan);
606 if (empty($lesson->password)) {
607 unset($lesson->password);
612 * Runs any processes that must be run
613 * after a lesson insert/update
616 * @param object $lesson Lesson form data
619 function lesson_process_post_save(&$lesson) {
621 require_once($CFG->dirroot.'/calendar/lib.php');
622 require_once($CFG->dirroot . '/mod/lesson/locallib.php');
624 if ($events = $DB->get_records('event', array('modulename'=>'lesson', 'instance'=>$lesson->id))) {
625 foreach($events as $event) {
626 $event = calendar_event::load($event->id);
631 $event = new stdClass;
632 $event->description = $lesson->name;
633 $event->courseid = $lesson->course;
636 $event->modulename = 'lesson';
637 $event->instance = $lesson->id;
638 $event->eventtype = 'open';
639 $event->timestart = $lesson->available;
641 $event->visible = instance_is_visible('lesson', $lesson);
643 $event->timeduration = ($lesson->deadline - $lesson->available);
645 if ($lesson->deadline and $lesson->available and $event->timeduration <= LESSON_MAX_EVENT_LENGTH) {
646 // Single event for the whole lesson.
647 $event->name = $lesson->name;
648 calendar_event::create(clone($event));
650 // Separate start and end events.
651 $event->timeduration = 0;
652 if ($lesson->available) {
653 $event->name = $lesson->name.' ('.get_string('lessonopens', 'lesson').')';
654 calendar_event::create(clone($event));
655 } else if ($lesson->deadline) {
656 $event->name = $lesson->name.' ('.get_string('lessoncloses', 'lesson').')';
657 $event->timestart = $lesson->deadline;
658 $event->eventtype = 'close';
659 calendar_event::create(clone($event));
666 * Implementation of the function for printing the form elements that control
667 * whether the course reset functionality affects the lesson.
669 * @param $mform form passed by reference
671 function lesson_reset_course_form_definition(&$mform) {
672 $mform->addElement('header', 'lessonheader', get_string('modulenameplural', 'lesson'));
673 $mform->addElement('advcheckbox', 'reset_lesson', get_string('deleteallattempts','lesson'));
677 * Course reset form defaults.
678 * @param object $course
681 function lesson_reset_course_form_defaults($course) {
682 return array('reset_lesson'=>1);
686 * Removes all grades from gradebook
690 * @param int $courseid
691 * @param string optional type
693 function lesson_reset_gradebook($courseid, $type='') {
696 $sql = "SELECT l.*, cm.idnumber as cmidnumber, l.course as courseid
697 FROM {lesson} l, {course_modules} cm, {modules} m
698 WHERE m.name='lesson' AND m.id=cm.module AND cm.instance=l.id AND l.course=:course";
699 $params = array ("course" => $courseid);
700 if ($lessons = $DB->get_records_sql($sql,$params)) {
701 foreach ($lessons as $lesson) {
702 lesson_grade_item_update($lesson, 'reset');
708 * Actual implementation of the reset course functionality, delete all the
709 * lesson attempts for course $data->courseid.
713 * @param object $data the data submitted from the reset course.
714 * @return array status array
716 function lesson_reset_userdata($data) {
719 $componentstr = get_string('modulenameplural', 'lesson');
722 if (!empty($data->reset_lesson)) {
723 $lessonssql = "SELECT l.id
725 WHERE l.course=:course";
727 $params = array ("course" => $data->courseid);
728 $DB->delete_records_select('lesson_timer', "lessonid IN ($lessonssql)", $params);
729 $DB->delete_records_select('lesson_high_scores', "lessonid IN ($lessonssql)", $params);
730 $DB->delete_records_select('lesson_grades', "lessonid IN ($lessonssql)", $params);
731 $DB->delete_records_select('lesson_attempts', "lessonid IN ($lessonssql)", $params);
733 // remove all grades from gradebook
734 if (empty($data->reset_gradebook_grades)) {
735 lesson_reset_gradebook($data->courseid);
738 $status[] = array('component'=>$componentstr, 'item'=>get_string('deleteallattempts', 'lesson'), 'error'=>false);
741 /// updating dates - shift may be negative too
742 if ($data->timeshift) {
743 shift_course_mod_dates('lesson', array('available', 'deadline'), $data->timeshift, $data->courseid);
744 $status[] = array('component'=>$componentstr, 'item'=>get_string('datechanged'), 'error'=>false);
751 * Returns all other caps used in module
754 function lesson_get_extra_capabilities() {
755 return array('moodle/site:accessallgroups');
759 * @uses FEATURE_GROUPS
760 * @uses FEATURE_GROUPINGS
761 * @uses FEATURE_GROUPMEMBERSONLY
762 * @uses FEATURE_MOD_INTRO
763 * @uses FEATURE_COMPLETION_TRACKS_VIEWS
764 * @uses FEATURE_GRADE_HAS_GRADE
765 * @uses FEATURE_GRADE_OUTCOMES
766 * @param string $feature FEATURE_xx constant for requested feature
767 * @return mixed True if module supports feature, false if not, null if doesn't know
769 function lesson_supports($feature) {
771 case FEATURE_GROUPS: return false;
772 case FEATURE_GROUPINGS: return false;
773 case FEATURE_GROUPMEMBERSONLY: return true;
774 case FEATURE_MOD_INTRO: return false;
775 case FEATURE_COMPLETION_TRACKS_VIEWS: return true;
776 case FEATURE_GRADE_HAS_GRADE: return true;
777 case FEATURE_GRADE_OUTCOMES: return true;
778 case FEATURE_BACKUP_MOODLE2: return true;
779 default: return null;
784 * This function extends the global navigation for the site.
785 * It is important to note that you should not rely on PAGE objects within this
786 * body of code as there is no guarantee that during an AJAX request they are
789 * @param navigation_node $navigation The lesson node within the global navigation
790 * @param stdClass $course The course object returned from the DB
791 * @param stdClass $module The module object returned from the DB
792 * @param stdClass $cm The course module instance returned from the DB
794 function lesson_extend_navigation($navigation, $course, $module, $cm) {
796 * This is currently just a stub so that it can be easily expanded upon.
797 * When expanding just remove this comment and the line below and then add
800 $navigation->nodetype = navigation_node::NODETYPE_LEAF;
804 * This function extends the settings navigation block for the site.
806 * It is safe to rely on PAGE here as we will only ever be within the module
807 * context when this is called
809 * @param settings_navigation $settings
810 * @param navigation_node $lessonnode
812 function lesson_extend_settings_navigation($settings, $lessonnode) {
815 $canedit = has_capability('mod/lesson:edit', $PAGE->cm->context);
817 $url = new moodle_url('/mod/lesson/view.php', array('id'=>$PAGE->cm->id));
818 $lessonnode->add(get_string('preview', 'lesson'), $url);
821 $url = new moodle_url('/mod/lesson/edit.php', array('id'=>$PAGE->cm->id));
822 $lessonnode->add(get_string('edit', 'lesson'), $url);
825 if (has_capability('mod/lesson:manage', $PAGE->cm->context)) {
826 $reportsnode = $lessonnode->add(get_string('reports', 'lesson'));
827 $url = new moodle_url('/mod/lesson/report.php', array('id'=>$PAGE->cm->id, 'action'=>'reportoverview'));
828 $reportsnode->add(get_string('overview', 'lesson'), $url);
829 $url = new moodle_url('/mod/lesson/report.php', array('id'=>$PAGE->cm->id, 'action'=>'reportdetail'));
830 $reportsnode->add(get_string('detailedstats', 'lesson'), $url);
834 $url = new moodle_url('/mod/lesson/essay.php', array('id'=>$PAGE->cm->id));
835 $lessonnode->add(get_string('manualgrading', 'lesson'), $url);
838 if ($PAGE->activityrecord->highscores) {
839 $url = new moodle_url('/mod/lesson/highscores.php', array('id'=>$PAGE->cm->id));
840 $lessonnode->add(get_string('highscores', 'lesson'), $url);
845 * Get list of available import or export formats
847 * Copied and modified from lib/questionlib.php
849 * @param string $type 'import' if import list, otherwise export list assumed
850 * @return array sorted list of import/export formats available
852 function lesson_get_import_export_formats($type) {
854 $fileformats = get_plugin_list("qformat");
856 $fileformatname=array();
857 foreach ($fileformats as $fileformat=>$fdir) {
858 $format_file = "$fdir/format.php";
859 if (file_exists($format_file) ) {
860 require_once($format_file);
864 $classname = "qformat_$fileformat";
865 $format_class = new $classname();
866 if ($type=='import') {
867 $provided = $format_class->provide_import();
869 $provided = $format_class->provide_export();
872 //TODO: do NOT rely on [[]] any more!!
873 $formatname = get_string($fileformat, 'quiz');
874 if ($formatname == "[[$fileformat]]") {
875 $formatname = get_string($fileformat, 'qformat_'.$fileformat);
876 if ($formatname == "[[$fileformat]]") {
877 $formatname = $fileformat; // Just use the raw folder name
880 $fileformatnames[$fileformat] = $formatname;
883 natcasesort($fileformatnames);
885 return $fileformatnames;
889 * Serves the lesson attachments. Implements needed access control ;-)
891 * @param object $course
893 * @param object $context
894 * @param string $filearea
896 * @param bool $forcedownload
897 * @return bool false if file not found, does not return if found - justsend the file
899 function lesson_pluginfile($course, $cm, $context, $filearea, $args, $forcedownload) {
902 if ($context->contextlevel != CONTEXT_MODULE) {
906 $fileareas = lesson_get_file_areas();
907 if (!array_key_exists($filearea, $fileareas)) {
911 if (!$lesson = $DB->get_record('lesson', array('id'=>$cm->instance))) {
915 require_course_login($course, true, $cm);
917 if ($filearea === 'page_contents') {
918 $pageid = (int)array_shift($args);
919 if (!$page = $DB->get_record('lesson_pages', array('id'=>$pageid))) {
922 $fullpath = "/$context->id/mod_lesson/$filearea/$pageid/".implode('/', $args);
924 } else if ($filearea === 'mediafile') {
925 array_shift($args); // ignore itemid - caching only
926 $fullpath = "/$context->id/mod_lesson/$filearea/0/".implode('/', $args);
932 $fs = get_file_storage();
933 if (!$file = $fs->get_file_by_hash(sha1($fullpath)) or $file->is_directory()) {
937 // finally send the file
938 send_stored_file($file, 0, 0, $forcedownload); // download MUST be forced - security!
942 * Returns an array of file areas
945 function lesson_get_file_areas() {
947 $areas['page_contents'] = 'Page contents'; //TODO: localize!!!!
948 $areas['mediafile'] = 'Media file'; //TODO: localize!!!!
954 * Returns a file_info_stored object for the file being requested here
956 * @global <type> $CFG
957 * @param file_browse $browser
958 * @param array $areas
959 * @param object $course
961 * @param object $context
962 * @param string $filearea
964 * @param string $filepath
965 * @param string $filename
966 * @return file_info_stored
968 function lesson_get_file_info($browser, $areas, $course, $cm, $context, $filearea, $itemid, $filepath, $filename) {
970 if (has_capability('moodle/course:managefiles', $context)) {
971 // no peaking here for students!!
975 $fs = get_file_storage();
976 $filepath = is_null($filepath) ? '/' : $filepath;
977 $filename = is_null($filename) ? '.' : $filename;
978 $urlbase = $CFG->wwwroot.'/pluginfile.php';
979 if (!$storedfile = $fs->get_file($context->id, 'mod_lesson', $filearea, $itemid, $filepath, $filename)) {
982 return new file_info_stored($browser, $context, $storedfile, $urlbase, $filearea, $itemid, true, true, false);