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
22 * @copyright 1999 onwards Martin Dougiamas {@link http://moodle.com}
23 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
26 defined('MOODLE_INTERNAL') ||
die();
28 /* Do not include any libraries here! */
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.
38 * @param object $lesson Lesson post data from the form
41 function lesson_add_instance($data, $mform) {
44 $cmid = $data->coursemodule
;
45 $draftitemid = $data->mediafile
;
46 $context = context_module
::instance($cmid);
48 lesson_process_pre_save($data);
50 unset($data->mediafile
);
51 $lessonid = $DB->insert_record("lesson", $data);
52 $data->id
= $lessonid;
54 $lesson = $DB->get_record('lesson', array('id'=>$lessonid), '*', MUST_EXIST
);
56 lesson_update_media_file($lessonid, $context, $draftitemid);
58 lesson_process_post_save($data);
60 lesson_grade_item_update($data);
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.
71 * @param object $lesson Lesson post data from the form
74 function lesson_update_instance($data, $mform) {
77 $data->id
= $data->instance
;
78 $cmid = $data->coursemodule
;
79 $draftitemid = $data->mediafile
;
80 $context = context_module
::instance($cmid);
82 lesson_process_pre_save($data);
84 unset($data->mediafile
);
85 $DB->update_record("lesson", $data);
87 lesson_update_media_file($data->id
, $context, $draftitemid);
89 lesson_process_post_save($data);
91 // update grade item definition
92 lesson_grade_item_update($data);
94 // update grades - TODO: do it only when grading style changes
95 lesson_update_grades($data, 0, false);
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.
110 function lesson_delete_instance($id) {
112 require_once($CFG->dirroot
. '/mod/lesson/locallib.php');
114 $lesson = $DB->get_record("lesson", array("id"=>$id), '*', MUST_EXIST
);
115 $lesson = new lesson($lesson);
116 return $lesson->delete();
120 * Given a course object, this function will clean up anything that
121 * would be leftover after all the instances were deleted
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
128 function lesson_delete_course($course, $feedback=true) {
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
140 * @param object $course
141 * @param object $user
143 * @param object $lesson
146 function lesson_user_outline($course, $user, $mod, $lesson) {
149 require_once("$CFG->libdir/gradelib.php");
150 $grades = grade_get_grades($course->id
, 'mod', 'lesson', $lesson->id
, $user->id
);
152 $return = new stdClass();
153 if (empty($grades->items
[0]->grades
)) {
154 $return->info
= get_string("no")." ".get_string("attempts", "lesson");
156 $grade = reset($grades->items
[0]->grades
);
157 $return->info
= get_string("grade") . ': ' . $grade->str_long_grade
;
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
;
165 $return->time
= $grade->datesubmitted
;
172 * Print a detailed representation of what a user has done with
173 * a given particular instance of this module, for user activity reports.
176 * @param object $course
177 * @param object $user
179 * @param object $lesson
182 function lesson_user_complete($course, $user, $mod, $lesson) {
183 global $DB, $OUTPUT, $CFG;
185 require_once("$CFG->libdir/gradelib.php");
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
);
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;
213 foreach ($attempts as $attempt) {
214 if ($attempt->retry
== $retry) {
216 if ($attempt->correct
) {
219 $timeseen = $attempt->timeseen
;
221 $table->data
[] = array($retry +
1, $npages, $ncorrect, userdate($timeseen));
224 if ($attempt->correct
) {
232 $table->data
[] = array($retry +
1, $npages, $ncorrect, userdate($timeseen));
234 echo html_writer
::table($table);
235 echo $OUTPUT->box_end();
242 * Prints lesson summaries on MyMoodle Page
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.
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 )
256 function lesson_print_overview($courses, &$htmlarray) {
257 global $USER, $CFG, $DB, $OUTPUT;
259 if (!$lessons = get_all_instances_in_courses('lesson', $courses)) {
263 /// Get Necessary Strings
264 $strlesson = get_string('modulename', 'lesson');
265 $strnotattempted = get_string('nolessonattempts', 'lesson');
266 $strattempted = get_string('lessonattempted', 'lesson');
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
275 if (!$lesson->visible
) {
276 $class = ' class="dimmed"';
280 $str = $OUTPUT->box("$strlesson: <a$class href=\"$CFG->wwwroot/mod/lesson/view.php?id=$lesson->coursemodule\">".
281 format_string($lesson->name
).'</a>', 'name');
284 $str .= $OUTPUT->box(get_string('lessoncloseson', 'lesson', userdate($lesson->deadline
)), 'info');
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');
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');
296 $str .= $OUTPUT->box($strnotattempted, 'info');
299 $str = $OUTPUT->box($str, 'lesson overview');
301 if (empty($htmlarray[$lesson->course
]['lesson'])) {
302 $htmlarray[$lesson->course
]['lesson'] = $str;
304 $htmlarray[$lesson->course
]['lesson'] .= $str;
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 ...
317 function lesson_cron () {
324 * Return grade for given user or all users.
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
332 function lesson_get_user_grades($lesson, $userid=0) {
335 $params = array("lessonid" => $lesson->id
,"lessonid2" => $lesson->id
);
337 if (!empty($userid)) {
338 $params["userid"] = $userid;
339 $params["userid2"] = $userid;
340 $user = "AND u.id = :userid";
341 $fuser = "AND uu.id = :userid2";
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
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
362 unset($params['lessonid2']);
363 unset($params['userid2']);
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
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
379 return $DB->get_records_sql($sql, $params);
383 * Update grades in central gradebook
386 * @param object $lesson
387 * @param int $userid specific user only, 0 means all
388 * @param bool $nullifnone
390 function lesson_update_grades($lesson, $userid=0, $nullifnone=true) {
392 require_once($CFG->libdir
.'/gradelib.php');
394 if ($lesson->grade
== 0) {
395 lesson_grade_item_update($lesson);
397 } else if ($grades = lesson_get_user_grades($lesson, $userid)) {
398 lesson_grade_item_update($lesson, $grades);
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);
407 lesson_grade_item_update($lesson);
412 * Update all grades in gradebook.
416 function lesson_upgrade_grades() {
419 $sql = "SELECT COUNT('x')
420 FROM {lesson} l, {course_modules} cm, {modules} m
421 WHERE m.name='lesson' AND m.id=cm.module AND cm.instance=l.id";
422 $count = $DB->count_records_sql($sql);
424 $sql = "SELECT l.*, cm.idnumber AS cmidnumber, l.course AS courseid
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 $rs = $DB->get_recordset_sql($sql);
429 $pbar = new progress_bar('lessonupgradegrades', 500, true);
431 foreach ($rs as $lesson) {
433 upgrade_set_timeout(60*5); // set up timeout, may also abort execution
434 lesson_update_grades($lesson, 0, false);
435 $pbar->update($i, $count, "Updating Lesson grades ($i/$count).");
442 * Create grade item for given lesson
445 * @uses GRADE_TYPE_VALUE
446 * @uses GRADE_TYPE_NONE
447 * @param object $lesson object with extra cmidnumber
448 * @param array|object $grades optional array/object of grade(s); 'reset' means reset grades in gradebook
449 * @return int 0 if ok, error code otherwise
451 function lesson_grade_item_update($lesson, $grades=null) {
453 if (!function_exists('grade_update')) { //workaround for buggy PHP versions
454 require_once($CFG->libdir
.'/gradelib.php');
457 if (array_key_exists('cmidnumber', $lesson)) { //it may not be always present
458 $params = array('itemname'=>$lesson->name
, 'idnumber'=>$lesson->cmidnumber
);
460 $params = array('itemname'=>$lesson->name
);
463 if (!$lesson->practice
and $lesson->grade
> 0) {
464 $params['gradetype'] = GRADE_TYPE_VALUE
;
465 $params['grademax'] = $lesson->grade
;
466 $params['grademin'] = 0;
467 } else if (!$lesson->practice
and $lesson->grade
< 0) {
468 $params['gradetype'] = GRADE_TYPE_SCALE
;
469 $params['scaleid'] = -$lesson->grade
;
471 // Make sure current grade fetched correctly from $grades
472 $currentgrade = null;
473 if (!empty($grades)) {
474 if (is_array($grades)) {
475 $currentgrade = reset($grades);
477 $currentgrade = $grades;
481 // When converting a score to a scale, use scale's grade maximum to calculate it.
482 if (!empty($currentgrade) && $currentgrade->rawgrade
!== null) {
483 $grade = grade_get_grades($lesson->course
, 'mod', 'lesson', $lesson->id
, $currentgrade->userid
);
484 $params['grademax'] = reset($grade->items
)->grademax
;
487 $params['gradetype'] = GRADE_TYPE_NONE
;
490 if ($grades === 'reset') {
491 $params['reset'] = true;
493 } else if (!empty($grades)) {
494 // Need to calculate raw grade (Note: $grades has many forms)
495 if (is_object($grades)) {
496 $grades = array($grades->userid
=> $grades);
497 } else if (array_key_exists('userid', $grades)) {
498 $grades = array($grades['userid'] => $grades);
500 foreach ($grades as $key => $grade) {
501 if (!is_array($grade)) {
502 $grades[$key] = $grade = (array) $grade;
504 //check raw grade isnt null otherwise we erroneously insert a grade of 0
505 if ($grade['rawgrade'] !== null) {
506 $grades[$key]['rawgrade'] = ($grade['rawgrade'] * $params['grademax'] / 100);
508 //setting rawgrade to null just in case user is deleting a grade
509 $grades[$key]['rawgrade'] = null;
514 return grade_update('mod/lesson', $lesson->course
, 'mod', 'lesson', $lesson->id
, 0, $grades, $params);
518 * Delete grade item for given lesson
521 * @param object $lesson object
522 * @return object lesson
524 function lesson_grade_item_delete($lesson) {
530 * List the actions that correspond to a view of this module.
531 * This is used by the participation report.
533 * Note: This is not used by new logging system. Event with
534 * crud = 'r' and edulevel = LEVEL_PARTICIPATING will
535 * be considered as view action.
539 function lesson_get_view_actions() {
540 return array('view','view all');
544 * List the actions that correspond to a post of this module.
545 * This is used by the participation report.
547 * Note: This is not used by new logging system. Event with
548 * crud = ('c' || 'u' || 'd') and edulevel = LEVEL_PARTICIPATING
549 * will be considered as post action.
553 function lesson_get_post_actions() {
554 return array('end','start');
558 * Runs any processes that must run before
559 * a lesson insert/update
562 * @param object $lesson Lesson form data
565 function lesson_process_pre_save(&$lesson) {
568 $lesson->timemodified
= time();
570 if (empty($lesson->timed
)) {
573 if (empty($lesson->timespent
) or !is_numeric($lesson->timespent
) or $lesson->timespent
< 0) {
574 $lesson->timespent
= 0;
576 if (!isset($lesson->completed
)) {
577 $lesson->completed
= 0;
579 if (empty($lesson->gradebetterthan
) or !is_numeric($lesson->gradebetterthan
) or $lesson->gradebetterthan
< 0) {
580 $lesson->gradebetterthan
= 0;
581 } else if ($lesson->gradebetterthan
> 100) {
582 $lesson->gradebetterthan
= 100;
585 if (empty($lesson->width
)) {
586 $lesson->width
= 640;
588 if (empty($lesson->height
)) {
589 $lesson->height
= 480;
591 if (empty($lesson->bgcolor
)) {
592 $lesson->bgcolor
= '#FFFFFF';
595 // Conditions for dependency
596 $conditions = new stdClass
;
597 $conditions->timespent
= $lesson->timespent
;
598 $conditions->completed
= $lesson->completed
;
599 $conditions->gradebetterthan
= $lesson->gradebetterthan
;
600 $lesson->conditions
= serialize($conditions);
601 unset($lesson->timespent
);
602 unset($lesson->completed
);
603 unset($lesson->gradebetterthan
);
605 if (empty($lesson->password
)) {
606 unset($lesson->password
);
611 * Runs any processes that must be run
612 * after a lesson insert/update
615 * @param object $lesson Lesson form data
618 function lesson_process_post_save(&$lesson) {
620 require_once($CFG->dirroot
.'/calendar/lib.php');
621 require_once($CFG->dirroot
. '/mod/lesson/locallib.php');
623 if ($events = $DB->get_records('event', array('modulename'=>'lesson', 'instance'=>$lesson->id
))) {
624 foreach($events as $event) {
625 $event = calendar_event
::load($event->id
);
630 $event = new stdClass
;
631 $event->description
= $lesson->name
;
632 $event->courseid
= $lesson->course
;
635 $event->modulename
= 'lesson';
636 $event->instance
= $lesson->id
;
637 $event->eventtype
= 'open';
638 $event->timestart
= $lesson->available
;
640 $event->visible
= instance_is_visible('lesson', $lesson);
642 $event->timeduration
= ($lesson->deadline
- $lesson->available
);
644 if ($lesson->deadline
and $lesson->available
and $event->timeduration
<= LESSON_MAX_EVENT_LENGTH
) {
645 // Single event for the whole lesson.
646 $event->name
= $lesson->name
;
647 calendar_event
::create(clone($event));
649 // Separate start and end events.
650 $event->timeduration
= 0;
651 if ($lesson->available
) {
652 $event->name
= $lesson->name
.' ('.get_string('lessonopens', 'lesson').')';
653 calendar_event
::create(clone($event));
656 if ($lesson->deadline
) {
657 $event->name
= $lesson->name
.' ('.get_string('lessoncloses', 'lesson').')';
658 $event->timestart
= $lesson->deadline
;
659 $event->eventtype
= 'close';
660 calendar_event
::create(clone($event));
667 * Implementation of the function for printing the form elements that control
668 * whether the course reset functionality affects the lesson.
670 * @param $mform form passed by reference
672 function lesson_reset_course_form_definition(&$mform) {
673 $mform->addElement('header', 'lessonheader', get_string('modulenameplural', 'lesson'));
674 $mform->addElement('advcheckbox', 'reset_lesson', get_string('deleteallattempts','lesson'));
678 * Course reset form defaults.
679 * @param object $course
682 function lesson_reset_course_form_defaults($course) {
683 return array('reset_lesson'=>1);
687 * Removes all grades from gradebook
691 * @param int $courseid
692 * @param string optional type
694 function lesson_reset_gradebook($courseid, $type='') {
697 $sql = "SELECT l.*, cm.idnumber as cmidnumber, l.course as courseid
698 FROM {lesson} l, {course_modules} cm, {modules} m
699 WHERE m.name='lesson' AND m.id=cm.module AND cm.instance=l.id AND l.course=:course";
700 $params = array ("course" => $courseid);
701 if ($lessons = $DB->get_records_sql($sql,$params)) {
702 foreach ($lessons as $lesson) {
703 lesson_grade_item_update($lesson, 'reset');
709 * Actual implementation of the reset course functionality, delete all the
710 * lesson attempts for course $data->courseid.
714 * @param object $data the data submitted from the reset course.
715 * @return array status array
717 function lesson_reset_userdata($data) {
720 $componentstr = get_string('modulenameplural', 'lesson');
723 if (!empty($data->reset_lesson
)) {
724 $lessonssql = "SELECT l.id
726 WHERE l.course=:course";
728 $params = array ("course" => $data->courseid
);
729 $DB->delete_records_select('lesson_timer', "lessonid IN ($lessonssql)", $params);
730 $DB->delete_records_select('lesson_high_scores', "lessonid IN ($lessonssql)", $params);
731 $DB->delete_records_select('lesson_grades', "lessonid IN ($lessonssql)", $params);
732 $DB->delete_records_select('lesson_attempts', "lessonid IN ($lessonssql)", $params);
734 // remove all grades from gradebook
735 if (empty($data->reset_gradebook_grades
)) {
736 lesson_reset_gradebook($data->courseid
);
739 $status[] = array('component'=>$componentstr, 'item'=>get_string('deleteallattempts', 'lesson'), 'error'=>false);
742 /// updating dates - shift may be negative too
743 if ($data->timeshift
) {
744 shift_course_mod_dates('lesson', array('available', 'deadline'), $data->timeshift
, $data->courseid
);
745 $status[] = array('component'=>$componentstr, 'item'=>get_string('datechanged'), 'error'=>false);
752 * Returns all other caps used in module
755 function lesson_get_extra_capabilities() {
756 return array('moodle/site:accessallgroups');
760 * @uses FEATURE_GROUPS
761 * @uses FEATURE_GROUPINGS
762 * @uses FEATURE_GROUPMEMBERSONLY
763 * @uses FEATURE_MOD_INTRO
764 * @uses FEATURE_COMPLETION_TRACKS_VIEWS
765 * @uses FEATURE_GRADE_HAS_GRADE
766 * @uses FEATURE_GRADE_OUTCOMES
767 * @param string $feature FEATURE_xx constant for requested feature
768 * @return mixed True if module supports feature, false if not, null if doesn't know
770 function lesson_supports($feature) {
772 case FEATURE_GROUPS
: return false;
773 case FEATURE_GROUPINGS
: return false;
774 case FEATURE_GROUPMEMBERSONLY
: return true;
775 case FEATURE_MOD_INTRO
: return false;
776 case FEATURE_COMPLETION_TRACKS_VIEWS
: return true;
777 case FEATURE_GRADE_HAS_GRADE
: return true;
778 case FEATURE_GRADE_OUTCOMES
: return true;
779 case FEATURE_BACKUP_MOODLE2
: return true;
780 default: return null;
785 * This function extends the settings navigation block for the site.
787 * It is safe to rely on PAGE here as we will only ever be within the module
788 * context when this is called
790 * @param settings_navigation $settings
791 * @param navigation_node $lessonnode
793 function lesson_extend_settings_navigation($settings, $lessonnode) {
796 $canedit = has_capability('mod/lesson:edit', $PAGE->cm
->context
);
799 $url = new moodle_url('/mod/lesson/view.php', array('id' => $PAGE->cm
->id
));
800 $lessonnode->add(get_string('preview', 'lesson'), $url);
801 $url = new moodle_url('/mod/lesson/edit.php', array('id'=>$PAGE->cm
->id
));
802 $lessonnode->add(get_string('edit', 'lesson'), $url);
805 if (has_capability('mod/lesson:manage', $PAGE->cm
->context
)) {
806 $reportsnode = $lessonnode->add(get_string('reports', 'lesson'));
807 $url = new moodle_url('/mod/lesson/report.php', array('id'=>$PAGE->cm
->id
, 'action'=>'reportoverview'));
808 $reportsnode->add(get_string('overview', 'lesson'), $url);
809 $url = new moodle_url('/mod/lesson/report.php', array('id'=>$PAGE->cm
->id
, 'action'=>'reportdetail'));
810 $reportsnode->add(get_string('detailedstats', 'lesson'), $url);
814 $url = new moodle_url('/mod/lesson/essay.php', array('id'=>$PAGE->cm
->id
));
815 $lessonnode->add(get_string('manualgrading', 'lesson'), $url);
818 if ($PAGE->activityrecord
->highscores
) {
819 $url = new moodle_url('/mod/lesson/highscores.php', array('id'=>$PAGE->cm
->id
));
820 $lessonnode->add(get_string('highscores', 'lesson'), $url);
825 * Get list of available import or export formats
827 * Copied and modified from lib/questionlib.php
829 * @param string $type 'import' if import list, otherwise export list assumed
830 * @return array sorted list of import/export formats available
832 function lesson_get_import_export_formats($type) {
834 $fileformats = core_component
::get_plugin_list("qformat");
836 $fileformatname=array();
837 foreach ($fileformats as $fileformat=>$fdir) {
838 $format_file = "$fdir/format.php";
839 if (file_exists($format_file) ) {
840 require_once($format_file);
844 $classname = "qformat_$fileformat";
845 $format_class = new $classname();
846 if ($type=='import') {
847 $provided = $format_class->provide_import();
849 $provided = $format_class->provide_export();
852 $fileformatnames[$fileformat] = get_string('pluginname', 'qformat_'.$fileformat);
855 natcasesort($fileformatnames);
857 return $fileformatnames;
861 * Serves the lesson attachments. Implements needed access control ;-)
863 * @package mod_lesson
865 * @param stdClass $course course object
866 * @param stdClass $cm course module object
867 * @param stdClass $context context object
868 * @param string $filearea file area
869 * @param array $args extra arguments
870 * @param bool $forcedownload whether or not force download
871 * @param array $options additional options affecting the file serving
872 * @return bool false if file not found, does not return if found - justsend the file
874 function lesson_pluginfile($course, $cm, $context, $filearea, $args, $forcedownload, array $options=array()) {
877 if ($context->contextlevel
!= CONTEXT_MODULE
) {
881 $fileareas = lesson_get_file_areas();
882 if (!array_key_exists($filearea, $fileareas)) {
886 if (!$lesson = $DB->get_record('lesson', array('id'=>$cm->instance
))) {
890 require_course_login($course, true, $cm);
892 if ($filearea === 'page_contents') {
893 $pageid = (int)array_shift($args);
894 if (!$page = $DB->get_record('lesson_pages', array('id'=>$pageid))) {
897 $fullpath = "/$context->id/mod_lesson/$filearea/$pageid/".implode('/', $args);
899 } else if ($filearea === 'mediafile') {
900 if (count($args) > 1) {
901 // Remove the itemid when it appears to be part of the arguments. If there is only one argument
902 // then it is surely the file name. The itemid is sometimes used to prevent browser caching.
905 $fullpath = "/$context->id/mod_lesson/$filearea/0/".implode('/', $args);
911 $fs = get_file_storage();
912 if (!$file = $fs->get_file_by_hash(sha1($fullpath)) or $file->is_directory()) {
916 // finally send the file
917 send_stored_file($file, 0, 0, $forcedownload, $options); // download MUST be forced - security!
921 * Returns an array of file areas
923 * @package mod_lesson
925 * @return array a list of available file areas
927 function lesson_get_file_areas() {
929 $areas['page_contents'] = get_string('pagecontents', 'mod_lesson');
930 $areas['mediafile'] = get_string('mediafile', 'mod_lesson');
935 * Returns a file_info_stored object for the file being requested here
937 * @package mod_lesson
939 * @global stdClass $CFG
940 * @param file_browse $browser file browser instance
941 * @param array $areas file areas
942 * @param stdClass $course course object
943 * @param stdClass $cm course module object
944 * @param stdClass $context context object
945 * @param string $filearea file area
946 * @param int $itemid item ID
947 * @param string $filepath file path
948 * @param string $filename file name
949 * @return file_info_stored
951 function lesson_get_file_info($browser, $areas, $course, $cm, $context, $filearea, $itemid, $filepath, $filename) {
954 if (!has_capability('moodle/course:managefiles', $context)) {
955 // No peaking here for students!
959 // Mediafile area does not have sub directories, so let's select the default itemid to prevent
960 // the user from selecting a directory to access the mediafile content.
961 if ($filearea == 'mediafile' && is_null($itemid)) {
965 if (is_null($itemid)) {
966 return new mod_lesson_file_info($browser, $course, $cm, $context, $areas, $filearea);
969 $fs = get_file_storage();
970 $filepath = is_null($filepath) ?
'/' : $filepath;
971 $filename = is_null($filename) ?
'.' : $filename;
972 if (!$storedfile = $fs->get_file($context->id
, 'mod_lesson', $filearea, $itemid, $filepath, $filename)) {
976 $itemname = $filearea;
977 if ($filearea == 'page_contents') {
978 $itemname = $DB->get_field('lesson_pages', 'title', array('lessonid' => $cm->instance
, 'id' => $itemid));
979 $itemname = format_string($itemname, true, array('context' => $context));
981 $areas = lesson_get_file_areas();
982 if (isset($areas[$filearea])) {
983 $itemname = $areas[$filearea];
987 $urlbase = $CFG->wwwroot
. '/pluginfile.php';
988 return new file_info_stored($browser, $context, $storedfile, $urlbase, $itemname, $itemid, true, true, false);
993 * Return a list of page types
994 * @param string $pagetype current page type
995 * @param stdClass $parentcontext Block's parent context
996 * @param stdClass $currentcontext Current context of block
998 function lesson_page_type_list($pagetype, $parentcontext, $currentcontext) {
999 $module_pagetype = array(
1000 'mod-lesson-*'=>get_string('page-mod-lesson-x', 'lesson'),
1001 'mod-lesson-view'=>get_string('page-mod-lesson-view', 'lesson'),
1002 'mod-lesson-edit'=>get_string('page-mod-lesson-edit', 'lesson'));
1003 return $module_pagetype;
1007 * Update the lesson activity to include any file
1008 * that was uploaded, or if there is none, set the
1009 * mediafile field to blank.
1011 * @param int $lessonid the lesson id
1012 * @param stdClass $context the context
1013 * @param int $draftitemid the draft item
1015 function lesson_update_media_file($lessonid, $context, $draftitemid) {
1018 // Set the filestorage object.
1019 $fs = get_file_storage();
1020 // Save the file if it exists that is currently in the draft area.
1021 file_save_draft_area_files($draftitemid, $context->id
, 'mod_lesson', 'mediafile', 0);
1022 // Get the file if it exists.
1023 $files = $fs->get_area_files($context->id
, 'mod_lesson', 'mediafile', 0, 'itemid, filepath, filename', false);
1024 // Check that there is a file to process.
1025 if (count($files) == 1) {
1026 // Get the first (and only) file.
1027 $file = reset($files);
1028 // Set the mediafile column in the lessons table.
1029 $DB->set_field('lesson', 'mediafile', '/' . $file->get_filename(), array('id' => $lessonid));
1031 // Set the mediafile column in the lessons table.
1032 $DB->set_field('lesson', 'mediafile', '', array('id' => $lessonid));